blob: 7eeb91ab8dc19782bccf8d16603218a1c5d2aeb9 [file] [log] [blame]
Varsha Mishrae58d93b2017-05-20 20:54:41 +05301/*
2 **************************************************************************
Stephen Wang3e2dbd12018-03-14 17:28:17 -07003 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
Varsha Mishrae58d93b2017-05-20 20:54:41 +05304 * 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 copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
16
17#include "nss_tx_rx_common.h"
Yu Huang8c107082017-07-24 14:58:26 -070018#include "nss_wifili_stats.h"
Sachin Shashidharc7b2e002018-08-20 13:52:51 -070019#include "nss_wifili_log.h"
Varsha Mishrae58d93b2017-05-20 20:54:41 +053020
21#define NSS_WIFILI_TX_TIMEOUT 1000 /* Millisecond to jiffies*/
22
23/*
24 * nss_wifili_pvt
25 * Private data structure
26 */
27static struct nss_wifili_pvt {
28 struct semaphore sem;
29 struct completion complete;
30 int response;
31 void *cb;
32 void *app_data;
33} wifili_pvt;
34
35/*
Varsha Mishrae58d93b2017-05-20 20:54:41 +053036 * nss_wifili_handler()
37 * Handle NSS -> HLOS messages for wifi
38 */
39static void nss_wifili_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
40{
41 struct nss_wifili_msg *ntm = (struct nss_wifili_msg *)ncm;
42 void *ctx;
43 nss_wifili_msg_callback_t cb;
44
45 nss_info("%p: NSS->HLOS message for wifili\n", nss_ctx);
46
47 /*
48 * The interface number shall be wifili soc interface or wifili radio interface
49 */
50 BUG_ON((nss_is_dynamic_interface(ncm->interface)) || ncm->interface != NSS_WIFILI_INTERFACE);
51
52 /*
Sachin Shashidharc7b2e002018-08-20 13:52:51 -070053 * Trace messages.
54 */
55 nss_wifili_log_rx_msg(ntm);
56
57 /*
Varsha Mishrae58d93b2017-05-20 20:54:41 +053058 * Is this a valid request/response packet?
59 */
60 if (ncm->type >= NSS_WIFILI_MAX_MSG) {
61 nss_warning("%p: Received invalid message %d for wifili interface", nss_ctx, ncm->type);
62 return;
63 }
64
65 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_wifili_msg)) {
66 nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
67 return;
68 }
69
70 /*
71 * Snoop messages for local driver and handle
72 */
73 switch (ntm->cm.type) {
Aniruddha Paul1b170c22017-05-29 12:30:39 +053074 case NSS_WIFILI_STATS_MSG:
Varsha Mishrae58d93b2017-05-20 20:54:41 +053075 nss_wifili_stats_sync(nss_ctx, &ntm->msg.wlsoc_stats, ncm->interface);
76 break;
77 }
78
79 /*
80 * Update the callback and app_data for notify messages, wifili sends all notify messages
81 * to the same callback/app_data.
82 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +053083 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
Varsha Mishrae58d93b2017-05-20 20:54:41 +053084 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->wifili_msg_callback;
85 }
86
87 /*
88 * Log failures
89 */
90 nss_core_log_msg_failures(nss_ctx, ncm);
91
92 /*
93 * Do we have a call back
94 */
95 if (!ncm->cb) {
96 nss_info("%p: cb null for wifili interface %d", nss_ctx, ncm->interface);
97 return;
98 }
99
100 /*
101 * Get callback & context
102 */
103 cb = (nss_wifili_msg_callback_t)ncm->cb;
104 ctx = nss_ctx->subsys_dp_register[ncm->interface].ndev;
105
106 /*
107 * call wifili msg callback
108 */
109 if (!ctx) {
110 nss_warning("%p: Event received for wifili interface %d before registration", nss_ctx, ncm->interface);
111 return;
112 }
113
114 cb(ctx, ntm);
115}
116
117/*
118 * nss_wifili_callback()
119 * Callback to handle the completion of NSS->HLOS messages.
120 */
121static void nss_wifili_callback(void *app_data, struct nss_wifili_msg *nvm)
122{
123 nss_wifili_msg_callback_t callback = (nss_wifili_msg_callback_t)wifili_pvt.cb;
124 void *data = wifili_pvt.app_data;
125
126 wifili_pvt.response = NSS_TX_SUCCESS;
127 wifili_pvt.cb = NULL;
128 wifili_pvt.app_data = NULL;
129
130 if (nvm->cm.response != NSS_CMN_RESPONSE_ACK) {
131 nss_warning("wifili error response %d\n", nvm->cm.response);
132 wifili_pvt.response = nvm->cm.response;
133 }
134
135 if (callback) {
136 callback(data, nvm);
137 }
138 complete(&wifili_pvt.complete);
139}
140
141/*
142 * nss_wifili_tx_msg
143 * Transmit a wifili message to NSS FW
144 *
145 * NOTE: The caller is expected to handle synchronous wait for message
146 * response if needed.
147 */
148nss_tx_status_t nss_wifili_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_wifili_msg *msg)
149{
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530150 struct nss_cmn_msg *ncm = &msg->cm;
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530151
Sachin Shashidharc7b2e002018-08-20 13:52:51 -0700152 /*
153 * Trace messages.
154 */
155 nss_wifili_log_tx_msg(msg);
156
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530157 if (ncm->type >= NSS_WIFILI_MAX_MSG) {
158 nss_warning("%p: wifili message type out of range: %d", nss_ctx, ncm->type);
159 return NSS_TX_FAILURE;
160 }
161
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530162 /*
163 * The interface number shall be wifili soc interface or wifili radio interface
164 */
165 if (ncm->interface != NSS_WIFILI_INTERFACE) {
166 nss_warning("%p: tx request for interface that is not a wifili: %d", nss_ctx, ncm->interface);
167 return NSS_TX_FAILURE;
168 }
169
Stephen Wang3e2dbd12018-03-14 17:28:17 -0700170 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530171}
172EXPORT_SYMBOL(nss_wifili_tx_msg);
173
174/*
175 * nss_wifili_tx_msg_sync()
176 * Transmit a wifili message to NSS firmware synchronously.
177 */
178nss_tx_status_t nss_wifili_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_wifili_msg *nvm)
179{
180 nss_tx_status_t status;
181 int ret = 0;
182
183 down(&wifili_pvt.sem);
184 wifili_pvt.cb = (void *)nvm->cm.cb;
185 wifili_pvt.app_data = (void *)nvm->cm.app_data;
186
187 nvm->cm.cb = (nss_ptr_t)nss_wifili_callback;
188 nvm->cm.app_data = (nss_ptr_t)NULL;
189
190 status = nss_wifili_tx_msg(nss_ctx, nvm);
191 if (status != NSS_TX_SUCCESS) {
192 nss_warning("%p: wifili_tx_msg failed\n", nss_ctx);
193 up(&wifili_pvt.sem);
194 return status;
195 }
196
197 ret = wait_for_completion_timeout(&wifili_pvt.complete, msecs_to_jiffies(NSS_WIFILI_TX_TIMEOUT));
198 if (!ret) {
199 nss_warning("%p: wifili msg tx failed due to timeout\n", nss_ctx);
200 wifili_pvt.response = NSS_TX_FAILURE;
201 }
202
203 status = wifili_pvt.response;
204 up(&wifili_pvt.sem);
205 return status;
206}
207EXPORT_SYMBOL(nss_wifili_tx_msg_sync);
208
209/*
210 * nss_wifili_get_context()
211 */
212struct nss_ctx_instance *nss_wifili_get_context(void)
213{
214 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
215}
216EXPORT_SYMBOL(nss_wifili_get_context);
217
218/*
219 * nss_wifili_msg_init()
220 * Initialize nss_wifili_msg.
221 */
222void nss_wifili_msg_init(struct nss_wifili_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
223{
224 nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
225}
226EXPORT_SYMBOL(nss_wifili_msg_init);
227
228/*
229 ****************************************
230 * Register/Unregister/Miscellaneous APIs
231 ****************************************
232 */
233
234/*
235 * nss_register_wifili_if()
236 * Register wifili with nss driver
237 */
238struct nss_ctx_instance *nss_register_wifili_if(uint32_t if_num, nss_wifili_callback_t wifili_callback,
239 nss_wifili_callback_t wifili_ext_callback,
240 nss_wifili_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
241{
242 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
243
244 /*
245 * The interface number shall be wifili soc interface
246 */
247 nss_assert(if_num == NSS_WIFILI_INTERFACE);
248
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530249 nss_info("nss_register_wifili_if if_num %d wifictx %p", if_num, netdev);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530250
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700251 nss_core_register_subsys_dp(nss_ctx, if_num, wifili_callback, wifili_ext_callback, NULL, netdev, features);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530252
253 nss_top_main.wifili_msg_callback = event_callback;
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530254
255 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
256}
257EXPORT_SYMBOL(nss_register_wifili_if);
258
259/*
260 * nss_unregister_wifili_if()
261 * Unregister wifili with nss driver
262 */
263void nss_unregister_wifili_if(uint32_t if_num)
264{
265 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
266
267 /*
268 * The interface number shall be wifili soc interface
269 */
270 nss_assert(if_num == NSS_WIFILI_INTERFACE);
271
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700272 nss_core_unregister_subsys_dp(nss_ctx, if_num);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530273}
274EXPORT_SYMBOL(nss_unregister_wifili_if);
275
276/*
277 * nss_register_wifili_radio_if()
278 * Register wifili radio with nss driver
279 */
280struct nss_ctx_instance *nss_register_wifili_radio_if(uint32_t if_num, nss_wifili_callback_t wifili_callback,
281 nss_wifili_callback_t wifili_ext_callback,
282 nss_wifili_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
283{
284 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
285
286 /*
287 * The interface number shall be wifili radio dynamic interface
288 */
289 nss_assert(nss_is_dynamic_interface(if_num));
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530290 nss_info("nss_register_wifili_if if_num %d wifictx %p", if_num, netdev);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530291
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700292 nss_core_register_subsys_dp(nss_ctx, if_num, wifili_callback, wifili_ext_callback, NULL, netdev, features);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530293
294 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
295}
296EXPORT_SYMBOL(nss_register_wifili_radio_if);
297
298/*
299 * nss_unregister_wifili_radio_if()
300 * Unregister wifili radio with nss driver
301 */
302void nss_unregister_wifili_radio_if(uint32_t if_num)
303{
304 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
305
306 /*
307 * The interface number shall be wifili radio dynamic interface
308 */
309 nss_assert(nss_is_dynamic_interface(if_num));
310
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700311 nss_core_unregister_subsys_dp(nss_ctx, if_num);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530312}
313EXPORT_SYMBOL(nss_unregister_wifili_radio_if);
314
315/*
316 * nss_wifili_register_handler()
317 * Register handle for notfication messages received on wifi interface
318 */
Aniruddha Paul1b170c22017-05-29 12:30:39 +0530319void nss_wifili_register_handler(void)
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530320{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700321 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
322
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530323 nss_info("nss_wifili_register_handler");
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700324 nss_core_register_handler(nss_ctx, NSS_WIFILI_INTERFACE, nss_wifili_handler, NULL);
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530325
Yu Huang8c107082017-07-24 14:58:26 -0700326 nss_wifili_stats_dentry_create();
327
Varsha Mishrae58d93b2017-05-20 20:54:41 +0530328 sema_init(&wifili_pvt.sem, 1);
329 init_completion(&wifili_pvt.complete);
330}