From 6e9344fd8e90ff0bd8e74c15ec7c21eae7d54bd3 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 12 Mar 2015 00:38:40 -0700 Subject: mwifiex: use del_timer variant in interrupt context We might be in interrupt context at few places. So replace del_timer_sync() with del_timer(). This patch fixes a kernel trace problem seen occasionally during our testing. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/mwifiex/main.c') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 74488aba92bd..42bf8846771b 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -247,7 +247,7 @@ process_start: if (IS_CARD_RX_RCVD(adapter)) { adapter->data_received = false; adapter->pm_wakeup_fw_try = false; - del_timer_sync(&adapter->wakeup_timer); + del_timer(&adapter->wakeup_timer); if (adapter->ps_state == PS_STATE_SLEEP) adapter->ps_state = PS_STATE_AWAKE; } else { -- cgit v1.2.1 From a9adbcb3355c31faf4274932f513f19225b61747 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 13 Mar 2015 17:37:51 +0530 Subject: mwifiex: lock main process till reinitialization of vif is over A crash was detected while changing virtual interface type is in progress. This was tracked to race condition in accessing bss_priority table while change is in progress. This patch ensures that main_process and rx_process works are locked while we change virtual interface. Signed-off-by: Cathy Luo Signed-off-by: Avinash Patil Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/mwifiex/main.c') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 42bf8846771b..9c11eb882a0e 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -189,7 +189,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) spin_lock_irqsave(&adapter->main_proc_lock, flags); /* Check if already processing */ - if (adapter->mwifiex_processing) { + if (adapter->mwifiex_processing || adapter->main_locked) { adapter->more_task_flag = true; spin_unlock_irqrestore(&adapter->main_proc_lock, flags); goto exit_main_proc; -- cgit v1.2.1 From b2713f67f7a4c3226772c5ac581c7f37d7c473f1 Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Fri, 13 Mar 2015 17:37:54 +0530 Subject: mwifiex: avoid queue_work while work is ongoing Current code does not check whether main_work_queue or rx_work_queue is running when preparing to do queue_work, this code fix add check before calling queue_work, reducing unnecessary queue_work switch. This change instead sets more_task flag to ensure we run main_process superloop once again. Signed-off-by: Shengzhen Li Signed-off-by: Zhaoyang Liu Reviewed-by: Cathy Luo Reviewed-by: Amitkumar Karwar Reviewed-by: Avinash Patil Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 38 +++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/mwifiex/main.c') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 9c11eb882a0e..d96d60a7ae7c 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -131,6 +131,34 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) return 0; } +void mwifiex_queue_main_work(struct mwifiex_adapter *adapter) +{ + unsigned long flags; + + spin_lock_irqsave(&adapter->main_proc_lock, flags); + if (adapter->mwifiex_processing) { + adapter->more_task_flag = true; + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + } else { + spin_unlock_irqrestore(&adapter->main_proc_lock, flags); + queue_work(adapter->workqueue, &adapter->main_work); + } +} +EXPORT_SYMBOL_GPL(mwifiex_queue_main_work); + +static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter) +{ + unsigned long flags; + + spin_lock_irqsave(&adapter->rx_proc_lock, flags); + if (adapter->rx_processing) { + spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); + } else { + spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); + queue_work(adapter->rx_workqueue, &adapter->rx_work); + } +} + static int mwifiex_process_rx(struct mwifiex_adapter *adapter) { unsigned long flags; @@ -154,7 +182,7 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter) if (adapter->if_ops.submit_rem_rx_urbs) adapter->if_ops.submit_rem_rx_urbs(adapter); adapter->delay_main_work = false; - queue_work(adapter->workqueue, &adapter->main_work); + mwifiex_queue_main_work(adapter); } mwifiex_handle_rx_packet(adapter, skb); } @@ -214,9 +242,7 @@ process_start: if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING && adapter->iface_type != MWIFIEX_USB) { adapter->delay_main_work = true; - if (!adapter->rx_processing) - queue_work(adapter->rx_workqueue, - &adapter->rx_work); + mwifiex_queue_rx_work(adapter); break; } @@ -229,7 +255,7 @@ process_start: } if (adapter->rx_work_enabled && adapter->data_received) - queue_work(adapter->rx_workqueue, &adapter->rx_work); + mwifiex_queue_rx_work(adapter); /* Need to wake up the card ? */ if ((adapter->ps_state == PS_STATE_SLEEP) && @@ -606,7 +632,7 @@ 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); - queue_work(priv->adapter->workqueue, &priv->adapter->main_work); + mwifiex_queue_main_work(priv->adapter); return 0; } -- cgit v1.2.1 From e35000ead491d71e59ab6f7458971321e06150a0 Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 13 Mar 2015 17:37:57 +0530 Subject: mwifiex: preprocess packets from TX queue During profiling, we discovered that driver remains idle for time when pakcet is downloaded to FW but no TX_DONE has been received i.e. while data_sent is true. This patch adds enhancement to TX routine where we preprocess packets from TX queue, make them ready for TX and add them to separate TX queue. Signed-off-by: Zhaoyang Liu Signed-off-by: Marc Yang Signed-off-by: Chin-ran Lo Reviewed-by: Cathy Luo Reviewed-by: Amitkumar Karwar Reviewed-by: Avinash Patil Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/mwifiex/main.c') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d96d60a7ae7c..b242c3e8df3f 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -262,6 +262,7 @@ process_start: (adapter->pm_wakeup_card_req && !adapter->pm_wakeup_fw_try) && (is_command_pending(adapter) || + !skb_queue_empty(&adapter->tx_data_q) || !mwifiex_wmm_lists_empty(adapter))) { adapter->pm_wakeup_fw_try = true; mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3)); @@ -286,7 +287,8 @@ process_start: if ((!adapter->scan_chan_gap_enabled && adapter->scan_processing) || adapter->data_sent || - mwifiex_wmm_lists_empty(adapter)) { + (mwifiex_wmm_lists_empty(adapter) && + skb_queue_empty(&adapter->tx_data_q))) { if (adapter->cmd_sent || adapter->curr_cmd || (!is_command_pending(adapter))) break; @@ -336,6 +338,20 @@ process_start: } } + if ((adapter->scan_chan_gap_enabled || + !adapter->scan_processing) && + !adapter->data_sent && + !skb_queue_empty(&adapter->tx_data_q)) { + mwifiex_process_tx_queue(adapter); + if (adapter->hs_activated) { + adapter->is_hs_configured = false; + mwifiex_hs_activated_event + (mwifiex_get_priv + (adapter, MWIFIEX_BSS_ROLE_ANY), + false); + } + } + if ((adapter->scan_chan_gap_enabled || !adapter->scan_processing) && !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { @@ -351,7 +367,8 @@ process_start: if (adapter->delay_null_pkt && !adapter->cmd_sent && !adapter->curr_cmd && !is_command_pending(adapter) && - mwifiex_wmm_lists_empty(adapter)) { + (mwifiex_wmm_lists_empty(adapter) && + skb_queue_empty(&adapter->tx_data_q))) { if (!mwifiex_send_null_packet (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | -- cgit v1.2.1 From 92263a841b1502d2ef19199deaa669fe4c0102e9 Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 13 Mar 2015 17:37:58 +0530 Subject: mwifiex: add SDIO rx single port aggregation This patch brings in support for SDIO single port rx aggregation to mwifiex. Maximum read size support by SDIO cmd53 is 64K. Based on multi port aggregation which is already part of mwifiex, idea here is multiple packets received in FW can be aggregated into single buffer. A separate upload type is defined for such packet aggregated to single port. Packets from this single buffer are later deaggregated into individual packets. This way, driver can receive more packets each time through single SDIO cmd53; thereby reducing no of times MMC bus is accessed. SDIO SP aggregation support is advertised by FW during load time and driver would get FW block size in command response of HostCmd_CMD_SDIO_SP_RX_AGGR_CFG. Signed-off-by: Zhaoyang Liu Signed-off-by: Marc Yang Reviewed-by: Amitkumar Karwar Reviewed-by: Cathy Luo Reviewed-by: Avinash Patil Signed-off-by: Avinash Patil Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/mwifiex/main.c') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index b242c3e8df3f..eaaacecbdef6 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -163,6 +163,7 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter) { unsigned long flags; struct sk_buff *skb; + struct mwifiex_rxinfo *rx_info; spin_lock_irqsave(&adapter->rx_proc_lock, flags); if (adapter->rx_processing || adapter->rx_locked) { @@ -184,7 +185,14 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter) adapter->delay_main_work = false; mwifiex_queue_main_work(adapter); } - mwifiex_handle_rx_packet(adapter, skb); + rx_info = MWIFIEX_SKB_RXCB(skb); + if (rx_info->buf_type == MWIFIEX_TYPE_AGGR_DATA) { + if (adapter->if_ops.deaggr_pkt) + adapter->if_ops.deaggr_pkt(adapter, skb); + dev_kfree_skb_any(skb); + } else { + mwifiex_handle_rx_packet(adapter, skb); + } } spin_lock_irqsave(&adapter->rx_proc_lock, flags); adapter->rx_processing = false; -- cgit v1.2.1 From 2f5872b60146eadf74b8d349a3596f5aaf687401 Mon Sep 17 00:00:00 2001 From: Maithili Hinge Date: Sun, 22 Mar 2015 23:01:25 -0700 Subject: mwifiex: Fix issue in the SDIO reset path of mwifiex. SDIO reset was not happening properly on mwifiex as cancel_work_sync in mwifiex_sdio_remove used to kill the calling work function itself. Due to this, the interface was not getting removed and card was not getting added again. Reset work function has been made independent of adapter variable and cancel_work_sync has been moved to cleanup function. Signed-off-by: Maithili Hinge Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net/wireless/mwifiex/main.c') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index eaaacecbdef6..a3c2bb122c09 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -1149,9 +1149,6 @@ mwifiex_add_card(void *card, struct semaphore *sem, 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); - /* Register the device. Fill up the private data structure with relevant information from the card. */ if (adapter->if_ops.register_dev(adapter)) { -- cgit v1.2.1