Commit f276ba06 authored by Daniel Mack's avatar Daniel Mack Committed by Kalle Valo

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: default avatarDaniel Mack <daniel@zonque.org>
Reviewed-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent e5f99081
...@@ -2411,54 +2411,63 @@ static void wcn36xx_ind_smd_work(struct work_struct *work) ...@@ -2411,54 +2411,63 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
{ {
struct wcn36xx *wcn = struct wcn36xx *wcn =
container_of(work, struct wcn36xx, hal_ind_work); 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, spin_lock_irqsave(&wcn->hal_ind_lock, flags);
struct wcn36xx_hal_ind_msg,
list);
list_del(wcn->hal_ind_queue.next);
spin_unlock_irqrestore(&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) { hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
case WCN36XX_HAL_COEX_IND: struct wcn36xx_hal_ind_msg,
case WCN36XX_HAL_DEL_BA_IND: list);
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND: list_del(&hal_ind_msg->list);
break; spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
case WCN36XX_HAL_OTA_TX_COMPL_IND:
wcn36xx_smd_tx_compl_ind(wcn, msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
hal_ind_msg->msg,
hal_ind_msg->msg_len); switch (msg_header->msg_type) {
break; case WCN36XX_HAL_COEX_IND:
case WCN36XX_HAL_MISSED_BEACON_IND: case WCN36XX_HAL_DEL_BA_IND:
wcn36xx_smd_missed_beacon_ind(wcn, case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
hal_ind_msg->msg, break;
hal_ind_msg->msg_len); case WCN36XX_HAL_OTA_TX_COMPL_IND:
break; wcn36xx_smd_tx_compl_ind(wcn,
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: hal_ind_msg->msg,
wcn36xx_smd_delete_sta_context_ind(wcn, hal_ind_msg->msg_len);
hal_ind_msg->msg, break;
hal_ind_msg->msg_len); case WCN36XX_HAL_MISSED_BEACON_IND:
break; wcn36xx_smd_missed_beacon_ind(wcn,
case WCN36XX_HAL_PRINT_REG_INFO_IND: hal_ind_msg->msg,
wcn36xx_smd_print_reg_info_ind(wcn, hal_ind_msg->msg_len);
hal_ind_msg->msg, break;
hal_ind_msg->msg_len); case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
break; wcn36xx_smd_delete_sta_context_ind(wcn,
case WCN36XX_HAL_SCAN_OFFLOAD_IND: hal_ind_msg->msg,
wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg, hal_ind_msg->msg_len);
hal_ind_msg->msg_len); break;
break; case WCN36XX_HAL_PRINT_REG_INFO_IND:
default: wcn36xx_smd_print_reg_info_ind(wcn,
wcn36xx_err("SMD_EVENT (%d) not supported\n", hal_ind_msg->msg,
msg_header->msg_type); 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) int wcn36xx_smd_open(struct wcn36xx *wcn)
{ {
......
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