From: Ming Lei <[email protected]>
This patch detects the disconnect in wmi register write path,
then speedup the disconnect handling.
---
drivers/net/wireless/ath/ath9k/hw.c | 2 ++
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/wmi.c | 8 ++++++++
3 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 9aa40df..bcc48ff 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -111,6 +111,8 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
BUG_ON(timeout < AH_TIME_QUANTUM);
for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) {
+ if (AR_SREV_9271(ah) && ah->htc_disconnected)
+ break;
if ((REG_READ(ah, reg) & mask) == val)
return true;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 8158e8e..6b22158 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -635,6 +635,7 @@ struct ath_hw {
u32 ah_flags;
bool htc_reset_init;
+ bool htc_disconnected;
enum nl80211_iftype opmode;
enum ath9k_power_mode power_mode;
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index dc6c6fc..fbd44c7 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -279,6 +279,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
if (!wmi)
return -EINVAL;
+ if (ah->htc_disconnected)
+ return -ENODEV;
+
skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
@@ -324,6 +327,11 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
return 0;
out:
+ if (ret == -ENODEV) {
+ ah->htc_disconnected = 1;
+ ath_print(common, ATH_DBG_WMI,"HTC disconnected!\n");
+ }
+
ath_print(common, ATH_DBG_WMI,
"WMI failure for: %s\n", wmi_cmd_to_name(cmd_id));
mutex_unlock(&wmi->op_mutex);
--
1.6.2.5
Ming Lei wrote:
> If ATH_DBG_RESET is enabled, you will find the debug messages
> below[1] during disconnecting. From the messages, the short hang should
> be caused by the 'RTC stuck in MAC reset'. Once the patch is applied,
> no such issue will happen.
I take it that you didn't have ATH_DBG_WMI in your debug mask.
A simpler way to fix this issue is to deny all WMI commands once
the target has been unplugged - something like the attached patch.
Can you check if it fixes your issue ?
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index c765ff4..b771e20 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -329,6 +329,7 @@ struct htc_beacon_config {
#define OP_ASSOCIATED BIT(8)
#define OP_ENABLE_BEACON BIT(9)
#define OP_LED_DEINIT BIT(10)
+#define OP_UNPLUGGED BIT(11)
struct ath9k_htc_priv {
struct device *dev;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index a861896..701f2ef 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -744,6 +744,9 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
if (ret)
goto err_init;
+ /* The device may have been unplugged earlier. */
+ priv->op_flags &= ~OP_UNPLUGGED;
+
ret = ath9k_init_device(priv, devid);
if (ret)
goto err_init;
@@ -760,6 +763,11 @@ err_free:
void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
{
if (htc_handle->drv_priv) {
+
+ /* Check if the device has been yanked out. */
+ if (hotunplug)
+ htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
+
ath9k_deinit_device(htc_handle->drv_priv);
ath9k_deinit_wmi(htc_handle->drv_priv);
ieee80211_free_hw(htc_handle->drv_priv->hw);
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index dc6c6fc..c688545 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -276,6 +276,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
int time_left, ret = 0;
unsigned long flags;
+ if (wmi->drv_priv->op_flags & OP_UNPLUGGED)
+ return 0;
+
if (!wmi)
return -EINVAL;
2010/4/20 Sujith <[email protected]>:
> [email protected] wrote:
>> This patch detects the disconnect in wmi register write path,
>> then speedup the disconnect handling.
>
> What bug does this fix ? Submission of URBs in the REGOUT pipe
> should not really fail, and if it does, it is indicative of a deeper
> problem and recovery mechanisms are needed.
After the 9271 device is unplugged, you will find your machine hung for
several hundreds of milliseconds.
>
> If you do get WMI failures, can you post the relevant sections
> from the kernel log ?
If ATH_DBG_RESET is enabled, you will find the debug messages
below[1] during disconnecting. From the messages, the short hang should
be caused by the 'RTC stuck in MAC reset'. Once the patch is applied,
no such issue will happen.
[1], debug messages during 9287 disconnecting
[12873.291066] usb 2-1.3: USB disconnect, address 15
[12873.291800] device: 'ep_01': device_unregister
[12873.291809] PM: Removing info for No Bus:ep_01
[12873.292465] device: 'ep_82': device_unregister
[12873.292472] PM: Removing info for No Bus:ep_82
[12873.292654] device: 'ep_83': device_unregister
[12873.292661] PM: Removing info for No Bus:ep_83
[12873.292828] device: 'ep_04': device_unregister
[12873.292834] PM: Removing info for No Bus:ep_04
[12873.292999] device: 'ep_05': device_unregister
[12873.293431] PM: Removing info for No Bus:ep_05
[12873.293612] device: 'ep_06': device_unregister
[12873.293689] PM: Removing info for No Bus:ep_06
[12873.293868] PM: Removing info for usb:2-1.3:1.0
[12873.294338] bus: 'usb': remove device 2-1.3:1.0
[12873.294373] usb 2-1.3: __pm_runtime_resume()!
[12873.294380] usb 2-1.3: __pm_runtime_resume() returns 1!
[12873.294392] device: 'ath9k-phy12::assoc': device_unregister
[12873.294399] PM: Removing info for No Bus:ath9k-phy12::assoc
[12873.294732] device: 'ath9k-phy12::assoc': device_create_release
[12873.294771] device: 'ath9k-phy12::tx': device_unregister
[12873.294778] PM: Removing info for No Bus:ath9k-phy12::tx
[12873.295676] device: 'ath9k-phy12::tx': device_create_release
[12873.295718] device: 'ath9k-phy12::rx': device_unregister
[12873.295725] PM: Removing info for No Bus:ath9k-phy12::rx
[12873.296316] device: 'ath9k-phy12::rx': device_create_release
[12873.296351] device: 'ath9k-phy12::radio': device_unregister
[12873.296358] PM: Removing info for No Bus:ath9k-phy12::radio
[12873.296701] device: 'ath9k-phy12::radio': device_create_release
[12874.349767] ath: timeout (100000 us) on reg 0x7000: 0xfffffffb &
0x00000003 != 0x00000000
[12874.349774] ath: RTC stuck in MAC reset
[12874.349777] ath: Chip reset failed
[12874.349779] ath: Unable to reset channel (2437 Mhz) reset status -22
[12874.349784] ath: Unable to set channel
[12874.349939] ath: ah->misc_mode 0x4
[12874.350750] ath: Unable to remove station entry for: 00:03:7f:13:02:d3
[12874.352092] phy12: Removed STA 00:03:7f:13:02:d3
[12874.352224] phy12: Destroyed STA 00:03:7f:13:02:d3
[12874.352232] wlan14: deauthenticating from 00:03:7f:13:02:d3 by
local choice (reason=3)
[12874.352494] phy12: device now idle
[12875.177375] ath: timeout (100000 us) on reg 0x7000: 0xfffffffb &
0x00000003 != 0x00000000
[12875.177382] ath: RTC stuck in MAC reset
[12875.988627] ath: timeout (100000 us) on reg 0x7000: 0xfffffffb &
0x00000003 != 0x00000000
[12875.988633] ath: RTC stuck in MAC reset
[12875.988638] ath: AWAKE -> FULL-SLEEP
[12876.000157] PM: Removing info for No Bus:wlan14
[12876.005146] cfg80211: All devices are disconnected, going to
restore regulatory settings
[12876.005157] cfg80211: Restoring regulatory settings
[12876.005175] cfg80211: Calling CRDA to update world regulatory domain
[12876.006494] PM: Removing info for No Bus:rfkill13
[12876.013231] PM: Removing info for No Bus:phy12
[12876.026482] usb 2-1.3: ath9k_htc: USB layer deinitialized
[12876.027680] device: 'ep_00': device_unregister
[12876.027684] PM: Removing info for No Bus:ep_00
[12876.027781] PM: Removing info for usb:2-1.3
[12876.029678] bus: 'usb': remove device 2-1.3
[12876.045047] cfg80211: World regulatory domain updated:
[12876.045051] (start_freq - end_freq @ bandwidth),
(max_antenna_gain, max_eirp)
[12876.045054] (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[12876.045057] (2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
[12876.045060] (2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
[12876.045062] (5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[12876.045065] (5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[12876.144805] hub 2-1:1.0: __pm_runtime_suspend()!
[12876.144832] hub 2-1:1.0: __pm_runtime_suspend() returns 0!
[12878.705219] usb 2-1: __pm_runtime_suspend() from workqueue!
[12878.716694] usb 2-1: __pm_runtime_suspend() returns 0!
[12881.705105] usb usb2: __pm_runtime_suspend() from workqueue!
[12881.705175] usb usb2: __pm_runtime_suspend() returns 0!
--
Lei Ming
2010/4/20 Sujith <[email protected]>:
> Ming Lei wrote:
>> If ATH_DBG_RESET is enabled, you will find the debug messages
>> below[1] during disconnecting. ?From the messages, the short hang should
>> be caused by the 'RTC stuck in MAC reset'. Once the patch is applied,
>> no such issue will happen.
>
> I take it that you didn't have ATH_DBG_WMI in your debug mask.
> A simpler way to fix this issue is to deny all WMI commands once
> the target has been unplugged - something like the attached patch.
>
> Can you check if it fixes your issue ?
Yes, the patch does fix the issue.
Thanks,
--
Lei Ming
[email protected] wrote:
> This patch detects the disconnect in wmi register write path,
> then speedup the disconnect handling.
What bug does this fix ? Submission of URBs in the REGOUT pipe
should not really fail, and if it does, it is indicative of a deeper
problem and recovery mechanisms are needed.
If you do get WMI failures, can you post the relevant sections
from the kernel log ?
Sujith