diff options
-rw-r--r-- | drivers/staging/wlan-ng/hfa384x_usb.c | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 0df9a67c85d..a26609bdc4a 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -2960,19 +2960,38 @@ int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) * Call context: * process ----------------------------------------------------------------*/ + int hfa384x_drvr_start(hfa384x_t *hw) { - int result; + int result, result1, result2; + u16 status; DBFENTER; might_sleep(); - if (usb_clear_halt(hw->usb, hw->endp_in)) { + /* Clear endpoint stalls - but only do this if the endpoint + * is showing a stall status. Some prism2 cards seem to behave + * badly if a clear_halt is called when the endpoint is already + * ok + */ + result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status); + if (result < 0) { + WLAN_LOG_ERROR( + "Cannot get bulk in endpoint status.\n"); + goto done; + } + if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_in)) { WLAN_LOG_ERROR( "Failed to reset bulk in endpoint.\n"); } - if (usb_clear_halt(hw->usb, hw->endp_out)) { + result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status); + if (result < 0) { + WLAN_LOG_ERROR( + "Cannot get bulk out endpoint status.\n"); + goto done; + } + if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_out)) { WLAN_LOG_ERROR( "Failed to reset bulk out endpoint.\n"); } @@ -2989,14 +3008,37 @@ int hfa384x_drvr_start(hfa384x_t *hw) goto done; } - /* call initialize */ - result = hfa384x_cmd_initialize(hw); - if (result != 0) { - usb_kill_urb(&hw->rx_urb); - WLAN_LOG_ERROR( - "cmd_initialize() failed, result=%d\n", - result); - goto done; + /* Call initialize twice, with a 1 second sleep in between. + * This is a nasty work-around since many prism2 cards seem to + * need time to settle after an init from cold. The second + * call to initialize in theory is not necessary - but we call + * it anyway as a double insurance policy: + * 1) If the first init should fail, the second may well succeed + * and the card can still be used + * 2) It helps ensures all is well with the card after the first + * init and settle time. + */ + result1 = hfa384x_cmd_initialize(hw); + msleep(1000); + result = result2 = hfa384x_cmd_initialize(hw); + if (result1 != 0) { + if (result2 != 0) { + WLAN_LOG_ERROR( + "cmd_initialize() failed on two attempts, results %d and %d\n", + result1, result2); + usb_kill_urb(&hw->rx_urb); + goto done; + } else { + WLAN_LOG_DEBUG(0, "First cmd_initialize() failed (result %d),\n", + result1); + WLAN_LOG_DEBUG(0, "but second attempt succeeded. All should be ok\n"); + } + } else if (result2 != 0) { + WLAN_LOG_WARNING( + "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n", + result2); + WLAN_LOG_WARNING("Most likely the card will be functional\n"); + goto done; } hw->state = HFA384x_STATE_RUNNING; |