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

Commit 70398a59 authored by Hante Meuleman's avatar Hante Meuleman Committed by John W. Linville
Browse files

brcmfmac: use wait_event_timeout for fw control packets over usb.



firmware control packets over usb are async acked. This is
awaited for by using interruptible wait. This can be
interrupted by signal which results in undesirable behavior.
Instead wait_event_timeout is used.

Reviewed-by: default avatarArend Van Spriel <arend@broadcom.com>
Signed-off-by: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2d838bb6
Loading
Loading
Loading
Loading
+9 −37
Original line number Original line Diff line number Diff line
@@ -160,40 +160,17 @@ static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
	return brcmf_usb_get_buspub(dev)->devinfo;
	return brcmf_usb_get_buspub(dev)->devinfo;
}
}


static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo,
static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo)
	 uint *condition, bool *pending)
{
{
	DECLARE_WAITQUEUE(wait, current);
	return wait_event_timeout(devinfo->ioctl_resp_wait,
	int timeout = IOCTL_RESP_TIMEOUT;
				  devinfo->ctl_completed,

				  msecs_to_jiffies(IOCTL_RESP_TIMEOUT));
	/* Convert timeout in millsecond to jiffies */
	timeout = msecs_to_jiffies(timeout);
	/* Wait until control frame is available */
	add_wait_queue(&devinfo->ioctl_resp_wait, &wait);
	set_current_state(TASK_INTERRUPTIBLE);

	smp_mb();
	while (!(*condition) && (!signal_pending(current) && timeout)) {
		timeout = schedule_timeout(timeout);
		/* Wait until control frame is available */
		smp_mb();
	}

	if (signal_pending(current))
		*pending = true;

	set_current_state(TASK_RUNNING);
	remove_wait_queue(&devinfo->ioctl_resp_wait, &wait);

	return timeout;
}
}


static int brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
{
{
	if (waitqueue_active(&devinfo->ioctl_resp_wait))
	if (waitqueue_active(&devinfo->ioctl_resp_wait))
		wake_up_interruptible(&devinfo->ioctl_resp_wait);
		wake_up(&devinfo->ioctl_resp_wait);

	return 0;
}
}


static void
static void
@@ -322,7 +299,6 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
{
{
	int err = 0;
	int err = 0;
	int timeout = 0;
	int timeout = 0;
	bool pending;
	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);


	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
@@ -340,9 +316,7 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
		clear_bit(0, &devinfo->ctl_op);
		clear_bit(0, &devinfo->ctl_op);
		return err;
		return err;
	}
	}

	timeout = brcmf_usb_ioctl_resp_wait(devinfo);
	timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed,
					    &pending);
	clear_bit(0, &devinfo->ctl_op);
	clear_bit(0, &devinfo->ctl_op);
	if (!timeout) {
	if (!timeout) {
		brcmf_dbg(ERROR, "Txctl wait timed out\n");
		brcmf_dbg(ERROR, "Txctl wait timed out\n");
@@ -355,7 +329,6 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
{
{
	int err = 0;
	int err = 0;
	int timeout = 0;
	int timeout = 0;
	bool pending;
	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);


	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
@@ -365,15 +338,14 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
	if (test_and_set_bit(0, &devinfo->ctl_op))
	if (test_and_set_bit(0, &devinfo->ctl_op))
		return -EIO;
		return -EIO;


	devinfo->ctl_completed = false;
	err = brcmf_usb_recv_ctl(devinfo, buf, len);
	err = brcmf_usb_recv_ctl(devinfo, buf, len);
	if (err) {
	if (err) {
		brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
		brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
		clear_bit(0, &devinfo->ctl_op);
		clear_bit(0, &devinfo->ctl_op);
		return err;
		return err;
	}
	}
	devinfo->ctl_completed = false;
	timeout = brcmf_usb_ioctl_resp_wait(devinfo);
	timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed,
					    &pending);
	err = devinfo->ctl_urb_status;
	err = devinfo->ctl_urb_status;
	clear_bit(0, &devinfo->ctl_op);
	clear_bit(0, &devinfo->ctl_op);
	if (!timeout) {
	if (!timeout) {