blob: 825b989a16282e3668c505704a90abfd52666819 [file] [log] [blame]
Rajeev Kumar Sirasanagandla4725ae42018-05-24 22:33:34 +05301/*
2 * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/**
20 * DOC: Implement various notification handlers which are accessed
21 * internally in action_oui component only.
22 */
23
24#include "wlan_action_oui_main.h"
25#include "wlan_action_oui_public_struct.h"
26#include "wlan_action_oui_tgt_api.h"
27#include "target_if_action_oui.h"
28
29/**
30 * action_oui_allocate() - Allocates memory for various actions.
31 * @psoc_priv: pointer to action_oui psoc priv obj
32 *
33 * This function allocates memory for all the action_oui types
34 * and initializes the respective lists to store extensions
35 * extracted from action_oui_extract().
36 *
37 * Return: QDF_STATUS
38 */
39static QDF_STATUS
40action_oui_allocate(struct action_oui_psoc_priv *psoc_priv)
41{
42 struct action_oui_priv *oui_priv;
43 uint32_t i;
44 uint32_t j;
45
46 for (i = 0; i < ACTION_OUI_MAXIMUM_ID; i++) {
47 oui_priv = qdf_mem_malloc(sizeof(*oui_priv));
48 if (!oui_priv) {
49 action_oui_err("Mem alloc failed for oui_priv id: %u",
50 i);
51 goto free_mem;
52 }
53 oui_priv->id = i;
54 qdf_list_create(&oui_priv->extension_list,
55 ACTION_OUI_MAX_EXTENSIONS);
56 qdf_mutex_create(&oui_priv->extension_lock);
57 psoc_priv->oui_priv[i] = oui_priv;
58 }
59
60 return QDF_STATUS_SUCCESS;
61
62free_mem:
63 for (j = 0; j < i; j++) {
64 oui_priv = psoc_priv->oui_priv[j];
65 if (!oui_priv)
66 continue;
67
68 qdf_list_destroy(&oui_priv->extension_list);
69 qdf_mutex_destroy(&oui_priv->extension_lock);
70 psoc_priv->oui_priv[j] = NULL;
71 }
72
73 return QDF_STATUS_E_NOMEM;
74}
75
76/**
77 * action_oui_destroy() - Deallocates memory for various actions.
78 * @psoc_priv: pointer to action_oui psoc priv obj
79 *
80 * This function Deallocates memory for all the action_oui types.
81 * As a part of deallocate, all extensions are destroyed.
82 *
83 * Return: None
84 */
85static void
86action_oui_destroy(struct action_oui_psoc_priv *psoc_priv)
87{
88 struct action_oui_priv *oui_priv;
89 struct action_oui_extension_priv *ext_priv;
90 qdf_list_t *ext_list;
91 QDF_STATUS status;
92 qdf_list_node_t *node = NULL;
93 uint32_t i;
94
95 psoc_priv->total_extensions = 0;
96 for (i = 0; i < ACTION_OUI_MAXIMUM_ID; i++) {
97 oui_priv = psoc_priv->oui_priv[i];
98 psoc_priv->oui_priv[i] = NULL;
99 if (!oui_priv)
100 continue;
101
102 ext_list = &oui_priv->extension_list;
103 qdf_mutex_acquire(&oui_priv->extension_lock);
104 while (!qdf_list_empty(ext_list)) {
105 status = qdf_list_remove_front(ext_list, &node);
106 if (!QDF_IS_STATUS_SUCCESS(status)) {
107 action_oui_err("Invalid delete in action: %u",
108 oui_priv->id);
109 break;
110 }
111 ext_priv = qdf_container_of(node,
112 struct action_oui_extension_priv,
113 item);
114 qdf_mem_free(ext_priv);
115 ext_priv = NULL;
116 }
117
118 qdf_list_destroy(ext_list);
119 qdf_mutex_release(&oui_priv->extension_lock);
120 qdf_mutex_destroy(&oui_priv->extension_lock);
121 qdf_mem_free(oui_priv);
122 oui_priv = NULL;
123 }
124}
125
126QDF_STATUS
127action_oui_psoc_create_notification(struct wlan_objmgr_psoc *psoc, void *arg)
128{
129 struct action_oui_psoc_priv *psoc_priv;
130 QDF_STATUS status;
131
132 ACTION_OUI_ENTER();
133
134 psoc_priv = qdf_mem_malloc(sizeof(*psoc_priv));
135 if (!psoc_priv) {
136 action_oui_err("Failed to allocate psoc_priv");
137 status = QDF_STATUS_E_NOMEM;
138 goto exit;
139 }
140
141 status = wlan_objmgr_psoc_component_obj_attach(psoc,
142 WLAN_UMAC_COMP_ACTION_OUI,
143 (void *)psoc_priv, QDF_STATUS_SUCCESS);
144 if (!QDF_IS_STATUS_SUCCESS(status)) {
145 action_oui_err("Failed to attach priv with psoc");
146 goto free_psoc_priv;
147 }
148
149 target_if_action_oui_register_tx_ops(&psoc_priv->tx_ops);
150 psoc_priv->psoc = psoc;
151
152 status = action_oui_allocate(psoc_priv);
153 if (!QDF_IS_STATUS_SUCCESS(status)) {
154 action_oui_err("Failed to alloc action_oui");
155 goto detach_psoc_priv;
156 }
157
158 action_oui_debug("psoc priv attached");
159 goto exit;
160
161detach_psoc_priv:
162 wlan_objmgr_psoc_component_obj_detach(psoc,
163 WLAN_UMAC_COMP_ACTION_OUI,
164 (void *)psoc_priv);
165free_psoc_priv:
166 qdf_mem_free(psoc_priv);
167 status = QDF_STATUS_E_INVAL;
168exit:
169 ACTION_OUI_EXIT();
170 return status;
171}
172
173QDF_STATUS
174action_oui_psoc_destroy_notification(struct wlan_objmgr_psoc *psoc, void *arg)
175{
176 struct action_oui_psoc_priv *psoc_priv = NULL;
177 QDF_STATUS status = QDF_STATUS_E_FAILURE;
178
179 ACTION_OUI_ENTER();
180
181 psoc_priv = action_oui_psoc_get_priv(psoc);
182 if (!psoc_priv) {
183 action_oui_err("psoc priv is NULL");
184 goto exit;
185 }
186
187 status = wlan_objmgr_psoc_component_obj_detach(psoc,
188 WLAN_UMAC_COMP_ACTION_OUI,
189 (void *)psoc_priv);
190 if (!QDF_IS_STATUS_SUCCESS(status))
191 action_oui_err("Failed to detach priv with psoc");
192
193 action_oui_destroy(psoc_priv);
194 qdf_mem_free(psoc_priv);
195
196exit:
197 ACTION_OUI_EXIT();
198 return status;
199}