1 /*
2 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /**
18 * DOC: wlan_afc_main.c
19 * This file provides implementation for UMAC AFC common APIs.
20 */
21
22 #include <wlan_afc_main.h>
23 #include "wlan_afc_priv.h"
24 #include "wlan_reg_ucfg_api.h"
25 #include "wlan_cfg80211_afc.h"
26
27 /**
28 * wlan_send_afc_request() - PDEV callback function to send AFC request
29 * @pdev: Pointer to PDEV object
30 * @afc_req: Pointer to AFC request from regulatory component
31 * @arg: Pointer to argument list of callback function
32 *
33 * Return: None
34 */
35 static void
wlan_send_afc_request(struct wlan_objmgr_pdev * pdev,struct wlan_afc_host_request * afc_req,void * arg)36 wlan_send_afc_request(struct wlan_objmgr_pdev *pdev,
37 struct wlan_afc_host_request *afc_req,
38 void *arg)
39 {
40 struct wlan_objmgr_psoc *psoc;
41 struct wlan_afc_psoc_priv *afc_priv;
42
43 psoc = wlan_pdev_get_psoc(pdev);
44
45 afc_priv = afc_psoc_priv(psoc);
46 if (!afc_priv) {
47 afc_err("psoc AFC private null");
48 return;
49 }
50
51 if (afc_priv->cbs.afc_req_func)
52 afc_priv->cbs.afc_req_func(pdev, afc_req);
53 }
54
55 /**
56 * wlan_send_afc_power_event() - PDEV callback function to send AFC power
57 * update complete event.
58 * @pdev: Pointer to PDEV object
59 * @afc_pwr_evt: Pointer to AFC power event from regulatory component
60 * @arg: Pointer to argument list of callback function
61 *
62 * Return: None
63 */
64 static void
wlan_send_afc_power_event(struct wlan_objmgr_pdev * pdev,struct reg_fw_afc_power_event * afc_pwr_evt,void * arg)65 wlan_send_afc_power_event(struct wlan_objmgr_pdev *pdev,
66 struct reg_fw_afc_power_event *afc_pwr_evt,
67 void *arg)
68 {
69 struct wlan_objmgr_psoc *psoc;
70 struct wlan_afc_psoc_priv *afc_priv;
71
72 psoc = wlan_pdev_get_psoc(pdev);
73
74 afc_priv = afc_psoc_priv(psoc);
75 if (!afc_priv) {
76 afc_err("psoc AFC private null");
77 return;
78 }
79
80 if (afc_priv->cbs.afc_updated_func)
81 afc_priv->cbs.afc_updated_func(pdev, afc_pwr_evt);
82 }
83
wlan_afc_data_send(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev,struct wlan_afc_host_resp * data,uint32_t len)84 int wlan_afc_data_send(struct wlan_objmgr_psoc *psoc,
85 struct wlan_objmgr_pdev *pdev,
86 struct wlan_afc_host_resp *data,
87 uint32_t len)
88 {
89 struct wlan_afc_psoc_priv *afc_priv;
90
91 afc_priv = afc_psoc_priv(psoc);
92 if (!afc_priv) {
93 afc_err("psoc AFC private null");
94 return -EINVAL;
95 }
96
97 if (afc_priv->cbs.afc_rsp_cp_func)
98 return afc_priv->cbs.afc_rsp_cp_func(psoc, pdev, data, len);
99
100 return -EINVAL;
101 }
102
wlan_afc_register_data_send_cb(struct wlan_objmgr_psoc * psoc,send_response_to_afcmem func)103 QDF_STATUS wlan_afc_register_data_send_cb(struct wlan_objmgr_psoc *psoc,
104 send_response_to_afcmem func)
105 {
106 struct wlan_afc_psoc_priv *afc_priv;
107
108 afc_priv = afc_psoc_priv(psoc);
109 if (!afc_priv) {
110 afc_err("psoc AFC private null");
111 return QDF_STATUS_E_FAILURE;
112 }
113
114 afc_priv->cbs.afc_rsp_cp_func = func;
115
116 return QDF_STATUS_SUCCESS;
117 }
118
119 QDF_STATUS
wlan_afc_psoc_created_notification(struct wlan_objmgr_psoc * psoc,void * arg)120 wlan_afc_psoc_created_notification(struct wlan_objmgr_psoc *psoc,
121 void *arg)
122 {
123 QDF_STATUS status;
124 struct wlan_afc_psoc_priv *afc_priv;
125
126 afc_priv = qdf_mem_malloc(sizeof(*afc_priv));
127 if (!afc_priv)
128 return QDF_STATUS_E_NOMEM;
129
130 status = wlan_objmgr_psoc_component_obj_attach(psoc,
131 WLAN_UMAC_COMP_AFC,
132 afc_priv,
133 QDF_STATUS_SUCCESS);
134
135 if (QDF_IS_STATUS_ERROR(status)) {
136 qdf_mem_free(afc_priv);
137 afc_err("Failed to attach psoc AFC component");
138 return status;
139 }
140
141 afc_priv->psoc = psoc;
142 afc_priv->cbs.afc_req_func = wlan_cfg80211_afc_send_request;
143 afc_priv->cbs.afc_updated_func = wlan_cfg80211_afc_send_update_complete;
144
145 return status;
146 }
147
148 QDF_STATUS
wlan_afc_psoc_destroyed_notification(struct wlan_objmgr_psoc * psoc,void * arg)149 wlan_afc_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc,
150 void *arg)
151 {
152 QDF_STATUS status;
153 void *afc_priv;
154
155 afc_priv = afc_psoc_priv(psoc);
156 if (!afc_priv) {
157 afc_err("Failed to get psoc AFC component private");
158 return QDF_STATUS_E_FAILURE;
159 }
160
161 status = wlan_objmgr_psoc_component_obj_detach(psoc,
162 WLAN_UMAC_COMP_AFC,
163 afc_priv);
164 if (QDF_IS_STATUS_ERROR(status))
165 afc_err("Failed to detach AFC component");
166
167 qdf_mem_free(afc_priv);
168
169 return status;
170 }
171
172 QDF_STATUS
wlan_afc_pdev_obj_create_handler(struct wlan_objmgr_pdev * pdev,void * arg)173 wlan_afc_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev,
174 void *arg)
175 {
176 QDF_STATUS status;
177
178 status = ucfg_reg_register_afc_req_rx_callback(pdev,
179 wlan_send_afc_request,
180 NULL);
181 if (QDF_IS_STATUS_ERROR(status)) {
182 afc_err("Failed to register AFC request callback");
183 return status;
184 }
185
186 status = ucfg_reg_register_afc_power_event_callback(pdev,
187 wlan_send_afc_power_event,
188 NULL);
189 if (QDF_IS_STATUS_ERROR(status)) {
190 afc_err("Failed to register AFC power callback");
191 ucfg_reg_unregister_afc_req_rx_callback(pdev,
192 wlan_send_afc_request);
193 return status;
194 }
195
196 return status;
197 }
198
199 QDF_STATUS
wlan_afc_pdev_obj_destroy_handler(struct wlan_objmgr_pdev * pdev,void * arg)200 wlan_afc_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg)
201 {
202 ucfg_reg_unregister_afc_req_rx_callback(pdev,
203 wlan_send_afc_request);
204 ucfg_reg_unregister_afc_power_event_callback(pdev,
205 wlan_send_afc_power_event);
206
207 return QDF_STATUS_SUCCESS;
208 }
209