summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJes Sorensen <Jes.Sorensen@redhat.com>2014-04-26 18:54:57 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-26 10:16:13 -0700
commitd97e2d2b55525853d02a318f7f8a6ca214e24699 (patch)
treede328d8cfe85866909367b9f7c8c00d931048715
parent6f1c59bf2c00eeba0f9ad9ce176cce731de1a8e5 (diff)
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 <Jes.Sorensen@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/rtl8723au/core/rtw_cmd.c211
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c12
-rw-r--r--drivers/staging/rtl8723au/include/rtw_cmd.h11
-rw-r--r--drivers/staging/rtl8723au/os_dep/os_intfs.c15
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 068374a911fc..813897f82185 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 0a86923e7def..346aeca7ec9c 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 ba6d572b81b3..8f2b9a4ea729 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 fd9de2a60bf7..23e0a3f01424 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);
}