mwifiex: avoid queue_work while work is ongoing
authorShengzhen Li <szli@marvell.com>
Fri, 13 Mar 2015 12:07:54 +0000 (17:37 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 16 Mar 2015 16:12:25 +0000 (18:12 +0200)
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 <szli@marvell.com>
Signed-off-by: Zhaoyang Liu <liuzy@marvell.com>
Reviewed-by: Cathy Luo <cluo@marvell.com>
Reviewed-by: Amitkumar Karwar <akarwar@marvell.com>
Reviewed-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/mwifiex/usb.c

index 9c11eb882a0e8463d4436f2e2139ceb05c5eb529..d96d60a7ae7cd42358a4767da1531781119c85f3 100644 (file)
@@ -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;
 }
index d609d16cf18ca21414ee1f56ef9b0b42d32119db..a319abe844233834d2d3aba5dd09ec0648e4bb55 100644 (file)
@@ -1424,6 +1424,7 @@ u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
 
 void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter);
 void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
+void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
 
 #ifdef CONFIG_DEBUG_FS
 void mwifiex_debugfs_init(void);
index fc59c1db36150026fad93541d2f2bf0f97cf78e0..b31c9a70ffaaa4de5f0a426966d39eb888b2959a 100644 (file)
@@ -2101,7 +2101,7 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
                goto exit;
 
        mwifiex_interrupt_status(adapter);
-       queue_work(adapter->workqueue, &adapter->main_work);
+       mwifiex_queue_main_work(adapter);
 
 exit:
        return IRQ_HANDLED;
index 8beb38c578d015de979078a5afac394049e062de..fd8027f200a0ddd61c178ee1f7107e7e0931c1c1 100644 (file)
@@ -193,7 +193,7 @@ static void mwifiex_usb_rx_complete(struct urb *urb)
                dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n",
                        recv_length, status);
                if (status == -EINPROGRESS) {
-                       queue_work(adapter->workqueue, &adapter->main_work);
+                       mwifiex_queue_main_work(adapter);
 
                        /* urb for data_ep is re-submitted now;
                         * urb for cmd_ep will be re-submitted in callback
@@ -262,7 +262,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
                                            urb->status ? -1 : 0);
        }
 
-       queue_work(adapter->workqueue, &adapter->main_work);
+       mwifiex_queue_main_work(adapter);
 
        return;
 }