diff options
author | David S. Miller <davem@davemloft.net> | 2014-09-26 21:19:05 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-26 21:39:24 +0200 |
commit | 57219dc7bfc5cae48c8309974054733499a0dc63 (patch) | |
tree | d078e6726dee978e3cc14c6a1467dce1fe2f3225 /drivers/net/wireless/mwifiex/main.c | |
parent | net: Change netdev_<level> logging functions to return void (diff) | |
parent | ath9k: enable ext channel pulse detection (diff) | |
download | linux-57219dc7bfc5cae48c8309974054733499a0dc63.tar.xz linux-57219dc7bfc5cae48c8309974054733499a0dc63.zip |
Merge tag 'master-2014-09-16' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says:
====================
pull request: wireless-next 2014-09-22
Please pull this batch of updates intended for the 3.18 stream...
For the mac80211 bits, Johannes says:
"This time, I have some rate minstrel improvements, support for a very
small feature from CCX that Steinar reverse-engineered, dynamic ACK
timeout support, a number of changes for TDLS, early support for radio
resource measurement and many fixes. Also, I'm changing a number of
places to clear key memory when it's freed and Intel claims copyright
for code they developed."
For the bluetooth bits, Johan says:
"Here are some more patches intended for 3.18. Most of them are cleanups
or fixes for SMP. The only exception is a fix for BR/EDR L2CAP fixed
channels which should now work better together with the L2CAP
information request procedure."
For the iwlwifi bits, Emmanuel says:
"I fix here dvm which was broken by my last pull request. Arik
continues to work on TDLS and Luca solved a few issues in CT-Kill. Eyal
keeps digging into rate scaling code, more to come soon. Besides this,
nothing really special here."
Beyond that, there are the usual big batches of updates to ath9k, b43,
mwifiex, and wil6210 as well as a handful of other bits here and there.
Also, rtlwifi gets some btcoexist attention from Larry.
Please let me know if there are problems!
====================
Had to adjust the wil6210 code to comply with Joe Perches's recent
change in net-next to make the netdev_*() routines return void instead
of 'int'.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/mwifiex/main.c')
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 191 |
1 files changed, 95 insertions, 96 deletions
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index dfa37eadc4db..b522f7c36901 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -28,91 +28,6 @@ const char driver_version[] = "mwifiex " VERSION " (%s) "; static char *cal_data_cfg; module_param(cal_data_cfg, charp, 0); -static void scan_delay_timer_fn(unsigned long data) -{ - struct mwifiex_private *priv = (struct mwifiex_private *)data; - struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node, *tmp_node; - spinlock_t *scan_q_lock = &adapter->scan_pending_q_lock; - unsigned long flags; - - if (adapter->surprise_removed) - return; - - if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT || - !adapter->scan_processing) { - /* - * Abort scan operation by cancelling all pending scan - * commands - */ - spin_lock_irqsave(scan_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(scan_q_lock, flags); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - adapter->scan_delay_cnt = 0; - adapter->empty_tx_q_cnt = 0; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - if (priv->scan_request) { - dev_dbg(adapter->dev, "info: aborting scan\n"); - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - } else { - priv->scan_aborting = false; - dev_dbg(adapter->dev, "info: scan already aborted\n"); - } - goto done; - } - - if (!atomic_read(&priv->adapter->is_tx_received)) { - adapter->empty_tx_q_cnt++; - if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) { - /* - * No Tx traffic for 200msec. Get scan command from - * scan pending queue and put to cmd pending queue to - * resume scan operation - */ - adapter->scan_delay_cnt = 0; - adapter->empty_tx_q_cnt = 0; - spin_lock_irqsave(scan_q_lock, flags); - - if (list_empty(&adapter->scan_pending_q)) { - spin_unlock_irqrestore(scan_q_lock, flags); - goto done; - } - - cmd_node = list_first_entry(&adapter->scan_pending_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(scan_q_lock, flags); - - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, - true); - queue_work(adapter->workqueue, &adapter->main_work); - goto done; - } - } else { - adapter->empty_tx_q_cnt = 0; - } - - /* Delay scan operation further by 20msec */ - mod_timer(&priv->scan_delay_timer, jiffies + - msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); - adapter->scan_delay_cnt++; - -done: - if (atomic_read(&priv->adapter->is_tx_received)) - atomic_set(&priv->adapter->is_tx_received, false); - - return; -} - /* * This function registers the device and performs all the necessary * initializations. @@ -160,10 +75,6 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, adapter->priv[i]->adapter = adapter; adapter->priv_num++; - - setup_timer(&adapter->priv[i]->scan_delay_timer, - scan_delay_timer_fn, - (unsigned long)adapter->priv[i]); } mwifiex_init_lock_list(adapter); @@ -207,7 +118,6 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; i++) { if (adapter->priv[i]) { mwifiex_free_curr_bcn(adapter->priv[i]); - del_timer_sync(&adapter->priv[i]->scan_delay_timer); kfree(adapter->priv[i]); } } @@ -216,6 +126,42 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) return 0; } +static int mwifiex_process_rx(struct mwifiex_adapter *adapter) +{ + unsigned long flags; + struct sk_buff *skb; + bool delay_main_work = adapter->delay_main_work; + + spin_lock_irqsave(&adapter->rx_proc_lock, flags); + if (adapter->rx_processing || adapter->rx_locked) { + spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); + goto exit_rx_proc; + } else { + adapter->rx_processing = true; + spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); + } + + /* Check for Rx data */ + while ((skb = skb_dequeue(&adapter->rx_data_q))) { + atomic_dec(&adapter->rx_pending); + if (adapter->delay_main_work && + (atomic_dec_return(&adapter->rx_pending) < + LOW_RX_PENDING)) { + adapter->delay_main_work = false; + queue_work(adapter->rx_workqueue, &adapter->rx_work); + } + mwifiex_handle_rx_packet(adapter, skb); + } + spin_lock_irqsave(&adapter->rx_proc_lock, flags); + adapter->rx_processing = false; + spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); + + if (delay_main_work) + queue_work(adapter->workqueue, &adapter->main_work); +exit_rx_proc: + return 0; +} + /* * The main process. * @@ -253,6 +199,19 @@ process_start: (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)) break; + /* If we process interrupts first, it would increase RX pending + * even further. Avoid this by checking if rx_pending has + * crossed high threshold and schedule rx work queue + * and then process interrupts + */ + if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING) { + adapter->delay_main_work = true; + if (!adapter->rx_processing) + queue_work(adapter->rx_workqueue, + &adapter->rx_work); + break; + } + /* Handle pending interrupt if any */ if (adapter->int_status) { if (adapter->hs_activated) @@ -261,6 +220,9 @@ process_start: adapter->if_ops.process_int_status(adapter); } + if (adapter->rx_work_enabled && adapter->data_received) + queue_work(adapter->rx_workqueue, &adapter->rx_work); + /* Need to wake up the card ? */ if ((adapter->ps_state == PS_STATE_SLEEP) && (adapter->pm_wakeup_card_req && @@ -273,6 +235,7 @@ process_start: } if (IS_CARD_RX_RCVD(adapter)) { + adapter->data_received = false; adapter->pm_wakeup_fw_try = false; if (adapter->ps_state == PS_STATE_SLEEP) adapter->ps_state = PS_STATE_AWAKE; @@ -284,8 +247,8 @@ process_start: adapter->tx_lock_flag) break; - if ((adapter->scan_processing && - !adapter->scan_delay_cnt) || adapter->data_sent || + if ((!adapter->scan_chan_gap_enabled && + adapter->scan_processing) || adapter->data_sent || mwifiex_wmm_lists_empty(adapter)) { if (adapter->cmd_sent || adapter->curr_cmd || (!is_command_pending(adapter))) @@ -339,7 +302,8 @@ process_start: } } - if ((!adapter->scan_processing || adapter->scan_delay_cnt) && + if ((adapter->scan_chan_gap_enabled || + !adapter->scan_processing) && !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { mwifiex_wmm_process_tx(adapter); if (adapter->hs_activated) { @@ -407,6 +371,12 @@ static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter) flush_workqueue(adapter->workqueue); destroy_workqueue(adapter->workqueue); adapter->workqueue = NULL; + + if (adapter->rx_workqueue) { + flush_workqueue(adapter->rx_workqueue); + destroy_workqueue(adapter->rx_workqueue); + adapter->rx_workqueue = NULL; + } } /* @@ -598,9 +568,6 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) atomic_inc(&priv->adapter->tx_pending); mwifiex_wmm_add_buf_txqueue(priv, skb); - if (priv->adapter->scan_delay_cnt) - atomic_set(&priv->adapter->is_tx_received, true); - queue_work(priv->adapter->workqueue, &priv->adapter->main_work); return 0; @@ -824,6 +791,21 @@ int is_command_pending(struct mwifiex_adapter *adapter) } /* + * This is the RX work queue function. + * + * It handles the RX operations. + */ +static void mwifiex_rx_work_queue(struct work_struct *work) +{ + struct mwifiex_adapter *adapter = + container_of(work, struct mwifiex_adapter, rx_work); + + if (adapter->surprise_removed) + return; + mwifiex_process_rx(adapter); +} + +/* * This is the main work queue function. * * It handles the main process, which in turn handles the complete @@ -879,6 +861,11 @@ mwifiex_add_card(void *card, struct semaphore *sem, adapter->cmd_wait_q.status = 0; adapter->scan_wait_q_woken = false; + if (num_possible_cpus() > 1) { + adapter->rx_work_enabled = true; + pr_notice("rx work enabled, cpus %d\n", num_possible_cpus()); + } + adapter->workqueue = alloc_workqueue("MWIFIEX_WORK_QUEUE", WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); @@ -886,6 +873,18 @@ mwifiex_add_card(void *card, struct semaphore *sem, goto err_kmalloc; INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); + + if (adapter->rx_work_enabled) { + adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE", + WQ_HIGHPRI | + WQ_MEM_RECLAIM | + WQ_UNBOUND, 1); + if (!adapter->rx_workqueue) + goto err_kmalloc; + + INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue); + } + if (adapter->if_ops.iface_work) INIT_WORK(&adapter->iface_work, adapter->if_ops.iface_work); |