blob: f0219efc895386bf8f507ec8a64e94809d17c743 [file] [log] [blame]
Bing Zhao5e6e3a92011-03-21 18:00:50 -07001/*
2 * Marvell Wireless LAN device driver: major functions
3 *
4 * Copyright (C) 2011, Marvell International Ltd.
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#include "main.h"
21#include "wmm.h"
22#include "cfg80211.h"
23#include "11n.h"
24
25#define VERSION "1.0"
26
27const char driver_version[] = "mwifiex " VERSION " (%s) ";
28
Bing Zhao5e6e3a92011-03-21 18:00:50 -070029/*
30 * This function registers the device and performs all the necessary
31 * initializations.
32 *
33 * The following initialization operations are performed -
34 * - Allocate adapter structure
35 * - Save interface specific operations table in adapter
36 * - Call interface specific initialization routine
37 * - Allocate private structures
38 * - Set default adapter structure parameters
39 * - Initialize locks
40 *
41 * In case of any errors during inittialization, this function also ensures
42 * proper cleanup before exiting.
43 */
44static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
Amitkumar Karwar287546d2011-06-08 20:39:20 +053045 void **padapter)
Bing Zhao5e6e3a92011-03-21 18:00:50 -070046{
Amitkumar Karwar2be78592011-04-15 20:50:42 -070047 struct mwifiex_adapter *adapter;
48 int i;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070049
50 adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL);
Bing Zhao5e6e3a92011-03-21 18:00:50 -070051 if (!adapter)
Christoph Fritzb53575e2011-05-08 22:50:09 +020052 return -ENOMEM;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070053
Amitkumar Karwar287546d2011-06-08 20:39:20 +053054 *padapter = adapter;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070055 adapter->card = card;
56
57 /* Save interface specific operations in adapter */
58 memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops));
59
60 /* card specific initialization has been deferred until now .. */
Amitkumar Karwar4daffe32012-04-18 20:08:28 -070061 if (adapter->if_ops.init_if)
62 if (adapter->if_ops.init_if(adapter))
63 goto error;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070064
65 adapter->priv_num = 0;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070066
Avinash Patil64b05e22012-05-08 18:30:13 -070067 for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
68 /* Allocate memory for private structure */
69 adapter->priv[i] =
70 kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL);
71 if (!adapter->priv[i])
72 goto error;
73
74 adapter->priv[i]->adapter = adapter;
75 adapter->priv[i]->bss_priority = i;
76 adapter->priv_num++;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070077 }
Amitkumar Karwar44b815c2011-09-29 20:43:41 -070078 mwifiex_init_lock_list(adapter);
Bing Zhao5e6e3a92011-03-21 18:00:50 -070079
80 init_timer(&adapter->cmd_timer);
81 adapter->cmd_timer.function = mwifiex_cmd_timeout_func;
82 adapter->cmd_timer.data = (unsigned long) adapter;
83
Bing Zhao5e6e3a92011-03-21 18:00:50 -070084 return 0;
85
86error:
87 dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n");
88
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -070089 for (i = 0; i < adapter->priv_num; i++)
Bing Zhao5e6e3a92011-03-21 18:00:50 -070090 kfree(adapter->priv[i]);
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -070091
Bing Zhao5e6e3a92011-03-21 18:00:50 -070092 kfree(adapter);
93
94 return -1;
95}
96
97/*
98 * This function unregisters the device and performs all the necessary
99 * cleanups.
100 *
101 * The following cleanup operations are performed -
102 * - Free the timers
103 * - Free beacon buffers
104 * - Free private structures
105 * - Free adapter structure
106 */
107static int mwifiex_unregister(struct mwifiex_adapter *adapter)
108{
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700109 s32 i;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700110
111 del_timer(&adapter->cmd_timer);
112
113 /* Free private structures */
114 for (i = 0; i < adapter->priv_num; i++) {
115 if (adapter->priv[i]) {
116 mwifiex_free_curr_bcn(adapter->priv[i]);
117 kfree(adapter->priv[i]);
118 }
119 }
120
121 kfree(adapter);
122 return 0;
123}
124
125/*
126 * The main process.
127 *
128 * This function is the main procedure of the driver and handles various driver
129 * operations. It runs in a loop and provides the core functionalities.
130 *
131 * The main responsibilities of this function are -
132 * - Ensure concurrency control
133 * - Handle pending interrupts and call interrupt handlers
134 * - Wake up the card if required
135 * - Handle command responses and call response handlers
136 * - Handle events and call event handlers
137 * - Execute pending commands
138 * - Transmit pending data packets
139 */
140int mwifiex_main_process(struct mwifiex_adapter *adapter)
141{
142 int ret = 0;
143 unsigned long flags;
Amitkumar Karwar4daffe32012-04-18 20:08:28 -0700144 struct sk_buff *skb;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700145
146 spin_lock_irqsave(&adapter->main_proc_lock, flags);
147
148 /* Check if already processing */
149 if (adapter->mwifiex_processing) {
150 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
151 goto exit_main_proc;
152 } else {
153 adapter->mwifiex_processing = true;
154 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
155 }
156process_start:
157 do {
158 if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) ||
159 (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY))
160 break;
161
162 /* Handle pending interrupt if any */
163 if (adapter->int_status) {
164 if (adapter->hs_activated)
165 mwifiex_process_hs_config(adapter);
Amitkumar Karwar4daffe32012-04-18 20:08:28 -0700166 if (adapter->if_ops.process_int_status)
167 adapter->if_ops.process_int_status(adapter);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700168 }
169
170 /* Need to wake up the card ? */
171 if ((adapter->ps_state == PS_STATE_SLEEP) &&
172 (adapter->pm_wakeup_card_req &&
173 !adapter->pm_wakeup_fw_try) &&
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700174 (is_command_pending(adapter) ||
175 !mwifiex_wmm_lists_empty(adapter))) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700176 adapter->pm_wakeup_fw_try = true;
177 adapter->if_ops.wakeup(adapter);
178 continue;
179 }
Amitkumar Karwar4daffe32012-04-18 20:08:28 -0700180
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700181 if (IS_CARD_RX_RCVD(adapter)) {
182 adapter->pm_wakeup_fw_try = false;
183 if (adapter->ps_state == PS_STATE_SLEEP)
184 adapter->ps_state = PS_STATE_AWAKE;
185 } else {
186 /* We have tried to wakeup the card already */
187 if (adapter->pm_wakeup_fw_try)
188 break;
189 if (adapter->ps_state != PS_STATE_AWAKE ||
190 adapter->tx_lock_flag)
191 break;
192
Amitkumar Karwarf931c7702012-06-20 19:58:36 -0700193 if ((adapter->scan_processing &&
194 !adapter->scan_delay_cnt) || adapter->data_sent ||
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700195 mwifiex_wmm_lists_empty(adapter)) {
196 if (adapter->cmd_sent || adapter->curr_cmd ||
197 (!is_command_pending(adapter)))
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700198 break;
199 }
200 }
201
Amitkumar Karwar4daffe32012-04-18 20:08:28 -0700202 /* Check Rx data for USB */
203 if (adapter->iface_type == MWIFIEX_USB)
204 while ((skb = skb_dequeue(&adapter->usb_rx_data_q)))
205 mwifiex_handle_rx_packet(adapter, skb);
206
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700207 /* Check for Cmd Resp */
208 if (adapter->cmd_resp_received) {
209 adapter->cmd_resp_received = false;
210 mwifiex_process_cmdresp(adapter);
211
212 /* call mwifiex back when init_fw is done */
213 if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) {
214 adapter->hw_status = MWIFIEX_HW_STATUS_READY;
215 mwifiex_init_fw_complete(adapter);
216 }
217 }
218
219 /* Check for event */
220 if (adapter->event_received) {
221 adapter->event_received = false;
222 mwifiex_process_event(adapter);
223 }
224
225 /* Check if we need to confirm Sleep Request
226 received previously */
227 if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
228 if (!adapter->cmd_sent && !adapter->curr_cmd)
229 mwifiex_check_ps_cond(adapter);
230 }
231
232 /* * The ps_state may have been changed during processing of
233 * Sleep Request event.
234 */
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700235 if ((adapter->ps_state == PS_STATE_SLEEP) ||
236 (adapter->ps_state == PS_STATE_PRE_SLEEP) ||
237 (adapter->ps_state == PS_STATE_SLEEP_CFM) ||
238 adapter->tx_lock_flag)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700239 continue;
240
241 if (!adapter->cmd_sent && !adapter->curr_cmd) {
242 if (mwifiex_exec_next_cmd(adapter) == -1) {
243 ret = -1;
244 break;
245 }
246 }
247
Amitkumar Karwar3249ba72012-06-06 21:12:41 -0700248 if ((!adapter->scan_processing || adapter->scan_delay_cnt) &&
249 !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700250 mwifiex_wmm_process_tx(adapter);
251 if (adapter->hs_activated) {
252 adapter->is_hs_configured = false;
253 mwifiex_hs_activated_event
254 (mwifiex_get_priv
255 (adapter, MWIFIEX_BSS_ROLE_ANY),
256 false);
257 }
258 }
259
260 if (adapter->delay_null_pkt && !adapter->cmd_sent &&
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700261 !adapter->curr_cmd && !is_command_pending(adapter) &&
262 mwifiex_wmm_lists_empty(adapter)) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700263 if (!mwifiex_send_null_packet
264 (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
265 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
266 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) {
267 adapter->delay_null_pkt = false;
268 adapter->ps_state = PS_STATE_SLEEP;
269 }
270 break;
271 }
272 } while (true);
273
274 if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter))
275 goto process_start;
276
277 spin_lock_irqsave(&adapter->main_proc_lock, flags);
278 adapter->mwifiex_processing = false;
279 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
280
281exit_main_proc:
282 if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING)
283 mwifiex_shutdown_drv(adapter);
284 return ret;
285}
286
287/*
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700288 * This function frees the adapter structure.
289 *
290 * Additionally, this closes the netlink socket, frees the timers
291 * and private structures.
292 */
293static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
294{
295 if (!adapter) {
296 pr_err("%s: adapter is NULL\n", __func__);
297 return;
298 }
299
300 mwifiex_unregister(adapter);
301 pr_debug("info: %s: free adapter\n", __func__);
302}
303
304/*
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700305 * This function gets firmware and initializes it.
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700306 *
307 * The main initialization steps followed are -
308 * - Download the correct firmware to card
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700309 * - Issue the init commands to firmware
310 */
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700311static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700312{
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700313 int ret;
314 char fmt[64];
315 struct mwifiex_private *priv;
316 struct mwifiex_adapter *adapter = context;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700317 struct mwifiex_fw_image fw;
318
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700319 if (!firmware) {
320 dev_err(adapter->dev,
321 "Failed to get firmware %s\n", adapter->fw_name);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700322 goto done;
323 }
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700324
325 memset(&fw, 0, sizeof(struct mwifiex_fw_image));
326 adapter->firmware = firmware;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700327 fw.fw_buf = (u8 *) adapter->firmware->data;
328 fw.fw_len = adapter->firmware->size;
329
Amitkumar Karwar4daffe32012-04-18 20:08:28 -0700330 if (adapter->if_ops.dnld_fw)
331 ret = adapter->if_ops.dnld_fw(adapter, &fw);
332 else
333 ret = mwifiex_dnld_fw(adapter, &fw);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700334 if (ret == -1)
335 goto done;
336
337 dev_notice(adapter->dev, "WLAN FW is active\n");
338
339 adapter->init_wait_q_woken = false;
340 ret = mwifiex_init_fw(adapter);
341 if (ret == -1) {
342 goto done;
343 } else if (!ret) {
344 adapter->hw_status = MWIFIEX_HW_STATUS_READY;
345 goto done;
346 }
347 /* Wait for mwifiex_init to complete */
348 wait_event_interruptible(adapter->init_wait_q,
349 adapter->init_wait_q_woken);
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700350 if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700351 goto done;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700352
Avinash Patild6bffe82012-05-08 18:30:15 -0700353 priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
354 if (mwifiex_register_cfg80211(adapter)) {
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700355 dev_err(adapter->dev, "cannot register with cfg80211\n");
356 goto err_init_fw;
357 }
358
359 rtnl_lock();
360 /* Create station interface by default */
Avinash Patild6bffe82012-05-08 18:30:15 -0700361 if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700362 NL80211_IFTYPE_STATION, NULL, NULL)) {
363 dev_err(adapter->dev, "cannot create default STA interface\n");
364 goto err_add_intf;
365 }
Avinash Patild6bffe82012-05-08 18:30:15 -0700366
367 /* Create AP interface by default */
368 if (!mwifiex_add_virtual_intf(adapter->wiphy, "uap%d",
369 NL80211_IFTYPE_AP, NULL, NULL)) {
370 dev_err(adapter->dev, "cannot create default AP interface\n");
371 goto err_add_intf;
372 }
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700373 rtnl_unlock();
374
375 mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
376 dev_notice(adapter->dev, "driver_version = %s\n", fmt);
377 goto done;
378
379err_add_intf:
Avinash Patild6bffe82012-05-08 18:30:15 -0700380 mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700381 rtnl_unlock();
382err_init_fw:
383 pr_debug("info: %s: unregister device\n", __func__);
384 adapter->if_ops.unregister_dev(adapter);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700385done:
Jesper Juhl4fb25c52012-04-09 22:51:12 +0200386 release_firmware(adapter->firmware);
Amitkumar Karwar59a4cc22012-04-09 20:06:57 -0700387 complete(&adapter->fw_load);
388 return;
389}
390
391/*
392 * This function initializes the hardware and gets firmware.
393 */
394static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
395{
396 int ret;
397
398 init_completion(&adapter->fw_load);
399 ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name,
400 adapter->dev, GFP_KERNEL, adapter,
401 mwifiex_fw_dpc);
402 if (ret < 0)
403 dev_err(adapter->dev,
404 "request_firmware_nowait() returned error %d\n", ret);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700405 return ret;
406}
407
408/*
409 * This function fills a driver buffer.
410 *
411 * The function associates a given SKB with the provided driver buffer
412 * and also updates some of the SKB parameters, including IP header,
413 * priority and timestamp.
414 */
415static void
416mwifiex_fill_buffer(struct sk_buff *skb)
417{
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700418 struct ethhdr *eth;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700419 struct iphdr *iph;
420 struct timeval tv;
421 u8 tid = 0;
422
423 eth = (struct ethhdr *) skb->data;
424 switch (eth->h_proto) {
425 case __constant_htons(ETH_P_IP):
426 iph = ip_hdr(skb);
427 tid = IPTOS_PREC(iph->tos);
428 pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700429 eth->h_proto, tid, skb->priority);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700430 break;
431 case __constant_htons(ETH_P_ARP):
432 pr_debug("data: ARP packet: %04x\n", eth->h_proto);
433 default:
434 break;
435 }
436/* Offset for TOS field in the IP header */
437#define IPTOS_OFFSET 5
438 tid = (tid >> IPTOS_OFFSET);
439 skb->priority = tid;
440 /* Record the current time the packet was queued; used to
441 determine the amount of time the packet was queued in
442 the driver before it was sent to the firmware.
443 The delay is then sent along with the packet to the
444 firmware for aggregate delay calculation for stats and
445 MSDU lifetime expiry.
446 */
447 do_gettimeofday(&tv);
448 skb->tstamp = timeval_to_ktime(tv);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700449}
450
451/*
452 * CFG802.11 network device handler for open.
453 *
454 * Starts the data queue.
455 */
456static int
457mwifiex_open(struct net_device *dev)
458{
Avinash Patilbbea3bc2011-12-08 20:41:05 -0800459 netif_tx_start_all_queues(dev);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700460 return 0;
461}
462
463/*
464 * CFG802.11 network device handler for close.
465 */
466static int
467mwifiex_close(struct net_device *dev)
468{
469 return 0;
470}
471
472/*
473 * CFG802.11 network device handler for data transmission.
474 */
475static int
476mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
477{
478 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700479 struct sk_buff *new_skb;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700480 struct mwifiex_txinfo *tx_info;
481
Yogesh Ashok Powar9da9a3b2012-01-11 20:06:11 -0800482 dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700483 jiffies, priv->bss_type, priv->bss_num);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700484
485 if (priv->adapter->surprise_removed) {
Christoph Fritzb53575e2011-05-08 22:50:09 +0200486 kfree_skb(skb);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700487 priv->stats.tx_dropped++;
488 return 0;
489 }
490 if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
491 dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len);
Christoph Fritzb53575e2011-05-08 22:50:09 +0200492 kfree_skb(skb);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700493 priv->stats.tx_dropped++;
494 return 0;
495 }
496 if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
497 dev_dbg(priv->adapter->dev,
498 "data: Tx: insufficient skb headroom %d\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700499 skb_headroom(skb));
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700500 /* Insufficient skb headroom - allocate a new skb */
501 new_skb =
502 skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
503 if (unlikely(!new_skb)) {
504 dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n");
Christoph Fritzb53575e2011-05-08 22:50:09 +0200505 kfree_skb(skb);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700506 priv->stats.tx_dropped++;
507 return 0;
508 }
509 kfree_skb(skb);
510 skb = new_skb;
511 dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700512 skb_headroom(skb));
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700513 }
514
515 tx_info = MWIFIEX_SKB_TXCB(skb);
Yogesh Ashok Powar9da9a3b2012-01-11 20:06:11 -0800516 tx_info->bss_num = priv->bss_num;
517 tx_info->bss_type = priv->bss_type;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700518 mwifiex_fill_buffer(skb);
519
Avinash Patil2690e1b2012-01-24 20:50:24 -0800520 mwifiex_wmm_add_buf_txqueue(priv, skb);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700521 atomic_inc(&priv->adapter->tx_pending);
522
523 if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
Avinash Patilbbea3bc2011-12-08 20:41:05 -0800524 mwifiex_set_trans_start(dev);
525 mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700526 }
527
528 queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
529
530 return 0;
531}
532
533/*
534 * CFG802.11 network device handler for setting MAC address.
535 */
536static int
537mwifiex_set_mac_address(struct net_device *dev, void *addr)
538{
539 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
Amitkumar Karwara5ffddb2011-06-20 15:21:48 -0700540 struct sockaddr *hw_addr = addr;
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700541 int ret;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700542
543 memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
544
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700545 /* Send request to firmware */
546 ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
547 HostCmd_ACT_GEN_SET, 0, NULL);
548
549 if (!ret)
550 memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
551 else
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700552 dev_err(priv->adapter->dev,
553 "set mac address failed: ret=%d\n", ret);
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700554
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700555 memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
556
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700557 return ret;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700558}
559
560/*
561 * CFG802.11 network device handler for setting multicast list.
562 */
563static void mwifiex_set_multicast_list(struct net_device *dev)
564{
565 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700566 struct mwifiex_multicast_list mcast_list;
567
568 if (dev->flags & IFF_PROMISC) {
569 mcast_list.mode = MWIFIEX_PROMISC_MODE;
570 } else if (dev->flags & IFF_ALLMULTI ||
571 netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) {
572 mcast_list.mode = MWIFIEX_ALL_MULTI_MODE;
573 } else {
574 mcast_list.mode = MWIFIEX_MULTICAST_MODE;
575 if (netdev_mc_count(dev))
576 mcast_list.num_multicast_addr =
577 mwifiex_copy_mcast_addr(&mcast_list, dev);
578 }
579 mwifiex_request_set_multicast_list(priv, &mcast_list);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700580}
581
582/*
583 * CFG802.11 network device handler for transmission timeout.
584 */
585static void
586mwifiex_tx_timeout(struct net_device *dev)
587{
588 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
589
Yogesh Ashok Powar9da9a3b2012-01-11 20:06:11 -0800590 dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_type-num = %d-%d\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700591 jiffies, priv->bss_type, priv->bss_num);
Avinash Patilbbea3bc2011-12-08 20:41:05 -0800592 mwifiex_set_trans_start(dev);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700593 priv->num_tx_timeout++;
594}
595
596/*
597 * CFG802.11 network device handler for statistics retrieval.
598 */
599static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
600{
601 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
602
603 return &priv->stats;
604}
605
606/* Network device handlers */
607static const struct net_device_ops mwifiex_netdev_ops = {
608 .ndo_open = mwifiex_open,
609 .ndo_stop = mwifiex_close,
610 .ndo_start_xmit = mwifiex_hard_start_xmit,
611 .ndo_set_mac_address = mwifiex_set_mac_address,
612 .ndo_tx_timeout = mwifiex_tx_timeout,
613 .ndo_get_stats = mwifiex_get_stats,
Jiri Pirkoafc4b132011-08-16 06:29:01 +0000614 .ndo_set_rx_mode = mwifiex_set_multicast_list,
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700615};
616
617/*
618 * This function initializes the private structure parameters.
619 *
620 * The following wait queues are initialized -
621 * - IOCTL wait queue
622 * - Command wait queue
623 * - Statistics wait queue
624 *
625 * ...and the following default parameters are set -
626 * - Current key index : Set to 0
627 * - Rate index : Set to auto
628 * - Media connected : Set to disconnected
629 * - Adhoc link sensed : Set to false
630 * - Nick name : Set to null
631 * - Number of Tx timeout : Set to 0
632 * - Device address : Set to current address
633 *
634 * In addition, the CFG80211 work queue is also created.
635 */
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700636void mwifiex_init_priv_params(struct mwifiex_private *priv,
637 struct net_device *dev)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700638{
639 dev->netdev_ops = &mwifiex_netdev_ops;
640 /* Initialize private structure */
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700641 priv->current_key_index = 0;
642 priv->media_connected = false;
643 memset(&priv->nick_name, 0, sizeof(priv->nick_name));
Avinash Patilede98bf2012-05-08 18:30:28 -0700644 memset(priv->mgmt_ie, 0,
645 sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX);
Avinash Patilf31acab2012-05-08 18:30:29 -0700646 priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK;
647 priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK;
648 priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK;
649 priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700650 priv->num_tx_timeout = 0;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700651 memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
652}
653
654/*
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700655 * This function check if command is pending.
656 */
657int is_command_pending(struct mwifiex_adapter *adapter)
658{
659 unsigned long flags;
660 int is_cmd_pend_q_empty;
661
662 spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
663 is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
664 spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
665
666 return !is_cmd_pend_q_empty;
667}
668
669/*
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700670 * This is the main work queue function.
671 *
672 * It handles the main process, which in turn handles the complete
673 * driver operations.
674 */
675static void mwifiex_main_work_queue(struct work_struct *work)
676{
677 struct mwifiex_adapter *adapter =
678 container_of(work, struct mwifiex_adapter, main_work);
679
680 if (adapter->surprise_removed)
681 return;
682 mwifiex_main_process(adapter);
683}
684
685/*
686 * This function cancels all works in the queue and destroys
687 * the main workqueue.
688 */
689static void
690mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
691{
692 flush_workqueue(adapter->workqueue);
693 destroy_workqueue(adapter->workqueue);
694 adapter->workqueue = NULL;
695}
696
697/*
698 * This function adds the card.
699 *
700 * This function follows the following major steps to set up the device -
701 * - Initialize software. This includes probing the card, registering
702 * the interface operations table, and allocating/initializing the
703 * adapter structure
704 * - Set up the netlink socket
705 * - Create and start the main work queue
706 * - Register the device
707 * - Initialize firmware and hardware
708 * - Add logical interfaces
709 */
710int
711mwifiex_add_card(void *card, struct semaphore *sem,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700712 struct mwifiex_if_ops *if_ops, u8 iface_type)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700713{
Amitkumar Karwar2be78592011-04-15 20:50:42 -0700714 struct mwifiex_adapter *adapter;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700715
716 if (down_interruptible(sem))
717 goto exit_sem_err;
718
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700719 if (mwifiex_register(card, if_ops, (void **)&adapter)) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700720 pr_err("%s: software init failed\n", __func__);
721 goto err_init_sw;
722 }
723
Amitkumar Karward930fae2011-10-11 17:41:21 -0700724 adapter->iface_type = iface_type;
725
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700726 adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700727 adapter->surprise_removed = false;
728 init_waitqueue_head(&adapter->init_wait_q);
729 adapter->is_suspended = false;
730 adapter->hs_activated = false;
731 init_waitqueue_head(&adapter->hs_activate_wait_q);
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700732 adapter->cmd_wait_q_required = false;
733 init_waitqueue_head(&adapter->cmd_wait_q.wait);
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700734 adapter->cmd_wait_q.status = 0;
Amitkumar Karwarefaaa8b2011-10-12 20:28:06 -0700735 adapter->scan_wait_q_woken = false;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700736
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700737 adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");
738 if (!adapter->workqueue)
739 goto err_kmalloc;
740
741 INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
742
743 /* Register the device. Fill up the private data structure with relevant
744 information from the card and request for the required IRQ. */
745 if (adapter->if_ops.register_dev(adapter)) {
746 pr_err("%s: failed to register mwifiex device\n", __func__);
747 goto err_registerdev;
748 }
749
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700750 if (mwifiex_init_hw_fw(adapter)) {
751 pr_err("%s: firmware init failed\n", __func__);
752 goto err_init_fw;
753 }
Amitkumar Karwar2be78592011-04-15 20:50:42 -0700754
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700755 up(sem);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700756 return 0;
757
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700758err_init_fw:
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700759 pr_debug("info: %s: unregister device\n", __func__);
Amitkumar Karwar4daffe32012-04-18 20:08:28 -0700760 if (adapter->if_ops.unregister_dev)
761 adapter->if_ops.unregister_dev(adapter);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700762err_registerdev:
763 adapter->surprise_removed = true;
764 mwifiex_terminate_workqueue(adapter);
765err_kmalloc:
766 if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
767 (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
768 pr_debug("info: %s: shutdown mwifiex\n", __func__);
769 adapter->init_wait_q_woken = false;
Yogesh Ashok Powar636c4592011-04-15 20:50:40 -0700770
771 if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700772 wait_event_interruptible(adapter->init_wait_q,
773 adapter->init_wait_q_woken);
774 }
775
776 mwifiex_free_adapter(adapter);
777
778err_init_sw:
779 up(sem);
780
781exit_sem_err:
782 return -1;
783}
784EXPORT_SYMBOL_GPL(mwifiex_add_card);
785
786/*
787 * This function removes the card.
788 *
789 * This function follows the following major steps to remove the device -
790 * - Stop data traffic
791 * - Shutdown firmware
792 * - Remove the logical interfaces
793 * - Terminate the work queue
794 * - Unregister the device
795 * - Free the adapter structure
796 */
797int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
798{
799 struct mwifiex_private *priv = NULL;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700800 int i;
801
802 if (down_interruptible(sem))
803 goto exit_sem_err;
804
805 if (!adapter)
806 goto exit_remove;
807
808 adapter->surprise_removed = true;
809
810 /* Stop data */
811 for (i = 0; i < adapter->priv_num; i++) {
812 priv = adapter->priv[i];
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700813 if (priv && priv->netdev) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700814 if (!netif_queue_stopped(priv->netdev))
Avinash Patilbbea3bc2011-12-08 20:41:05 -0800815 mwifiex_stop_net_dev_queue(priv->netdev,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700816 adapter);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700817 if (netif_carrier_ok(priv->netdev))
818 netif_carrier_off(priv->netdev);
819 }
820 }
821
822 dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n");
823 adapter->init_wait_q_woken = false;
Yogesh Ashok Powar636c4592011-04-15 20:50:40 -0700824
825 if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700826 wait_event_interruptible(adapter->init_wait_q,
827 adapter->init_wait_q_woken);
828 dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n");
829 if (atomic_read(&adapter->rx_pending) ||
830 atomic_read(&adapter->tx_pending) ||
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700831 atomic_read(&adapter->cmd_pending)) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700832 dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, "
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700833 "cmd_pending=%d\n",
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700834 atomic_read(&adapter->rx_pending),
835 atomic_read(&adapter->tx_pending),
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700836 atomic_read(&adapter->cmd_pending));
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700837 }
838
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700839 for (i = 0; i < adapter->priv_num; i++) {
840 priv = adapter->priv[i];
841
842 if (!priv)
843 continue;
844
845 rtnl_lock();
Amitkumar Karwar2da8cbf2012-02-03 20:34:02 -0800846 if (priv->wdev && priv->netdev)
Avinash Patild6bffe82012-05-08 18:30:15 -0700847 mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700848 rtnl_unlock();
849 }
850
Yogesh Ashok Powar3d82de02011-10-05 14:58:24 -0700851 priv = adapter->priv[0];
Avinash Patil64b05e22012-05-08 18:30:13 -0700852 if (!priv || !priv->wdev)
Yogesh Ashok Powar3d82de02011-10-05 14:58:24 -0700853 goto exit_remove;
854
Avinash Patil64b05e22012-05-08 18:30:13 -0700855 wiphy_unregister(priv->wdev->wiphy);
856 wiphy_free(priv->wdev->wiphy);
857
858 for (i = 0; i < adapter->priv_num; i++) {
859 priv = adapter->priv[i];
860 if (priv)
861 kfree(priv->wdev);
Amitkumar Karwar2da8cbf2012-02-03 20:34:02 -0800862 }
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700863
864 mwifiex_terminate_workqueue(adapter);
865
866 /* Unregister device */
867 dev_dbg(adapter->dev, "info: unregister device\n");
Amitkumar Karwar4daffe32012-04-18 20:08:28 -0700868 if (adapter->if_ops.unregister_dev)
869 adapter->if_ops.unregister_dev(adapter);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700870 /* Free adapter structure */
871 dev_dbg(adapter->dev, "info: free adapter\n");
872 mwifiex_free_adapter(adapter);
873
874exit_remove:
875 up(sem);
876exit_sem_err:
877 return 0;
878}
879EXPORT_SYMBOL_GPL(mwifiex_remove_card);
880
881/*
882 * This function initializes the module.
883 *
884 * The debug FS is also initialized if configured.
885 */
886static int
887mwifiex_init_module(void)
888{
889#ifdef CONFIG_DEBUG_FS
890 mwifiex_debugfs_init();
891#endif
892 return 0;
893}
894
895/*
896 * This function cleans up the module.
897 *
898 * The debug FS is removed if available.
899 */
900static void
901mwifiex_cleanup_module(void)
902{
903#ifdef CONFIG_DEBUG_FS
904 mwifiex_debugfs_remove();
905#endif
906}
907
908module_init(mwifiex_init_module);
909module_exit(mwifiex_cleanup_module);
910
911MODULE_AUTHOR("Marvell International Ltd.");
912MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION);
913MODULE_VERSION(VERSION);
914MODULE_LICENSE("GPL v2");