Skip to content

Commit

Permalink
brcmfmac: use wait_event_timeout for fw control packets over usb.
Browse files Browse the repository at this point in the history
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: Arend Van Spriel <arend@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Hante Meuleman authored and John W. Linville committed Sep 28, 2012
1 parent 2d838bb commit 70398a5
Showing 1 changed file with 9 additions and 37 deletions.
46 changes: 9 additions & 37 deletions drivers/net/wireless/brcm80211/brcmfmac/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,40 +160,17 @@ static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
return brcmf_usb_get_buspub(dev)->devinfo;
}

static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo,
uint *condition, bool *pending)
static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo)
{
DECLARE_WAITQUEUE(wait, current);
int timeout = 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;
return wait_event_timeout(devinfo->ioctl_resp_wait,
devinfo->ctl_completed,
msecs_to_jiffies(IOCTL_RESP_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))
wake_up_interruptible(&devinfo->ioctl_resp_wait);

return 0;
wake_up(&devinfo->ioctl_resp_wait);
}

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

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

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

if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
Expand All @@ -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))
return -EIO;

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

0 comments on commit 70398a5

Please sign in to comment.