staging: rtl8723au: Use a workqueue for command handling
authorJes Sorensen <Jes.Sorensen@redhat.com>
Sat, 26 Apr 2014 16:54:57 +0000 (18:54 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 26 Apr 2014 17:16:13 +0000 (10:16 -0700)
Rewrite the old thread based code to use a workqueue instead. This
removes a pile of complexity, locks and queues and eliminates problem
that cmd handling could have been killed from userspace.

This was suggested by Tejun Heo - thanks!

Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/rtl8723au/core/rtw_cmd.c
drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
drivers/staging/rtl8723au/include/rtw_cmd.h
drivers/staging/rtl8723au/os_dep/os_intfs.c

index 068374a..813897f 100644 (file)
@@ -176,13 +176,6 @@ int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv)
 {
        int res = _SUCCESS;
 
-       sema_init(&pcmdpriv->cmd_queue_sema, 0);
-       sema_init(&pcmdpriv->terminate_cmdthread_sema, 0);
-
-       _rtw_init_queue23a(&pcmdpriv->cmd_queue);
-
-       pcmdpriv->cmd_seq = 1;
-
        pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
                                              GFP_KERNEL);
 
@@ -209,6 +202,11 @@ int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv)
        pcmdpriv->cmd_done_cnt = 0;
        pcmdpriv->rsp_cnt = 0;
 
+
+       pcmdpriv->wq = alloc_workqueue("rtl8723au", 0, 1);
+       if (!pcmdpriv->wq)
+               res = _FAIL;
+
 exit:
 
        return res;
@@ -260,32 +258,6 @@ void _rtw_free_cmd_priv23a(struct cmd_priv *pcmdpriv)
        }
 }
 
-/*
-Calling Context:
-rtw_enqueue_cmd23a can only be called between kernel thread,
-since only spin_lock is used.
-
-ISR/Call-Back functions can't call this sub-function.
-*/
-
-int _rtw_enqueue_cmd23a(struct rtw_queue *queue, struct cmd_obj *obj)
-{
-       unsigned long irqL;
-
-       if (obj == NULL)
-               goto exit;
-
-       spin_lock_irqsave(&queue->lock, irqL);
-
-       list_add_tail(&obj->list, &queue->queue);
-
-       spin_unlock_irqrestore(&queue->lock, irqL);
-
-exit:
-
-       return _SUCCESS;
-}
-
 u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv)
 {
        int res;
@@ -330,21 +302,21 @@ static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
        if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
                bAllow = true;
 
-       if ((pcmdpriv->padapter->hw_init_completed == false &&
-            bAllow == false) || pcmdpriv->cmdthd_running == false)
+       if (pcmdpriv->padapter->hw_init_completed == false && bAllow == false)
                return _FAIL;
        return _SUCCESS;
 }
 
-u32 rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+static void rtw_cmd_work(struct work_struct *work);
+
+int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
 {
        int res = _FAIL;
-       struct rtw_adapter *padapter = pcmdpriv->padapter;
 
        if (!cmd_obj)
                goto exit;
 
-       cmd_obj->padapter = padapter;
+       cmd_obj->padapter = pcmdpriv->padapter;
 
        res = rtw_cmd_filter(pcmdpriv, cmd_obj);
        if (res == _FAIL) {
@@ -352,32 +324,18 @@ u32 rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
                goto exit;
        }
 
-       res = _rtw_enqueue_cmd23a(&pcmdpriv->cmd_queue, cmd_obj);
+       INIT_WORK(&cmd_obj->work, rtw_cmd_work);
 
-       if (res == _SUCCESS)
-               up(&pcmdpriv->cmd_queue_sema);
+       res = queue_work(pcmdpriv->wq, &cmd_obj->work);
 
+       if (!res) {
+               printk(KERN_ERR "%s: Call to queue_work() failed\n", __func__);
+               res = _FAIL;
+       } else
+               res = _SUCCESS;
 exit:
-       return res;
-}
 
-static struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
-{
-       struct cmd_obj *obj;
-       struct rtw_queue *queue = &pcmdpriv->cmd_queue;
-       unsigned long irqL;
-
-       spin_lock_irqsave(&queue->lock, irqL);
-       if (list_empty(&queue->queue))
-               obj = NULL;
-       else {
-               obj = container_of((&queue->queue)->next, struct cmd_obj, list);
-               list_del_init(&obj->list);
-       }
-
-       spin_unlock_irqrestore(&queue->lock, irqL);
-
-       return obj;
+       return res;
 }
 
 void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv)
@@ -404,116 +362,65 @@ void rtw_free_cmd_obj23a(struct cmd_obj *pcmd)
        kfree(pcmd);
 }
 
-int rtw_cmd_thread23a(void *context)
+static void rtw_cmd_work(struct work_struct *work)
 {
-       u8 ret;
-       struct cmd_obj *pcmd;
-       u8 *pcmdbuf, *prspbuf;
        u8 (*cmd_hdl)(struct rtw_adapter *padapter, u8* pbuf);
        void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd);
-       struct rtw_adapter *padapter = (struct rtw_adapter *)context;
-       struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
-       allow_signal(SIGTERM);
+       struct cmd_priv *pcmdpriv;
+       struct cmd_obj *pcmd = container_of(work, struct cmd_obj, work);
+       u8 *pcmdbuf;
 
+       pcmdpriv = &pcmd->padapter->cmdpriv;
        pcmdbuf = pcmdpriv->cmd_buf;
-       prspbuf = pcmdpriv->rsp_buf;
 
-       pcmdpriv->cmdthd_running = true;
-       up(&pcmdpriv->terminate_cmdthread_sema);
-
-       RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
-                ("start r871x rtw_cmd_thread23a !!!!\n"));
-
-       while(1) {
-               if (down_interruptible(&pcmdpriv->cmd_queue_sema))
-                       break;
-_next:
-               if ((padapter->bDriverStopped == true) ||
-                   (padapter->bSurpriseRemoved == true)) {
-                       DBG_8723A("%s: DriverStopped(%d) SurpriseRemoved(%d) "
-                                 "break at line %d\n", __func__,
-                                 padapter->bDriverStopped,
-                                 padapter->bSurpriseRemoved, __LINE__);
-                       break;
-               }
-
-               if (!(pcmd = rtw_dequeue_cmd(pcmdpriv)))
-                       continue;
-
-               if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
-                       pcmd->res = H2C_DROPPED;
-                       goto post_process;
-               }
-
-               pcmdpriv->cmd_issued_cnt++;
-
-               pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4);
+       if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
+               pcmd->res = H2C_DROPPED;
+               goto post_process;
+       }
 
-               memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
+       pcmdpriv->cmd_issued_cnt++;
 
-               if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) {
-                       cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
+       pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4);
 
-                       if (cmd_hdl) {
-                               ret = cmd_hdl(pcmd->padapter, pcmdbuf);
-                               pcmd->res = ret;
-                       }
+       memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
 
-                       pcmdpriv->cmd_seq++;
-               } else
-                       pcmd->res = H2C_PARAMETERS_ERROR;
+       if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) {
+               cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
 
-               cmd_hdl = NULL;
+               if (cmd_hdl)
+                       pcmd->res = cmd_hdl(pcmd->padapter, pcmdbuf);
+               else
+                       pcmd->res = H2C_DROPPED;
+       } else
+               pcmd->res = H2C_PARAMETERS_ERROR;
 
 post_process:
-               /* call callback function for post-processed */
-               if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) /
-                                    sizeof(struct _cmd_callback))) {
-                       pcmd_callback =
-                               rtw_cmd_callback[pcmd->cmdcode].callback;
-                       if (!pcmd_callback) {
-                               RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
-                                        ("mlme_cmd_hdl(): pcmd_callback = "
-                                         "0x%p, cmdcode = 0x%x\n",
-                                         pcmd_callback, pcmd->cmdcode));
-                               rtw_free_cmd_obj23a(pcmd);
-                       } else {
-                               /* todo: !!! fill rsp_buf to pcmd->rsp
-                                  if (pcmd->rsp!= NULL) */
-                               /* need conider that free cmd_obj in
-                                  rtw_cmd_callback */
-                               pcmd_callback(pcmd->padapter, pcmd);
-                       }
-               } else {
-                       RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
-                                ("%s: cmdcode = 0x%x callback not defined!\n",
-                                 __func__, pcmd->cmdcode));
+       /* call callback function for post-processed */
+       if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) /
+                            sizeof(struct _cmd_callback))) {
+               pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
+               if (!pcmd_callback) {
+                       RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
+                                ("mlme_cmd_hdl(): pcmd_callback = 0x%p, "
+                                 "cmdcode = 0x%x\n",
+                                 pcmd_callback, pcmd->cmdcode));
                        rtw_free_cmd_obj23a(pcmd);
+               } else {
+                       /* todo: !!! fill rsp_buf to pcmd->rsp
+                          if (pcmd->rsp!= NULL) */
+                       /* need conider that free cmd_obj in
+                          rtw_cmd_callback */
+                       pcmd_callback(pcmd->padapter, pcmd);
                }
-
-               if (signal_pending (current))
-                       flush_signals(current);
-
-               goto _next;
-
-       }
-       pcmdpriv->cmdthd_running = false;
-
-       /*  free all cmd_obj resources */
-       do {
-               pcmd = rtw_dequeue_cmd(pcmdpriv);
-               if (!pcmd)
-                       break;
-
+       } else {
+               RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
+                        ("%s: cmdcode = 0x%x callback not defined!\n",
+                         __func__, pcmd->cmdcode));
                rtw_free_cmd_obj23a(pcmd);
-       } while(1);
-
-       up(&pcmdpriv->terminate_cmdthread_sema);
-
-       complete_and_exit(NULL, 0);
+       }
 }
 
+
 u8 rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter,
                         struct cfg80211_ssid *ssid, int ssid_num,
                         struct rtw_ieee80211_channel *ch, int ch_num)
index 0a86923..346aeca 100644 (file)
@@ -1738,8 +1738,8 @@ void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc)
                &rtl8723a_SetBeaconRelatedRegisters;
 
        pHalFunc->Add_RateATid = &rtl8723a_add_rateatid;
-       pHalFunc->run_thread = &rtl8723a_start_thread;
-       pHalFunc->cancel_thread = &rtl8723a_stop_thread;
+       pHalFunc->run_thread = NULL;
+       pHalFunc->cancel_thread = NULL;
 
        pHalFunc->read_bbreg = &PHY_QueryBBReg;
        pHalFunc->write_bbreg = &PHY_SetBBReg;
@@ -3187,11 +3187,3 @@ void rtl8723a_clone_haldata(struct rtw_adapter *dst_adapter,
        memcpy(dst_adapter->HalData, src_adapter->HalData,
               dst_adapter->hal_data_sz);
 }
-
-void rtl8723a_start_thread(struct rtw_adapter *padapter)
-{
-}
-
-void rtl8723a_stop_thread(struct rtw_adapter *padapter)
-{
-}
index ba6d572..8f2b9a4 100644 (file)
@@ -34,6 +34,7 @@
 #define CMDBUFF_ALIGN_SZ 512
 
 struct cmd_obj {
+       struct work_struct work;
        struct rtw_adapter *padapter;
        u16     cmdcode;
        u8      res;
@@ -41,16 +42,11 @@ struct cmd_obj {
        u32     cmdsz;
        u8      *rsp;
        u32     rspsz;
-       /* struct semaphore             cmd_sem; */
        struct list_head        list;
 };
 
 struct cmd_priv {
-       struct semaphore        cmd_queue_sema;
-       /* struct semaphore     cmd_done_sema; */
-       struct semaphore        terminate_cmdthread_sema;
-       struct rtw_queue        cmd_queue;
-       u8      cmd_seq;
+       struct workqueue_struct *wq;
        u8      *cmd_buf;       /* shall be non-paged, and 4 bytes aligned */
        u8      *cmd_allocated_buf;
        u8      *rsp_buf;       /* shall be non-paged, and 4 bytes aligned */
@@ -58,7 +54,6 @@ struct cmd_priv {
        u32     cmd_issued_cnt;
        u32     cmd_done_cnt;
        u32     rsp_cnt;
-       u8 cmdthd_running;
        struct rtw_adapter *padapter;
 };
 
@@ -94,7 +89,7 @@ struct c2h_evt_hdr {
 
 #define c2h_evt_exist(c2h_evt) ((c2h_evt)->id || (c2h_evt)->plen)
 
-u32 rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
+int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
 void rtw_free_cmd_obj23a(struct cmd_obj *pcmd);
 
 int rtw_cmd_thread23a(void *context);
index fd9de2a..23e0a3f 100644 (file)
@@ -383,14 +383,7 @@ u32 rtw_start_drv_threads23a(struct rtw_adapter *padapter)
 
        RT_TRACE(_module_os_intfs_c_, _drv_info_,
                 ("+rtw_start_drv_threads23a\n"));
-       padapter->cmdThread = kthread_run(rtw_cmd_thread23a, padapter,
-                                         "RTW_CMD_THREAD");
-       if (IS_ERR(padapter->cmdThread)) {
-               _status = _FAIL;
-       } else {
-               /* wait for cmd_thread to run */
-               down(&padapter->cmdpriv.terminate_cmdthread_sema);
-       }
+
        rtw_hal_start_thread23a(padapter);
        return _status;
 }
@@ -399,10 +392,8 @@ void rtw_stop_drv_threads23a(struct rtw_adapter *padapter)
 {
        RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_stop_drv_threads23a\n"));
 
-       /* Below is to termindate rtw_cmd_thread23a & event_thread... */
-       up(&padapter->cmdpriv.cmd_queue_sema);
-       if (padapter->cmdThread)
-               down(&padapter->cmdpriv.terminate_cmdthread_sema);
+       flush_workqueue(padapter->cmdpriv.wq);
+
        rtw_hal_stop_thread23a(padapter);
 }