Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+52 −43
Original line number Original line Diff line number Diff line
@@ -2411,16 +2411,23 @@ 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);

	for (;;) {
		struct wcn36xx_hal_msg_header *msg_header;
		struct wcn36xx_hal_msg_header *msg_header;
		struct wcn36xx_hal_ind_msg *hal_ind_msg;
		struct wcn36xx_hal_ind_msg *hal_ind_msg;
		unsigned long flags;
		unsigned long flags;


		spin_lock_irqsave(&wcn->hal_ind_lock, flags);
		spin_lock_irqsave(&wcn->hal_ind_lock, flags);


		if (list_empty(&wcn->hal_ind_queue)) {
			spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
			return;
		}

		hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
		hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
					       struct wcn36xx_hal_ind_msg,
					       struct wcn36xx_hal_ind_msg,
					       list);
					       list);
	list_del(wcn->hal_ind_queue.next);
		list_del(&hal_ind_msg->list);
		spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
		spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);


		msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
		msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
@@ -2458,8 +2465,10 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
			wcn36xx_err("SMD_EVENT (%d) not supported\n",
			wcn36xx_err("SMD_EVENT (%d) not supported\n",
				    msg_header->msg_type);
				    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)
{
{
	int ret = 0;
	int ret = 0;