From d97e2d2b55525853d02a318f7f8a6ca214e24699 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Sat, 26 Apr 2014 18:54:57 +0200 Subject: [PATCH] staging: rtl8723au: Use a workqueue for command handling 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 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/core/rtw_cmd.c | 211 ++++++---------------- drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c | 12 +- drivers/staging/rtl8723au/include/rtw_cmd.h | 11 +- drivers/staging/rtl8723au/os_dep/os_intfs.c | 15 +- 4 files changed, 67 insertions(+), 182 deletions(-) diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c index 068374a..813897f 100644 --- a/drivers/staging/rtl8723au/core/rtw_cmd.c +++ b/drivers/staging/rtl8723au/core/rtw_cmd.c @@ -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) diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c index 0a86923..346aeca 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c @@ -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) -{ -} diff --git a/drivers/staging/rtl8723au/include/rtw_cmd.h b/drivers/staging/rtl8723au/include/rtw_cmd.h index ba6d572b..8f2b9a4 100644 --- a/drivers/staging/rtl8723au/include/rtw_cmd.h +++ b/drivers/staging/rtl8723au/include/rtw_cmd.h @@ -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); diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c index fd9de2a..23e0a3f 100644 --- a/drivers/staging/rtl8723au/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723au/os_dep/os_intfs.c @@ -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); } -- 2.7.4