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