Commit d97e2d2b authored by Jes Sorensen's avatar Jes Sorensen Committed by Greg Kroah-Hartman

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: default avatarJes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6f1c59bf
...@@ -176,13 +176,6 @@ int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv) ...@@ -176,13 +176,6 @@ int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv)
{ {
int res = _SUCCESS; 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, pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
GFP_KERNEL); GFP_KERNEL);
...@@ -209,6 +202,11 @@ int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv) ...@@ -209,6 +202,11 @@ int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv)
pcmdpriv->cmd_done_cnt = 0; pcmdpriv->cmd_done_cnt = 0;
pcmdpriv->rsp_cnt = 0; pcmdpriv->rsp_cnt = 0;
pcmdpriv->wq = alloc_workqueue("rtl8723au", 0, 1);
if (!pcmdpriv->wq)
res = _FAIL;
exit: exit:
return res; return res;
...@@ -260,32 +258,6 @@ void _rtw_free_cmd_priv23a(struct cmd_priv *pcmdpriv) ...@@ -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) u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv)
{ {
int res; int res;
...@@ -330,21 +302,21 @@ static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) ...@@ -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)) if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
bAllow = true; bAllow = true;
if ((pcmdpriv->padapter->hw_init_completed == false && if (pcmdpriv->padapter->hw_init_completed == false && bAllow == false)
bAllow == false) || pcmdpriv->cmdthd_running == false)
return _FAIL; return _FAIL;
return _SUCCESS; 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; int res = _FAIL;
struct rtw_adapter *padapter = pcmdpriv->padapter;
if (!cmd_obj) if (!cmd_obj)
goto exit; goto exit;
cmd_obj->padapter = padapter; cmd_obj->padapter = pcmdpriv->padapter;
res = rtw_cmd_filter(pcmdpriv, cmd_obj); res = rtw_cmd_filter(pcmdpriv, cmd_obj);
if (res == _FAIL) { if (res == _FAIL) {
...@@ -352,32 +324,18 @@ u32 rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) ...@@ -352,32 +324,18 @@ u32 rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
goto exit; goto exit;
} }
res = _rtw_enqueue_cmd23a(&pcmdpriv->cmd_queue, cmd_obj); INIT_WORK(&cmd_obj->work, rtw_cmd_work);
if (res == _SUCCESS) res = queue_work(pcmdpriv->wq, &cmd_obj->work);
up(&pcmdpriv->cmd_queue_sema);
if (!res) {
printk(KERN_ERR "%s: Call to queue_work() failed\n", __func__);
res = _FAIL;
} else
res = _SUCCESS;
exit: 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 res;
return obj;
} }
void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv) void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv)
...@@ -404,42 +362,16 @@ void rtw_free_cmd_obj23a(struct cmd_obj *pcmd) ...@@ -404,42 +362,16 @@ void rtw_free_cmd_obj23a(struct cmd_obj *pcmd)
kfree(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); u8 (*cmd_hdl)(struct rtw_adapter *padapter, u8* pbuf);
void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd); void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd);
struct rtw_adapter *padapter = (struct rtw_adapter *)context; struct cmd_priv *pcmdpriv;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv; struct cmd_obj *pcmd = container_of(work, struct cmd_obj, work);
u8 *pcmdbuf;
allow_signal(SIGTERM);
pcmdpriv = &pcmd->padapter->cmdpriv;
pcmdbuf = pcmdpriv->cmd_buf; 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) { if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
pcmd->res = H2C_DROPPED; pcmd->res = H2C_DROPPED;
...@@ -455,27 +387,22 @@ int rtw_cmd_thread23a(void *context) ...@@ -455,27 +387,22 @@ int rtw_cmd_thread23a(void *context)
if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) { if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) {
cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
if (cmd_hdl) { if (cmd_hdl)
ret = cmd_hdl(pcmd->padapter, pcmdbuf); pcmd->res = cmd_hdl(pcmd->padapter, pcmdbuf);
pcmd->res = ret; else
} pcmd->res = H2C_DROPPED;
pcmdpriv->cmd_seq++;
} else } else
pcmd->res = H2C_PARAMETERS_ERROR; pcmd->res = H2C_PARAMETERS_ERROR;
cmd_hdl = NULL;
post_process: post_process:
/* call callback function for post-processed */ /* call callback function for post-processed */
if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) / if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) /
sizeof(struct _cmd_callback))) { sizeof(struct _cmd_callback))) {
pcmd_callback = pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
rtw_cmd_callback[pcmd->cmdcode].callback;
if (!pcmd_callback) { if (!pcmd_callback) {
RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
("mlme_cmd_hdl(): pcmd_callback = " ("mlme_cmd_hdl(): pcmd_callback = 0x%p, "
"0x%p, cmdcode = 0x%x\n", "cmdcode = 0x%x\n",
pcmd_callback, pcmd->cmdcode)); pcmd_callback, pcmd->cmdcode));
rtw_free_cmd_obj23a(pcmd); rtw_free_cmd_obj23a(pcmd);
} else { } else {
...@@ -491,29 +418,9 @@ int rtw_cmd_thread23a(void *context) ...@@ -491,29 +418,9 @@ int rtw_cmd_thread23a(void *context)
__func__, pcmd->cmdcode)); __func__, pcmd->cmdcode));
rtw_free_cmd_obj23a(pcmd); rtw_free_cmd_obj23a(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;
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, u8 rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter,
struct cfg80211_ssid *ssid, int ssid_num, struct cfg80211_ssid *ssid, int ssid_num,
struct rtw_ieee80211_channel *ch, int ch_num) struct rtw_ieee80211_channel *ch, int ch_num)
......
...@@ -1738,8 +1738,8 @@ void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc) ...@@ -1738,8 +1738,8 @@ void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc)
&rtl8723a_SetBeaconRelatedRegisters; &rtl8723a_SetBeaconRelatedRegisters;
pHalFunc->Add_RateATid = &rtl8723a_add_rateatid; pHalFunc->Add_RateATid = &rtl8723a_add_rateatid;
pHalFunc->run_thread = &rtl8723a_start_thread; pHalFunc->run_thread = NULL;
pHalFunc->cancel_thread = &rtl8723a_stop_thread; pHalFunc->cancel_thread = NULL;
pHalFunc->read_bbreg = &PHY_QueryBBReg; pHalFunc->read_bbreg = &PHY_QueryBBReg;
pHalFunc->write_bbreg = &PHY_SetBBReg; pHalFunc->write_bbreg = &PHY_SetBBReg;
...@@ -3187,11 +3187,3 @@ void rtl8723a_clone_haldata(struct rtw_adapter *dst_adapter, ...@@ -3187,11 +3187,3 @@ void rtl8723a_clone_haldata(struct rtw_adapter *dst_adapter,
memcpy(dst_adapter->HalData, src_adapter->HalData, memcpy(dst_adapter->HalData, src_adapter->HalData,
dst_adapter->hal_data_sz); dst_adapter->hal_data_sz);
} }
void rtl8723a_start_thread(struct rtw_adapter *padapter)
{
}
void rtl8723a_stop_thread(struct rtw_adapter *padapter)
{
}
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define CMDBUFF_ALIGN_SZ 512 #define CMDBUFF_ALIGN_SZ 512
struct cmd_obj { struct cmd_obj {
struct work_struct work;
struct rtw_adapter *padapter; struct rtw_adapter *padapter;
u16 cmdcode; u16 cmdcode;
u8 res; u8 res;
...@@ -41,16 +42,11 @@ struct cmd_obj { ...@@ -41,16 +42,11 @@ struct cmd_obj {
u32 cmdsz; u32 cmdsz;
u8 *rsp; u8 *rsp;
u32 rspsz; u32 rspsz;
/* struct semaphore cmd_sem; */
struct list_head list; struct list_head list;
}; };
struct cmd_priv { struct cmd_priv {
struct semaphore cmd_queue_sema; struct workqueue_struct *wq;
/* struct semaphore cmd_done_sema; */
struct semaphore terminate_cmdthread_sema;
struct rtw_queue cmd_queue;
u8 cmd_seq;
u8 *cmd_buf; /* shall be non-paged, and 4 bytes aligned */ u8 *cmd_buf; /* shall be non-paged, and 4 bytes aligned */
u8 *cmd_allocated_buf; u8 *cmd_allocated_buf;
u8 *rsp_buf; /* shall be non-paged, and 4 bytes aligned */ u8 *rsp_buf; /* shall be non-paged, and 4 bytes aligned */
...@@ -58,7 +54,6 @@ struct cmd_priv { ...@@ -58,7 +54,6 @@ struct cmd_priv {
u32 cmd_issued_cnt; u32 cmd_issued_cnt;
u32 cmd_done_cnt; u32 cmd_done_cnt;
u32 rsp_cnt; u32 rsp_cnt;
u8 cmdthd_running;
struct rtw_adapter *padapter; struct rtw_adapter *padapter;
}; };
...@@ -94,7 +89,7 @@ struct c2h_evt_hdr { ...@@ -94,7 +89,7 @@ struct c2h_evt_hdr {
#define c2h_evt_exist(c2h_evt) ((c2h_evt)->id || (c2h_evt)->plen) #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); void rtw_free_cmd_obj23a(struct cmd_obj *pcmd);
int rtw_cmd_thread23a(void *context); int rtw_cmd_thread23a(void *context);
......
...@@ -383,14 +383,7 @@ u32 rtw_start_drv_threads23a(struct rtw_adapter *padapter) ...@@ -383,14 +383,7 @@ u32 rtw_start_drv_threads23a(struct rtw_adapter *padapter)
RT_TRACE(_module_os_intfs_c_, _drv_info_, RT_TRACE(_module_os_intfs_c_, _drv_info_,
("+rtw_start_drv_threads23a\n")); ("+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); rtw_hal_start_thread23a(padapter);
return _status; return _status;
} }
...@@ -399,10 +392,8 @@ void rtw_stop_drv_threads23a(struct rtw_adapter *padapter) ...@@ -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")); RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_stop_drv_threads23a\n"));
/* Below is to termindate rtw_cmd_thread23a & event_thread... */ flush_workqueue(padapter->cmdpriv.wq);
up(&padapter->cmdpriv.cmd_queue_sema);
if (padapter->cmdThread)
down(&padapter->cmdpriv.terminate_cmdthread_sema);
rtw_hal_stop_thread23a(padapter); rtw_hal_stop_thread23a(padapter);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment