Loading drivers/net/wireless/ath9k/core.c +78 −140 Original line number Diff line number Diff line Loading @@ -186,17 +186,10 @@ static int ath_setup_channels(struct ath_softc *sc) struct ath9k_channel *c; /* Fill in ah->ah_channels */ if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan, regclassids, ATH_REGCLASSIDS_MAX, &nregclass, CTRY_DEFAULT, false, 1)) { if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan, regclassids, ATH_REGCLASSIDS_MAX, &nregclass, CTRY_DEFAULT, false, 1)) { u32 rd = ah->ah_currentRD; DPRINTF(sc, ATH_DBG_FATAL, "%s: unable to collect channel list; " "regdomain likely %u country code %u\n", Loading @@ -217,40 +210,32 @@ static int ath_setup_channels(struct ath_softc *sc) chan_2ghz[a].max_power = c->maxTxPower; if (c->privFlags & CHANNEL_DISALLOW_ADHOC) chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS; chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS; if (c->channelFlags & CHANNEL_PASSIVE) chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN; chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN; band_2ghz->n_channels = ++a; DPRINTF(sc, ATH_DBG_CONFIG, "%s: 2MHz channel: %d, " "channelFlags: 0x%x\n", __func__, c->channel, c->channelFlags); __func__, c->channel, c->channelFlags); } else if (IS_CHAN_5GHZ(c)) { chan_5ghz[b].band = IEEE80211_BAND_5GHZ; chan_5ghz[b].center_freq = c->channel; chan_5ghz[b].max_power = c->maxTxPower; if (c->privFlags & CHANNEL_DISALLOW_ADHOC) chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS; chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS; if (c->channelFlags & CHANNEL_PASSIVE) chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN; chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN; band_5ghz->n_channels = ++b; DPRINTF(sc, ATH_DBG_CONFIG, "%s: 5MHz channel: %d, " "channelFlags: 0x%x\n", __func__, c->channel, c->channelFlags); __func__, c->channel, c->channelFlags); } } Loading Loading @@ -291,44 +276,6 @@ static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) return ATH9K_MODE_11B; } /* * Stop the device, grabbing the top-level lock to protect * against concurrent entry through ath_init (which can happen * if another thread does a system call and the thread doing the * stop is preempted). */ static int ath_stop(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n", __func__, sc->sc_flags & SC_OP_INVALID); /* * Shutdown the hardware and driver: * stop output from above * turn off timers * disable interrupts * clear transmit machinery * clear receive machinery * turn off the radio * reclaim beacon resources * * Note that some of this work is not possible if the * hardware is gone (invalid). */ ath_draintxq(sc, false); if (!(sc->sc_flags & SC_OP_INVALID)) { ath_stoprecv(sc); ath9k_hw_phy_disable(ah); } else sc->sc_rxlink = NULL; return 0; } /* * Set the current channel * Loading Loading @@ -650,16 +597,6 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_ah->ah_opmode); /* * Stop anything previously setup. This is safe * whether this is the first time through or not. */ ath_stop(sc); /* Initialize chanmask selection */ sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; /* Reset SERDES registers */ ath9k_hw_configpcipowersave(ah, 0); Loading @@ -685,6 +622,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) goto done; } spin_unlock_bh(&sc->sc_resetlock); /* * This is needed only to setup initial state * but it's best done after a reset. Loading @@ -704,6 +642,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) error = -EIO; goto done; } /* Setup our intr mask. */ sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN Loading Loading @@ -733,30 +672,61 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) (sc->sc_ah->ah_opmode == ATH9K_M_STA) && !sc->sc_config.swBeaconProcess) sc->sc_imask |= ATH9K_INT_TIM; ath_setcurmode(sc, ath_chan2mode(initial_chan)); /* * Don't enable interrupts here as we've not yet built our * vap and node data structures, which will be needed as soon * as we start receiving. */ ath_setcurmode(sc, ath_chan2mode(initial_chan)); /* XXX: we must make sure h/w is ready and clear invalid flag * before turning on interrupt. */ sc->sc_flags &= ~SC_OP_INVALID; ieee80211_wake_queues(sc->hw); done: return error; } void ath_stop(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; DPRINTF(sc, ATH_DBG_CONFIG, "%s: Cleaning up\n", __func__); ieee80211_stop_queues(sc->hw); /* make sure h/w will not generate any interrupt * before setting the invalid flag. */ ath9k_hw_set_interrupts(ah, 0); if (!(sc->sc_flags & SC_OP_INVALID)) { ath_draintxq(sc, false); ath_stoprecv(sc); ath9k_hw_phy_disable(ah); } else sc->sc_rxlink = NULL; #ifdef CONFIG_RFKILL if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); #endif /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); ath9k_hw_configpcipowersave(sc->sc_ah, 1); sc->sc_flags |= SC_OP_INVALID; } int ath_reset(struct ath_softc *sc, bool retry_tx) { struct ath_hal *ah = sc->sc_ah; int status; int error = 0; ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ ath_draintxq(sc, retry_tx); /* stop xmit */ ath_stoprecv(sc); /* stop recv */ ath_flushrecv(sc); /* flush recv queue */ ath9k_hw_set_interrupts(ah, 0); ath_draintxq(sc, retry_tx); ath_stoprecv(sc); ath_flushrecv(sc); /* Reset chip */ spin_lock_bh(&sc->sc_resetlock); Loading @@ -771,7 +741,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) } spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) /* restart recv */ if (ath_startrecv(sc) != 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: unable to start recv logic\n", __func__); Loading Loading @@ -804,29 +774,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) return error; } int ath_suspend(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; /* No I/O if device has been surprise removed */ if (sc->sc_flags & SC_OP_INVALID) return -EIO; /* Shut off the interrupt before setting sc->sc_invalid to '1' */ ath9k_hw_set_interrupts(ah, 0); /* XXX: we must make sure h/w will not generate any interrupt * before setting the invalid flag. */ sc->sc_flags |= SC_OP_INVALID; /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); ath9k_hw_configpcipowersave(sc->sc_ah, 1); return 0; } /* Interrupt handler. Most of the actual processing is deferred. * It's the caller's responsibility to ensure the chip is awake. */ Loading Loading @@ -994,11 +941,9 @@ int ath_init(u16 devid, struct ath_softc *sc) /* XXX: hardware will not be ready until ath_open() being called */ sc->sc_flags |= SC_OP_INVALID; sc->sc_debug = DBG_DEFAULT; DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid); /* Initialize tasklet */ spin_lock_init(&sc->sc_resetlock); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, (unsigned long)sc); Loading @@ -1011,8 +956,6 @@ int ath_init(u16 devid, struct ath_softc *sc) /* XXX assert csz is non-zero */ sc->sc_cachelsz = csz << 2; /* convert to bytes */ spin_lock_init(&sc->sc_resetlock); ah = ath9k_hw_attach(devid, sc, sc->mem, &status); if (ah == NULL) { DPRINTF(sc, ATH_DBG_FATAL, Loading @@ -1023,10 +966,6 @@ int ath_init(u16 devid, struct ath_softc *sc) } sc->sc_ah = ah; /* Initializes the noise floor to a reasonable default value. * Later on this will be updated during ANI processing. */ sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; /* Get the hardware key cache size. */ sc->sc_keymax = ah->ah_caps.keycache_size; if (sc->sc_keymax > ATH_KEYMAX) { Loading Loading @@ -1054,17 +993,14 @@ int ath_init(u16 devid, struct ath_softc *sc) set_bit(i + 64, sc->sc_keymap); set_bit(i + 32 + 64, sc->sc_keymap); } /* * Collect the channel list using the default country * code and including outdoor channels. The 802.11 layer * is resposible for filtering this list based on settings * like the phy mode. */ /* Collect the channel list using the default country code */ error = ath_setup_channels(sc); if (error) goto bad; /* default to STA mode */ /* default to MONITOR mode */ sc->sc_ah->ah_opmode = ATH9K_M_MONITOR; /* Setup rate tables */ Loading Loading @@ -1134,6 +1070,10 @@ int ath_init(u16 devid, struct ath_softc *sc) goto bad2; } /* Initializes the noise floor to a reasonable default value. * Later on this will be updated during ANI processing. */ sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc); sc->sc_rc = ath_rate_attach(ah); Loading Loading @@ -1194,6 +1134,7 @@ int ath_init(u16 devid, struct ath_softc *sc) ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask); ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); } sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ /* initialize beacon slots */ Loading @@ -1208,6 +1149,22 @@ int ath_init(u16 devid, struct ath_softc *sc) ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127); #endif /* setup channels and rates */ sc->sbands[IEEE80211_BAND_2GHZ].channels = sc->channels[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].bitrates = sc->rates[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { sc->sbands[IEEE80211_BAND_5GHZ].channels = sc->channels[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].bitrates = sc->rates[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; } return 0; bad2: /* cleanup tx queues */ Loading @@ -1217,27 +1174,8 @@ int ath_init(u16 devid, struct ath_softc *sc) bad: if (ah) ath9k_hw_detach(ah); return error; } void ath_deinit(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; int i; DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); tasklet_kill(&sc->intr_tq); tasklet_kill(&sc->bcon_tasklet); ath_stop(sc); if (!(sc->sc_flags & SC_OP_INVALID)) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); ath_rate_detach(sc->sc_rc); /* cleanup tx queues */ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->sc_txq[i]); ath9k_hw_detach(ah); return error; } /*******************/ Loading drivers/net/wireless/ath9k/core.h +1 −2 Original line number Diff line number Diff line Loading @@ -997,9 +997,8 @@ struct ath_softc { }; int ath_init(u16 devid, struct ath_softc *sc); void ath_deinit(struct ath_softc *sc); int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan); int ath_suspend(struct ath_softc *sc); void ath_stop(struct ath_softc *sc); irqreturn_t ath_isr(int irq, void *dev); int ath_reset(struct ath_softc *sc, bool retry_tx); int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan); Loading drivers/net/wireless/ath9k/main.c +79 −106 Original line number Diff line number Diff line Loading @@ -616,6 +616,7 @@ static void ath_init_leds(struct ath_softc *sc) } #ifdef CONFIG_RFKILL /*******************/ /* Rfkill */ /*******************/ Loading Loading @@ -816,43 +817,72 @@ static void ath_deinit_rfkill(struct ath_softc *sc) sc->rf_kill.rfkill = NULL; } } static int ath_start_rfkill_poll(struct ath_softc *sc) { if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, 0); if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { if (rfkill_register(sc->rf_kill.rfkill)) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to register rfkill\n"); rfkill_free(sc->rf_kill.rfkill); /* Deinitialize the device */ if (sc->pdev->irq) free_irq(sc->pdev->irq, sc); ath_detach(sc); pci_iounmap(sc->pdev, sc->mem); pci_release_region(sc->pdev, 0); pci_disable_device(sc->pdev); ieee80211_free_hw(hw); return -EIO; } else { sc->sc_flags |= SC_OP_RFKILL_REGISTERED; } } return 0; } #endif /* CONFIG_RFKILL */ static int ath_detach(struct ath_softc *sc) static void ath_detach(struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; int i = 0; DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); /* Deinit LED control */ ieee80211_unregister_hw(hw); ath_deinit_leds(sc); #ifdef CONFIG_RFKILL /* deinit rfkill */ ath_deinit_rfkill(sc); #endif /* Unregister hw */ ieee80211_unregister_hw(hw); /* unregister Rate control */ ath_rate_control_unregister(); /* tx/rx cleanup */ ath_rate_detach(sc->sc_rc); ath_rx_cleanup(sc); ath_tx_cleanup(sc); /* Deinit */ tasklet_kill(&sc->intr_tq); tasklet_kill(&sc->bcon_tasklet); ath_deinit(sc); if (!(sc->sc_flags & SC_OP_INVALID)) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); return 0; /* cleanup tx queues */ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->sc_txq[i]); ath9k_hw_detach(sc->sc_ah); } static int ath_attach(u16 devid, struct ath_softc *sc) static int ath_attach(u16 devid, struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; int error = 0; Loading @@ -867,36 +897,15 @@ static int ath_attach(u16 devid, SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); /* setup channels and rates */ sc->sbands[IEEE80211_BAND_2GHZ].channels = sc->channels[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].bitrates = sc->rates[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) /* Setup HT capabilities for 2.4Ghz*/ setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { sc->sbands[IEEE80211_BAND_5GHZ].channels = sc->channels[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].bitrates = sc->rates[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) /* Setup HT capabilities for 5Ghz*/ setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION; hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; } hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->queues = 4; hw->sta_data_size = sizeof(struct ath_node); Loading @@ -913,6 +922,17 @@ static int ath_attach(u16 devid, goto bad; } if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); } hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; error = ieee80211_register_hw(hw); if (error != 0) { ath_rate_control_unregister(); Loading Loading @@ -963,49 +983,26 @@ static int ath9k_start(struct ieee80211_hw *hw) pos = ath_get_channel(sc, curchan); if (pos == -1) { DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); return -EINVAL; error = -EINVAL; goto exit; } sc->sc_ah->ah_channels[pos].chanmode = (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; /* open ath_dev */ error = ath_open(sc, &sc->sc_ah->ah_channels[pos]); if (error) { DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to complete ath_open\n", __func__); return error; goto exit; } #ifdef CONFIG_RFKILL /* Start rfkill polling */ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, 0); if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { if (rfkill_register(sc->rf_kill.rfkill)) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to register rfkill\n"); rfkill_free(sc->rf_kill.rfkill); /* Deinitialize the device */ if (sc->pdev->irq) free_irq(sc->pdev->irq, sc); ath_detach(sc); pci_iounmap(sc->pdev, sc->mem); pci_release_region(sc->pdev, 0); pci_disable_device(sc->pdev); ieee80211_free_hw(hw); return -EIO; } else { sc->sc_flags |= SC_OP_RFKILL_REGISTERED; } } error = ath_start_rfkill_poll(sc); #endif ieee80211_wake_queues(hw); return 0; exit: return error; } static int ath9k_tx(struct ieee80211_hw *hw, Loading Loading @@ -1065,21 +1062,15 @@ static int ath9k_tx(struct ieee80211_hw *hw, static void ath9k_stop(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; int error; DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); error = ath_suspend(sc); if (error) DPRINTF(sc, ATH_DBG_CONFIG, "%s: Device is no longer present\n", __func__); if (sc->sc_flags & SC_OP_INVALID) { DPRINTF(sc, ATH_DBG_ANY, "%s: Device not present\n", __func__); return; } ieee80211_stop_queues(hw); ath_stop(sc); #ifdef CONFIG_RFKILL if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); #endif DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); } static int ath9k_add_interface(struct ieee80211_hw *hw, Loading Loading @@ -1643,17 +1634,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto bad2; } hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | IEEE80211_HW_AMPDU_AGGREGATION; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); SET_IEEE80211_DEV(hw, &pdev->dev); pci_set_drvdata(pdev, hw); Loading Loading @@ -1701,17 +1681,10 @@ static void ath_pci_remove(struct pci_dev *pdev) { struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_softc *sc = hw->priv; enum ath9k_int status; if (pdev->irq) { ath9k_hw_set_interrupts(sc->sc_ah, 0); /* clear the ISR */ ath9k_hw_getisr(sc->sc_ah, &status); sc->sc_flags |= SC_OP_INVALID; free_irq(pdev->irq, sc); } ath_detach(sc); if (pdev->irq) free_irq(pdev->irq, sc); pci_iounmap(pdev, sc->mem); pci_release_region(pdev, 0); pci_disable_device(pdev); Loading Loading
drivers/net/wireless/ath9k/core.c +78 −140 Original line number Diff line number Diff line Loading @@ -186,17 +186,10 @@ static int ath_setup_channels(struct ath_softc *sc) struct ath9k_channel *c; /* Fill in ah->ah_channels */ if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan, regclassids, ATH_REGCLASSIDS_MAX, &nregclass, CTRY_DEFAULT, false, 1)) { if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan, regclassids, ATH_REGCLASSIDS_MAX, &nregclass, CTRY_DEFAULT, false, 1)) { u32 rd = ah->ah_currentRD; DPRINTF(sc, ATH_DBG_FATAL, "%s: unable to collect channel list; " "regdomain likely %u country code %u\n", Loading @@ -217,40 +210,32 @@ static int ath_setup_channels(struct ath_softc *sc) chan_2ghz[a].max_power = c->maxTxPower; if (c->privFlags & CHANNEL_DISALLOW_ADHOC) chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS; chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS; if (c->channelFlags & CHANNEL_PASSIVE) chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN; chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN; band_2ghz->n_channels = ++a; DPRINTF(sc, ATH_DBG_CONFIG, "%s: 2MHz channel: %d, " "channelFlags: 0x%x\n", __func__, c->channel, c->channelFlags); __func__, c->channel, c->channelFlags); } else if (IS_CHAN_5GHZ(c)) { chan_5ghz[b].band = IEEE80211_BAND_5GHZ; chan_5ghz[b].center_freq = c->channel; chan_5ghz[b].max_power = c->maxTxPower; if (c->privFlags & CHANNEL_DISALLOW_ADHOC) chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS; chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS; if (c->channelFlags & CHANNEL_PASSIVE) chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN; chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN; band_5ghz->n_channels = ++b; DPRINTF(sc, ATH_DBG_CONFIG, "%s: 5MHz channel: %d, " "channelFlags: 0x%x\n", __func__, c->channel, c->channelFlags); __func__, c->channel, c->channelFlags); } } Loading Loading @@ -291,44 +276,6 @@ static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) return ATH9K_MODE_11B; } /* * Stop the device, grabbing the top-level lock to protect * against concurrent entry through ath_init (which can happen * if another thread does a system call and the thread doing the * stop is preempted). */ static int ath_stop(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n", __func__, sc->sc_flags & SC_OP_INVALID); /* * Shutdown the hardware and driver: * stop output from above * turn off timers * disable interrupts * clear transmit machinery * clear receive machinery * turn off the radio * reclaim beacon resources * * Note that some of this work is not possible if the * hardware is gone (invalid). */ ath_draintxq(sc, false); if (!(sc->sc_flags & SC_OP_INVALID)) { ath_stoprecv(sc); ath9k_hw_phy_disable(ah); } else sc->sc_rxlink = NULL; return 0; } /* * Set the current channel * Loading Loading @@ -650,16 +597,6 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_ah->ah_opmode); /* * Stop anything previously setup. This is safe * whether this is the first time through or not. */ ath_stop(sc); /* Initialize chanmask selection */ sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; /* Reset SERDES registers */ ath9k_hw_configpcipowersave(ah, 0); Loading @@ -685,6 +622,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) goto done; } spin_unlock_bh(&sc->sc_resetlock); /* * This is needed only to setup initial state * but it's best done after a reset. Loading @@ -704,6 +642,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) error = -EIO; goto done; } /* Setup our intr mask. */ sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN Loading Loading @@ -733,30 +672,61 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) (sc->sc_ah->ah_opmode == ATH9K_M_STA) && !sc->sc_config.swBeaconProcess) sc->sc_imask |= ATH9K_INT_TIM; ath_setcurmode(sc, ath_chan2mode(initial_chan)); /* * Don't enable interrupts here as we've not yet built our * vap and node data structures, which will be needed as soon * as we start receiving. */ ath_setcurmode(sc, ath_chan2mode(initial_chan)); /* XXX: we must make sure h/w is ready and clear invalid flag * before turning on interrupt. */ sc->sc_flags &= ~SC_OP_INVALID; ieee80211_wake_queues(sc->hw); done: return error; } void ath_stop(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; DPRINTF(sc, ATH_DBG_CONFIG, "%s: Cleaning up\n", __func__); ieee80211_stop_queues(sc->hw); /* make sure h/w will not generate any interrupt * before setting the invalid flag. */ ath9k_hw_set_interrupts(ah, 0); if (!(sc->sc_flags & SC_OP_INVALID)) { ath_draintxq(sc, false); ath_stoprecv(sc); ath9k_hw_phy_disable(ah); } else sc->sc_rxlink = NULL; #ifdef CONFIG_RFKILL if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); #endif /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); ath9k_hw_configpcipowersave(sc->sc_ah, 1); sc->sc_flags |= SC_OP_INVALID; } int ath_reset(struct ath_softc *sc, bool retry_tx) { struct ath_hal *ah = sc->sc_ah; int status; int error = 0; ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ ath_draintxq(sc, retry_tx); /* stop xmit */ ath_stoprecv(sc); /* stop recv */ ath_flushrecv(sc); /* flush recv queue */ ath9k_hw_set_interrupts(ah, 0); ath_draintxq(sc, retry_tx); ath_stoprecv(sc); ath_flushrecv(sc); /* Reset chip */ spin_lock_bh(&sc->sc_resetlock); Loading @@ -771,7 +741,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) } spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) /* restart recv */ if (ath_startrecv(sc) != 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: unable to start recv logic\n", __func__); Loading Loading @@ -804,29 +774,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) return error; } int ath_suspend(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; /* No I/O if device has been surprise removed */ if (sc->sc_flags & SC_OP_INVALID) return -EIO; /* Shut off the interrupt before setting sc->sc_invalid to '1' */ ath9k_hw_set_interrupts(ah, 0); /* XXX: we must make sure h/w will not generate any interrupt * before setting the invalid flag. */ sc->sc_flags |= SC_OP_INVALID; /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); ath9k_hw_configpcipowersave(sc->sc_ah, 1); return 0; } /* Interrupt handler. Most of the actual processing is deferred. * It's the caller's responsibility to ensure the chip is awake. */ Loading Loading @@ -994,11 +941,9 @@ int ath_init(u16 devid, struct ath_softc *sc) /* XXX: hardware will not be ready until ath_open() being called */ sc->sc_flags |= SC_OP_INVALID; sc->sc_debug = DBG_DEFAULT; DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid); /* Initialize tasklet */ spin_lock_init(&sc->sc_resetlock); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, (unsigned long)sc); Loading @@ -1011,8 +956,6 @@ int ath_init(u16 devid, struct ath_softc *sc) /* XXX assert csz is non-zero */ sc->sc_cachelsz = csz << 2; /* convert to bytes */ spin_lock_init(&sc->sc_resetlock); ah = ath9k_hw_attach(devid, sc, sc->mem, &status); if (ah == NULL) { DPRINTF(sc, ATH_DBG_FATAL, Loading @@ -1023,10 +966,6 @@ int ath_init(u16 devid, struct ath_softc *sc) } sc->sc_ah = ah; /* Initializes the noise floor to a reasonable default value. * Later on this will be updated during ANI processing. */ sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; /* Get the hardware key cache size. */ sc->sc_keymax = ah->ah_caps.keycache_size; if (sc->sc_keymax > ATH_KEYMAX) { Loading Loading @@ -1054,17 +993,14 @@ int ath_init(u16 devid, struct ath_softc *sc) set_bit(i + 64, sc->sc_keymap); set_bit(i + 32 + 64, sc->sc_keymap); } /* * Collect the channel list using the default country * code and including outdoor channels. The 802.11 layer * is resposible for filtering this list based on settings * like the phy mode. */ /* Collect the channel list using the default country code */ error = ath_setup_channels(sc); if (error) goto bad; /* default to STA mode */ /* default to MONITOR mode */ sc->sc_ah->ah_opmode = ATH9K_M_MONITOR; /* Setup rate tables */ Loading Loading @@ -1134,6 +1070,10 @@ int ath_init(u16 devid, struct ath_softc *sc) goto bad2; } /* Initializes the noise floor to a reasonable default value. * Later on this will be updated during ANI processing. */ sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc); sc->sc_rc = ath_rate_attach(ah); Loading Loading @@ -1194,6 +1134,7 @@ int ath_init(u16 devid, struct ath_softc *sc) ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask); ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); } sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ /* initialize beacon slots */ Loading @@ -1208,6 +1149,22 @@ int ath_init(u16 devid, struct ath_softc *sc) ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127); #endif /* setup channels and rates */ sc->sbands[IEEE80211_BAND_2GHZ].channels = sc->channels[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].bitrates = sc->rates[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { sc->sbands[IEEE80211_BAND_5GHZ].channels = sc->channels[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].bitrates = sc->rates[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; } return 0; bad2: /* cleanup tx queues */ Loading @@ -1217,27 +1174,8 @@ int ath_init(u16 devid, struct ath_softc *sc) bad: if (ah) ath9k_hw_detach(ah); return error; } void ath_deinit(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; int i; DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); tasklet_kill(&sc->intr_tq); tasklet_kill(&sc->bcon_tasklet); ath_stop(sc); if (!(sc->sc_flags & SC_OP_INVALID)) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); ath_rate_detach(sc->sc_rc); /* cleanup tx queues */ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->sc_txq[i]); ath9k_hw_detach(ah); return error; } /*******************/ Loading
drivers/net/wireless/ath9k/core.h +1 −2 Original line number Diff line number Diff line Loading @@ -997,9 +997,8 @@ struct ath_softc { }; int ath_init(u16 devid, struct ath_softc *sc); void ath_deinit(struct ath_softc *sc); int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan); int ath_suspend(struct ath_softc *sc); void ath_stop(struct ath_softc *sc); irqreturn_t ath_isr(int irq, void *dev); int ath_reset(struct ath_softc *sc, bool retry_tx); int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan); Loading
drivers/net/wireless/ath9k/main.c +79 −106 Original line number Diff line number Diff line Loading @@ -616,6 +616,7 @@ static void ath_init_leds(struct ath_softc *sc) } #ifdef CONFIG_RFKILL /*******************/ /* Rfkill */ /*******************/ Loading Loading @@ -816,43 +817,72 @@ static void ath_deinit_rfkill(struct ath_softc *sc) sc->rf_kill.rfkill = NULL; } } static int ath_start_rfkill_poll(struct ath_softc *sc) { if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, 0); if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { if (rfkill_register(sc->rf_kill.rfkill)) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to register rfkill\n"); rfkill_free(sc->rf_kill.rfkill); /* Deinitialize the device */ if (sc->pdev->irq) free_irq(sc->pdev->irq, sc); ath_detach(sc); pci_iounmap(sc->pdev, sc->mem); pci_release_region(sc->pdev, 0); pci_disable_device(sc->pdev); ieee80211_free_hw(hw); return -EIO; } else { sc->sc_flags |= SC_OP_RFKILL_REGISTERED; } } return 0; } #endif /* CONFIG_RFKILL */ static int ath_detach(struct ath_softc *sc) static void ath_detach(struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; int i = 0; DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); /* Deinit LED control */ ieee80211_unregister_hw(hw); ath_deinit_leds(sc); #ifdef CONFIG_RFKILL /* deinit rfkill */ ath_deinit_rfkill(sc); #endif /* Unregister hw */ ieee80211_unregister_hw(hw); /* unregister Rate control */ ath_rate_control_unregister(); /* tx/rx cleanup */ ath_rate_detach(sc->sc_rc); ath_rx_cleanup(sc); ath_tx_cleanup(sc); /* Deinit */ tasklet_kill(&sc->intr_tq); tasklet_kill(&sc->bcon_tasklet); ath_deinit(sc); if (!(sc->sc_flags & SC_OP_INVALID)) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); return 0; /* cleanup tx queues */ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->sc_txq[i]); ath9k_hw_detach(sc->sc_ah); } static int ath_attach(u16 devid, struct ath_softc *sc) static int ath_attach(u16 devid, struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; int error = 0; Loading @@ -867,36 +897,15 @@ static int ath_attach(u16 devid, SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); /* setup channels and rates */ sc->sbands[IEEE80211_BAND_2GHZ].channels = sc->channels[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].bitrates = sc->rates[IEEE80211_BAND_2GHZ]; sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) /* Setup HT capabilities for 2.4Ghz*/ setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { sc->sbands[IEEE80211_BAND_5GHZ].channels = sc->channels[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].bitrates = sc->rates[IEEE80211_BAND_5GHZ]; sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) /* Setup HT capabilities for 5Ghz*/ setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION; hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; } hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->queues = 4; hw->sta_data_size = sizeof(struct ath_node); Loading @@ -913,6 +922,17 @@ static int ath_attach(u16 devid, goto bad; } if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); } hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; error = ieee80211_register_hw(hw); if (error != 0) { ath_rate_control_unregister(); Loading Loading @@ -963,49 +983,26 @@ static int ath9k_start(struct ieee80211_hw *hw) pos = ath_get_channel(sc, curchan); if (pos == -1) { DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); return -EINVAL; error = -EINVAL; goto exit; } sc->sc_ah->ah_channels[pos].chanmode = (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; /* open ath_dev */ error = ath_open(sc, &sc->sc_ah->ah_channels[pos]); if (error) { DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to complete ath_open\n", __func__); return error; goto exit; } #ifdef CONFIG_RFKILL /* Start rfkill polling */ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, 0); if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { if (rfkill_register(sc->rf_kill.rfkill)) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to register rfkill\n"); rfkill_free(sc->rf_kill.rfkill); /* Deinitialize the device */ if (sc->pdev->irq) free_irq(sc->pdev->irq, sc); ath_detach(sc); pci_iounmap(sc->pdev, sc->mem); pci_release_region(sc->pdev, 0); pci_disable_device(sc->pdev); ieee80211_free_hw(hw); return -EIO; } else { sc->sc_flags |= SC_OP_RFKILL_REGISTERED; } } error = ath_start_rfkill_poll(sc); #endif ieee80211_wake_queues(hw); return 0; exit: return error; } static int ath9k_tx(struct ieee80211_hw *hw, Loading Loading @@ -1065,21 +1062,15 @@ static int ath9k_tx(struct ieee80211_hw *hw, static void ath9k_stop(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; int error; DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); error = ath_suspend(sc); if (error) DPRINTF(sc, ATH_DBG_CONFIG, "%s: Device is no longer present\n", __func__); if (sc->sc_flags & SC_OP_INVALID) { DPRINTF(sc, ATH_DBG_ANY, "%s: Device not present\n", __func__); return; } ieee80211_stop_queues(hw); ath_stop(sc); #ifdef CONFIG_RFKILL if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); #endif DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); } static int ath9k_add_interface(struct ieee80211_hw *hw, Loading Loading @@ -1643,17 +1634,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto bad2; } hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | IEEE80211_HW_AMPDU_AGGREGATION; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); SET_IEEE80211_DEV(hw, &pdev->dev); pci_set_drvdata(pdev, hw); Loading Loading @@ -1701,17 +1681,10 @@ static void ath_pci_remove(struct pci_dev *pdev) { struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_softc *sc = hw->priv; enum ath9k_int status; if (pdev->irq) { ath9k_hw_set_interrupts(sc->sc_ah, 0); /* clear the ISR */ ath9k_hw_getisr(sc->sc_ah, &status); sc->sc_flags |= SC_OP_INVALID; free_irq(pdev->irq, sc); } ath_detach(sc); if (pdev->irq) free_irq(pdev->irq, sc); pci_iounmap(pdev, sc->mem); pci_release_region(pdev, 0); pci_disable_device(pdev); Loading