wcn36xx: dequeue all pending indicator messages
In case wcn36xx_smd_rsp_process() is called more than once before hal_ind_work was dispatched, the messages will end up in hal_ind_queue, but wcn36xx_ind_smd_work() will only look at the first message in that list. Fix this by dequeing the messages from the list in a loop, and only stop when it's empty. This issue was found during a review of the driver. In my tests, that race never actually occured. Signed-off-by: Daniel Mack <daniel@zonque.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
e5f9908155
commit
f276ba06e8
|
@ -2411,54 +2411,63 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
|
|||
{
|
||||
struct wcn36xx *wcn =
|
||||
container_of(work, struct wcn36xx, hal_ind_work);
|
||||
struct wcn36xx_hal_msg_header *msg_header;
|
||||
struct wcn36xx_hal_ind_msg *hal_ind_msg;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&wcn->hal_ind_lock, flags);
|
||||
for (;;) {
|
||||
struct wcn36xx_hal_msg_header *msg_header;
|
||||
struct wcn36xx_hal_ind_msg *hal_ind_msg;
|
||||
unsigned long flags;
|
||||
|
||||
hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
|
||||
struct wcn36xx_hal_ind_msg,
|
||||
list);
|
||||
list_del(wcn->hal_ind_queue.next);
|
||||
spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
|
||||
spin_lock_irqsave(&wcn->hal_ind_lock, flags);
|
||||
|
||||
msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
|
||||
if (list_empty(&wcn->hal_ind_queue)) {
|
||||
spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg_header->msg_type) {
|
||||
case WCN36XX_HAL_COEX_IND:
|
||||
case WCN36XX_HAL_DEL_BA_IND:
|
||||
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
|
||||
break;
|
||||
case WCN36XX_HAL_OTA_TX_COMPL_IND:
|
||||
wcn36xx_smd_tx_compl_ind(wcn,
|
||||
hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
case WCN36XX_HAL_MISSED_BEACON_IND:
|
||||
wcn36xx_smd_missed_beacon_ind(wcn,
|
||||
hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
|
||||
wcn36xx_smd_delete_sta_context_ind(wcn,
|
||||
hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
case WCN36XX_HAL_PRINT_REG_INFO_IND:
|
||||
wcn36xx_smd_print_reg_info_ind(wcn,
|
||||
hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
case WCN36XX_HAL_SCAN_OFFLOAD_IND:
|
||||
wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
default:
|
||||
wcn36xx_err("SMD_EVENT (%d) not supported\n",
|
||||
msg_header->msg_type);
|
||||
hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
|
||||
struct wcn36xx_hal_ind_msg,
|
||||
list);
|
||||
list_del(&hal_ind_msg->list);
|
||||
spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
|
||||
|
||||
msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
|
||||
|
||||
switch (msg_header->msg_type) {
|
||||
case WCN36XX_HAL_COEX_IND:
|
||||
case WCN36XX_HAL_DEL_BA_IND:
|
||||
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
|
||||
break;
|
||||
case WCN36XX_HAL_OTA_TX_COMPL_IND:
|
||||
wcn36xx_smd_tx_compl_ind(wcn,
|
||||
hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
case WCN36XX_HAL_MISSED_BEACON_IND:
|
||||
wcn36xx_smd_missed_beacon_ind(wcn,
|
||||
hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
|
||||
wcn36xx_smd_delete_sta_context_ind(wcn,
|
||||
hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
case WCN36XX_HAL_PRINT_REG_INFO_IND:
|
||||
wcn36xx_smd_print_reg_info_ind(wcn,
|
||||
hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
case WCN36XX_HAL_SCAN_OFFLOAD_IND:
|
||||
wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
|
||||
hal_ind_msg->msg_len);
|
||||
break;
|
||||
default:
|
||||
wcn36xx_err("SMD_EVENT (%d) not supported\n",
|
||||
msg_header->msg_type);
|
||||
}
|
||||
|
||||
kfree(hal_ind_msg);
|
||||
}
|
||||
kfree(hal_ind_msg);
|
||||
}
|
||||
int wcn36xx_smd_open(struct wcn36xx *wcn)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue