diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2011-06-21 05:23:51 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-06-22 16:09:57 -0400 |
commit | 7d95847c9b3631d31f657d8cede153b518ed9e2e (patch) | |
tree | 033508bc12802ca4e5121d61f3893e112e625e2c /drivers | |
parent | 4187afa29a73fec1f68243c03437e7c1b37f315d (diff) |
ath9k: add external_reset callback to ath9k_platfom_data for AR9330
The patch adds a callback to ath9k_platform_data. If the
callback is provided by the platform code, then it can be
used to hard reset the WMAC device.
The callback is required for doing a hard reset of the AR9330
chips to get them working again after a hang.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 1 |
3 files changed, 37 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4da5284c7773..839ba64c9e49 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1161,6 +1161,41 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1161 | rst_flags |= AR_RTC_RC_MAC_COLD; | 1161 | rst_flags |= AR_RTC_RC_MAC_COLD; |
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | if (AR_SREV_9330(ah)) { | ||
1165 | int npend = 0; | ||
1166 | int i; | ||
1167 | |||
1168 | /* AR9330 WAR: | ||
1169 | * call external reset function to reset WMAC if: | ||
1170 | * - doing a cold reset | ||
1171 | * - we have pending frames in the TX queues | ||
1172 | */ | ||
1173 | |||
1174 | for (i = 0; i < AR_NUM_QCU; i++) { | ||
1175 | npend = ath9k_hw_numtxpending(ah, i); | ||
1176 | if (npend) | ||
1177 | break; | ||
1178 | } | ||
1179 | |||
1180 | if (ah->external_reset && | ||
1181 | (npend || type == ATH9K_RESET_COLD)) { | ||
1182 | int reset_err = 0; | ||
1183 | |||
1184 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, | ||
1185 | "reset MAC via external reset\n"); | ||
1186 | |||
1187 | reset_err = ah->external_reset(); | ||
1188 | if (reset_err) { | ||
1189 | ath_err(ath9k_hw_common(ah), | ||
1190 | "External reset failed, err=%d\n", | ||
1191 | reset_err); | ||
1192 | return false; | ||
1193 | } | ||
1194 | |||
1195 | REG_WRITE(ah, AR_RTC_RESET, 1); | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1164 | REG_WRITE(ah, AR_RTC_RC, rst_flags); | 1199 | REG_WRITE(ah, AR_RTC_RC, rst_flags); |
1165 | 1200 | ||
1166 | REGWRITE_BUFFER_FLUSH(ah); | 1201 | REGWRITE_BUFFER_FLUSH(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 0749fa8c3a58..818acdd1ba90 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -863,6 +863,7 @@ struct ath_hw { | |||
863 | 863 | ||
864 | bool is_clk_25mhz; | 864 | bool is_clk_25mhz; |
865 | int (*get_mac_revision)(void); | 865 | int (*get_mac_revision)(void); |
866 | int (*external_reset)(void); | ||
866 | }; | 867 | }; |
867 | 868 | ||
868 | struct ath_bus_ops { | 869 | struct ath_bus_ops { |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 1851c222fff0..50103b2792b5 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -575,6 +575,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
575 | sc->sc_ah->led_pin = pdata->led_pin; | 575 | sc->sc_ah->led_pin = pdata->led_pin; |
576 | ah->is_clk_25mhz = pdata->is_clk_25mhz; | 576 | ah->is_clk_25mhz = pdata->is_clk_25mhz; |
577 | ah->get_mac_revision = pdata->get_mac_revision; | 577 | ah->get_mac_revision = pdata->get_mac_revision; |
578 | ah->external_reset = pdata->external_reset; | ||
578 | } | 579 | } |
579 | 580 | ||
580 | common = ath9k_hw_common(ah); | 581 | common = ath9k_hw_common(ah); |