From cee7593d81dfb5a3fdb66e101d7a768ce81f405c Mon Sep 17 00:00:00 2001 From: pizza Date: Thu, 31 Jan 2008 14:37:27 +0000 Subject: [PATCH] Apply patch from Karl Relton that improves the reliability of USB device initialization and operation. --- CHANGES | 3 ++ src/prism2/driver/hfa384x_usb.c | 65 +++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index 67bd8ee..9573d9c 100644 --- a/CHANGES +++ b/CHANGES @@ -41,6 +41,9 @@ * Intersil Corporation as part of PRISM(R) chipset product development. * * -------------------------------------------------------------------- + - Apply a patch from Karl Relton that improves USB reliability. + - When in wlan_wext_write=1 mode, auto-transition to ifstate_enable + and bypass userspace firmware load altogether. - Fix bug in the GIWENCODE handler (Richard Kennedy & Tormod Volden) - Support 2.6.24 kernels (modified patch from Tormod Volden) - Support 2.6.23 kernels. (With apologies to Martin Dauskardt for a diff --git a/src/prism2/driver/hfa384x_usb.c b/src/prism2/driver/hfa384x_usb.c index 02fc393..f6abbea 100644 --- a/src/prism2/driver/hfa384x_usb.c +++ b/src/prism2/driver/hfa384x_usb.c @@ -3269,17 +3269,35 @@ int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) ----------------------------------------------------------------*/ 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"); } @@ -3296,14 +3314,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;