blob: 8b05b4f5ffe2d4a7299561a0e47d1d8b1c2e4f1f [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 .. */
Yogesh Ashok Powar636c4592011-04-15 20:50:40 -070061 if (adapter->if_ops.init_if(adapter))
Bing Zhao5e6e3a92011-03-21 18:00:50 -070062 goto error;
63
64 adapter->priv_num = 0;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070065
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -070066 /* Allocate memory for private structure */
67 adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private),
68 GFP_KERNEL);
69 if (!adapter->priv[0]) {
70 dev_err(adapter->dev, "%s: failed to alloc priv[0]\n",
71 __func__);
72 goto error;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070073 }
74
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -070075 adapter->priv_num++;
76
77 adapter->priv[0]->adapter = adapter;
Bing Zhao5e6e3a92011-03-21 18:00:50 -070078 if (mwifiex_init_lock_list(adapter))
79 goto error;
80
81 init_timer(&adapter->cmd_timer);
82 adapter->cmd_timer.function = mwifiex_cmd_timeout_func;
83 adapter->cmd_timer.data = (unsigned long) adapter;
84
Bing Zhao5e6e3a92011-03-21 18:00:50 -070085 return 0;
86
87error:
88 dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n");
89
Bing Zhao5e6e3a92011-03-21 18:00:50 -070090 mwifiex_free_lock_list(adapter);
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -070091
92 for (i = 0; i < adapter->priv_num; i++)
Bing Zhao5e6e3a92011-03-21 18:00:50 -070093 kfree(adapter->priv[i]);
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -070094
Bing Zhao5e6e3a92011-03-21 18:00:50 -070095 kfree(adapter);
96
97 return -1;
98}
99
100/*
101 * This function unregisters the device and performs all the necessary
102 * cleanups.
103 *
104 * The following cleanup operations are performed -
105 * - Free the timers
106 * - Free beacon buffers
107 * - Free private structures
108 * - Free adapter structure
109 */
110static int mwifiex_unregister(struct mwifiex_adapter *adapter)
111{
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700112 s32 i;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700113
114 del_timer(&adapter->cmd_timer);
115
116 /* Free private structures */
117 for (i = 0; i < adapter->priv_num; i++) {
118 if (adapter->priv[i]) {
119 mwifiex_free_curr_bcn(adapter->priv[i]);
120 kfree(adapter->priv[i]);
121 }
122 }
123
124 kfree(adapter);
125 return 0;
126}
127
128/*
129 * The main process.
130 *
131 * This function is the main procedure of the driver and handles various driver
132 * operations. It runs in a loop and provides the core functionalities.
133 *
134 * The main responsibilities of this function are -
135 * - Ensure concurrency control
136 * - Handle pending interrupts and call interrupt handlers
137 * - Wake up the card if required
138 * - Handle command responses and call response handlers
139 * - Handle events and call event handlers
140 * - Execute pending commands
141 * - Transmit pending data packets
142 */
143int mwifiex_main_process(struct mwifiex_adapter *adapter)
144{
145 int ret = 0;
146 unsigned long flags;
147
148 spin_lock_irqsave(&adapter->main_proc_lock, flags);
149
150 /* Check if already processing */
151 if (adapter->mwifiex_processing) {
152 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
153 goto exit_main_proc;
154 } else {
155 adapter->mwifiex_processing = true;
156 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
157 }
158process_start:
159 do {
160 if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) ||
161 (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY))
162 break;
163
164 /* Handle pending interrupt if any */
165 if (adapter->int_status) {
166 if (adapter->hs_activated)
167 mwifiex_process_hs_config(adapter);
168 adapter->if_ops.process_int_status(adapter);
169 }
170
171 /* Need to wake up the card ? */
172 if ((adapter->ps_state == PS_STATE_SLEEP) &&
173 (adapter->pm_wakeup_card_req &&
174 !adapter->pm_wakeup_fw_try) &&
175 (is_command_pending(adapter)
176 || !mwifiex_wmm_lists_empty(adapter))) {
177 adapter->pm_wakeup_fw_try = true;
178 adapter->if_ops.wakeup(adapter);
179 continue;
180 }
181 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
193 if (adapter->scan_processing || adapter->data_sent
194 || mwifiex_wmm_lists_empty(adapter)) {
195 if (adapter->cmd_sent || adapter->curr_cmd
196 || (!is_command_pending(adapter)))
197 break;
198 }
199 }
200
201 /* Check for Cmd Resp */
202 if (adapter->cmd_resp_received) {
203 adapter->cmd_resp_received = false;
204 mwifiex_process_cmdresp(adapter);
205
206 /* call mwifiex back when init_fw is done */
207 if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) {
208 adapter->hw_status = MWIFIEX_HW_STATUS_READY;
209 mwifiex_init_fw_complete(adapter);
210 }
211 }
212
213 /* Check for event */
214 if (adapter->event_received) {
215 adapter->event_received = false;
216 mwifiex_process_event(adapter);
217 }
218
219 /* Check if we need to confirm Sleep Request
220 received previously */
221 if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
222 if (!adapter->cmd_sent && !adapter->curr_cmd)
223 mwifiex_check_ps_cond(adapter);
224 }
225
226 /* * The ps_state may have been changed during processing of
227 * Sleep Request event.
228 */
229 if ((adapter->ps_state == PS_STATE_SLEEP)
230 || (adapter->ps_state == PS_STATE_PRE_SLEEP)
231 || (adapter->ps_state == PS_STATE_SLEEP_CFM)
232 || adapter->tx_lock_flag)
233 continue;
234
235 if (!adapter->cmd_sent && !adapter->curr_cmd) {
236 if (mwifiex_exec_next_cmd(adapter) == -1) {
237 ret = -1;
238 break;
239 }
240 }
241
242 if (!adapter->scan_processing && !adapter->data_sent &&
243 !mwifiex_wmm_lists_empty(adapter)) {
244 mwifiex_wmm_process_tx(adapter);
245 if (adapter->hs_activated) {
246 adapter->is_hs_configured = false;
247 mwifiex_hs_activated_event
248 (mwifiex_get_priv
249 (adapter, MWIFIEX_BSS_ROLE_ANY),
250 false);
251 }
252 }
253
254 if (adapter->delay_null_pkt && !adapter->cmd_sent &&
255 !adapter->curr_cmd && !is_command_pending(adapter)
256 && mwifiex_wmm_lists_empty(adapter)) {
257 if (!mwifiex_send_null_packet
258 (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
259 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
260 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) {
261 adapter->delay_null_pkt = false;
262 adapter->ps_state = PS_STATE_SLEEP;
263 }
264 break;
265 }
266 } while (true);
267
268 if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter))
269 goto process_start;
270
271 spin_lock_irqsave(&adapter->main_proc_lock, flags);
272 adapter->mwifiex_processing = false;
273 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
274
275exit_main_proc:
276 if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING)
277 mwifiex_shutdown_drv(adapter);
278 return ret;
279}
280
281/*
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700282 * This function frees the adapter structure.
283 *
284 * Additionally, this closes the netlink socket, frees the timers
285 * and private structures.
286 */
287static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
288{
289 if (!adapter) {
290 pr_err("%s: adapter is NULL\n", __func__);
291 return;
292 }
293
294 mwifiex_unregister(adapter);
295 pr_debug("info: %s: free adapter\n", __func__);
296}
297
298/*
299 * This function initializes the hardware and firmware.
300 *
301 * The main initialization steps followed are -
302 * - Download the correct firmware to card
303 * - Allocate and initialize the adapter structure
304 * - Initialize the private structures
305 * - Issue the init commands to firmware
306 */
307static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
308{
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700309 int ret, err;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700310 struct mwifiex_fw_image fw;
311
312 memset(&fw, 0, sizeof(struct mwifiex_fw_image));
313
Amitkumar Karwar4a7f5db2011-05-23 18:00:17 -0700314 err = request_firmware(&adapter->firmware, adapter->fw_name,
315 adapter->dev);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700316 if (err < 0) {
317 dev_err(adapter->dev, "request_firmware() returned"
318 " error code %#x\n", err);
319 ret = -1;
320 goto done;
321 }
322 fw.fw_buf = (u8 *) adapter->firmware->data;
323 fw.fw_len = adapter->firmware->size;
324
325 ret = mwifiex_dnld_fw(adapter, &fw);
326 if (ret == -1)
327 goto done;
328
329 dev_notice(adapter->dev, "WLAN FW is active\n");
330
331 adapter->init_wait_q_woken = false;
332 ret = mwifiex_init_fw(adapter);
333 if (ret == -1) {
334 goto done;
335 } else if (!ret) {
336 adapter->hw_status = MWIFIEX_HW_STATUS_READY;
337 goto done;
338 }
339 /* Wait for mwifiex_init to complete */
340 wait_event_interruptible(adapter->init_wait_q,
341 adapter->init_wait_q_woken);
342 if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) {
343 ret = -1;
344 goto done;
345 }
346 ret = 0;
347
348done:
349 if (adapter->firmware)
350 release_firmware(adapter->firmware);
351 if (ret)
352 ret = -1;
353 return ret;
354}
355
356/*
357 * This function fills a driver buffer.
358 *
359 * The function associates a given SKB with the provided driver buffer
360 * and also updates some of the SKB parameters, including IP header,
361 * priority and timestamp.
362 */
363static void
364mwifiex_fill_buffer(struct sk_buff *skb)
365{
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700366 struct ethhdr *eth;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700367 struct iphdr *iph;
368 struct timeval tv;
369 u8 tid = 0;
370
371 eth = (struct ethhdr *) skb->data;
372 switch (eth->h_proto) {
373 case __constant_htons(ETH_P_IP):
374 iph = ip_hdr(skb);
375 tid = IPTOS_PREC(iph->tos);
376 pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n",
377 eth->h_proto, tid, skb->priority);
378 break;
379 case __constant_htons(ETH_P_ARP):
380 pr_debug("data: ARP packet: %04x\n", eth->h_proto);
381 default:
382 break;
383 }
384/* Offset for TOS field in the IP header */
385#define IPTOS_OFFSET 5
386 tid = (tid >> IPTOS_OFFSET);
387 skb->priority = tid;
388 /* Record the current time the packet was queued; used to
389 determine the amount of time the packet was queued in
390 the driver before it was sent to the firmware.
391 The delay is then sent along with the packet to the
392 firmware for aggregate delay calculation for stats and
393 MSDU lifetime expiry.
394 */
395 do_gettimeofday(&tv);
396 skb->tstamp = timeval_to_ktime(tv);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700397}
398
399/*
400 * CFG802.11 network device handler for open.
401 *
402 * Starts the data queue.
403 */
404static int
405mwifiex_open(struct net_device *dev)
406{
407 netif_start_queue(dev);
408 return 0;
409}
410
411/*
412 * CFG802.11 network device handler for close.
413 */
414static int
415mwifiex_close(struct net_device *dev)
416{
417 return 0;
418}
419
420/*
421 * CFG802.11 network device handler for data transmission.
422 */
423static int
424mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
425{
426 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700427 struct sk_buff *new_skb;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700428 struct mwifiex_txinfo *tx_info;
429
430 dev_dbg(priv->adapter->dev, "data: %lu BSS(%d): Data <= kernel\n",
431 jiffies, priv->bss_index);
432
433 if (priv->adapter->surprise_removed) {
Christoph Fritzb53575e2011-05-08 22:50:09 +0200434 kfree_skb(skb);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700435 priv->stats.tx_dropped++;
436 return 0;
437 }
438 if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
439 dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len);
Christoph Fritzb53575e2011-05-08 22:50:09 +0200440 kfree_skb(skb);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700441 priv->stats.tx_dropped++;
442 return 0;
443 }
444 if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
445 dev_dbg(priv->adapter->dev,
446 "data: Tx: insufficient skb headroom %d\n",
447 skb_headroom(skb));
448 /* Insufficient skb headroom - allocate a new skb */
449 new_skb =
450 skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
451 if (unlikely(!new_skb)) {
452 dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n");
Christoph Fritzb53575e2011-05-08 22:50:09 +0200453 kfree_skb(skb);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700454 priv->stats.tx_dropped++;
455 return 0;
456 }
457 kfree_skb(skb);
458 skb = new_skb;
459 dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n",
460 skb_headroom(skb));
461 }
462
463 tx_info = MWIFIEX_SKB_TXCB(skb);
464 tx_info->bss_index = priv->bss_index;
465 mwifiex_fill_buffer(skb);
466
467 mwifiex_wmm_add_buf_txqueue(priv->adapter, skb);
468 atomic_inc(&priv->adapter->tx_pending);
469
470 if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
471 netif_stop_queue(priv->netdev);
472 dev->trans_start = jiffies;
473 }
474
475 queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
476
477 return 0;
478}
479
480/*
481 * CFG802.11 network device handler for setting MAC address.
482 */
483static int
484mwifiex_set_mac_address(struct net_device *dev, void *addr)
485{
486 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
Amitkumar Karwara5ffddb2011-06-20 15:21:48 -0700487 struct sockaddr *hw_addr = addr;
Yogesh Ashok Powar270e58e2011-05-03 20:11:46 -0700488 int ret;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700489
490 memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
491
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700492 /* Send request to firmware */
493 ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
494 HostCmd_ACT_GEN_SET, 0, NULL);
495
496 if (!ret)
497 memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
498 else
499 dev_err(priv->adapter->dev, "set mac address failed: ret=%d"
500 "\n", ret);
501
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700502 memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
503
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700504 return ret;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700505}
506
507/*
508 * CFG802.11 network device handler for setting multicast list.
509 */
510static void mwifiex_set_multicast_list(struct net_device *dev)
511{
512 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700513 struct mwifiex_multicast_list mcast_list;
514
515 if (dev->flags & IFF_PROMISC) {
516 mcast_list.mode = MWIFIEX_PROMISC_MODE;
517 } else if (dev->flags & IFF_ALLMULTI ||
518 netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) {
519 mcast_list.mode = MWIFIEX_ALL_MULTI_MODE;
520 } else {
521 mcast_list.mode = MWIFIEX_MULTICAST_MODE;
522 if (netdev_mc_count(dev))
523 mcast_list.num_multicast_addr =
524 mwifiex_copy_mcast_addr(&mcast_list, dev);
525 }
526 mwifiex_request_set_multicast_list(priv, &mcast_list);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700527}
528
529/*
530 * CFG802.11 network device handler for transmission timeout.
531 */
532static void
533mwifiex_tx_timeout(struct net_device *dev)
534{
535 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
536
537 dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n",
538 jiffies, priv->bss_index);
539 dev->trans_start = jiffies;
540 priv->num_tx_timeout++;
541}
542
543/*
544 * CFG802.11 network device handler for statistics retrieval.
545 */
546static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
547{
548 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
549
550 return &priv->stats;
551}
552
553/* Network device handlers */
554static const struct net_device_ops mwifiex_netdev_ops = {
555 .ndo_open = mwifiex_open,
556 .ndo_stop = mwifiex_close,
557 .ndo_start_xmit = mwifiex_hard_start_xmit,
558 .ndo_set_mac_address = mwifiex_set_mac_address,
559 .ndo_tx_timeout = mwifiex_tx_timeout,
560 .ndo_get_stats = mwifiex_get_stats,
561 .ndo_set_multicast_list = mwifiex_set_multicast_list,
562};
563
564/*
565 * This function initializes the private structure parameters.
566 *
567 * The following wait queues are initialized -
568 * - IOCTL wait queue
569 * - Command wait queue
570 * - Statistics wait queue
571 *
572 * ...and the following default parameters are set -
573 * - Current key index : Set to 0
574 * - Rate index : Set to auto
575 * - Media connected : Set to disconnected
576 * - Adhoc link sensed : Set to false
577 * - Nick name : Set to null
578 * - Number of Tx timeout : Set to 0
579 * - Device address : Set to current address
580 *
581 * In addition, the CFG80211 work queue is also created.
582 */
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700583void mwifiex_init_priv_params(struct mwifiex_private *priv,
584 struct net_device *dev)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700585{
586 dev->netdev_ops = &mwifiex_netdev_ops;
587 /* Initialize private structure */
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700588 priv->current_key_index = 0;
589 priv->media_connected = false;
590 memset(&priv->nick_name, 0, sizeof(priv->nick_name));
591 priv->num_tx_timeout = 0;
592 priv->workqueue = create_singlethread_workqueue("cfg80211_wq");
593 INIT_WORK(&priv->cfg_workqueue, mwifiex_cfg80211_results);
594 memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
595}
596
597/*
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700598 * This function check if command is pending.
599 */
600int is_command_pending(struct mwifiex_adapter *adapter)
601{
602 unsigned long flags;
603 int is_cmd_pend_q_empty;
604
605 spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
606 is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
607 spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
608
609 return !is_cmd_pend_q_empty;
610}
611
612/*
613 * This function returns the correct private structure pointer based
614 * upon the BSS number.
615 */
616struct mwifiex_private *
617mwifiex_bss_index_to_priv(struct mwifiex_adapter *adapter, u8 bss_index)
618{
619 if (!adapter || (bss_index >= adapter->priv_num))
620 return NULL;
621 return adapter->priv[bss_index];
622}
623
624/*
625 * This is the main work queue function.
626 *
627 * It handles the main process, which in turn handles the complete
628 * driver operations.
629 */
630static void mwifiex_main_work_queue(struct work_struct *work)
631{
632 struct mwifiex_adapter *adapter =
633 container_of(work, struct mwifiex_adapter, main_work);
634
635 if (adapter->surprise_removed)
636 return;
637 mwifiex_main_process(adapter);
638}
639
640/*
641 * This function cancels all works in the queue and destroys
642 * the main workqueue.
643 */
644static void
645mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
646{
647 flush_workqueue(adapter->workqueue);
648 destroy_workqueue(adapter->workqueue);
649 adapter->workqueue = NULL;
650}
651
652/*
653 * This function adds the card.
654 *
655 * This function follows the following major steps to set up the device -
656 * - Initialize software. This includes probing the card, registering
657 * the interface operations table, and allocating/initializing the
658 * adapter structure
659 * - Set up the netlink socket
660 * - Create and start the main work queue
661 * - Register the device
662 * - Initialize firmware and hardware
663 * - Add logical interfaces
664 */
665int
666mwifiex_add_card(void *card, struct semaphore *sem,
667 struct mwifiex_if_ops *if_ops)
668{
Amitkumar Karwar2be78592011-04-15 20:50:42 -0700669 struct mwifiex_adapter *adapter;
Amitkumar Karwar5674fbb72011-08-02 18:42:23 -0700670 char fmt[64];
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700671 struct mwifiex_private *priv;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700672
673 if (down_interruptible(sem))
674 goto exit_sem_err;
675
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700676 if (mwifiex_register(card, if_ops, (void **)&adapter)) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700677 pr_err("%s: software init failed\n", __func__);
678 goto err_init_sw;
679 }
680
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700681 adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700682 adapter->surprise_removed = false;
683 init_waitqueue_head(&adapter->init_wait_q);
684 adapter->is_suspended = false;
685 adapter->hs_activated = false;
686 init_waitqueue_head(&adapter->hs_activate_wait_q);
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700687 adapter->cmd_wait_q_required = false;
688 init_waitqueue_head(&adapter->cmd_wait_q.wait);
689 adapter->cmd_wait_q.condition = false;
690 adapter->cmd_wait_q.status = 0;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700691
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700692 adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");
693 if (!adapter->workqueue)
694 goto err_kmalloc;
695
696 INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
697
698 /* Register the device. Fill up the private data structure with relevant
699 information from the card and request for the required IRQ. */
700 if (adapter->if_ops.register_dev(adapter)) {
701 pr_err("%s: failed to register mwifiex device\n", __func__);
702 goto err_registerdev;
703 }
704
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700705 if (mwifiex_init_hw_fw(adapter)) {
706 pr_err("%s: firmware init failed\n", __func__);
707 goto err_init_fw;
708 }
Amitkumar Karwar2be78592011-04-15 20:50:42 -0700709
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700710 priv = adapter->priv[0];
711
712 if (mwifiex_register_cfg80211(priv) != 0) {
713 dev_err(adapter->dev, "cannot register netdevice"
714 " with cfg80211\n");
715 goto err_init_fw;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700716 }
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700717
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700718 rtnl_lock();
719 /* Create station interface by default */
720 if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
721 NL80211_IFTYPE_STATION, NULL, NULL)) {
722 rtnl_unlock();
723 dev_err(adapter->dev, "cannot create default station"
724 " interface\n");
725 goto err_add_intf;
726 }
727
728 rtnl_unlock();
729
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700730 up(sem);
731
Amitkumar Karwar5674fbb72011-08-02 18:42:23 -0700732 mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
733 dev_notice(adapter->dev, "driver_version = %s\n", fmt);
734
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700735 return 0;
736
737err_add_intf:
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700738 rtnl_lock();
739 mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
740 rtnl_unlock();
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700741err_init_fw:
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700742 pr_debug("info: %s: unregister device\n", __func__);
743 adapter->if_ops.unregister_dev(adapter);
744err_registerdev:
745 adapter->surprise_removed = true;
746 mwifiex_terminate_workqueue(adapter);
747err_kmalloc:
748 if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
749 (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
750 pr_debug("info: %s: shutdown mwifiex\n", __func__);
751 adapter->init_wait_q_woken = false;
Yogesh Ashok Powar636c4592011-04-15 20:50:40 -0700752
753 if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700754 wait_event_interruptible(adapter->init_wait_q,
755 adapter->init_wait_q_woken);
756 }
757
758 mwifiex_free_adapter(adapter);
759
760err_init_sw:
761 up(sem);
762
763exit_sem_err:
764 return -1;
765}
766EXPORT_SYMBOL_GPL(mwifiex_add_card);
767
768/*
769 * This function removes the card.
770 *
771 * This function follows the following major steps to remove the device -
772 * - Stop data traffic
773 * - Shutdown firmware
774 * - Remove the logical interfaces
775 * - Terminate the work queue
776 * - Unregister the device
777 * - Free the adapter structure
778 */
779int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
780{
781 struct mwifiex_private *priv = NULL;
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700782 int i;
783
784 if (down_interruptible(sem))
785 goto exit_sem_err;
786
787 if (!adapter)
788 goto exit_remove;
789
790 adapter->surprise_removed = true;
791
792 /* Stop data */
793 for (i = 0; i < adapter->priv_num; i++) {
794 priv = adapter->priv[i];
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700795 if (priv && priv->netdev) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700796 if (!netif_queue_stopped(priv->netdev))
797 netif_stop_queue(priv->netdev);
798 if (netif_carrier_ok(priv->netdev))
799 netif_carrier_off(priv->netdev);
800 }
801 }
802
803 dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n");
804 adapter->init_wait_q_woken = false;
Yogesh Ashok Powar636c4592011-04-15 20:50:40 -0700805
806 if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700807 wait_event_interruptible(adapter->init_wait_q,
808 adapter->init_wait_q_woken);
809 dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n");
810 if (atomic_read(&adapter->rx_pending) ||
811 atomic_read(&adapter->tx_pending) ||
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700812 atomic_read(&adapter->cmd_pending)) {
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700813 dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, "
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700814 "cmd_pending=%d\n",
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700815 atomic_read(&adapter->rx_pending),
816 atomic_read(&adapter->tx_pending),
Amitkumar Karwar600f5d92011-04-13 17:27:06 -0700817 atomic_read(&adapter->cmd_pending));
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700818 }
819
Yogesh Ashok Powar93a1df42011-09-26 20:37:26 -0700820 for (i = 0; i < adapter->priv_num; i++) {
821 priv = adapter->priv[i];
822
823 if (!priv)
824 continue;
825
826 rtnl_lock();
827 mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
828 rtnl_unlock();
829 }
830
831 wiphy_unregister(priv->wdev->wiphy);
832 wiphy_free(priv->wdev->wiphy);
833 kfree(priv->wdev);
Bing Zhao5e6e3a92011-03-21 18:00:50 -0700834
835 mwifiex_terminate_workqueue(adapter);
836
837 /* Unregister device */
838 dev_dbg(adapter->dev, "info: unregister device\n");
839 adapter->if_ops.unregister_dev(adapter);
840 /* Free adapter structure */
841 dev_dbg(adapter->dev, "info: free adapter\n");
842 mwifiex_free_adapter(adapter);
843
844exit_remove:
845 up(sem);
846exit_sem_err:
847 return 0;
848}
849EXPORT_SYMBOL_GPL(mwifiex_remove_card);
850
851/*
852 * This function initializes the module.
853 *
854 * The debug FS is also initialized if configured.
855 */
856static int
857mwifiex_init_module(void)
858{
859#ifdef CONFIG_DEBUG_FS
860 mwifiex_debugfs_init();
861#endif
862 return 0;
863}
864
865/*
866 * This function cleans up the module.
867 *
868 * The debug FS is removed if available.
869 */
870static void
871mwifiex_cleanup_module(void)
872{
873#ifdef CONFIG_DEBUG_FS
874 mwifiex_debugfs_remove();
875#endif
876}
877
878module_init(mwifiex_init_module);
879module_exit(mwifiex_cleanup_module);
880
881MODULE_AUTHOR("Marvell International Ltd.");
882MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION);
883MODULE_VERSION(VERSION);
884MODULE_LICENSE("GPL v2");