Commit a4765fa7 authored by David S. Miller's avatar David S. Miller
parents 089282fb 9f2a0fac
...@@ -139,12 +139,12 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ...@@ -139,12 +139,12 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
/* Fill the ath5k_hw struct with the needed functions */ /* Fill the ath5k_hw struct with the needed functions */
ret = ath5k_hw_init_desc_functions(ah); ret = ath5k_hw_init_desc_functions(ah);
if (ret) if (ret)
goto err_free; goto err;
/* Bring device out of sleep and reset its units */ /* Bring device out of sleep and reset its units */
ret = ath5k_hw_nic_wakeup(ah, 0, true); ret = ath5k_hw_nic_wakeup(ah, 0, true);
if (ret) if (ret)
goto err_free; goto err;
/* Get MAC, PHY and RADIO revisions */ /* Get MAC, PHY and RADIO revisions */
ah->ah_mac_srev = srev; ah->ah_mac_srev = srev;
...@@ -234,7 +234,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ...@@ -234,7 +234,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
} else { } else {
ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
ret = -ENODEV; ret = -ENODEV;
goto err_free; goto err;
} }
} }
...@@ -244,7 +244,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ...@@ -244,7 +244,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
(srev < AR5K_SREV_AR2425)) { (srev < AR5K_SREV_AR2425)) {
ATH5K_ERR(sc, "Device not yet supported.\n"); ATH5K_ERR(sc, "Device not yet supported.\n");
ret = -ENODEV; ret = -ENODEV;
goto err_free; goto err;
} }
/* /*
...@@ -252,7 +252,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ...@@ -252,7 +252,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
*/ */
ret = ath5k_hw_post(ah); ret = ath5k_hw_post(ah);
if (ret) if (ret)
goto err_free; goto err;
/* Enable pci core retry fix on Hainan (5213A) and later chips */ /* Enable pci core retry fix on Hainan (5213A) and later chips */
if (srev >= AR5K_SREV_AR5213A) if (srev >= AR5K_SREV_AR5213A)
...@@ -265,7 +265,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ...@@ -265,7 +265,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
ret = ath5k_eeprom_init(ah); ret = ath5k_eeprom_init(ah);
if (ret) { if (ret) {
ATH5K_ERR(sc, "unable to init EEPROM\n"); ATH5K_ERR(sc, "unable to init EEPROM\n");
goto err_free; goto err;
} }
ee = &ah->ah_capabilities.cap_eeprom; ee = &ah->ah_capabilities.cap_eeprom;
...@@ -307,7 +307,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ...@@ -307,7 +307,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
if (ret) { if (ret) {
ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
sc->pdev->device); sc->pdev->device);
goto err_free; goto err;
} }
/* Crypto settings */ /* Crypto settings */
...@@ -341,8 +341,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ...@@ -341,8 +341,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); ath5k_hw_set_ledstate(ah, AR5K_LED_INIT);
return 0; return 0;
err_free: err:
kfree(ah);
return ret; return ret;
} }
......
...@@ -310,7 +310,7 @@ struct ath_rx { ...@@ -310,7 +310,7 @@ struct ath_rx {
u8 rxotherant; u8 rxotherant;
u32 *rxlink; u32 *rxlink;
unsigned int rxfilter; unsigned int rxfilter;
spinlock_t rxflushlock; spinlock_t pcu_lock;
spinlock_t rxbuflock; spinlock_t rxbuflock;
struct list_head rxbuf; struct list_head rxbuf;
struct ath_descdma rxdma; struct ath_descdma rxdma;
......
...@@ -801,10 +801,16 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) ...@@ -801,10 +801,16 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
} }
kfree(buf); kfree(buf);
if ((hif_dev->device_id == 0x7010) || (hif_dev->device_id == 0x7015)) switch (hif_dev->device_id) {
case 0x7010:
case 0x7015:
case 0x9018:
firm_offset = AR7010_FIRMWARE_TEXT; firm_offset = AR7010_FIRMWARE_TEXT;
else break;
default:
firm_offset = AR9271_FIRMWARE_TEXT; firm_offset = AR9271_FIRMWARE_TEXT;
break;
}
/* /*
* Issue FW download complete command to firmware. * Issue FW download complete command to firmware.
......
...@@ -241,6 +241,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, ...@@ -241,6 +241,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
*/ */
ath9k_hw_set_interrupts(ah, 0); ath9k_hw_set_interrupts(ah, 0);
ath_drain_all_txq(sc, false); ath_drain_all_txq(sc, false);
spin_lock_bh(&sc->rx.pcu_lock);
stopped = ath_stoprecv(sc); stopped = ath_stoprecv(sc);
/* XXX: do not flush receive queue here. We don't want /* XXX: do not flush receive queue here. We don't want
...@@ -268,6 +271,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, ...@@ -268,6 +271,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
"reset status %d\n", "reset status %d\n",
channel->center_freq, r); channel->center_freq, r);
spin_unlock_bh(&sc->sc_resetlock); spin_unlock_bh(&sc->sc_resetlock);
spin_unlock_bh(&sc->rx.pcu_lock);
goto ps_restore; goto ps_restore;
} }
spin_unlock_bh(&sc->sc_resetlock); spin_unlock_bh(&sc->sc_resetlock);
...@@ -276,9 +280,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, ...@@ -276,9 +280,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
ath_print(common, ATH_DBG_FATAL, ath_print(common, ATH_DBG_FATAL,
"Unable to restart recv logic\n"); "Unable to restart recv logic\n");
r = -EIO; r = -EIO;
spin_unlock_bh(&sc->rx.pcu_lock);
goto ps_restore; goto ps_restore;
} }
spin_unlock_bh(&sc->rx.pcu_lock);
ath_update_txpow(sc); ath_update_txpow(sc);
ath9k_hw_set_interrupts(ah, ah->imask); ath9k_hw_set_interrupts(ah, ah->imask);
...@@ -613,7 +620,7 @@ void ath9k_tasklet(unsigned long data) ...@@ -613,7 +620,7 @@ void ath9k_tasklet(unsigned long data)
rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
if (status & rxmask) { if (status & rxmask) {
spin_lock_bh(&sc->rx.rxflushlock); spin_lock_bh(&sc->rx.pcu_lock);
/* Check for high priority Rx first */ /* Check for high priority Rx first */
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
...@@ -621,7 +628,7 @@ void ath9k_tasklet(unsigned long data) ...@@ -621,7 +628,7 @@ void ath9k_tasklet(unsigned long data)
ath_rx_tasklet(sc, 0, true); ath_rx_tasklet(sc, 0, true);
ath_rx_tasklet(sc, 0, false); ath_rx_tasklet(sc, 0, false);
spin_unlock_bh(&sc->rx.rxflushlock); spin_unlock_bh(&sc->rx.pcu_lock);
} }
if (status & ATH9K_INT_TX) { if (status & ATH9K_INT_TX) {
...@@ -876,6 +883,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -876,6 +883,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
if (!ah->curchan) if (!ah->curchan)
ah->curchan = ath_get_curchannel(sc, sc->hw); ah->curchan = ath_get_curchannel(sc, sc->hw);
spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_resetlock); spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) { if (r) {
...@@ -890,8 +898,10 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -890,8 +898,10 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
if (ath_startrecv(sc) != 0) { if (ath_startrecv(sc) != 0) {
ath_print(common, ATH_DBG_FATAL, ath_print(common, ATH_DBG_FATAL,
"Unable to restart recv logic\n"); "Unable to restart recv logic\n");
spin_unlock_bh(&sc->rx.pcu_lock);
return; return;
} }
spin_unlock_bh(&sc->rx.pcu_lock);
if (sc->sc_flags & SC_OP_BEACONS) if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, NULL); /* restart beacons */ ath_beacon_config(sc, NULL); /* restart beacons */
...@@ -930,6 +940,9 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -930,6 +940,9 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_hw_set_interrupts(ah, 0); ath9k_hw_set_interrupts(ah, 0);
ath_drain_all_txq(sc, false); /* clear pending tx frames */ ath_drain_all_txq(sc, false); /* clear pending tx frames */
spin_lock_bh(&sc->rx.pcu_lock);
ath_stoprecv(sc); /* turn off frame recv */ ath_stoprecv(sc); /* turn off frame recv */
ath_flushrecv(sc); /* flush recv queue */ ath_flushrecv(sc); /* flush recv queue */
...@@ -947,6 +960,9 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) ...@@ -947,6 +960,9 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_resetlock); spin_unlock_bh(&sc->sc_resetlock);
ath9k_hw_phy_disable(ah); ath9k_hw_phy_disable(ah);
spin_unlock_bh(&sc->rx.pcu_lock);
ath9k_hw_configpcipowersave(ah, 1, 1); ath9k_hw_configpcipowersave(ah, 1, 1);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
...@@ -966,6 +982,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) ...@@ -966,6 +982,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
ath9k_hw_set_interrupts(ah, 0); ath9k_hw_set_interrupts(ah, 0);
ath_drain_all_txq(sc, retry_tx); ath_drain_all_txq(sc, retry_tx);
spin_lock_bh(&sc->rx.pcu_lock);
ath_stoprecv(sc); ath_stoprecv(sc);
ath_flushrecv(sc); ath_flushrecv(sc);
...@@ -980,6 +999,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) ...@@ -980,6 +999,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
ath_print(common, ATH_DBG_FATAL, ath_print(common, ATH_DBG_FATAL,
"Unable to start recv logic\n"); "Unable to start recv logic\n");
spin_unlock_bh(&sc->rx.pcu_lock);
/* /*
* We may be doing a reset in response to a request * We may be doing a reset in response to a request
* that changes the channel so update any state that * that changes the channel so update any state that
...@@ -1142,6 +1163,7 @@ static int ath9k_start(struct ieee80211_hw *hw) ...@@ -1142,6 +1163,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
* be followed by initialization of the appropriate bits * be followed by initialization of the appropriate bits
* and then setup of the interrupt mask. * and then setup of the interrupt mask.
*/ */
spin_lock_bh(&sc->rx.pcu_lock);
spin_lock_bh(&sc->sc_resetlock); spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
if (r) { if (r) {
...@@ -1150,6 +1172,7 @@ static int ath9k_start(struct ieee80211_hw *hw) ...@@ -1150,6 +1172,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
"(freq %u MHz)\n", r, "(freq %u MHz)\n", r,
curchan->center_freq); curchan->center_freq);
spin_unlock_bh(&sc->sc_resetlock); spin_unlock_bh(&sc->sc_resetlock);
spin_unlock_bh(&sc->rx.pcu_lock);
goto mutex_unlock; goto mutex_unlock;
} }
spin_unlock_bh(&sc->sc_resetlock); spin_unlock_bh(&sc->sc_resetlock);
...@@ -1171,8 +1194,10 @@ static int ath9k_start(struct ieee80211_hw *hw) ...@@ -1171,8 +1194,10 @@ static int ath9k_start(struct ieee80211_hw *hw)
ath_print(common, ATH_DBG_FATAL, ath_print(common, ATH_DBG_FATAL,
"Unable to start recv logic\n"); "Unable to start recv logic\n");
r = -EIO; r = -EIO;
spin_unlock_bh(&sc->rx.pcu_lock);
goto mutex_unlock; goto mutex_unlock;
} }
spin_unlock_bh(&sc->rx.pcu_lock);
/* Setup our intr mask. */ /* Setup our intr mask. */
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
...@@ -1371,12 +1396,14 @@ static void ath9k_stop(struct ieee80211_hw *hw) ...@@ -1371,12 +1396,14 @@ static void ath9k_stop(struct ieee80211_hw *hw)
* before setting the invalid flag. */ * before setting the invalid flag. */
ath9k_hw_set_interrupts(ah, 0); ath9k_hw_set_interrupts(ah, 0);
spin_lock_bh(&sc->rx.pcu_lock);
if (!(sc->sc_flags & SC_OP_INVALID)) { if (!(sc->sc_flags & SC_OP_INVALID)) {
ath_drain_all_txq(sc, false); ath_drain_all_txq(sc, false);
ath_stoprecv(sc); ath_stoprecv(sc);
ath9k_hw_phy_disable(ah); ath9k_hw_phy_disable(ah);
} else } else
sc->rx.rxlink = NULL; sc->rx.rxlink = NULL;
spin_unlock_bh(&sc->rx.pcu_lock);
/* disable HAL and put h/w to sleep */ /* disable HAL and put h/w to sleep */
ath9k_hw_disable(ah); ath9k_hw_disable(ah);
......
...@@ -527,7 +527,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, ...@@ -527,7 +527,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
for (i = 0; i < rateset->rs_nrates; i++) { for (i = 0; i < rateset->rs_nrates; i++) {
for (j = 0; j < rate_table->rate_cnt; j++) { for (j = 0; j < rate_table->rate_cnt; j++) {
u32 phy = rate_table->info[j].phy; u32 phy = rate_table->info[j].phy;
u16 rate_flags = rate_table->info[i].rate_flags; u16 rate_flags = rate_table->info[j].rate_flags;
u8 rate = rateset->rs_rates[i]; u8 rate = rateset->rs_rates[i];
u8 dot11rate = rate_table->info[j].dot11rate; u8 dot11rate = rate_table->info[j].dot11rate;
......
...@@ -297,19 +297,17 @@ static void ath_edma_start_recv(struct ath_softc *sc) ...@@ -297,19 +297,17 @@ static void ath_edma_start_recv(struct ath_softc *sc)
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP, ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize); sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
spin_unlock_bh(&sc->rx.rxbuflock);
ath_opmode_init(sc); ath_opmode_init(sc);
ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
spin_unlock_bh(&sc->rx.rxbuflock);
} }
static void ath_edma_stop_recv(struct ath_softc *sc) static void ath_edma_stop_recv(struct ath_softc *sc)
{ {
spin_lock_bh(&sc->rx.rxbuflock);
ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
spin_unlock_bh(&sc->rx.rxbuflock);
} }
int ath_rx_init(struct ath_softc *sc, int nbufs) int ath_rx_init(struct ath_softc *sc, int nbufs)
...@@ -319,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) ...@@ -319,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
struct ath_buf *bf; struct ath_buf *bf;
int error = 0; int error = 0;
spin_lock_init(&sc->rx.rxflushlock); spin_lock_init(&sc->rx.pcu_lock);
sc->sc_flags &= ~SC_OP_RXFLUSH; sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_lock_init(&sc->rx.rxbuflock); spin_lock_init(&sc->rx.rxbuflock);
...@@ -506,10 +504,11 @@ int ath_startrecv(struct ath_softc *sc) ...@@ -506,10 +504,11 @@ int ath_startrecv(struct ath_softc *sc)
ath9k_hw_rxena(ah); ath9k_hw_rxena(ah);
start_recv: start_recv:
spin_unlock_bh(&sc->rx.rxbuflock);
ath_opmode_init(sc); ath_opmode_init(sc);
ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
spin_unlock_bh(&sc->rx.rxbuflock);
return 0; return 0;
} }
...@@ -518,6 +517,7 @@ bool ath_stoprecv(struct ath_softc *sc) ...@@ -518,6 +517,7 @@ bool ath_stoprecv(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
bool stopped; bool stopped;
spin_lock_bh(&sc->rx.rxbuflock);
ath9k_hw_stoppcurecv(ah); ath9k_hw_stoppcurecv(ah);
ath9k_hw_setrxfilter(ah, 0); ath9k_hw_setrxfilter(ah, 0);
stopped = ath9k_hw_stopdmarecv(ah); stopped = ath9k_hw_stopdmarecv(ah);
...@@ -526,19 +526,18 @@ bool ath_stoprecv(struct ath_softc *sc) ...@@ -526,19 +526,18 @@ bool ath_stoprecv(struct ath_softc *sc)
ath_edma_stop_recv(sc); ath_edma_stop_recv(sc);
else else
sc->rx.rxlink = NULL; sc->rx.rxlink = NULL;
spin_unlock_bh(&sc->rx.rxbuflock);
return stopped; return stopped;
} }
void ath_flushrecv(struct ath_softc *sc) void ath_flushrecv(struct ath_softc *sc)
{ {
spin_lock_bh(&sc->rx.rxflushlock);
sc->sc_flags |= SC_OP_RXFLUSH; sc->sc_flags |= SC_OP_RXFLUSH;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ath_rx_tasklet(sc, 1, true); ath_rx_tasklet(sc, 1, true);
ath_rx_tasklet(sc, 1, false); ath_rx_tasklet(sc, 1, false);
sc->sc_flags &= ~SC_OP_RXFLUSH; sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_unlock_bh(&sc->rx.rxflushlock);
} }
static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
......
...@@ -1089,15 +1089,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) ...@@ -1089,15 +1089,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
txq->axq_tx_inprogress = false; txq->axq_tx_inprogress = false;
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
/* flush any pending frames if aggregation is enabled */
if (sc->sc_flags & SC_OP_TXAGGR) {
if (!retry_tx) {
spin_lock_bh(&txq->axq_lock);
ath_txq_drain_pending_buffers(sc, txq);
spin_unlock_bh(&txq->axq_lock);
}
}
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
spin_lock_bh(&txq->axq_lock); spin_lock_bh(&txq->axq_lock);
while (!list_empty(&txq->txq_fifo_pending)) { while (!list_empty(&txq->txq_fifo_pending)) {
...@@ -1118,6 +1109,15 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) ...@@ -1118,6 +1109,15 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
} }
spin_unlock_bh(&txq->axq_lock); spin_unlock_bh(&txq->axq_lock);
} }
/* flush any pending frames if aggregation is enabled */
if (sc->sc_flags & SC_OP_TXAGGR) {
if (!retry_tx) {
spin_lock_bh(&txq->axq_lock);
ath_txq_drain_pending_buffers(sc, txq);
spin_unlock_bh(&txq->axq_lock);
}
}
} }
void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
......
...@@ -175,7 +175,9 @@ static void b43_sdio_remove(struct sdio_func *func) ...@@ -175,7 +175,9 @@ static void b43_sdio_remove(struct sdio_func *func)
struct b43_sdio *sdio = sdio_get_drvdata(func); struct b43_sdio *sdio = sdio_get_drvdata(func);
ssb_bus_unregister(&sdio->ssb); ssb_bus_unregister(&sdio->ssb);
sdio_claim_host(func);
sdio_disable_func(func); sdio_disable_func(func);
sdio_release_host(func);
kfree(sdio); kfree(sdio);
sdio_set_drvdata(func, NULL); sdio_set_drvdata(func, NULL);
} }
......
...@@ -684,18 +684,40 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) ...@@ -684,18 +684,40 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
lbs_deb_enter(LBS_DEB_SDIO); lbs_deb_enter(LBS_DEB_SDIO);
/*
* Disable interrupts
*/
sdio_claim_host(card->func);
sdio_writeb(card->func, 0x00, IF_SDIO_H_INT_MASK, &ret);
sdio_release_host(card->func);
sdio_claim_host(card->func); sdio_claim_host(card->func);
scratch = if_sdio_read_scratch(card, &ret); scratch = if_sdio_read_scratch(card, &ret);
sdio_release_host(card->func); sdio_release_host(card->func);
lbs_deb_sdio("firmware status = %#x\n", scratch);
lbs_deb_sdio("scratch ret = %d\n", ret);
if (ret) if (ret)
goto out; goto out;
lbs_deb_sdio("firmware status = %#x\n", scratch);
/*
* The manual clearly describes that FEDC is the right code to use
* to detect firmware presence, but for SD8686 it is not that simple.
* Scratch is also used to store the RX packet length, so we lose
* the FEDC value early on. So we use a non-zero check in order
* to validate firmware presence.
* Additionally, the SD8686 in the Gumstix always has the high scratch
* bit set, even when the firmware is not loaded. So we have to
* exclude that from the test.
*/
if (scratch == IF_SDIO_FIRMWARE_OK) { if (scratch == IF_SDIO_FIRMWARE_OK) {
lbs_deb_sdio("firmware already loaded\n"); lbs_deb_sdio("firmware already loaded\n");
goto success; goto success;
} else if ((card->model == MODEL_8686) && (scratch & 0x7fff)) {
lbs_deb_sdio("firmware may be running\n");
goto success;
} }
ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name,
...@@ -709,10 +731,14 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) ...@@ -709,10 +731,14 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
if (ret) if (ret)
goto out; goto out;
lbs_deb_sdio("Helper firmware loaded\n");
ret = if_sdio_prog_real(card, mainfw); ret = if_sdio_prog_real(card, mainfw);
if (ret) if (ret)
goto out; goto out;
lbs_deb_sdio("Firmware loaded\n");
success: success:
sdio_claim_host(card->func); sdio_claim_host(card->func);
sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
...@@ -1042,8 +1068,6 @@ static int if_sdio_probe(struct sdio_func *func, ...@@ -1042,8 +1068,6 @@ static int if_sdio_probe(struct sdio_func *func,
priv->exit_deep_sleep = if_sdio_exit_deep_sleep; priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
priv->fw_ready = 1;
sdio_claim_host(func); sdio_claim_host(func);
/* /*
...@@ -1064,6 +1088,8 @@ static int if_sdio_probe(struct sdio_func *func, ...@@ -1064,6 +1088,8 @@ static int if_sdio_probe(struct sdio_func *func,
if (ret) if (ret)
goto reclaim; goto reclaim;
priv->fw_ready = 1;
/* /*
* FUNC_INIT is required for SD8688 WLAN/BT multiple functions * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
*/ */
......
...@@ -203,9 +203,13 @@ static ssize_t key_key_read(struct file *file, char __user *userbuf, ...@@ -203,9 +203,13 @@ static ssize_t key_key_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ieee80211_key *key = file->private_data; struct ieee80211_key *key = file->private_data;
int i, res, bufsize = 2 * key->conf.keylen + 2; int i, bufsize = 2 * key->conf.keylen + 2;
char *buf = kmalloc(bufsize, GFP_KERNEL); char *buf = kmalloc(bufsize, GFP_KERNEL);
char *p = buf; char *p = buf;
ssize_t res;
if (!buf)
return -ENOMEM;
for (i = 0; i < key->conf.keylen; i++) for (i = 0; i < key->conf.keylen; i++)
p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]);
......
...@@ -677,10 +677,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -677,10 +677,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
/* /*
* Calculate scan IE length -- we need this to alloc * Calculate scan IE length -- we need this to alloc
* memory and to subtract from the driver limit. It * memory and to subtract from the driver limit. It
* includes the (extended) supported rates and HT * includes the DS Params, (extended) supported rates, and HT
* information -- SSID is the driver's responsibility. * information -- SSID is the driver's responsibility.
*/ */
local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */ local->scan_ies_len = 4 + max_bitrates /* (ext) supp rates */ +
3 /* DS Params */;
if (supp_ht) if (supp_ht)
local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment