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>
This commit is contained in:
parent
6f1c59bf2c
commit
d97e2d2b55
|
@ -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,34 +324,20 @@ 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;
|
||||
}
|
||||
|
||||
void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv)
|
||||
{
|
||||
pcmdpriv->cmd_done_cnt++;
|
||||
|
@ -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);
|
||||
if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
|
||||
pcmd->res = H2C_DROPPED;
|
||||
goto post_process;
|
||||
}
|
||||
|
||||
RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
|
||||
("start r871x rtw_cmd_thread23a !!!!\n"));
|
||||
pcmdpriv->cmd_issued_cnt++;
|
||||
|
||||
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;
|
||||
}
|
||||
pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4);
|
||||
|
||||
if (!(pcmd = rtw_dequeue_cmd(pcmdpriv)))
|
||||
continue;
|
||||
memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
|
||||
|
||||
if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
|
||||
if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) {
|
||||
cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
|
||||
|
||||
if (cmd_hdl)
|
||||
pcmd->res = cmd_hdl(pcmd->padapter, pcmdbuf);
|
||||
else
|
||||
pcmd->res = H2C_DROPPED;
|
||||
goto post_process;
|
||||
}
|
||||
|
||||
pcmdpriv->cmd_issued_cnt++;
|
||||
|
||||
pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4);
|
||||
|
||||
memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
|
||||
|
||||
if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) {
|
||||
cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
|
||||
|
||||
if (cmd_hdl) {
|
||||
ret = cmd_hdl(pcmd->padapter, pcmdbuf);
|
||||
pcmd->res = ret;
|
||||
}
|
||||
|
||||
pcmdpriv->cmd_seq++;
|
||||
} else
|
||||
pcmd->res = H2C_PARAMETERS_ERROR;
|
||||
|
||||
cmd_hdl = NULL;
|
||||
} 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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue