mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
3a999e6eb5
@ -88,27 +88,6 @@ Who: Luis R. Rodriguez <lrodriguez@atheros.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: CONFIG_WIRELESS_OLD_REGULATORY - old static regulatory information
|
||||
When: March 2010 / desktop catchup
|
||||
|
||||
Why: The old regulatory infrastructure has been replaced with a new one
|
||||
which does not require statically defined regulatory domains. We do
|
||||
not want to keep static regulatory domains in the kernel due to the
|
||||
the dynamic nature of regulatory law and localization. We kept around
|
||||
the old static definitions for the regulatory domains of:
|
||||
|
||||
* US
|
||||
* JP
|
||||
* EU
|
||||
|
||||
and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was
|
||||
set. We will remove this option once the standard Linux desktop catches
|
||||
up with the new userspace APIs we have implemented.
|
||||
|
||||
Who: Luis R. Rodriguez <lrodriguez@atheros.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: dev->power.power_state
|
||||
When: July 2007
|
||||
Why: Broken design for runtime control over driver power states, confusing
|
||||
|
@ -1400,15 +1400,15 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev,
|
||||
}
|
||||
|
||||
static int adm8211_add_interface(struct ieee80211_hw *dev,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct adm8211_priv *priv = dev->priv;
|
||||
if (priv->mode != NL80211_IFTYPE_MONITOR)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
priv->mode = conf->type;
|
||||
priv->mode = vif->type;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
@ -1416,8 +1416,8 @@ static int adm8211_add_interface(struct ieee80211_hw *dev,
|
||||
|
||||
ADM8211_IDLE();
|
||||
|
||||
ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr));
|
||||
ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
|
||||
ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr));
|
||||
ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4)));
|
||||
|
||||
adm8211_update_mode(dev);
|
||||
|
||||
@ -1427,7 +1427,7 @@ static int adm8211_add_interface(struct ieee80211_hw *dev,
|
||||
}
|
||||
|
||||
static void adm8211_remove_interface(struct ieee80211_hw *dev,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct adm8211_priv *priv = dev->priv;
|
||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
||||
|
@ -1789,7 +1789,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
static int at76_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct at76_priv *priv = hw->priv;
|
||||
int ret = 0;
|
||||
@ -1798,7 +1798,7 @@ static int at76_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&priv->mtx);
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
priv->iw_mode = IW_MODE_INFRA;
|
||||
break;
|
||||
@ -1814,7 +1814,7 @@ exit:
|
||||
}
|
||||
|
||||
static void at76_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
at76_dbg(DBG_MAC80211, "%s()", __func__);
|
||||
}
|
||||
|
@ -1939,7 +1939,7 @@ err_free:
|
||||
}
|
||||
|
||||
static int ar9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
struct ath_common *common = &ar->common;
|
||||
@ -1952,8 +1952,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ar->vif = conf->vif;
|
||||
memcpy(common->macaddr, conf->mac_addr, ETH_ALEN);
|
||||
ar->vif = vif;
|
||||
memcpy(common->macaddr, vif->addr, ETH_ALEN);
|
||||
|
||||
if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
|
||||
ar->rx_software_decryption = true;
|
||||
@ -1973,7 +1973,7 @@ unlock:
|
||||
}
|
||||
|
||||
static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
|
||||
|
@ -225,9 +225,9 @@ static int ath5k_reset_wake(struct ath5k_softc *sc);
|
||||
static int ath5k_start(struct ieee80211_hw *hw);
|
||||
static void ath5k_stop(struct ieee80211_hw *hw);
|
||||
static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
struct ieee80211_vif *vif);
|
||||
static void ath5k_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
struct ieee80211_vif *vif);
|
||||
static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
|
||||
static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_addr_list *mc_list);
|
||||
@ -1903,17 +1903,6 @@ accept:
|
||||
rxs->noise = sc->ah->ah_noise_floor;
|
||||
rxs->signal = rxs->noise + rs.rs_rssi;
|
||||
|
||||
/* An rssi of 35 indicates you should be able use
|
||||
* 54 Mbps reliably. A more elaborate scheme can be used
|
||||
* here but it requires a map of SNR/throughput for each
|
||||
* possible mode used */
|
||||
rxs->qual = rs.rs_rssi * 100 / 35;
|
||||
|
||||
/* rssi can be more than 35 though, anything above that
|
||||
* should be considered at 100% */
|
||||
if (rxs->qual > 100)
|
||||
rxs->qual = 100;
|
||||
|
||||
rxs->antenna = rs.rs_antenna;
|
||||
rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
|
||||
rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
|
||||
@ -2381,6 +2370,9 @@ ath5k_init(struct ath5k_softc *sc)
|
||||
*/
|
||||
ath5k_stop_locked(sc);
|
||||
|
||||
/* Set PHY calibration interval */
|
||||
ah->ah_cal_intval = ath5k_calinterval;
|
||||
|
||||
/*
|
||||
* The basic interface to setting the hardware in a good
|
||||
* state is ``reset''. On return the hardware is known to
|
||||
@ -2408,10 +2400,6 @@ ath5k_init(struct ath5k_softc *sc)
|
||||
|
||||
/* Set ack to be sent at low bit-rates */
|
||||
ath5k_hw_set_ack_bitrate_high(ah, false);
|
||||
|
||||
/* Set PHY calibration inteval */
|
||||
ah->ah_cal_intval = ath5k_calinterval;
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
mmiowb();
|
||||
@ -2785,7 +2773,7 @@ static void ath5k_stop(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
int ret;
|
||||
@ -2796,22 +2784,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
goto end;
|
||||
}
|
||||
|
||||
sc->vif = conf->vif;
|
||||
sc->vif = vif;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
sc->opmode = conf->type;
|
||||
sc->opmode = vif->type;
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
|
||||
ath5k_hw_set_lladdr(sc->ah, vif->addr);
|
||||
ath5k_mode_setup(sc);
|
||||
|
||||
ret = 0;
|
||||
@ -2822,13 +2810,13 @@ end:
|
||||
|
||||
static void
|
||||
ath5k_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
u8 mac[ETH_ALEN] = {};
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
if (sc->vif != conf->vif)
|
||||
if (sc->vif != vif)
|
||||
goto end;
|
||||
|
||||
ath5k_hw_set_lladdr(sc->ah, mac);
|
||||
|
@ -77,6 +77,9 @@
|
||||
#define ATH9K_TXERR_XTXOP 0x08
|
||||
#define ATH9K_TXERR_TIMER_EXPIRED 0x10
|
||||
#define ATH9K_TX_ACKED 0x20
|
||||
#define ATH9K_TXERR_MASK \
|
||||
(ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \
|
||||
ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
|
||||
|
||||
#define ATH9K_TX_BA 0x01
|
||||
#define ATH9K_TX_PWRMGMT 0x02
|
||||
|
@ -2504,6 +2504,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
return; /* another wiphy still in use */
|
||||
}
|
||||
|
||||
/* Ensure HW is awake when we try to shut it down. */
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
if (ah->btcoex_hw.enabled) {
|
||||
ath9k_hw_btcoex_disable(ah);
|
||||
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
|
||||
@ -2524,6 +2527,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
/* disable HAL and put h/w to sleep */
|
||||
ath9k_hw_disable(ah);
|
||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
/* Finally, put the chip in FULL SLEEP mode */
|
||||
ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
|
||||
|
||||
sc->sc_flags |= SC_OP_INVALID;
|
||||
@ -2534,12 +2540,12 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
static int ath9k_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_vif *avp = (void *)conf->vif->drv_priv;
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
|
||||
int ret = 0;
|
||||
|
||||
@ -2551,7 +2557,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
ic_opmode = NL80211_IFTYPE_STATION;
|
||||
break;
|
||||
@ -2562,11 +2568,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
||||
ret = -ENOBUFS;
|
||||
goto out;
|
||||
}
|
||||
ic_opmode = conf->type;
|
||||
ic_opmode = vif->type;
|
||||
break;
|
||||
default:
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Interface type %d not yet supported\n", conf->type);
|
||||
"Interface type %d not yet supported\n", vif->type);
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
@ -2598,18 +2604,18 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
||||
* Enable MIB interrupts when there are hardware phy counters.
|
||||
* Note we only do this (at the moment) for station mode.
|
||||
*/
|
||||
if ((conf->type == NL80211_IFTYPE_STATION) ||
|
||||
(conf->type == NL80211_IFTYPE_ADHOC) ||
|
||||
(conf->type == NL80211_IFTYPE_MESH_POINT)) {
|
||||
if ((vif->type == NL80211_IFTYPE_STATION) ||
|
||||
(vif->type == NL80211_IFTYPE_ADHOC) ||
|
||||
(vif->type == NL80211_IFTYPE_MESH_POINT)) {
|
||||
sc->imask |= ATH9K_INT_MIB;
|
||||
sc->imask |= ATH9K_INT_TSFOOR;
|
||||
}
|
||||
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
|
||||
|
||||
if (conf->type == NL80211_IFTYPE_AP ||
|
||||
conf->type == NL80211_IFTYPE_ADHOC ||
|
||||
conf->type == NL80211_IFTYPE_MONITOR)
|
||||
if (vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_ADHOC ||
|
||||
vif->type == NL80211_IFTYPE_MONITOR)
|
||||
ath_start_ani(common);
|
||||
|
||||
out:
|
||||
@ -2618,12 +2624,12 @@ out:
|
||||
}
|
||||
|
||||
static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_vif *avp = (void *)conf->vif->drv_priv;
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
int i;
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
|
||||
@ -2637,14 +2643,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
|
||||
(sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
|
||||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
||||
ath_beacon_return(sc, avp);
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
sc->sc_flags &= ~SC_OP_BEACONS;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
|
||||
if (sc->beacon.bslot[i] == conf->vif) {
|
||||
if (sc->beacon.bslot[i] == vif) {
|
||||
printk(KERN_DEBUG "%s: vif had allocated beacon "
|
||||
"slot\n", __func__);
|
||||
sc->beacon.bslot[i] = NULL;
|
||||
@ -3087,15 +3095,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath_tx_aggr_start(sc, sta, tid, ssn);
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
ath9k_ps_restore(sc);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath_tx_aggr_stop(sc, sta, tid);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
ath9k_ps_restore(sc);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath_tx_aggr_resume(sc, sta, tid);
|
||||
ath9k_ps_restore(sc);
|
||||
break;
|
||||
default:
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
|
@ -96,7 +96,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common)
|
||||
pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
|
||||
}
|
||||
|
||||
const static struct ath_bus_ops ath_pci_bus_ops = {
|
||||
static const struct ath_bus_ops ath_pci_bus_ops = {
|
||||
.read_cachesize = ath_pci_read_cachesize,
|
||||
.cleanup = ath_pci_cleanup,
|
||||
.eeprom_read = ath_pci_eeprom_read,
|
||||
|
@ -2072,7 +2072,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
&txq->axq_q, lastbf->list.prev);
|
||||
|
||||
txq->axq_depth--;
|
||||
txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT);
|
||||
txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK);
|
||||
txq->axq_tx_inprogress = false;
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
|
||||
|
@ -3,6 +3,7 @@ config B43
|
||||
depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
|
||||
select SSB
|
||||
select FW_LOADER
|
||||
select SSB_BLOCKIO
|
||||
---help---
|
||||
b43 is a driver for the Broadcom 43xx series wireless devices.
|
||||
|
||||
@ -78,14 +79,6 @@ config B43_SDIO
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
# Data transfers to the device via PIO
|
||||
# This is only needed on PCMCIA and SDIO devices. All others can do DMA properly.
|
||||
config B43_PIO
|
||||
bool
|
||||
depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO)
|
||||
select SSB_BLOCKIO
|
||||
default y
|
||||
|
||||
config B43_NPHY
|
||||
bool "Pre IEEE 802.11n support (BROKEN)"
|
||||
depends on B43 && EXPERIMENTAL && BROKEN
|
||||
@ -137,12 +130,4 @@ config B43_DEBUG
|
||||
for production use.
|
||||
Only say Y, if you are debugging a problem in the b43 driver sourcecode.
|
||||
|
||||
config B43_FORCE_PIO
|
||||
bool "Force usage of PIO instead of DMA"
|
||||
depends on B43 && B43_DEBUG
|
||||
---help---
|
||||
This will disable DMA and always enable PIO instead.
|
||||
|
||||
Say N!
|
||||
This is only for debugging the PIO engine code. You do
|
||||
_NOT_ want to enable this.
|
||||
|
@ -12,7 +12,7 @@ b43-y += xmit.o
|
||||
b43-y += lo.o
|
||||
b43-y += wa.o
|
||||
b43-y += dma.o
|
||||
b43-$(CONFIG_B43_PIO) += pio.o
|
||||
b43-y += pio.o
|
||||
b43-y += rfkill.o
|
||||
b43-$(CONFIG_B43_LEDS) += leds.o
|
||||
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
|
||||
|
@ -821,11 +821,9 @@ struct b43_wl {
|
||||
/* The device LEDs. */
|
||||
struct b43_leds leds;
|
||||
|
||||
#ifdef CONFIG_B43_PIO
|
||||
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
|
||||
u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
|
||||
u8 pio_tailspace[4] __attribute__((__aligned__(8)));
|
||||
#endif /* CONFIG_B43_PIO */
|
||||
};
|
||||
|
||||
static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
|
||||
@ -876,20 +874,9 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
|
||||
|
||||
static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
|
||||
{
|
||||
#ifdef CONFIG_B43_PIO
|
||||
return dev->__using_pio_transfers;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_B43_FORCE_PIO
|
||||
# define B43_FORCE_PIO 1
|
||||
#else
|
||||
# define B43_FORCE_PIO 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Message printing */
|
||||
void b43info(struct b43_wl *wl, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
@ -383,160 +383,44 @@ static inline
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if a DMA region fits the device constraints.
|
||||
* Returns true, if the region is OK for usage with this device. */
|
||||
static inline bool b43_dma_address_ok(struct b43_dmaring *ring,
|
||||
dma_addr_t addr, size_t size)
|
||||
{
|
||||
switch (ring->type) {
|
||||
case B43_DMA_30BIT:
|
||||
if ((u64)addr + size > (1ULL << 30))
|
||||
return 0;
|
||||
break;
|
||||
case B43_DMA_32BIT:
|
||||
if ((u64)addr + size > (1ULL << 32))
|
||||
return 0;
|
||||
break;
|
||||
case B43_DMA_64BIT:
|
||||
/* Currently we can't have addresses beyond
|
||||
* 64bit in the kernel. */
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define is_4k_aligned(addr) (((u64)(addr) & 0x0FFFull) == 0)
|
||||
#define is_8k_aligned(addr) (((u64)(addr) & 0x1FFFull) == 0)
|
||||
|
||||
static void b43_unmap_and_free_ringmem(struct b43_dmaring *ring, void *base,
|
||||
dma_addr_t dmaaddr, size_t size)
|
||||
{
|
||||
ssb_dma_unmap_single(ring->dev->dev, dmaaddr, size, DMA_TO_DEVICE);
|
||||
free_pages((unsigned long)base, get_order(size));
|
||||
}
|
||||
|
||||
static void * __b43_get_and_map_ringmem(struct b43_dmaring *ring,
|
||||
dma_addr_t *dmaaddr, size_t size,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
void *base;
|
||||
|
||||
base = (void *)__get_free_pages(gfp_flags, get_order(size));
|
||||
if (!base)
|
||||
return NULL;
|
||||
memset(base, 0, size);
|
||||
*dmaaddr = ssb_dma_map_single(ring->dev->dev, base, size,
|
||||
DMA_TO_DEVICE);
|
||||
if (ssb_dma_mapping_error(ring->dev->dev, *dmaaddr)) {
|
||||
free_pages((unsigned long)base, get_order(size));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
static void * b43_get_and_map_ringmem(struct b43_dmaring *ring,
|
||||
dma_addr_t *dmaaddr, size_t size)
|
||||
{
|
||||
void *base;
|
||||
|
||||
base = __b43_get_and_map_ringmem(ring, dmaaddr, size,
|
||||
GFP_KERNEL);
|
||||
if (!base) {
|
||||
b43err(ring->dev->wl, "Failed to allocate or map pages "
|
||||
"for DMA ringmemory\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!b43_dma_address_ok(ring, *dmaaddr, size)) {
|
||||
/* The memory does not fit our device constraints.
|
||||
* Retry with GFP_DMA set to get lower memory. */
|
||||
b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
|
||||
base = __b43_get_and_map_ringmem(ring, dmaaddr, size,
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
if (!base) {
|
||||
b43err(ring->dev->wl, "Failed to allocate or map pages "
|
||||
"in the GFP_DMA region for DMA ringmemory\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!b43_dma_address_ok(ring, *dmaaddr, size)) {
|
||||
b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
|
||||
b43err(ring->dev->wl, "Failed to allocate DMA "
|
||||
"ringmemory that fits device constraints\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* We expect the memory to be 4k aligned, at least. */
|
||||
if (B43_WARN_ON(!is_4k_aligned(*dmaaddr))) {
|
||||
b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
static int alloc_ringmemory(struct b43_dmaring *ring)
|
||||
{
|
||||
unsigned int required;
|
||||
void *base;
|
||||
dma_addr_t dmaaddr;
|
||||
gfp_t flags = GFP_KERNEL;
|
||||
|
||||
/* There are several requirements to the descriptor ring memory:
|
||||
* - The memory region needs to fit the address constraints for the
|
||||
* device (same as for frame buffers).
|
||||
* - For 30/32bit DMA devices, the descriptor ring must be 4k aligned.
|
||||
* - For 64bit DMA devices, the descriptor ring must be 8k aligned.
|
||||
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
|
||||
* alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing
|
||||
* has shown that 4K is sufficient for the latter as long as the buffer
|
||||
* does not cross an 8K boundary.
|
||||
*
|
||||
* For unknown reasons - possibly a hardware error - the BCM4311 rev
|
||||
* 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
|
||||
* which accounts for the GFP_DMA flag below.
|
||||
*
|
||||
* The flags here must match the flags in free_ringmemory below!
|
||||
*/
|
||||
|
||||
if (ring->type == B43_DMA_64BIT)
|
||||
required = ring->nr_slots * sizeof(struct b43_dmadesc64);
|
||||
else
|
||||
required = ring->nr_slots * sizeof(struct b43_dmadesc32);
|
||||
if (B43_WARN_ON(required > 0x1000))
|
||||
flags |= GFP_DMA;
|
||||
ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
|
||||
B43_DMA_RINGMEMSIZE,
|
||||
&(ring->dmabase), flags);
|
||||
if (!ring->descbase) {
|
||||
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
|
||||
return -ENOMEM;
|
||||
|
||||
ring->alloc_descsize = 0x1000;
|
||||
base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize);
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
ring->alloc_descbase = base;
|
||||
ring->alloc_dmabase = dmaaddr;
|
||||
|
||||
if ((ring->type != B43_DMA_64BIT) || is_8k_aligned(dmaaddr)) {
|
||||
/* We're on <=32bit DMA, or we already got 8k aligned memory.
|
||||
* That's all we need, so we're fine. */
|
||||
ring->descbase = base;
|
||||
ring->dmabase = dmaaddr;
|
||||
return 0;
|
||||
}
|
||||
b43_unmap_and_free_ringmem(ring, base, dmaaddr, ring->alloc_descsize);
|
||||
|
||||
/* Ok, we failed at the 8k alignment requirement.
|
||||
* Try to force-align the memory region now. */
|
||||
ring->alloc_descsize = 0x2000;
|
||||
base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize);
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
ring->alloc_descbase = base;
|
||||
ring->alloc_dmabase = dmaaddr;
|
||||
|
||||
if (is_8k_aligned(dmaaddr)) {
|
||||
/* We're already 8k aligned. That Ok, too. */
|
||||
ring->descbase = base;
|
||||
ring->dmabase = dmaaddr;
|
||||
return 0;
|
||||
}
|
||||
/* Force-align it to 8k */
|
||||
ring->descbase = (void *)((u8 *)base + 0x1000);
|
||||
ring->dmabase = dmaaddr + 0x1000;
|
||||
B43_WARN_ON(!is_8k_aligned(ring->dmabase));
|
||||
memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_ringmemory(struct b43_dmaring *ring)
|
||||
{
|
||||
b43_unmap_and_free_ringmem(ring, ring->alloc_descbase,
|
||||
ring->alloc_dmabase, ring->alloc_descsize);
|
||||
gfp_t flags = GFP_KERNEL;
|
||||
|
||||
if (ring->type == B43_DMA_64BIT)
|
||||
flags |= GFP_DMA;
|
||||
|
||||
ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE,
|
||||
ring->descbase, ring->dmabase, flags);
|
||||
}
|
||||
|
||||
/* Reset the RX DMA channel */
|
||||
@ -646,14 +530,29 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
|
||||
if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
|
||||
return 1;
|
||||
|
||||
if (!b43_dma_address_ok(ring, addr, buffersize)) {
|
||||
/* We can't support this address. Unmap it again. */
|
||||
unmap_descbuffer(ring, addr, buffersize, dma_to_device);
|
||||
return 1;
|
||||
switch (ring->type) {
|
||||
case B43_DMA_30BIT:
|
||||
if ((u64)addr + buffersize > (1ULL << 30))
|
||||
goto address_error;
|
||||
break;
|
||||
case B43_DMA_32BIT:
|
||||
if ((u64)addr + buffersize > (1ULL << 32))
|
||||
goto address_error;
|
||||
break;
|
||||
case B43_DMA_64BIT:
|
||||
/* Currently we can't have addresses beyond
|
||||
* 64bit in the kernel. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* The address is OK. */
|
||||
return 0;
|
||||
|
||||
address_error:
|
||||
/* We can't support this address. Unmap it again. */
|
||||
unmap_descbuffer(ring, addr, buffersize, dma_to_device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb)
|
||||
@ -715,9 +614,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
|
||||
meta->dmaaddr = dmaaddr;
|
||||
ring->ops->fill_descriptor(ring, desc, dmaaddr,
|
||||
ring->rx_buffersize, 0, 0, 0);
|
||||
ssb_dma_sync_single_for_device(ring->dev->dev,
|
||||
ring->alloc_dmabase,
|
||||
ring->alloc_descsize, DMA_TO_DEVICE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1354,9 +1250,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
}
|
||||
/* Now transfer the whole frame. */
|
||||
wmb();
|
||||
ssb_dma_sync_single_for_device(ring->dev->dev,
|
||||
ring->alloc_dmabase,
|
||||
ring->alloc_descsize, DMA_TO_DEVICE);
|
||||
ops->poke_tx(ring, next_slot(ring, slot));
|
||||
return 0;
|
||||
|
||||
@ -1760,7 +1653,6 @@ void b43_dma_tx_resume(struct b43_wldev *dev)
|
||||
b43_power_saving_ctl_bits(dev, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_B43_PIO
|
||||
static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
|
||||
u16 mmio_base, bool enable)
|
||||
{
|
||||
@ -1794,4 +1686,3 @@ void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
|
||||
mmio_base = b43_dmacontroller_base(type, engine_index);
|
||||
direct_fifo_rx(dev, type, mmio_base, enable);
|
||||
}
|
||||
#endif /* CONFIG_B43_PIO */
|
||||
|
@ -157,6 +157,7 @@ struct b43_dmadesc_generic {
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* Misc DMA constants */
|
||||
#define B43_DMA_RINGMEMSIZE PAGE_SIZE
|
||||
#define B43_DMA0_RX_FRAMEOFFSET 30
|
||||
|
||||
/* DMA engine tuning knobs */
|
||||
@ -246,12 +247,6 @@ struct b43_dmaring {
|
||||
/* The QOS priority assigned to this ring. Only used for TX rings.
|
||||
* This is the mac80211 "queue" value. */
|
||||
u8 queue_prio;
|
||||
/* Pointers and size of the originally allocated and mapped memory
|
||||
* region for the descriptor ring. */
|
||||
void *alloc_descbase;
|
||||
dma_addr_t alloc_dmabase;
|
||||
unsigned int alloc_descsize;
|
||||
/* Pointer to our wireless device. */
|
||||
struct b43_wldev *dev;
|
||||
#ifdef CONFIG_B43_DEBUG
|
||||
/* Maximum number of used slots. */
|
||||
|
@ -102,6 +102,9 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
|
||||
module_param_named(verbose, b43_modparam_verbose, int, 0644);
|
||||
MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
|
||||
|
||||
static int modparam_pio;
|
||||
module_param_named(pio, modparam_pio, int, 0444);
|
||||
MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
|
||||
|
||||
static const struct ssb_device_id b43_ssb_tbl[] = {
|
||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
|
||||
@ -1786,8 +1789,8 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
|
||||
dma_reason[4], dma_reason[5]);
|
||||
b43err(dev->wl, "This device does not support DMA "
|
||||
"on your system. Please use PIO instead.\n");
|
||||
b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in "
|
||||
"your kernel configuration.\n");
|
||||
b43err(dev->wl, "Unload the b43 module and reload "
|
||||
"with 'pio=1'\n");
|
||||
return;
|
||||
}
|
||||
if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
|
||||
@ -4353,7 +4356,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
|
||||
|
||||
if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
|
||||
(dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
|
||||
B43_FORCE_PIO) {
|
||||
modparam_pio) {
|
||||
dev->__using_pio_transfers = 1;
|
||||
err = b43_pio_init(dev);
|
||||
} else {
|
||||
@ -4388,7 +4391,7 @@ err_busdown:
|
||||
}
|
||||
|
||||
static int b43_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev;
|
||||
@ -4396,24 +4399,24 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
/* TODO: allow WDS/AP devices to coexist */
|
||||
|
||||
if (conf->type != NL80211_IFTYPE_AP &&
|
||||
conf->type != NL80211_IFTYPE_MESH_POINT &&
|
||||
conf->type != NL80211_IFTYPE_STATION &&
|
||||
conf->type != NL80211_IFTYPE_WDS &&
|
||||
conf->type != NL80211_IFTYPE_ADHOC)
|
||||
if (vif->type != NL80211_IFTYPE_AP &&
|
||||
vif->type != NL80211_IFTYPE_MESH_POINT &&
|
||||
vif->type != NL80211_IFTYPE_STATION &&
|
||||
vif->type != NL80211_IFTYPE_WDS &&
|
||||
vif->type != NL80211_IFTYPE_ADHOC)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (wl->operating)
|
||||
goto out_mutex_unlock;
|
||||
|
||||
b43dbg(wl, "Adding Interface type %d\n", conf->type);
|
||||
b43dbg(wl, "Adding Interface type %d\n", vif->type);
|
||||
|
||||
dev = wl->current_dev;
|
||||
wl->operating = 1;
|
||||
wl->vif = conf->vif;
|
||||
wl->if_type = conf->type;
|
||||
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
|
||||
wl->vif = vif;
|
||||
wl->if_type = vif->type;
|
||||
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
|
||||
|
||||
b43_adjust_opmode(dev);
|
||||
b43_set_pretbtt(dev);
|
||||
@ -4428,17 +4431,17 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
static void b43_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev = wl->current_dev;
|
||||
|
||||
b43dbg(wl, "Removing Interface type %d\n", conf->type);
|
||||
b43dbg(wl, "Removing Interface type %d\n", vif->type);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
B43_WARN_ON(!wl->operating);
|
||||
B43_WARN_ON(wl->vif != conf->vif);
|
||||
B43_WARN_ON(wl->vif != vif);
|
||||
wl->vif = NULL;
|
||||
|
||||
wl->operating = 0;
|
||||
|
@ -55,8 +55,6 @@
|
||||
#define B43_PIO_MAX_NR_TXPACKETS 32
|
||||
|
||||
|
||||
#ifdef CONFIG_B43_PIO
|
||||
|
||||
struct b43_pio_txpacket {
|
||||
/* Pointer to the TX queue we belong to. */
|
||||
struct b43_pio_txqueue *queue;
|
||||
@ -169,42 +167,4 @@ void b43_pio_rx(struct b43_pio_rxqueue *q);
|
||||
void b43_pio_tx_suspend(struct b43_wldev *dev);
|
||||
void b43_pio_tx_resume(struct b43_wldev *dev);
|
||||
|
||||
|
||||
#else /* CONFIG_B43_PIO */
|
||||
|
||||
|
||||
static inline int b43_pio_init(struct b43_wldev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void b43_pio_free(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline void b43_pio_stop(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline int b43_pio_tx(struct b43_wldev *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
|
||||
const struct b43_txstatus *status)
|
||||
{
|
||||
}
|
||||
static inline void b43_pio_get_tx_stats(struct b43_wldev *dev,
|
||||
struct ieee80211_tx_queue_stats *stats)
|
||||
{
|
||||
}
|
||||
static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
|
||||
{
|
||||
}
|
||||
static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline void b43_pio_tx_resume(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_B43_PIO */
|
||||
#endif /* B43_PIO_H_ */
|
||||
|
@ -3361,7 +3361,7 @@ err_kfree_lo_control:
|
||||
}
|
||||
|
||||
static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
|
||||
struct b43legacy_wldev *dev;
|
||||
@ -3370,23 +3370,23 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
/* TODO: allow WDS/AP devices to coexist */
|
||||
|
||||
if (conf->type != NL80211_IFTYPE_AP &&
|
||||
conf->type != NL80211_IFTYPE_STATION &&
|
||||
conf->type != NL80211_IFTYPE_WDS &&
|
||||
conf->type != NL80211_IFTYPE_ADHOC)
|
||||
if (vif->type != NL80211_IFTYPE_AP &&
|
||||
vif->type != NL80211_IFTYPE_STATION &&
|
||||
vif->type != NL80211_IFTYPE_WDS &&
|
||||
vif->type != NL80211_IFTYPE_ADHOC)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (wl->operating)
|
||||
goto out_mutex_unlock;
|
||||
|
||||
b43legacydbg(wl, "Adding Interface type %d\n", conf->type);
|
||||
b43legacydbg(wl, "Adding Interface type %d\n", vif->type);
|
||||
|
||||
dev = wl->current_dev;
|
||||
wl->operating = 1;
|
||||
wl->vif = conf->vif;
|
||||
wl->if_type = conf->type;
|
||||
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
|
||||
wl->vif = vif;
|
||||
wl->if_type = vif->type;
|
||||
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
|
||||
|
||||
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||
b43legacy_adjust_opmode(dev);
|
||||
@ -3403,18 +3403,18 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
static void b43legacy_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
|
||||
struct b43legacy_wldev *dev = wl->current_dev;
|
||||
unsigned long flags;
|
||||
|
||||
b43legacydbg(wl, "Removing Interface type %d\n", conf->type);
|
||||
b43legacydbg(wl, "Removing Interface type %d\n", vif->type);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
B43legacy_WARN_ON(!wl->operating);
|
||||
B43legacy_WARN_ON(wl->vif != conf->vif);
|
||||
B43legacy_WARN_ON(wl->vif != vif);
|
||||
wl->vif = NULL;
|
||||
|
||||
wl->operating = 0;
|
||||
|
@ -681,19 +681,13 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
|
||||
snr = rx_stats_sig_avg / rx_stats_noise_diff;
|
||||
rx_status.noise = rx_status.signal -
|
||||
iwl3945_calc_db_from_ratio(snr);
|
||||
rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal,
|
||||
rx_status.noise);
|
||||
|
||||
/* If noise info not available, calculate signal quality indicator (%)
|
||||
* using just the dBm signal level. */
|
||||
} else {
|
||||
rx_status.noise = priv->last_rx_noise;
|
||||
rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0);
|
||||
}
|
||||
|
||||
|
||||
IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n",
|
||||
rx_status.signal, rx_status.noise, rx_status.qual,
|
||||
IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n",
|
||||
rx_status.signal, rx_status.noise,
|
||||
rx_stats_sig_avg, rx_stats_noise_diff);
|
||||
|
||||
header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
|
||||
|
@ -222,7 +222,6 @@ struct iwl3945_ibss_seq {
|
||||
*
|
||||
*****************************************************************************/
|
||||
extern int iwl3945_calc_db_from_ratio(int sig_ratio);
|
||||
extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm);
|
||||
extern void iwl3945_rx_replenish(void *data);
|
||||
extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
|
||||
extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
|
||||
|
@ -150,7 +150,7 @@ static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
|
||||
};
|
||||
|
||||
/* mbps, mcs */
|
||||
const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
|
||||
static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
|
||||
{ "1", "BPSK DSSS"},
|
||||
{ "2", "QPSK DSSS"},
|
||||
{"5.5", "BPSK CCK"},
|
||||
|
@ -2584,12 +2584,12 @@ int iwl_set_mode(struct iwl_priv *priv, int mode)
|
||||
EXPORT_SYMBOL(iwl_set_mode);
|
||||
|
||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
unsigned long flags;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
|
||||
IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type);
|
||||
|
||||
if (priv->vif) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
|
||||
@ -2597,19 +2597,19 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->vif = conf->vif;
|
||||
priv->iw_mode = conf->type;
|
||||
priv->vif = vif;
|
||||
priv->iw_mode = vif->type;
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (conf->mac_addr) {
|
||||
IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr);
|
||||
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
|
||||
if (vif->addr) {
|
||||
IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
|
||||
memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
if (iwl_set_mode(priv, conf->type) == -EAGAIN)
|
||||
if (iwl_set_mode(priv, vif->type) == -EAGAIN)
|
||||
/* we are not ready, will run again when ready */
|
||||
set_bit(STATUS_MODE_PENDING, &priv->status);
|
||||
|
||||
@ -2621,7 +2621,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
EXPORT_SYMBOL(iwl_mac_add_interface);
|
||||
|
||||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
||||
@ -2634,7 +2634,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
}
|
||||
if (priv->vif == conf->vif) {
|
||||
if (priv->vif == vif) {
|
||||
priv->vif = NULL;
|
||||
memset(priv->bssid, 0, ETH_ALEN);
|
||||
}
|
||||
|
@ -332,9 +332,9 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int iwl_commit_rxon(struct iwl_priv *priv);
|
||||
int iwl_set_mode(struct iwl_priv *priv, int mode);
|
||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void iwl_config_ap(struct iwl_priv *priv);
|
||||
int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
|
||||
|
@ -650,47 +650,6 @@ void iwl_reply_statistics(struct iwl_priv *priv,
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_reply_statistics);
|
||||
|
||||
#define PERFECT_RSSI (-20) /* dBm */
|
||||
#define WORST_RSSI (-95) /* dBm */
|
||||
#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
|
||||
|
||||
/* Calculate an indication of rx signal quality (a percentage, not dBm!).
|
||||
* See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
|
||||
* about formulas used below. */
|
||||
static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
|
||||
{
|
||||
int sig_qual;
|
||||
int degradation = PERFECT_RSSI - rssi_dbm;
|
||||
|
||||
/* If we get a noise measurement, use signal-to-noise ratio (SNR)
|
||||
* as indicator; formula is (signal dbm - noise dbm).
|
||||
* SNR at or above 40 is a great signal (100%).
|
||||
* Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
|
||||
* Weakest usable signal is usually 10 - 15 dB SNR. */
|
||||
if (noise_dbm) {
|
||||
if (rssi_dbm - noise_dbm >= 40)
|
||||
return 100;
|
||||
else if (rssi_dbm < noise_dbm)
|
||||
return 0;
|
||||
sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
|
||||
|
||||
/* Else use just the signal level.
|
||||
* This formula is a least squares fit of data points collected and
|
||||
* compared with a reference system that had a percentage (%) display
|
||||
* for signal quality. */
|
||||
} else
|
||||
sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
|
||||
(15 * RSSI_RANGE + 62 * degradation)) /
|
||||
(RSSI_RANGE * RSSI_RANGE);
|
||||
|
||||
if (sig_qual > 100)
|
||||
sig_qual = 100;
|
||||
else if (sig_qual < 1)
|
||||
sig_qual = 0;
|
||||
|
||||
return sig_qual;
|
||||
}
|
||||
|
||||
/* Calc max signal level (dBm) among 3 possible receivers */
|
||||
static inline int iwl_calc_rssi(struct iwl_priv *priv,
|
||||
struct iwl_rx_phy_res *rx_resp)
|
||||
@ -1101,11 +1060,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
if (iwl_is_associated(priv) &&
|
||||
!test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
rx_status.noise = priv->last_rx_noise;
|
||||
rx_status.qual = iwl_calc_sig_qual(rx_status.signal,
|
||||
rx_status.noise);
|
||||
} else {
|
||||
rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
|
||||
rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0);
|
||||
}
|
||||
|
||||
/* Reset beacon noise level if not associated. */
|
||||
@ -1118,8 +1074,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
iwl_dbg_report_frame(priv, phy_res, len, header, 1);
|
||||
#endif
|
||||
iwl_dbg_log_rx_data_frame(priv, len, header);
|
||||
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
|
||||
rx_status.signal, rx_status.noise, rx_status.qual,
|
||||
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n",
|
||||
rx_status.signal, rx_status.noise,
|
||||
(unsigned long long)rx_status.mactime);
|
||||
|
||||
/*
|
||||
|
@ -1299,47 +1299,6 @@ int iwl3945_calc_db_from_ratio(int sig_ratio)
|
||||
return (int)ratio2dB[sig_ratio];
|
||||
}
|
||||
|
||||
#define PERFECT_RSSI (-20) /* dBm */
|
||||
#define WORST_RSSI (-95) /* dBm */
|
||||
#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
|
||||
|
||||
/* Calculate an indication of rx signal quality (a percentage, not dBm!).
|
||||
* See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
|
||||
* about formulas used below. */
|
||||
int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm)
|
||||
{
|
||||
int sig_qual;
|
||||
int degradation = PERFECT_RSSI - rssi_dbm;
|
||||
|
||||
/* If we get a noise measurement, use signal-to-noise ratio (SNR)
|
||||
* as indicator; formula is (signal dbm - noise dbm).
|
||||
* SNR at or above 40 is a great signal (100%).
|
||||
* Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
|
||||
* Weakest usable signal is usually 10 - 15 dB SNR. */
|
||||
if (noise_dbm) {
|
||||
if (rssi_dbm - noise_dbm >= 40)
|
||||
return 100;
|
||||
else if (rssi_dbm < noise_dbm)
|
||||
return 0;
|
||||
sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
|
||||
|
||||
/* Else use just the signal level.
|
||||
* This formula is a least squares fit of data points collected and
|
||||
* compared with a reference system that had a percentage (%) display
|
||||
* for signal quality. */
|
||||
} else
|
||||
sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
|
||||
(15 * RSSI_RANGE + 62 * degradation)) /
|
||||
(RSSI_RANGE * RSSI_RANGE);
|
||||
|
||||
if (sig_qual > 100)
|
||||
sig_qual = 100;
|
||||
else if (sig_qual < 1)
|
||||
sig_qual = 0;
|
||||
|
||||
return sig_qual;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl3945_rx_handle - Main entry function for receiving responses from uCode
|
||||
*
|
||||
|
@ -268,7 +268,7 @@ struct iwm_priv {
|
||||
|
||||
struct sk_buff_head rx_list;
|
||||
struct list_head rx_tickets;
|
||||
struct list_head rx_packets[IWM_RX_ID_HASH];
|
||||
struct list_head rx_packets[IWM_RX_ID_HASH + 1];
|
||||
struct workqueue_struct *rx_wq;
|
||||
struct work_struct rx_worker;
|
||||
|
||||
|
@ -567,11 +567,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan)
|
||||
chan_count = lbs_scan_create_channel_list(priv, chan_list);
|
||||
|
||||
netif_stop_queue(priv->dev);
|
||||
netif_carrier_off(priv->dev);
|
||||
if (priv->mesh_dev) {
|
||||
if (priv->mesh_dev)
|
||||
netif_stop_queue(priv->mesh_dev);
|
||||
netif_carrier_off(priv->mesh_dev);
|
||||
}
|
||||
|
||||
/* Prepare to continue an interrupted scan */
|
||||
lbs_deb_scan("chan_count %d, scan_channel %d\n",
|
||||
@ -635,16 +632,13 @@ out2:
|
||||
priv->scan_channel = 0;
|
||||
|
||||
out:
|
||||
if (priv->connect_status == LBS_CONNECTED) {
|
||||
netif_carrier_on(priv->dev);
|
||||
if (!priv->tx_pending_len)
|
||||
netif_wake_queue(priv->dev);
|
||||
}
|
||||
if (priv->mesh_dev && lbs_mesh_connected(priv)) {
|
||||
netif_carrier_on(priv->mesh_dev);
|
||||
if (!priv->tx_pending_len)
|
||||
netif_wake_queue(priv->mesh_dev);
|
||||
}
|
||||
if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
|
||||
netif_wake_queue(priv->dev);
|
||||
|
||||
if (priv->mesh_dev && lbs_mesh_connected(priv) &&
|
||||
!priv->tx_pending_len)
|
||||
netif_wake_queue(priv->mesh_dev);
|
||||
|
||||
kfree(chan_list);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
|
||||
|
@ -318,14 +318,14 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
static int lbtf_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
if (priv->vif != NULL)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
priv->vif = conf->vif;
|
||||
switch (conf->type) {
|
||||
priv->vif = vif;
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
lbtf_set_mode(priv, LBTF_AP_MODE);
|
||||
@ -337,12 +337,12 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,
|
||||
priv->vif = NULL;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
lbtf_set_mac_address(priv, (u8 *) conf->mac_addr);
|
||||
lbtf_set_mac_address(priv, (u8 *) vif->addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
|
||||
@ -495,7 +495,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
|
||||
stats.band = IEEE80211_BAND_2GHZ;
|
||||
stats.signal = prxpd->snr;
|
||||
stats.noise = prxpd->nf;
|
||||
stats.qual = prxpd->snr - prxpd->nf;
|
||||
/* Marvell rate index has a hole at value 4 */
|
||||
if (prxpd->rx_rate > 4)
|
||||
--prxpd->rx_rate;
|
||||
|
@ -584,24 +584,24 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
|
||||
|
||||
|
||||
static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
|
||||
wiphy_name(hw->wiphy), __func__, conf->type,
|
||||
conf->mac_addr);
|
||||
hwsim_set_magic(conf->vif);
|
||||
wiphy_name(hw->wiphy), __func__, vif->type,
|
||||
vif->addr);
|
||||
hwsim_set_magic(vif);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void mac80211_hwsim_remove_interface(
|
||||
struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
|
||||
wiphy_name(hw->wiphy), __func__, conf->type,
|
||||
conf->mac_addr);
|
||||
hwsim_check_magic(conf->vif);
|
||||
hwsim_clear_magic(conf->vif);
|
||||
wiphy_name(hw->wiphy), __func__, vif->type,
|
||||
vif->addr);
|
||||
hwsim_check_magic(vif);
|
||||
hwsim_clear_magic(vif);
|
||||
}
|
||||
|
||||
|
||||
@ -896,6 +896,16 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
|
||||
{
|
||||
/*
|
||||
* In this special case, there's nothing we need to
|
||||
* do because hwsim does transmission synchronously.
|
||||
* In the future, when it does transmissions via
|
||||
* userspace, we may need to do something.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static const struct ieee80211_ops mac80211_hwsim_ops =
|
||||
{
|
||||
@ -912,6 +922,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
|
||||
.conf_tx = mac80211_hwsim_conf_tx,
|
||||
CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
|
||||
.ampdu_action = mac80211_hwsim_ampdu_action,
|
||||
.flush = mac80211_hwsim_flush,
|
||||
};
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,7 @@
|
||||
#define MAX_RID_LEN 1024
|
||||
|
||||
/* Helper routine to record keys
|
||||
* Do not call from interrupt context */
|
||||
* It is called under orinoco_lock so it may not sleep */
|
||||
static int orinoco_set_key(struct orinoco_private *priv, int index,
|
||||
enum orinoco_alg alg, const u8 *key, int key_len,
|
||||
const u8 *seq, int seq_len)
|
||||
@ -32,14 +32,14 @@ static int orinoco_set_key(struct orinoco_private *priv, int index,
|
||||
kzfree(priv->keys[index].seq);
|
||||
|
||||
if (key_len) {
|
||||
priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
|
||||
priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
|
||||
if (!priv->keys[index].key)
|
||||
goto nomem;
|
||||
} else
|
||||
priv->keys[index].key = NULL;
|
||||
|
||||
if (seq_len) {
|
||||
priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
|
||||
priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
|
||||
if (!priv->keys[index].seq)
|
||||
goto free_key;
|
||||
} else
|
||||
|
@ -216,7 +216,7 @@ static void p54_stop(struct ieee80211_hw *dev)
|
||||
}
|
||||
|
||||
static int p54_add_interface(struct ieee80211_hw *dev,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
|
||||
@ -226,28 +226,28 @@ static int p54_add_interface(struct ieee80211_hw *dev,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
priv->vif = conf->vif;
|
||||
priv->vif = vif;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
priv->mode = conf->type;
|
||||
priv->mode = vif->type;
|
||||
break;
|
||||
default:
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
|
||||
memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
|
||||
p54_setup_mac(priv);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void p54_remove_interface(struct ieee80211_hw *dev,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
|
||||
|
@ -54,12 +54,12 @@ config RT61PCI
|
||||
When compiled as a module, this driver will be called rt61pci.
|
||||
|
||||
config RT2800PCI_PCI
|
||||
tristate
|
||||
boolean
|
||||
depends on PCI
|
||||
default y
|
||||
|
||||
config RT2800PCI_SOC
|
||||
tristate
|
||||
boolean
|
||||
depends on RALINK_RT288X || RALINK_RT305X
|
||||
default y
|
||||
|
||||
|
@ -451,7 +451,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* RF2420 chipset don't need any additional actions.
|
||||
*/
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2420))
|
||||
if (rt2x00_rf(rt2x00dev, RF2420))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -1343,8 +1343,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2421)) {
|
||||
if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -440,8 +440,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* RT2525E and RT5222 need to flip TX I/Q
|
||||
*/
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
||||
if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
|
||||
rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
|
||||
rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1);
|
||||
rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1);
|
||||
@ -449,7 +448,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* RT2525E does not need RX I/Q Flip.
|
||||
*/
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525E))
|
||||
if (rt2x00_rf(rt2x00dev, RF2525E))
|
||||
rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
|
||||
} else {
|
||||
rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0);
|
||||
@ -475,14 +474,14 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
* Switch on tuning bits.
|
||||
* For RT2523 devices we do not need to update the R1 register.
|
||||
*/
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2523))
|
||||
if (!rt2x00_rf(rt2x00dev, RF2523))
|
||||
rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
|
||||
rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
|
||||
|
||||
/*
|
||||
* For RT2525 we should first set the channel to half band higher.
|
||||
*/
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525)) {
|
||||
if (rt2x00_rf(rt2x00dev, RF2525)) {
|
||||
static const u32 vals[] = {
|
||||
0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a,
|
||||
0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a,
|
||||
@ -516,7 +515,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
* Switch off tuning bits.
|
||||
* For RT2523 devices we do not need to update the R1 register.
|
||||
*/
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) {
|
||||
if (!rt2x00_rf(rt2x00dev, RF2523)) {
|
||||
rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
|
||||
rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
|
||||
}
|
||||
@ -640,7 +639,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
|
||||
* up to version C the link tuning should halt after 20
|
||||
* seconds while being associated.
|
||||
*/
|
||||
if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
|
||||
if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D &&
|
||||
rt2x00dev->intf_associated && count > 20)
|
||||
return;
|
||||
|
||||
@ -650,7 +649,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
|
||||
* should go straight to dynamic CCA tuning when they
|
||||
* are not associated.
|
||||
*/
|
||||
if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D ||
|
||||
if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D ||
|
||||
!rt2x00dev->intf_associated)
|
||||
goto dynamic_cca_tune;
|
||||
|
||||
@ -1507,12 +1506,12 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2523) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2524) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2525) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2525E) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
||||
if (!rt2x00_rf(rt2x00dev, RF2522) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2523) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2524) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2525) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2525E) &&
|
||||
!rt2x00_rf(rt2x00dev, RF5222)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -1744,22 +1743,22 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2522)) {
|
||||
if (rt2x00_rf(rt2x00dev, RF2522)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
|
||||
spec->channels = rf_vals_bg_2522;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2523)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
|
||||
spec->channels = rf_vals_bg_2523;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2524)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
|
||||
spec->channels = rf_vals_bg_2524;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2525)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
|
||||
spec->channels = rf_vals_bg_2525;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2525E)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
|
||||
spec->channels = rf_vals_bg_2525e;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF5222)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
|
||||
spec->channels = rf_vals_5222;
|
||||
|
@ -565,8 +565,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* RT2525E and RT5222 need to flip TX I/Q
|
||||
*/
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
||||
if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
|
||||
rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
|
||||
rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1);
|
||||
rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1);
|
||||
@ -574,7 +573,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* RT2525E does not need RX I/Q Flip.
|
||||
*/
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525E))
|
||||
if (rt2x00_rf(rt2x00dev, RF2525E))
|
||||
rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
|
||||
} else {
|
||||
rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0);
|
||||
@ -598,7 +597,7 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* For RT2525E we should first set the channel to half band higher.
|
||||
*/
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
|
||||
if (rt2x00_rf(rt2x00dev, RF2525E)) {
|
||||
static const u32 vals[] = {
|
||||
0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
|
||||
0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
|
||||
@ -793,7 +792,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1);
|
||||
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
||||
|
||||
if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
|
||||
if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) {
|
||||
rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®);
|
||||
rt2x00_set_field16(®, PHY_CSR2_LNA, 0);
|
||||
} else {
|
||||
@ -1411,19 +1410,18 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) ||
|
||||
rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
|
||||
|
||||
if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) ||
|
||||
rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2523) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2524) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2525) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2525E) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
||||
if (!rt2x00_rf(rt2x00dev, RF2522) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2523) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2524) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2525) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2525E) &&
|
||||
!rt2x00_rf(rt2x00dev, RF5222)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -1667,22 +1665,22 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2522)) {
|
||||
if (rt2x00_rf(rt2x00dev, RF2522)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
|
||||
spec->channels = rf_vals_bg_2522;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2523)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
|
||||
spec->channels = rf_vals_bg_2523;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2524)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
|
||||
spec->channels = rf_vals_bg_2524;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2525)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
|
||||
spec->channels = rf_vals_bg_2525;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2525E)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
|
||||
spec->channels = rf_vals_bg_2525e;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF5222)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
|
||||
spec->channels = rf_vals_5222;
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE)
|
||||
#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
|
||||
#include "rt2x00usb.h"
|
||||
#endif
|
||||
#include "rt2800lib.h"
|
||||
@ -220,8 +220,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
|
||||
/*
|
||||
* RT2880 and RT3052 don't support MCU requests.
|
||||
*/
|
||||
if (rt2x00_rt(&rt2x00dev->chip, RT2880) ||
|
||||
rt2x00_rt(&rt2x00dev->chip, RT3052))
|
||||
if (rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT3052))
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
@ -806,12 +805,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
unsigned int tx_pin;
|
||||
u8 bbp;
|
||||
|
||||
if ((rt2x00_rt(&rt2x00dev->chip, RT3070) ||
|
||||
rt2x00_rt(&rt2x00dev->chip, RT3090)) &&
|
||||
(rt2x00_rf(&rt2x00dev->chip, RF2020) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3020) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3021) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF3022)))
|
||||
if ((rt2x00_rt(rt2x00dev, RT3070) ||
|
||||
rt2x00_rt(rt2x00dev, RT3090)) &&
|
||||
(rt2x00_rf(rt2x00dev, RF2020) ||
|
||||
rt2x00_rf(rt2x00dev, RF3020) ||
|
||||
rt2x00_rf(rt2x00dev, RF3021) ||
|
||||
rt2x00_rf(rt2x00dev, RF3022)))
|
||||
rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
|
||||
else
|
||||
rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
|
||||
@ -878,7 +877,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
|
||||
rt2800_bbp_write(rt2x00dev, 3, bbp);
|
||||
|
||||
if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
|
||||
if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) {
|
||||
if (conf_is_ht40(conf)) {
|
||||
rt2800_bbp_write(rt2x00dev, 69, 0x1a);
|
||||
rt2800_bbp_write(rt2x00dev, 70, 0x0a);
|
||||
@ -1041,7 +1040,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
|
||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||
rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION)
|
||||
rt2x00_rev(rt2x00dev) == RT3070_VERSION)
|
||||
return 0x1c + (2 * rt2x00dev->lna_gain);
|
||||
else
|
||||
return 0x2e + rt2x00dev->lna_gain;
|
||||
@ -1072,7 +1071,7 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner);
|
||||
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
|
||||
const u32 count)
|
||||
{
|
||||
if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION)
|
||||
if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -1121,7 +1120,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
|
||||
#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE)
|
||||
#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
|
||||
rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
|
||||
USB_MODE_RESET, REGISTER_TIMEOUT);
|
||||
#endif
|
||||
@ -1158,7 +1157,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||
rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
|
||||
rt2x00_rev(rt2x00dev) == RT3070_VERSION) {
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
|
||||
@ -1185,8 +1184,8 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®);
|
||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
|
||||
if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION &&
|
||||
rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION)
|
||||
if (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION &&
|
||||
rt2x00_rev(rt2x00dev) < RT3070_VERSION)
|
||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2);
|
||||
else
|
||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1);
|
||||
@ -1465,22 +1464,22 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_bbp_write(rt2x00dev, 103, 0x00);
|
||||
rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
||||
|
||||
if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
|
||||
if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) {
|
||||
rt2800_bbp_write(rt2x00dev, 69, 0x16);
|
||||
rt2800_bbp_write(rt2x00dev, 73, 0x12);
|
||||
}
|
||||
|
||||
if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION)
|
||||
if (rt2x00_rev(rt2x00dev) > RT2860D_VERSION)
|
||||
rt2800_bbp_write(rt2x00dev, 84, 0x19);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||
rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
|
||||
rt2x00_rev(rt2x00dev) == RT3070_VERSION) {
|
||||
rt2800_bbp_write(rt2x00dev, 70, 0x0a);
|
||||
rt2800_bbp_write(rt2x00dev, 84, 0x99);
|
||||
rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
||||
}
|
||||
|
||||
if (rt2x00_rt(&rt2x00dev->chip, RT3052)) {
|
||||
if (rt2x00_rt(rt2x00dev, RT3052)) {
|
||||
rt2800_bbp_write(rt2x00dev, 31, 0x08);
|
||||
rt2800_bbp_write(rt2x00dev, 78, 0x0e);
|
||||
rt2800_bbp_write(rt2x00dev, 80, 0x08);
|
||||
@ -1566,13 +1565,13 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||||
u8 bbp;
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||
rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
|
||||
rt2x00_rev(rt2x00dev) != RT3070_VERSION)
|
||||
return 0;
|
||||
|
||||
if (rt2x00_intf_is_pci(rt2x00dev)) {
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3021) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3022))
|
||||
if (!rt2x00_rf(rt2x00dev, RF3020) &&
|
||||
!rt2x00_rf(rt2x00dev, RF3021) &&
|
||||
!rt2x00_rf(rt2x00dev, RF3022))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1737,7 +1736,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
|
||||
} else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
|
||||
} else if (rt2x00_rev(rt2x00dev) < RT2883_VERSION) {
|
||||
/*
|
||||
* There is a max of 2 RX streams for RT28x0 series
|
||||
*/
|
||||
@ -1839,17 +1838,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
struct rt2x00_chip *chip = &rt2x00dev->chip;
|
||||
|
||||
/*
|
||||
* The check for rt2860 is not a typo, some rt2870 hardware
|
||||
* identifies itself as rt2860 in the CSR register.
|
||||
*/
|
||||
if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) ||
|
||||
rt2x00_check_rev(chip, 0xfff00000, 0x28700000) ||
|
||||
rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) {
|
||||
if (rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28600000) ||
|
||||
rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28700000) ||
|
||||
rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28800000)) {
|
||||
rt2x00_set_chip_rt(rt2x00dev, RT2870);
|
||||
} else if (rt2x00_check_rev(chip, 0xffff0000, 0x30700000)) {
|
||||
} else if (rt2x00_check_rev(rt2x00dev, 0xffff0000, 0x30700000)) {
|
||||
rt2x00_set_chip_rt(rt2x00dev, RT3070);
|
||||
} else {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
@ -1858,14 +1855,14 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
}
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2850) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2720) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2750) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2020) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3021) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF3022)) {
|
||||
if (!rt2x00_rf(rt2x00dev, RF2820) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2850) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2720) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2750) &&
|
||||
!rt2x00_rf(rt2x00dev, RF3020) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2020) &&
|
||||
!rt2x00_rf(rt2x00dev, RF3021) &&
|
||||
!rt2x00_rf(rt2x00dev, RF3022)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -2013,7 +2010,6 @@ static const struct rf_channel rf_vals_302x[] = {
|
||||
|
||||
int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct rt2x00_chip *chip = &rt2x00dev->chip;
|
||||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||
struct channel_info *info;
|
||||
char *tx_power1;
|
||||
@ -2049,19 +2045,19 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
||||
|
||||
if (rt2x00_rf(chip, RF2820) ||
|
||||
rt2x00_rf(chip, RF2720) ||
|
||||
(rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) {
|
||||
if (rt2x00_rf(rt2x00dev, RF2820) ||
|
||||
rt2x00_rf(rt2x00dev, RF2720) ||
|
||||
(rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(rt2x00dev, RF3052))) {
|
||||
spec->num_channels = 14;
|
||||
spec->channels = rf_vals;
|
||||
} else if (rt2x00_rf(chip, RF2850) || rt2x00_rf(chip, RF2750)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals);
|
||||
spec->channels = rf_vals;
|
||||
} else if (rt2x00_rf(chip, RF3020) ||
|
||||
rt2x00_rf(chip, RF2020) ||
|
||||
rt2x00_rf(chip, RF3021) ||
|
||||
rt2x00_rf(chip, RF3022)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF3020) ||
|
||||
rt2x00_rf(rt2x00dev, RF2020) ||
|
||||
rt2x00_rf(rt2x00dev, RF3021) ||
|
||||
rt2x00_rf(rt2x00dev, RF3022)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_302x);
|
||||
spec->channels = rf_vals_302x;
|
||||
}
|
||||
@ -2069,7 +2065,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Initialize HT information.
|
||||
*/
|
||||
if (!rt2x00_rf(chip, RF2020))
|
||||
if (!rt2x00_rf(rt2x00dev, RF2020))
|
||||
spec->ht.ht_supported = true;
|
||||
else
|
||||
spec->ht.ht_supported = false;
|
||||
|
@ -48,14 +48,6 @@
|
||||
#include "rt2800.h"
|
||||
#include "rt2800pci.h"
|
||||
|
||||
#ifdef CONFIG_RT2800PCI_PCI_MODULE
|
||||
#define CONFIG_RT2800PCI_PCI
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RT2800PCI_WISOC_MODULE
|
||||
#define CONFIG_RT2800PCI_WISOC
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allow hardware encryption to be disabled.
|
||||
*/
|
||||
@ -87,7 +79,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
|
||||
rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RT2800PCI_WISOC
|
||||
#ifdef CONFIG_RT2800PCI_SOC
|
||||
static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */
|
||||
@ -98,7 +90,7 @@ static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
|
||||
static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_RT2800PCI_WISOC */
|
||||
#endif /* CONFIG_RT2800PCI_SOC */
|
||||
|
||||
#ifdef CONFIG_RT2800PCI_PCI
|
||||
static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
|
||||
@ -1129,8 +1121,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* This device requires firmware.
|
||||
*/
|
||||
if (!rt2x00_rt(&rt2x00dev->chip, RT2880) &&
|
||||
!rt2x00_rt(&rt2x00dev->chip, RT3052))
|
||||
if (!rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT3052))
|
||||
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
|
||||
@ -1251,7 +1242,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
|
||||
#endif /* CONFIG_RT2800PCI_PCI */
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifdef CONFIG_RT2800PCI_WISOC
|
||||
#ifdef CONFIG_RT2800PCI_SOC
|
||||
#if defined(CONFIG_RALINK_RT288X)
|
||||
__rt2x00soc_probe(RT2880, &rt2800pci_ops);
|
||||
#elif defined(CONFIG_RALINK_RT305X)
|
||||
@ -1269,7 +1260,7 @@ static struct platform_driver rt2800soc_driver = {
|
||||
.suspend = rt2x00soc_suspend,
|
||||
.resume = rt2x00soc_resume,
|
||||
};
|
||||
#endif /* CONFIG_RT2800PCI_WISOC */
|
||||
#endif /* CONFIG_RT2800PCI_SOC */
|
||||
|
||||
#ifdef CONFIG_RT2800PCI_PCI
|
||||
static struct pci_driver rt2800pci_driver = {
|
||||
@ -1286,7 +1277,7 @@ static int __init rt2800pci_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_RT2800PCI_WISOC
|
||||
#ifdef CONFIG_RT2800PCI_SOC
|
||||
ret = platform_driver_register(&rt2800soc_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1294,7 +1285,7 @@ static int __init rt2800pci_init(void)
|
||||
#ifdef CONFIG_RT2800PCI_PCI
|
||||
ret = pci_register_driver(&rt2800pci_driver);
|
||||
if (ret) {
|
||||
#ifdef CONFIG_RT2800PCI_WISOC
|
||||
#ifdef CONFIG_RT2800PCI_SOC
|
||||
platform_driver_unregister(&rt2800soc_driver);
|
||||
#endif
|
||||
return ret;
|
||||
@ -1309,7 +1300,7 @@ static void __exit rt2800pci_exit(void)
|
||||
#ifdef CONFIG_RT2800PCI_PCI
|
||||
pci_unregister_driver(&rt2800pci_driver);
|
||||
#endif
|
||||
#ifdef CONFIG_RT2800PCI_WISOC
|
||||
#ifdef CONFIG_RT2800PCI_SOC
|
||||
platform_driver_unregister(&rt2800soc_driver);
|
||||
#endif
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len)
|
||||
static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
const u8 *data, const size_t len)
|
||||
{
|
||||
u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff;
|
||||
u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff;
|
||||
size_t offset = 0;
|
||||
|
||||
/*
|
||||
@ -138,7 +138,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
u32 reg;
|
||||
u32 offset;
|
||||
u32 length;
|
||||
u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff;
|
||||
u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff;
|
||||
|
||||
/*
|
||||
* Check which section of the firmware we need.
|
||||
@ -933,6 +933,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Logitec */
|
||||
{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
|
@ -937,25 +937,25 @@ static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev);
|
||||
}
|
||||
|
||||
static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
|
||||
static inline char rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt)
|
||||
{
|
||||
return (chipset->rt == chip);
|
||||
return (rt2x00dev->chip.rt == rt);
|
||||
}
|
||||
|
||||
static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip)
|
||||
static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
|
||||
{
|
||||
return (chipset->rf == chip);
|
||||
return (rt2x00dev->chip.rf == rf);
|
||||
}
|
||||
|
||||
static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset)
|
||||
static inline u32 rt2x00_rev(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
return chipset->rev;
|
||||
return rt2x00dev->chip.rev;
|
||||
}
|
||||
|
||||
static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset,
|
||||
static inline bool rt2x00_check_rev(struct rt2x00_dev *rt2x00dev,
|
||||
const u32 mask, const u32 rev)
|
||||
{
|
||||
return ((chipset->rev & mask) == rev);
|
||||
return ((rt2x00dev->chip.rev & mask) == rev);
|
||||
}
|
||||
|
||||
static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev,
|
||||
@ -964,20 +964,20 @@ static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00dev->chip.intf = intf;
|
||||
}
|
||||
|
||||
static inline bool rt2x00_intf(const struct rt2x00_chip *chipset,
|
||||
static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev,
|
||||
enum rt2x00_chip_intf intf)
|
||||
{
|
||||
return (chipset->intf == intf);
|
||||
return (rt2x00dev->chip.intf == intf);
|
||||
}
|
||||
|
||||
static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_PCI);
|
||||
return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
|
||||
}
|
||||
|
||||
static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_USB);
|
||||
return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1019,9 +1019,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int rt2x00mac_start(struct ieee80211_hw *hw);
|
||||
void rt2x00mac_stop(struct ieee80211_hw *hw);
|
||||
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
struct ieee80211_vif *vif);
|
||||
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
struct ieee80211_vif *vif);
|
||||
int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
|
@ -187,10 +187,10 @@ void rt2x00mac_stop(struct ieee80211_hw *hw)
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
|
||||
|
||||
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_intf *intf = vif_to_intf(conf->vif);
|
||||
struct rt2x00_intf *intf = vif_to_intf(vif);
|
||||
struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
|
||||
struct queue_entry *entry = NULL;
|
||||
unsigned int i;
|
||||
@ -203,7 +203,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
||||
return -ENODEV;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
/*
|
||||
* We don't support mixed combinations of
|
||||
@ -263,7 +263,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||
* increase interface count and start initialization.
|
||||
*/
|
||||
|
||||
if (conf->type == NL80211_IFTYPE_AP)
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
rt2x00dev->intf_ap_count++;
|
||||
else
|
||||
rt2x00dev->intf_sta_count++;
|
||||
@ -273,16 +273,16 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||
mutex_init(&intf->beacon_skb_mutex);
|
||||
intf->beacon = entry;
|
||||
|
||||
if (conf->type == NL80211_IFTYPE_AP)
|
||||
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
|
||||
memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
memcpy(&intf->bssid, vif->addr, ETH_ALEN);
|
||||
memcpy(&intf->mac, vif->addr, ETH_ALEN);
|
||||
|
||||
/*
|
||||
* The MAC adddress must be configured after the device
|
||||
* has been initialized. Otherwise the device can reset
|
||||
* the MAC registers.
|
||||
*/
|
||||
rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
|
||||
rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL);
|
||||
|
||||
/*
|
||||
* Some filters depend on the current working mode. We can force
|
||||
@ -296,10 +296,10 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
|
||||
|
||||
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_intf *intf = vif_to_intf(conf->vif);
|
||||
struct rt2x00_intf *intf = vif_to_intf(vif);
|
||||
|
||||
/*
|
||||
* Don't allow interfaces to be remove while
|
||||
@ -307,11 +307,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
|
||||
* no interface is present.
|
||||
*/
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
|
||||
(conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
|
||||
(conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
|
||||
(vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
|
||||
(vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
|
||||
return;
|
||||
|
||||
if (conf->type == NL80211_IFTYPE_AP)
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
rt2x00dev->intf_ap_count--;
|
||||
else
|
||||
rt2x00dev->intf_sta_count--;
|
||||
|
@ -637,8 +637,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
|
||||
rt61pci_bbp_read(rt2x00dev, 4, &r4);
|
||||
rt61pci_bbp_read(rt2x00dev, 77, &r77);
|
||||
|
||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
|
||||
rt2x00_rf(&rt2x00dev->chip, RF5325));
|
||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325));
|
||||
|
||||
/*
|
||||
* Configure the RX antenna.
|
||||
@ -684,8 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
|
||||
rt61pci_bbp_read(rt2x00dev, 4, &r4);
|
||||
rt61pci_bbp_read(rt2x00dev, 77, &r77);
|
||||
|
||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2529));
|
||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
|
||||
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
|
||||
!test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
|
||||
|
||||
@ -833,12 +831,11 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF5325))
|
||||
if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))
|
||||
rt61pci_config_antenna_5x(rt2x00dev, ant);
|
||||
else if (rt2x00_rf(&rt2x00dev->chip, RF2527))
|
||||
else if (rt2x00_rf(rt2x00dev, RF2527))
|
||||
rt61pci_config_antenna_2x(rt2x00dev, ant);
|
||||
else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) {
|
||||
else if (rt2x00_rf(rt2x00dev, RF2529)) {
|
||||
if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
|
||||
rt61pci_config_antenna_2x(rt2x00dev, ant);
|
||||
else
|
||||
@ -879,8 +876,7 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
|
||||
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
|
||||
|
||||
smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2527));
|
||||
smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
|
||||
|
||||
rt61pci_bbp_read(rt2x00dev, 3, &r3);
|
||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
|
||||
@ -2302,10 +2298,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF5325) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2527) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2529)) {
|
||||
if (!rt2x00_rf(rt2x00dev, RF5225) &&
|
||||
!rt2x00_rf(rt2x00dev, RF5325) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2527) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2529)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -2360,7 +2356,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
* the antenna settings should be gathered from the NIC
|
||||
* eeprom word.
|
||||
*/
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2529) &&
|
||||
if (rt2x00_rf(rt2x00dev, RF2529) &&
|
||||
!test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
|
||||
rt2x00dev->default_ant.rx =
|
||||
ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
|
||||
@ -2571,8 +2567,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
spec->channels = rf_vals_seq;
|
||||
}
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF5325)) {
|
||||
if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_seq);
|
||||
}
|
||||
|
@ -136,8 +136,8 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
|
||||
* all others contain 20 bits.
|
||||
*/
|
||||
rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS,
|
||||
20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2527)));
|
||||
20 + (rt2x00_rf(rt2x00dev, RF5225) ||
|
||||
rt2x00_rf(rt2x00dev, RF2527)));
|
||||
rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
|
||||
rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
|
||||
|
||||
@ -741,11 +741,9 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF5226) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF5225))
|
||||
if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225))
|
||||
rt73usb_config_antenna_5x(rt2x00dev, ant);
|
||||
else if (rt2x00_rf(&rt2x00dev->chip, RF2528) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2527))
|
||||
else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527))
|
||||
rt73usb_config_antenna_2x(rt2x00dev, ant);
|
||||
}
|
||||
|
||||
@ -779,8 +777,7 @@ static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
|
||||
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
|
||||
|
||||
smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2527));
|
||||
smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
|
||||
|
||||
rt73usb_bbp_read(rt2x00dev, 3, &r3);
|
||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
|
||||
@ -1210,8 +1207,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
|
||||
|
||||
reg = 0x000023b0;
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
||||
rt2x00_rf(&rt2x00dev->chip, RF2527))
|
||||
if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527))
|
||||
rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1);
|
||||
rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
|
||||
|
||||
@ -1827,16 +1823,16 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) ||
|
||||
rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
|
||||
if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) ||
|
||||
rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!rt2x00_rf(&rt2x00dev->chip, RF5226) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2528) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
|
||||
!rt2x00_rf(&rt2x00dev->chip, RF2527)) {
|
||||
if (!rt2x00_rf(rt2x00dev, RF5226) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2528) &&
|
||||
!rt2x00_rf(rt2x00dev, RF5225) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2527)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -2081,17 +2077,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
||||
|
||||
if (rt2x00_rf(&rt2x00dev->chip, RF2528)) {
|
||||
if (rt2x00_rf(rt2x00dev, RF2528)) {
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
|
||||
spec->channels = rf_vals_bg_2528;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF5226)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_5226);
|
||||
spec->channels = rf_vals_5226;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF2527)) {
|
||||
spec->num_channels = 14;
|
||||
spec->channels = rf_vals_5225_2527;
|
||||
} else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
|
||||
} else if (rt2x00_rf(rt2x00dev, RF5225)) {
|
||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||
spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
|
||||
spec->channels = rf_vals_5225_2527;
|
||||
|
@ -60,7 +60,6 @@ struct rtl8180_priv {
|
||||
struct rtl818x_csr __iomem *map;
|
||||
const struct rtl818x_rf_ops *rf;
|
||||
struct ieee80211_vif *vif;
|
||||
int mode;
|
||||
|
||||
/* rtl8180 driver specific */
|
||||
spinlock_t lock;
|
||||
|
@ -82,8 +82,6 @@ static const struct ieee80211_channel rtl818x_channels[] = {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
@ -615,7 +613,6 @@ static int rtl8180_start(struct ieee80211_hw *dev)
|
||||
reg |= RTL818X_CMD_TX_ENABLE;
|
||||
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
|
||||
|
||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
||||
return 0;
|
||||
|
||||
err_free_rings:
|
||||
@ -633,8 +630,6 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
|
||||
u8 reg;
|
||||
int i;
|
||||
|
||||
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
|
||||
|
||||
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
|
||||
|
||||
reg = rtl818x_ioread8(priv, &priv->map->CMD);
|
||||
@ -657,38 +652,39 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
|
||||
}
|
||||
|
||||
static int rtl8180_add_interface(struct ieee80211_hw *dev,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
|
||||
if (priv->mode != NL80211_IFTYPE_MONITOR)
|
||||
return -EOPNOTSUPP;
|
||||
/*
|
||||
* We only support one active interface at a time.
|
||||
*/
|
||||
if (priv->vif)
|
||||
return -EBUSY;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
priv->mode = conf->type;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
priv->vif = conf->vif;
|
||||
priv->vif = vif;
|
||||
|
||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
|
||||
rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
|
||||
le32_to_cpu(*(__le32 *)conf->mac_addr));
|
||||
le32_to_cpu(*(__le32 *)vif->addr));
|
||||
rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4],
|
||||
le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
|
||||
le16_to_cpu(*(__le16 *)(vif->addr + 4)));
|
||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl8180_remove_interface(struct ieee80211_hw *dev,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
||||
priv->vif = NULL;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ struct rtl8187_priv {
|
||||
struct rtl818x_csr *map;
|
||||
const struct rtl818x_rf_ops *rf;
|
||||
struct ieee80211_vif *vif;
|
||||
int mode;
|
||||
|
||||
/* The mutex protects the TX loopback state.
|
||||
* Any attempt to set channels concurrently locks the device.
|
||||
*/
|
||||
|
@ -1018,31 +1018,30 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
|
||||
}
|
||||
|
||||
static int rtl8187_add_interface(struct ieee80211_hw *dev,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
int i;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
if (priv->mode != NL80211_IFTYPE_MONITOR)
|
||||
if (priv->vif)
|
||||
goto exit;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
priv->mode = conf->type;
|
||||
break;
|
||||
default:
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
priv->vif = conf->vif;
|
||||
priv->vif = vif;
|
||||
|
||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
rtl818x_iowrite8(priv, &priv->map->MAC[i],
|
||||
((u8 *)conf->mac_addr)[i]);
|
||||
((u8 *)vif->addr)[i]);
|
||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
|
||||
|
||||
exit:
|
||||
@ -1051,11 +1050,10 @@ exit:
|
||||
}
|
||||
|
||||
static void rtl8187_remove_interface(struct ieee80211_hw *dev,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
||||
priv->vif = NULL;
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
}
|
||||
@ -1365,7 +1363,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
|
||||
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
|
||||
|
||||
|
||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
||||
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_RX_INCLUDES_FCS;
|
||||
|
@ -33,7 +33,7 @@ static void led_turn_on(struct work_struct *work)
|
||||
struct rtl8187_led *led = &priv->led_tx;
|
||||
|
||||
/* Don't change the LED, when the device is down. */
|
||||
if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
|
||||
if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
|
||||
return ;
|
||||
|
||||
/* Skip if the LED is not registered. */
|
||||
@ -71,7 +71,7 @@ static void led_turn_off(struct work_struct *work)
|
||||
struct rtl8187_led *led = &priv->led_tx;
|
||||
|
||||
/* Don't change the LED, when the device is down. */
|
||||
if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
|
||||
if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
|
||||
return ;
|
||||
|
||||
/* Skip if the LED is not registered. */
|
||||
|
@ -256,7 +256,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
|
||||
}
|
||||
}
|
||||
|
||||
if (loop >= INIT_LOOP) {
|
||||
if (loop > INIT_LOOP) {
|
||||
wl1251_error("timeout waiting for the hardware to "
|
||||
"complete initialization");
|
||||
return -EIO;
|
||||
|
@ -511,13 +511,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
static int wl1251_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wl1251 *wl = hw->priv;
|
||||
int ret = 0;
|
||||
|
||||
wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
||||
conf->type, conf->mac_addr);
|
||||
vif->type, vif->addr);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (wl->vif) {
|
||||
@ -525,9 +525,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl->vif = conf->vif;
|
||||
wl->vif = vif;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
wl->bss_type = BSS_TYPE_STA_BSS;
|
||||
break;
|
||||
@ -539,8 +539,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) {
|
||||
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
|
||||
if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) {
|
||||
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
|
||||
SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
|
||||
ret = wl1251_acx_station_id(wl);
|
||||
if (ret < 0)
|
||||
@ -553,7 +553,7 @@ out:
|
||||
}
|
||||
|
||||
static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wl1251 *wl = hw->priv;
|
||||
|
||||
|
@ -107,10 +107,9 @@ enum {
|
||||
CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
|
||||
CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
|
||||
|
||||
#define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL)
|
||||
|
||||
#define WL1271_FW_NAME "wl1271-fw.bin"
|
||||
#define WL1271_NVS_NAME "wl1271-nvs.bin"
|
||||
#define WL1271_NVS_LEN 468
|
||||
|
||||
/*
|
||||
* Enable/disable 802.11a support for WL1273
|
||||
@ -276,6 +275,7 @@ struct wl1271_debugfs {
|
||||
|
||||
struct dentry *retry_count;
|
||||
struct dentry *excessive_retries;
|
||||
struct dentry *gpio_power;
|
||||
};
|
||||
|
||||
#define NUM_TX_QUEUES 4
|
||||
@ -322,6 +322,17 @@ struct wl1271 {
|
||||
enum wl1271_state state;
|
||||
struct mutex mutex;
|
||||
|
||||
#define WL1271_FLAG_STA_RATES_CHANGED (0)
|
||||
#define WL1271_FLAG_STA_ASSOCIATED (1)
|
||||
#define WL1271_FLAG_JOINED (2)
|
||||
#define WL1271_FLAG_GPIO_POWER (3)
|
||||
#define WL1271_FLAG_TX_QUEUE_STOPPED (4)
|
||||
#define WL1271_FLAG_SCANNING (5)
|
||||
#define WL1271_FLAG_IN_ELP (6)
|
||||
#define WL1271_FLAG_PSM (7)
|
||||
#define WL1271_FLAG_PSM_REQUESTED (8)
|
||||
unsigned long flags;
|
||||
|
||||
struct wl1271_partition_set part;
|
||||
|
||||
struct wl1271_chip chip;
|
||||
@ -359,7 +370,6 @@ struct wl1271 {
|
||||
|
||||
/* Frames scheduled for transmission, not handled yet */
|
||||
struct sk_buff_head tx_queue;
|
||||
bool tx_queue_stopped;
|
||||
|
||||
struct work_struct tx_work;
|
||||
|
||||
@ -387,14 +397,15 @@ struct wl1271 {
|
||||
u32 mbox_ptr[2];
|
||||
|
||||
/* Are we currently scanning */
|
||||
bool scanning;
|
||||
struct wl1271_scan scan;
|
||||
|
||||
/* Our association ID */
|
||||
u16 aid;
|
||||
|
||||
/* currently configured rate set */
|
||||
u32 sta_rate_set;
|
||||
u32 basic_rate_set;
|
||||
u32 rate_set;
|
||||
|
||||
/* The current band */
|
||||
enum ieee80211_band band;
|
||||
@ -405,18 +416,9 @@ struct wl1271 {
|
||||
unsigned int rx_config;
|
||||
unsigned int rx_filter;
|
||||
|
||||
/* is firmware in elp mode */
|
||||
bool elp;
|
||||
|
||||
struct completion *elp_compl;
|
||||
struct delayed_work elp_work;
|
||||
|
||||
/* we can be in psm, but not in elp, we have to differentiate */
|
||||
bool psm;
|
||||
|
||||
/* PSM mode requested */
|
||||
bool psm_requested;
|
||||
|
||||
/* retry counter for PSM entries */
|
||||
u8 psm_entry_retry;
|
||||
|
||||
@ -435,9 +437,6 @@ struct wl1271 {
|
||||
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
/* Used for a workaround to send disconnect before rejoining */
|
||||
bool joined;
|
||||
|
||||
/* Current chipset configuration */
|
||||
struct conf_drv_settings conf;
|
||||
|
||||
@ -455,7 +454,9 @@ int wl1271_plt_stop(struct wl1271 *wl);
|
||||
|
||||
#define WL1271_TX_QUEUE_MAX_LENGTH 20
|
||||
|
||||
/* WL1271 needs a 200ms sleep after power on */
|
||||
/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
|
||||
on in case is has been shut down shortly before */
|
||||
#define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */
|
||||
#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
|
||||
|
||||
static inline bool wl1271_11a_enabled(void)
|
||||
|
@ -390,6 +390,35 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_dco_itrim_params(struct wl1271 *wl)
|
||||
{
|
||||
struct acx_dco_itrim_params *dco;
|
||||
struct conf_itrim_settings *c = &wl->conf.itrim;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx dco itrim parameters");
|
||||
|
||||
dco = kzalloc(sizeof(*dco), GFP_KERNEL);
|
||||
if (!dco) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dco->enable = c->enable;
|
||||
dco->timeout = cpu_to_le32(c->timeout);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS,
|
||||
dco, sizeof(*dco));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("failed to set dco itrim parameters: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(dco);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
|
||||
{
|
||||
struct acx_beacon_filter_option *beacon_filter = NULL;
|
||||
@ -758,10 +787,11 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates)
|
||||
int wl1271_acx_rate_policies(struct wl1271 *wl)
|
||||
{
|
||||
struct acx_rate_policy *acx;
|
||||
struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
|
||||
int idx = 0;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx rate policies");
|
||||
@ -773,12 +803,21 @@ int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* configure one default (one-size-fits-all) rate class */
|
||||
acx->rate_class_cnt = cpu_to_le32(1);
|
||||
acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates);
|
||||
acx->rate_class[0].short_retry_limit = c->short_retry_limit;
|
||||
acx->rate_class[0].long_retry_limit = c->long_retry_limit;
|
||||
acx->rate_class[0].aflags = c->aflags;
|
||||
/* configure one basic rate class */
|
||||
idx = ACX_TX_BASIC_RATE;
|
||||
acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set);
|
||||
acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
|
||||
acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
|
||||
acx->rate_class[idx].aflags = c->aflags;
|
||||
|
||||
/* configure one AP supported rate class */
|
||||
idx = ACX_TX_AP_FULL_RATE;
|
||||
acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set);
|
||||
acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
|
||||
acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
|
||||
acx->rate_class[idx].aflags = c->aflags;
|
||||
|
||||
acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
@ -1012,59 +1051,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_smart_reflex(struct wl1271 *wl)
|
||||
{
|
||||
struct acx_smart_reflex_state *sr_state = NULL;
|
||||
struct acx_smart_reflex_config_params *sr_param = NULL;
|
||||
int i, ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx smart reflex");
|
||||
|
||||
sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL);
|
||||
if (!sr_param) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) {
|
||||
struct conf_mart_reflex_err_table *e =
|
||||
&(wl->conf.init.sr_err_tbl[i]);
|
||||
|
||||
sr_param->error_table[i].len = e->len;
|
||||
sr_param->error_table[i].upper_limit = e->upper_limit;
|
||||
memcpy(sr_param->error_table[i].values, e->values, e->len);
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS,
|
||||
sr_param, sizeof(*sr_param));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("failed to set smart reflex params: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL);
|
||||
if (!sr_state) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* enable smart reflex */
|
||||
sr_state->enable = wl->conf.init.sr_enable;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE,
|
||||
sr_state, sizeof(*sr_state));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("failed to set smart reflex params: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(sr_state);
|
||||
kfree(sr_param);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
|
||||
{
|
||||
struct wl1271_acx_bet_enable *acx = NULL;
|
||||
@ -1132,3 +1118,31 @@ out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_pm_config(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_acx_pm_config *acx = NULL;
|
||||
struct conf_pm_config_settings *c = &wl->conf.pm_config;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx pm config");
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
if (!acx) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time);
|
||||
acx->host_fast_wakeup_support = c->host_fast_wakeup_support;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx pm config failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(acx);
|
||||
return ret;
|
||||
}
|
||||
|
@ -415,23 +415,12 @@ struct acx_bt_wlan_coex {
|
||||
u8 pad[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct acx_smart_reflex_state {
|
||||
struct acx_dco_itrim_params {
|
||||
struct acx_header header;
|
||||
|
||||
u8 enable;
|
||||
u8 padding[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct smart_reflex_err_table {
|
||||
u8 len;
|
||||
s8 upper_limit;
|
||||
s8 values[14];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct acx_smart_reflex_config_params {
|
||||
struct acx_header header;
|
||||
|
||||
struct smart_reflex_err_table error_table[3];
|
||||
__le32 timeout;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define PTA_ANTENNA_TYPE_DEF (0)
|
||||
@ -837,6 +826,9 @@ struct acx_rate_class {
|
||||
u8 reserved;
|
||||
};
|
||||
|
||||
#define ACX_TX_BASIC_RATE 0
|
||||
#define ACX_TX_AP_FULL_RATE 1
|
||||
#define ACX_TX_RATE_POLICY_CNT 2
|
||||
struct acx_rate_policy {
|
||||
struct acx_header header;
|
||||
|
||||
@ -877,8 +869,8 @@ struct acx_tx_config_options {
|
||||
__le16 tx_compl_threshold; /* number of packets */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define ACX_RX_MEM_BLOCKS 64
|
||||
#define ACX_TX_MIN_MEM_BLOCKS 64
|
||||
#define ACX_RX_MEM_BLOCKS 70
|
||||
#define ACX_TX_MIN_MEM_BLOCKS 40
|
||||
#define ACX_TX_DESCRIPTORS 32
|
||||
#define ACX_NUM_SSID_PROFILES 1
|
||||
|
||||
@ -969,6 +961,13 @@ struct wl1271_acx_arp_filter {
|
||||
used. */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct wl1271_acx_pm_config {
|
||||
struct acx_header header;
|
||||
|
||||
__le32 host_clk_settling_time;
|
||||
u8 host_fast_wakeup_support;
|
||||
u8 padding[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum {
|
||||
ACX_WAKE_UP_CONDITIONS = 0x0002,
|
||||
@ -1027,13 +1026,13 @@ enum {
|
||||
ACX_HT_BSS_OPERATION = 0x0058,
|
||||
ACX_COEX_ACTIVITY = 0x0059,
|
||||
ACX_SET_SMART_REFLEX_DEBUG = 0x005A,
|
||||
ACX_SET_SMART_REFLEX_STATE = 0x005B,
|
||||
ACX_SET_SMART_REFLEX_PARAMS = 0x005F,
|
||||
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
|
||||
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
|
||||
DOT11_CUR_TX_PWR = 0x100D,
|
||||
DOT11_RX_DOT11_MODE = 0x1012,
|
||||
DOT11_RTS_THRESHOLD = 0x1013,
|
||||
DOT11_GROUP_ADDRESS_TBL = 0x1014,
|
||||
ACX_PM_CONFIG = 0x1016,
|
||||
|
||||
MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
|
||||
|
||||
@ -1056,6 +1055,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
|
||||
void *mc_list, u32 mc_list_len);
|
||||
int wl1271_acx_service_period_timeout(struct wl1271 *wl);
|
||||
int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
|
||||
int wl1271_acx_dco_itrim_params(struct wl1271 *wl);
|
||||
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
|
||||
int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
|
||||
int wl1271_acx_conn_monit_params(struct wl1271 *wl);
|
||||
@ -1069,7 +1069,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble);
|
||||
int wl1271_acx_cts_protect(struct wl1271 *wl,
|
||||
enum acx_ctsprotect_type ctsprotect);
|
||||
int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
|
||||
int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates);
|
||||
int wl1271_acx_rate_policies(struct wl1271 *wl);
|
||||
int wl1271_acx_ac_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_tid_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_frag_threshold(struct wl1271 *wl);
|
||||
@ -1081,5 +1081,6 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl);
|
||||
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
|
||||
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
|
||||
u8 version);
|
||||
int wl1271_acx_pm_config(struct wl1271 *wl);
|
||||
|
||||
#endif /* __WL1271_ACX_H__ */
|
||||
|
@ -225,9 +225,15 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
if (nvs == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (wl->nvs_len < WL1271_NVS_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
nvs_ptr = nvs;
|
||||
|
||||
nvs_len = wl->nvs_len;
|
||||
/* only the first part of the NVS needs to be uploaded */
|
||||
nvs_len = WL1271_NVS_LEN;
|
||||
|
||||
/* FIXME: read init settings from the remaining part of the NVS */
|
||||
|
||||
/* Update the device MAC address into the nvs */
|
||||
nvs[11] = wl->mac_addr[0];
|
||||
|
@ -209,6 +209,26 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
|
||||
gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer;
|
||||
gen_parms->settings = g->settings;
|
||||
|
||||
gen_parms->sr_state = g->sr_state;
|
||||
|
||||
memcpy(gen_parms->srf1,
|
||||
g->srf1,
|
||||
CONF_MAX_SMART_REFLEX_PARAMS);
|
||||
memcpy(gen_parms->srf2,
|
||||
g->srf2,
|
||||
CONF_MAX_SMART_REFLEX_PARAMS);
|
||||
memcpy(gen_parms->srf3,
|
||||
g->srf3,
|
||||
CONF_MAX_SMART_REFLEX_PARAMS);
|
||||
memcpy(gen_parms->sr_debug_table,
|
||||
g->sr_debug_table,
|
||||
CONF_MAX_SMART_REFLEX_PARAMS);
|
||||
|
||||
gen_parms->sr_sen_n_p = g->sr_sen_n_p;
|
||||
gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain;
|
||||
gen_parms->sr_sen_nrn = g->sr_sen_nrn;
|
||||
gen_parms->sr_sen_prn = g->sr_sen_prn;
|
||||
|
||||
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
|
||||
if (ret < 0)
|
||||
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
|
||||
@ -253,6 +273,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme,
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
|
||||
memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b,
|
||||
CONF_NUMBER_OF_CHANNELS_2_4);
|
||||
@ -263,6 +285,11 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
|
||||
memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS);
|
||||
|
||||
radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss;
|
||||
radio_parms->degraded_low_to_normal_threshold =
|
||||
r->degraded_low_to_normal_threshold;
|
||||
radio_parms->degraded_normal_to_high_threshold =
|
||||
r->degraded_normal_to_high_threshold;
|
||||
|
||||
|
||||
for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++)
|
||||
radio_parms->tx_ref_pd_voltage_5[i] =
|
||||
@ -275,6 +302,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
|
||||
r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_rate_limits_degraded_5,
|
||||
r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_rate_limits_extreme_5,
|
||||
r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_channel_limits_ofdm_5,
|
||||
r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5);
|
||||
memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5,
|
||||
@ -283,6 +312,10 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->rx_fem_insertion_loss_5,
|
||||
r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5);
|
||||
radio_parms->degraded_low_to_normal_threshold_5 =
|
||||
r->degraded_low_to_normal_threshold_5;
|
||||
radio_parms->degraded_normal_to_high_threshold_5 =
|
||||
r->degraded_normal_to_high_threshold_5;
|
||||
|
||||
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
|
||||
radio_parms, sizeof(*radio_parms));
|
||||
@ -311,19 +344,6 @@ int wl1271_cmd_join(struct wl1271 *wl)
|
||||
do_cal = false;
|
||||
}
|
||||
|
||||
/* FIXME: This is a workaround, because with the current stack, we
|
||||
* cannot know when we have disassociated. So, if we have already
|
||||
* joined, we disconnect before joining again. */
|
||||
if (wl->joined) {
|
||||
ret = wl1271_cmd_disconnect(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to disconnect before rejoining");
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl->joined = false;
|
||||
}
|
||||
|
||||
join = kzalloc(sizeof(*join), GFP_KERNEL);
|
||||
if (!join) {
|
||||
ret = -ENOMEM;
|
||||
@ -388,8 +408,6 @@ int wl1271_cmd_join(struct wl1271 *wl)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
wl->joined = true;
|
||||
|
||||
/*
|
||||
* ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
|
||||
* simplify locking we just sleep instead, for now
|
||||
@ -487,7 +505,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
|
||||
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
|
||||
{
|
||||
struct cmd_enabledisable_path *cmd;
|
||||
int ret;
|
||||
@ -501,7 +519,8 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->channel = channel;
|
||||
/* the channel here is only used for calibration, so hardcoded to 1 */
|
||||
cmd->channel = 1;
|
||||
|
||||
if (enable) {
|
||||
cmd_rx = CMD_ENABLE_RX;
|
||||
@ -514,22 +533,22 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
|
||||
ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("rx %s cmd for channel %d failed",
|
||||
enable ? "start" : "stop", channel);
|
||||
enable ? "start" : "stop", cmd->channel);
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d",
|
||||
enable ? "start" : "stop", channel);
|
||||
enable ? "start" : "stop", cmd->channel);
|
||||
|
||||
ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("tx %s cmd for channel %d failed",
|
||||
enable ? "start" : "stop", channel);
|
||||
enable ? "start" : "stop", cmd->channel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d",
|
||||
enable ? "start" : "stop", channel);
|
||||
enable ? "start" : "stop", cmd->channel);
|
||||
|
||||
out:
|
||||
kfree(cmd);
|
||||
@ -636,7 +655,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
|
||||
channels = wl->hw->wiphy->bands[ieee_band]->channels;
|
||||
n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels;
|
||||
|
||||
if (wl->scanning)
|
||||
if (test_bit(WL1271_FLAG_SCANNING, &wl->flags))
|
||||
return -EINVAL;
|
||||
|
||||
params = kzalloc(sizeof(*params), GFP_KERNEL);
|
||||
@ -711,7 +730,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
|
||||
|
||||
wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
|
||||
|
||||
wl->scanning = true;
|
||||
set_bit(WL1271_FLAG_SCANNING, &wl->flags);
|
||||
if (wl1271_11a_enabled()) {
|
||||
wl->scan.state = band;
|
||||
if (band == WL1271_SCAN_BAND_DUAL) {
|
||||
@ -729,7 +748,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
|
||||
ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("SCAN failed");
|
||||
wl->scanning = false;
|
||||
clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -777,7 +796,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_build_basic_rates(char *rates, u8 band)
|
||||
static int wl1271_build_basic_rates(u8 *rates, u8 band)
|
||||
{
|
||||
u8 index = 0;
|
||||
|
||||
@ -804,7 +823,7 @@ static int wl1271_build_basic_rates(char *rates, u8 band)
|
||||
return index;
|
||||
}
|
||||
|
||||
static int wl1271_build_extended_rates(char *rates, u8 band)
|
||||
static int wl1271_build_extended_rates(u8 *rates, u8 band)
|
||||
{
|
||||
u8 index = 0;
|
||||
|
||||
|
@ -37,7 +37,7 @@ int wl1271_cmd_join(struct wl1271 *wl);
|
||||
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
|
||||
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
|
||||
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
|
||||
int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable);
|
||||
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
|
||||
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
|
||||
size_t len);
|
||||
@ -437,6 +437,21 @@ struct wl1271_general_parms_cmd {
|
||||
u8 tx_bip_fem_autodetect;
|
||||
u8 tx_bip_fem_manufacturer;
|
||||
u8 settings;
|
||||
|
||||
u8 sr_state;
|
||||
|
||||
s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
|
||||
s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
|
||||
u8 sr_sen_n_p;
|
||||
u8 sr_sen_n_p_gain;
|
||||
u8 sr_sen_nrn;
|
||||
u8 sr_sen_prn;
|
||||
|
||||
u8 padding[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct wl1271_radio_parms_cmd {
|
||||
@ -458,11 +473,12 @@ struct wl1271_radio_parms_cmd {
|
||||
/* Dynamic radio parameters */
|
||||
/* 2.4GHz */
|
||||
__le16 tx_ref_pd_voltage;
|
||||
s8 tx_ref_power;
|
||||
u8 tx_ref_power;
|
||||
s8 tx_offset_db;
|
||||
|
||||
s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||
s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||
@ -471,15 +487,19 @@ struct wl1271_radio_parms_cmd {
|
||||
u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
u8 rx_fem_insertion_loss;
|
||||
|
||||
u8 padding2;
|
||||
u8 degraded_low_to_normal_threshold;
|
||||
u8 degraded_normal_to_high_threshold;
|
||||
|
||||
u8 padding1; /* our own padding, not in ref driver */
|
||||
|
||||
/* 5GHz */
|
||||
__le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
|
||||
s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
|
||||
s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
@ -488,7 +508,10 @@ struct wl1271_radio_parms_cmd {
|
||||
s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
|
||||
u8 padding3[2];
|
||||
u8 degraded_low_to_normal_threshold_5;
|
||||
u8 degraded_normal_to_high_threshold_5;
|
||||
|
||||
u8 padding2[2];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct wl1271_cmd_cal_channel_tune {
|
||||
|
@ -258,7 +258,8 @@ struct conf_rx_settings {
|
||||
#define CONF_TX_MAX_RATE_CLASSES 8
|
||||
|
||||
#define CONF_TX_RATE_MASK_UNSPECIFIED 0
|
||||
#define CONF_TX_RATE_MASK_ALL 0x1eff
|
||||
#define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \
|
||||
CONF_HW_BIT_RATE_2MBPS)
|
||||
#define CONF_TX_RATE_RETRY_LIMIT 10
|
||||
|
||||
struct conf_tx_rate_class {
|
||||
@ -722,31 +723,6 @@ struct conf_conn_settings {
|
||||
u8 psm_entry_retries;
|
||||
};
|
||||
|
||||
#define CONF_SR_ERR_TBL_MAX_VALUES 14
|
||||
|
||||
struct conf_mart_reflex_err_table {
|
||||
/*
|
||||
* Length of the error table values table.
|
||||
*
|
||||
* Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES
|
||||
*/
|
||||
u8 len;
|
||||
|
||||
/*
|
||||
* Smart Reflex error table upper limit.
|
||||
*
|
||||
* Range: s8
|
||||
*/
|
||||
s8 upper_limit;
|
||||
|
||||
/*
|
||||
* Smart Reflex error table values.
|
||||
*
|
||||
* Range: s8
|
||||
*/
|
||||
s8 values[CONF_SR_ERR_TBL_MAX_VALUES];
|
||||
};
|
||||
|
||||
enum {
|
||||
CONF_REF_CLK_19_2_E,
|
||||
CONF_REF_CLK_26_E,
|
||||
@ -759,6 +735,9 @@ enum single_dual_band_enum {
|
||||
CONF_DUAL_BAND
|
||||
};
|
||||
|
||||
|
||||
#define CONF_MAX_SMART_REFLEX_PARAMS 16
|
||||
|
||||
struct conf_general_parms {
|
||||
/*
|
||||
* RF Reference Clock type / speed
|
||||
@ -815,6 +794,20 @@ struct conf_general_parms {
|
||||
* Range: Unknown
|
||||
*/
|
||||
u8 settings;
|
||||
|
||||
/* Smart reflex settings */
|
||||
u8 sr_state;
|
||||
|
||||
s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
|
||||
s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
|
||||
u8 sr_sen_n_p;
|
||||
u8 sr_sen_n_p_gain;
|
||||
u8 sr_sen_nrn;
|
||||
u8 sr_sen_prn;
|
||||
};
|
||||
|
||||
#define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15
|
||||
@ -847,12 +840,13 @@ struct conf_radio_parms {
|
||||
*
|
||||
* Range: unknown
|
||||
*/
|
||||
s16 tx_ref_pd_voltage;
|
||||
s8 tx_ref_power;
|
||||
u16 tx_ref_pd_voltage;
|
||||
u8 tx_ref_power;
|
||||
s8 tx_offset_db;
|
||||
|
||||
s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||
s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||
@ -861,17 +855,22 @@ struct conf_radio_parms {
|
||||
u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
u8 rx_fem_insertion_loss;
|
||||
|
||||
u8 degraded_low_to_normal_threshold;
|
||||
u8 degraded_normal_to_high_threshold;
|
||||
|
||||
|
||||
/*
|
||||
* Dynamic radio parameters for 5GHz
|
||||
*
|
||||
* Range: unknown
|
||||
*/
|
||||
s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
|
||||
s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
|
||||
s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
@ -879,23 +878,12 @@ struct conf_radio_parms {
|
||||
/* FIXME: this is inconsistent with the types for 2.4GHz */
|
||||
s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
|
||||
u8 degraded_low_to_normal_threshold_5;
|
||||
u8 degraded_normal_to_high_threshold_5;
|
||||
};
|
||||
|
||||
#define CONF_SR_ERR_TBL_COUNT 3
|
||||
|
||||
struct conf_init_settings {
|
||||
/*
|
||||
* Configure Smart Reflex error table values.
|
||||
*/
|
||||
struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT];
|
||||
|
||||
/*
|
||||
* Smart Reflex enable flag.
|
||||
*
|
||||
* Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled
|
||||
*/
|
||||
u8 sr_enable;
|
||||
|
||||
/*
|
||||
* Configure general parameters.
|
||||
*/
|
||||
@ -908,12 +896,38 @@ struct conf_init_settings {
|
||||
|
||||
};
|
||||
|
||||
struct conf_itrim_settings {
|
||||
/* enable dco itrim */
|
||||
u8 enable;
|
||||
|
||||
/* moderation timeout in microsecs from the last TX */
|
||||
u32 timeout;
|
||||
};
|
||||
|
||||
struct conf_pm_config_settings {
|
||||
/*
|
||||
* Host clock settling time
|
||||
*
|
||||
* Range: 0 - 30000 us
|
||||
*/
|
||||
u32 host_clk_settling_time;
|
||||
|
||||
/*
|
||||
* Host fast wakeup support
|
||||
*
|
||||
* Range: true, false
|
||||
*/
|
||||
bool host_fast_wakeup_support;
|
||||
};
|
||||
|
||||
struct conf_drv_settings {
|
||||
struct conf_sg_settings sg;
|
||||
struct conf_rx_settings rx;
|
||||
struct conf_tx_settings tx;
|
||||
struct conf_conn_settings conn;
|
||||
struct conf_init_settings init;
|
||||
struct conf_itrim_settings itrim;
|
||||
struct conf_pm_config_settings pm_config;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -237,6 +237,64 @@ static const struct file_operations tx_queue_len_ops = {
|
||||
.open = wl1271_open_file_generic,
|
||||
};
|
||||
|
||||
static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||
|
||||
int res;
|
||||
char buf[10];
|
||||
|
||||
res = scnprintf(buf, sizeof(buf), "%d\n", state);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, res);
|
||||
}
|
||||
|
||||
static ssize_t gpio_power_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
char buf[10];
|
||||
size_t len;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
|
||||
ret = strict_strtoul(buf, 0, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value in gpio_power");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
wl->set_power(true);
|
||||
set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||
} else {
|
||||
wl->set_power(false);
|
||||
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations gpio_power_ops = {
|
||||
.read = gpio_power_read,
|
||||
.write = gpio_power_write,
|
||||
.open = wl1271_open_file_generic
|
||||
};
|
||||
|
||||
static void wl1271_debugfs_delete_files(struct wl1271 *wl)
|
||||
{
|
||||
DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
|
||||
@ -333,6 +391,8 @@ static void wl1271_debugfs_delete_files(struct wl1271 *wl)
|
||||
DEBUGFS_DEL(tx_queue_len);
|
||||
DEBUGFS_DEL(retry_count);
|
||||
DEBUGFS_DEL(excessive_retries);
|
||||
|
||||
DEBUGFS_DEL(gpio_power);
|
||||
}
|
||||
|
||||
static int wl1271_debugfs_add_files(struct wl1271 *wl)
|
||||
@ -434,6 +494,8 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl)
|
||||
DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
|
||||
DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
|
||||
|
||||
DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir);
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
wl1271_debugfs_delete_files(wl);
|
||||
|
@ -35,7 +35,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
|
||||
wl1271_debug(DEBUG_EVENT, "status: 0x%x",
|
||||
mbox->scheduled_scan_status);
|
||||
|
||||
if (wl->scanning) {
|
||||
if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) {
|
||||
if (wl->scan.state == WL1271_SCAN_BAND_DUAL) {
|
||||
wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
||||
NULL, size);
|
||||
@ -43,7 +43,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
|
||||
* to the wl1271_cmd_scan function that we are not
|
||||
* scanning as it checks that.
|
||||
*/
|
||||
wl->scanning = false;
|
||||
clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
|
||||
wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len,
|
||||
wl->scan.active,
|
||||
wl->scan.high_prio,
|
||||
@ -62,7 +62,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
|
||||
mutex_unlock(&wl->mutex);
|
||||
ieee80211_scan_completed(wl->hw, false);
|
||||
mutex_lock(&wl->mutex);
|
||||
wl->scanning = false;
|
||||
clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -78,7 +78,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
||||
|
||||
switch (mbox->ps_status) {
|
||||
case EVENT_ENTER_POWER_SAVE_FAIL:
|
||||
if (!wl->psm) {
|
||||
if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||
wl->psm_entry_retry = 0;
|
||||
break;
|
||||
}
|
||||
@ -89,7 +89,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
||||
} else {
|
||||
wl1271_error("PSM entry failed, giving up.\n");
|
||||
wl->psm_entry_retry = 0;
|
||||
*beacon_loss = true;
|
||||
}
|
||||
break;
|
||||
case EVENT_ENTER_POWER_SAVE_SUCCESS:
|
||||
@ -136,7 +135,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
* filtering) is enabled. Without PSM, the stack will receive all
|
||||
* beacons and can detect beacon loss by itself.
|
||||
*/
|
||||
if (vector & BSS_LOSE_EVENT_ID && wl->psm) {
|
||||
if (vector & BSS_LOSE_EVENT_ID &&
|
||||
test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||
wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
|
||||
|
||||
/* indicate to the stack, that beacons have been lost */
|
||||
@ -150,7 +150,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (beacon_loss) {
|
||||
if (wl->vif && beacon_loss) {
|
||||
/* Obviously, it's dangerous to release the mutex while
|
||||
we are holding many of the variables in the wl struct.
|
||||
That's why it's done last in the function, and care must
|
||||
@ -184,7 +184,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl)
|
||||
wl->mbox_ptr[0], wl->mbox_ptr[1]);
|
||||
}
|
||||
|
||||
int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack)
|
||||
int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
|
||||
{
|
||||
struct event_mailbox mbox;
|
||||
int ret;
|
||||
@ -204,9 +204,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack)
|
||||
return ret;
|
||||
|
||||
/* then we let the firmware know it can go on...*/
|
||||
if (do_ack)
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG,
|
||||
INTR_TRIG_EVENT_ACK);
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -112,6 +112,6 @@ struct event_mailbox {
|
||||
|
||||
int wl1271_event_unmask(struct wl1271 *wl);
|
||||
void wl1271_event_mbox_config(struct wl1271 *wl);
|
||||
int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack);
|
||||
int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
|
||||
|
||||
#endif
|
||||
|
@ -229,6 +229,10 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
ret = wl1271_acx_dco_itrim_params(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Initialize connection monitoring thresholds */
|
||||
ret = wl1271_acx_conn_monit_params(wl);
|
||||
if (ret < 0)
|
||||
@ -280,12 +284,12 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Configure TX rate classes */
|
||||
ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL);
|
||||
ret = wl1271_acx_rate_policies(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Enable data path */
|
||||
ret = wl1271_cmd_data_path(wl, wl->channel, 1);
|
||||
ret = wl1271_cmd_data_path(wl, 1);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
@ -299,8 +303,8 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Configure smart reflex */
|
||||
ret = wl1271_acx_smart_reflex(wl);
|
||||
/* configure PM */
|
||||
ret = wl1271_acx_pm_config(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
|
@ -47,6 +47,8 @@
|
||||
#include "wl1271_cmd.h"
|
||||
#include "wl1271_boot.h"
|
||||
|
||||
#define WL1271_BOOT_RETRIES 3
|
||||
|
||||
static struct conf_drv_settings default_conf = {
|
||||
.sg = {
|
||||
.per_threshold = 7500,
|
||||
@ -67,16 +69,17 @@ static struct conf_drv_settings default_conf = {
|
||||
.ps_poll_timeout = 15,
|
||||
.upsd_timeout = 15,
|
||||
.rts_threshold = 2347,
|
||||
.rx_cca_threshold = 0xFFEF,
|
||||
.irq_blk_threshold = 0,
|
||||
.irq_pkt_threshold = USHORT_MAX,
|
||||
.irq_timeout = 5,
|
||||
.rx_cca_threshold = 0,
|
||||
.irq_blk_threshold = 0xFFFF,
|
||||
.irq_pkt_threshold = 0,
|
||||
.irq_timeout = 600,
|
||||
.queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
|
||||
},
|
||||
.tx = {
|
||||
.tx_energy_detection = 0,
|
||||
.rc_conf = {
|
||||
.enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED,
|
||||
.enabled_rates = CONF_HW_BIT_RATE_1MBPS |
|
||||
CONF_HW_BIT_RATE_2MBPS,
|
||||
.short_retry_limit = 10,
|
||||
.long_retry_limit = 10,
|
||||
.aflags = 0
|
||||
@ -172,8 +175,8 @@ static struct conf_drv_settings default_conf = {
|
||||
}
|
||||
},
|
||||
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
|
||||
.tx_compl_timeout = 5,
|
||||
.tx_compl_threshold = 5
|
||||
.tx_compl_timeout = 700,
|
||||
.tx_compl_threshold = 4
|
||||
},
|
||||
.conn = {
|
||||
.wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
|
||||
@ -186,12 +189,12 @@ static struct conf_drv_settings default_conf = {
|
||||
.rule = CONF_BCN_RULE_PASS_ON_APPEARANCE,
|
||||
}
|
||||
},
|
||||
.synch_fail_thold = 5,
|
||||
.synch_fail_thold = 10,
|
||||
.bss_lose_timeout = 100,
|
||||
.beacon_rx_timeout = 10000,
|
||||
.broadcast_timeout = 20000,
|
||||
.rx_broadcast_in_ps = 1,
|
||||
.ps_poll_threshold = 4,
|
||||
.ps_poll_threshold = 20,
|
||||
.sig_trigger_count = 2,
|
||||
.sig_trigger = {
|
||||
[0] = {
|
||||
@ -226,46 +229,35 @@ static struct conf_drv_settings default_conf = {
|
||||
.psm_entry_retries = 3
|
||||
},
|
||||
.init = {
|
||||
.sr_err_tbl = {
|
||||
[0] = {
|
||||
.len = 7,
|
||||
.upper_limit = 0x03,
|
||||
.values = {
|
||||
0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
|
||||
0x00 }
|
||||
},
|
||||
[1] = {
|
||||
.len = 7,
|
||||
.upper_limit = 0x03,
|
||||
.values = {
|
||||
0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8,
|
||||
0x00 }
|
||||
},
|
||||
[2] = {
|
||||
.len = 7,
|
||||
.upper_limit = 0x03,
|
||||
.values = {
|
||||
0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8,
|
||||
0x00 }
|
||||
}
|
||||
},
|
||||
.sr_enable = 1,
|
||||
.genparam = {
|
||||
.ref_clk = CONF_REF_CLK_38_4_E,
|
||||
.settling_time = 5,
|
||||
.clk_valid_on_wakeup = 0,
|
||||
.dc2dcmode = 0,
|
||||
.single_dual_band = CONF_SINGLE_BAND,
|
||||
.tx_bip_fem_autodetect = 0,
|
||||
.tx_bip_fem_autodetect = 1,
|
||||
.tx_bip_fem_manufacturer = 1,
|
||||
.settings = 1,
|
||||
.sr_state = 1,
|
||||
.srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
|
||||
0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
|
||||
0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
|
||||
0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.sr_sen_n_p = 0,
|
||||
.sr_sen_n_p_gain = 0,
|
||||
.sr_sen_nrn = 0,
|
||||
.sr_sen_prn = 0,
|
||||
},
|
||||
.radioparam = {
|
||||
.rx_trace_loss = 10,
|
||||
.tx_trace_loss = 10,
|
||||
.rx_trace_loss = 0x24,
|
||||
.tx_trace_loss = 0x0,
|
||||
.rx_rssi_and_proc_compens = {
|
||||
0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
|
||||
0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8,
|
||||
0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8,
|
||||
0x00, 0x0a, 0x14 },
|
||||
.rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
|
||||
.tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
|
||||
@ -273,13 +265,15 @@ static struct conf_drv_settings default_conf = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00 },
|
||||
.tx_ref_pd_voltage = 0x24e,
|
||||
.tx_ref_power = 0x78,
|
||||
.tx_ref_pd_voltage = 0x1a9,
|
||||
.tx_ref_power = 0x80,
|
||||
.tx_offset_db = 0x0,
|
||||
.tx_rate_limits_normal = {
|
||||
0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 },
|
||||
0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 },
|
||||
.tx_rate_limits_degraded = {
|
||||
0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
|
||||
0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 },
|
||||
.tx_rate_limits_extreme = {
|
||||
0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
|
||||
.tx_channel_limits_11b = {
|
||||
0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
|
||||
@ -289,10 +283,12 @@ static struct conf_drv_settings default_conf = {
|
||||
0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
|
||||
0x20, 0x50 },
|
||||
.tx_pdv_rate_offsets = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
0x07, 0x08, 0x04, 0x02, 0x02, 0x00 },
|
||||
.tx_ibias = {
|
||||
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 },
|
||||
.rx_fem_insertion_loss = 0x14,
|
||||
0x11, 0x11, 0x15, 0x11, 0x15, 0x0f },
|
||||
.rx_fem_insertion_loss = 0x0e,
|
||||
.degraded_low_to_normal_threshold = 0x1e,
|
||||
.degraded_normal_to_high_threshold = 0x2d,
|
||||
.tx_ref_pd_voltage_5 = {
|
||||
0x0190, 0x01a4, 0x01c3, 0x01d8,
|
||||
0x020a, 0x021c },
|
||||
@ -304,6 +300,8 @@ static struct conf_drv_settings default_conf = {
|
||||
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||
.tx_rate_limits_degraded_5 = {
|
||||
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||
.tx_rate_limits_extreme_5 = {
|
||||
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||
.tx_channel_limits_ofdm_5 = {
|
||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
@ -315,8 +313,18 @@ static struct conf_drv_settings default_conf = {
|
||||
.tx_ibias_5 = {
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
|
||||
.rx_fem_insertion_loss_5 = {
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
|
||||
.degraded_low_to_normal_threshold_5 = 0x00,
|
||||
.degraded_normal_to_high_threshold_5 = 0x00
|
||||
}
|
||||
},
|
||||
.itrim = {
|
||||
.enable = false,
|
||||
.timeout = 50000,
|
||||
},
|
||||
.pm_config = {
|
||||
.host_clk_settling_time = 5000,
|
||||
.host_fast_wakeup_support = false
|
||||
}
|
||||
};
|
||||
|
||||
@ -359,7 +367,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_data_path(wl, wl->channel, 1);
|
||||
ret = wl1271_cmd_data_path(wl, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -374,11 +382,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl)
|
||||
static void wl1271_power_off(struct wl1271 *wl)
|
||||
{
|
||||
wl->set_power(false);
|
||||
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||
}
|
||||
|
||||
static void wl1271_power_on(struct wl1271 *wl)
|
||||
{
|
||||
wl->set_power(true);
|
||||
set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||
}
|
||||
|
||||
static void wl1271_fw_status(struct wl1271 *wl,
|
||||
@ -447,14 +457,13 @@ static void wl1271_irq_work(struct work_struct *work)
|
||||
intr &= WL1271_INTR_MASK;
|
||||
|
||||
if (intr & WL1271_ACX_INTR_EVENT_A) {
|
||||
bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true;
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
|
||||
wl1271_event_handle(wl, 0, do_ack);
|
||||
wl1271_event_handle(wl, 0);
|
||||
}
|
||||
|
||||
if (intr & WL1271_ACX_INTR_EVENT_B) {
|
||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
|
||||
wl1271_event_handle(wl, 1, true);
|
||||
wl1271_event_handle(wl, 1);
|
||||
}
|
||||
|
||||
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
|
||||
@ -614,6 +623,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
|
||||
struct wl1271_partition_set partition;
|
||||
int ret = 0;
|
||||
|
||||
msleep(WL1271_PRE_POWER_ON_SLEEP);
|
||||
wl1271_power_on(wl);
|
||||
msleep(WL1271_POWER_ON_SLEEP);
|
||||
wl1271_spi_reset(wl);
|
||||
@ -643,7 +653,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
|
||||
|
||||
ret = wl1271_setup(wl);
|
||||
if (ret < 0)
|
||||
goto out_power_off;
|
||||
goto out;
|
||||
break;
|
||||
case CHIP_ID_1271_PG20:
|
||||
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
|
||||
@ -651,38 +661,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
|
||||
|
||||
ret = wl1271_setup(wl);
|
||||
if (ret < 0)
|
||||
goto out_power_off;
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
|
||||
wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
|
||||
ret = -ENODEV;
|
||||
goto out_power_off;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wl->fw == NULL) {
|
||||
ret = wl1271_fetch_firmware(wl);
|
||||
if (ret < 0)
|
||||
goto out_power_off;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No NVS from netlink, try to get it from the filesystem */
|
||||
if (wl->nvs == NULL) {
|
||||
ret = wl1271_fetch_nvs(wl);
|
||||
if (ret < 0)
|
||||
goto out_power_off;
|
||||
goto out;
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
out_power_off:
|
||||
wl1271_power_off(wl);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_plt_start(struct wl1271 *wl)
|
||||
{
|
||||
int retries = WL1271_BOOT_RETRIES;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
@ -696,35 +702,48 @@ int wl1271_plt_start(struct wl1271 *wl)
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl->state = WL1271_STATE_PLT;
|
||||
while (retries) {
|
||||
retries--;
|
||||
ret = wl1271_chip_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto power_off;
|
||||
|
||||
ret = wl1271_chip_wakeup(wl);
|
||||
if (ret < 0)
|
||||
ret = wl1271_boot(wl);
|
||||
if (ret < 0)
|
||||
goto power_off;
|
||||
|
||||
ret = wl1271_plt_init(wl);
|
||||
if (ret < 0)
|
||||
goto irq_disable;
|
||||
|
||||
/* Make sure power saving is disabled */
|
||||
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
|
||||
if (ret < 0)
|
||||
goto irq_disable;
|
||||
|
||||
wl->state = WL1271_STATE_PLT;
|
||||
wl1271_notice("firmware booted in PLT mode (%s)",
|
||||
wl->chip.fw_ver);
|
||||
goto out;
|
||||
|
||||
ret = wl1271_boot(wl);
|
||||
if (ret < 0)
|
||||
goto out_power_off;
|
||||
|
||||
wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
|
||||
|
||||
ret = wl1271_plt_init(wl);
|
||||
if (ret < 0)
|
||||
goto out_irq_disable;
|
||||
|
||||
/* Make sure power saving is disabled */
|
||||
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
|
||||
if (ret < 0)
|
||||
goto out_irq_disable;
|
||||
|
||||
goto out;
|
||||
|
||||
out_irq_disable:
|
||||
wl1271_disable_interrupts(wl);
|
||||
|
||||
out_power_off:
|
||||
wl1271_power_off(wl);
|
||||
irq_disable:
|
||||
wl1271_disable_interrupts(wl);
|
||||
mutex_unlock(&wl->mutex);
|
||||
/* Unlocking the mutex in the middle of handling is
|
||||
inherently unsafe. In this case we deem it safe to do,
|
||||
because we need to let any possibly pending IRQ out of
|
||||
the system (and while we are WL1271_STATE_OFF the IRQ
|
||||
work function will not do anything.) Also, any other
|
||||
possible concurrent operations will fail due to the
|
||||
current state, hence the wl1271 struct should be safe. */
|
||||
cancel_work_sync(&wl->irq_work);
|
||||
mutex_lock(&wl->mutex);
|
||||
power_off:
|
||||
wl1271_power_off(wl);
|
||||
}
|
||||
|
||||
wl1271_error("firmware boot in PLT mode failed despite %d retries",
|
||||
WL1271_BOOT_RETRIES);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
@ -762,7 +781,20 @@ out:
|
||||
static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_sta *sta = txinfo->control.sta;
|
||||
unsigned long flags;
|
||||
|
||||
/* peek into the rates configured in the STA entry */
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) {
|
||||
wl->sta_rate_set = sta->supp_rates[conf->channel->band];
|
||||
set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
|
||||
/* queue the packet */
|
||||
skb_queue_tail(&wl->tx_queue, skb);
|
||||
|
||||
/*
|
||||
@ -784,7 +816,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
* protected. Maybe fix this by removing the stupid
|
||||
* variable altogether and checking the real queue state?
|
||||
*/
|
||||
wl->tx_queue_stopped = true;
|
||||
set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
@ -880,6 +912,7 @@ static struct notifier_block wl1271_dev_notifier = {
|
||||
static int wl1271_op_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
int retries = WL1271_BOOT_RETRIES;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 start");
|
||||
@ -893,30 +926,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_chip_wakeup(wl);
|
||||
if (ret < 0)
|
||||
while (retries) {
|
||||
retries--;
|
||||
ret = wl1271_chip_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto power_off;
|
||||
|
||||
ret = wl1271_boot(wl);
|
||||
if (ret < 0)
|
||||
goto power_off;
|
||||
|
||||
ret = wl1271_hw_init(wl);
|
||||
if (ret < 0)
|
||||
goto irq_disable;
|
||||
|
||||
wl->state = WL1271_STATE_ON;
|
||||
wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
|
||||
goto out;
|
||||
|
||||
ret = wl1271_boot(wl);
|
||||
if (ret < 0)
|
||||
goto out_power_off;
|
||||
|
||||
ret = wl1271_hw_init(wl);
|
||||
if (ret < 0)
|
||||
goto out_irq_disable;
|
||||
|
||||
wl->state = WL1271_STATE_ON;
|
||||
|
||||
wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
|
||||
|
||||
goto out;
|
||||
|
||||
out_irq_disable:
|
||||
wl1271_disable_interrupts(wl);
|
||||
|
||||
out_power_off:
|
||||
wl1271_power_off(wl);
|
||||
irq_disable:
|
||||
wl1271_disable_interrupts(wl);
|
||||
mutex_unlock(&wl->mutex);
|
||||
/* Unlocking the mutex in the middle of handling is
|
||||
inherently unsafe. In this case we deem it safe to do,
|
||||
because we need to let any possibly pending IRQ out of
|
||||
the system (and while we are WL1271_STATE_OFF the IRQ
|
||||
work function will not do anything.) Also, any other
|
||||
possible concurrent operations will fail due to the
|
||||
current state, hence the wl1271 struct should be safe. */
|
||||
cancel_work_sync(&wl->irq_work);
|
||||
mutex_lock(&wl->mutex);
|
||||
power_off:
|
||||
wl1271_power_off(wl);
|
||||
}
|
||||
|
||||
wl1271_error("firmware boot failed despite %d retries",
|
||||
WL1271_BOOT_RETRIES);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
@ -944,11 +989,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
||||
|
||||
WARN_ON(wl->state != WL1271_STATE_ON);
|
||||
|
||||
if (wl->scanning) {
|
||||
if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
ieee80211_scan_completed(wl->hw, true);
|
||||
mutex_lock(&wl->mutex);
|
||||
wl->scanning = false;
|
||||
}
|
||||
|
||||
wl->state = WL1271_STATE_OFF;
|
||||
@ -973,10 +1017,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
||||
wl->band = IEEE80211_BAND_2GHZ;
|
||||
|
||||
wl->rx_counter = 0;
|
||||
wl->elp = false;
|
||||
wl->psm = 0;
|
||||
wl->psm_entry_retry = 0;
|
||||
wl->tx_queue_stopped = false;
|
||||
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
|
||||
wl->tx_blocks_available = 0;
|
||||
wl->tx_results_count = 0;
|
||||
@ -986,7 +1027,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
||||
wl->tx_security_seq_32 = 0;
|
||||
wl->time_offset = 0;
|
||||
wl->session_counter = 0;
|
||||
wl->joined = false;
|
||||
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
|
||||
wl->sta_rate_set = 0;
|
||||
wl->flags = 0;
|
||||
|
||||
for (i = 0; i < NUM_TX_QUEUES; i++)
|
||||
wl->tx_blocks_freed[i] = 0;
|
||||
@ -996,13 +1039,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
||||
conf->type, conf->mac_addr);
|
||||
vif->type, vif->addr);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
if (wl->vif) {
|
||||
@ -1010,9 +1053,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl->vif = conf->vif;
|
||||
wl->vif = vif;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
wl->bss_type = BSS_TYPE_STA_BSS;
|
||||
break;
|
||||
@ -1032,7 +1075,7 @@ out:
|
||||
}
|
||||
|
||||
static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
|
||||
@ -1109,6 +1152,51 @@ out:
|
||||
}
|
||||
#endif
|
||||
|
||||
static int wl1271_join_channel(struct wl1271 *wl, int channel)
|
||||
{
|
||||
int ret = 0;
|
||||
/* we need to use a dummy BSSID for now */
|
||||
static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
|
||||
0xad, 0xbe, 0xef };
|
||||
|
||||
/* the dummy join is not required for ad-hoc */
|
||||
if (wl->bss_type == BSS_TYPE_IBSS)
|
||||
goto out;
|
||||
|
||||
/* disable mac filter, so we hear everything */
|
||||
wl->rx_config &= ~CFG_BSSID_FILTER_EN;
|
||||
|
||||
wl->channel = channel;
|
||||
memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
|
||||
|
||||
ret = wl1271_cmd_join(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
set_bit(WL1271_FLAG_JOINED, &wl->flags);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_unjoin_channel(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* to stop listening to a channel, we disconnect */
|
||||
ret = wl1271_cmd_disconnect(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
clear_bit(WL1271_FLAG_JOINED, &wl->flags);
|
||||
wl->channel = 0;
|
||||
memset(wl->bssid, 0, ETH_ALEN);
|
||||
wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
@ -1117,10 +1205,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s",
|
||||
channel,
|
||||
conf->flags & IEEE80211_CONF_PS ? "on" : "off",
|
||||
conf->power_level);
|
||||
conf->power_level,
|
||||
conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use");
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
@ -1130,34 +1219,44 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (channel != wl->channel) {
|
||||
/*
|
||||
* We assume that the stack will configure the right channel
|
||||
* before associating, so we don't need to send a join
|
||||
* command here. We will join the right channel when the
|
||||
* BSSID changes
|
||||
*/
|
||||
wl->channel = channel;
|
||||
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||
if (conf->flags & IEEE80211_CONF_IDLE &&
|
||||
test_bit(WL1271_FLAG_JOINED, &wl->flags))
|
||||
wl1271_unjoin_channel(wl);
|
||||
else if (!(conf->flags & IEEE80211_CONF_IDLE))
|
||||
wl1271_join_channel(wl, channel);
|
||||
|
||||
if (conf->flags & IEEE80211_CONF_IDLE) {
|
||||
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
|
||||
wl->sta_rate_set = 0;
|
||||
wl1271_acx_rate_policies(wl);
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
|
||||
wl1271_info("psm enabled");
|
||||
/* if the channel changes while joined, join again */
|
||||
if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags))
|
||||
wl1271_join_channel(wl, channel);
|
||||
|
||||
wl->psm_requested = true;
|
||||
if (conf->flags & IEEE80211_CONF_PS &&
|
||||
!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
|
||||
set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
|
||||
|
||||
/*
|
||||
* We enter PSM only if we're already associated.
|
||||
* If we're not, we'll enter it when joining an SSID,
|
||||
* through the bss_info_changed() hook.
|
||||
*/
|
||||
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
|
||||
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
|
||||
wl1271_info("psm enabled");
|
||||
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
|
||||
}
|
||||
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
|
||||
wl->psm_requested) {
|
||||
test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
|
||||
wl1271_info("psm disabled");
|
||||
|
||||
wl->psm_requested = false;
|
||||
clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
|
||||
|
||||
if (wl->psm)
|
||||
if (test_bit(WL1271_FLAG_PSM, &wl->flags))
|
||||
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
|
||||
}
|
||||
|
||||
@ -1440,22 +1539,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set)
|
||||
{
|
||||
struct ieee80211_supported_band *band;
|
||||
u32 enabled_rates = 0;
|
||||
int bit;
|
||||
|
||||
band = wl->hw->wiphy->bands[wl->band];
|
||||
for (bit = 0; bit < band->n_bitrates; bit++) {
|
||||
if (basic_rate_set & 0x1)
|
||||
enabled_rates |= band->bitrates[bit].hw_value;
|
||||
basic_rate_set >>= 1;
|
||||
}
|
||||
|
||||
return enabled_rates;
|
||||
}
|
||||
|
||||
static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
@ -1473,9 +1556,68 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if ((changed & BSS_CHANGED_BSSID) &&
|
||||
/*
|
||||
* Now we know the correct bssid, so we send a new join command
|
||||
* and enable the BSSID filter
|
||||
*/
|
||||
memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
|
||||
wl->rx_config |= CFG_BSSID_FILTER_EN;
|
||||
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
ret = wl1271_cmd_build_null_data(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("cmd buld null data failed %d",
|
||||
ret);
|
||||
goto out_sleep;
|
||||
}
|
||||
ret = wl1271_cmd_join(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("cmd join failed %d", ret);
|
||||
goto out_sleep;
|
||||
}
|
||||
set_bit(WL1271_FLAG_JOINED, &wl->flags);
|
||||
}
|
||||
|
||||
if (wl->bss_type == BSS_TYPE_IBSS) {
|
||||
/* FIXME: This implements rudimentary ad-hoc support -
|
||||
proper templates are on the wish list and notification
|
||||
on when they change. This patch will update the templates
|
||||
on every call to this function. Also, the firmware will not
|
||||
answer to probe-requests as it does not have the proper
|
||||
SSID set in the JOIN command. The probe-response template
|
||||
is set nevertheless, as the FW will ASSERT without it */
|
||||
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
|
||||
|
||||
if (beacon) {
|
||||
struct ieee80211_hdr *hdr;
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
|
||||
beacon->data,
|
||||
beacon->len);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_kfree_skb(beacon);
|
||||
goto out_sleep;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *) beacon->data;
|
||||
hdr->frame_control = cpu_to_le16(
|
||||
IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_PROBE_RESP);
|
||||
|
||||
ret = wl1271_cmd_template_set(wl,
|
||||
CMD_TEMPL_PROBE_RESPONSE,
|
||||
beacon->data,
|
||||
beacon->len);
|
||||
dev_kfree_skb(beacon);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
if (bss_conf->assoc) {
|
||||
wl->aid = bss_conf->aid;
|
||||
set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
|
||||
|
||||
/*
|
||||
* with wl1271, we don't need to update the
|
||||
@ -1492,7 +1634,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
goto out_sleep;
|
||||
|
||||
/* If we want to go in PSM but we're not there yet */
|
||||
if (wl->psm_requested && !wl->psm) {
|
||||
if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
|
||||
!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||
mode = STATION_POWER_SAVE_MODE;
|
||||
ret = wl1271_ps_set_mode(wl, mode);
|
||||
if (ret < 0)
|
||||
@ -1500,7 +1643,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
} else {
|
||||
/* use defaults when not associated */
|
||||
wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
|
||||
clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
|
||||
wl->aid = 0;
|
||||
}
|
||||
|
||||
@ -1535,17 +1678,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BASIC_RATES) {
|
||||
wl->basic_rate_set = wl1271_enabled_rates_get(
|
||||
wl, bss_conf->basic_rates);
|
||||
|
||||
ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Set rate policies failed %d", ret);
|
||||
goto out_sleep;
|
||||
}
|
||||
}
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
@ -1599,19 +1731,19 @@ static struct ieee80211_rate wl1271_rates[] = {
|
||||
|
||||
/* can't be const, mac80211 writes to this */
|
||||
static struct ieee80211_channel wl1271_channels[] = {
|
||||
{ .hw_value = 1, .center_freq = 2412},
|
||||
{ .hw_value = 2, .center_freq = 2417},
|
||||
{ .hw_value = 3, .center_freq = 2422},
|
||||
{ .hw_value = 4, .center_freq = 2427},
|
||||
{ .hw_value = 5, .center_freq = 2432},
|
||||
{ .hw_value = 6, .center_freq = 2437},
|
||||
{ .hw_value = 7, .center_freq = 2442},
|
||||
{ .hw_value = 8, .center_freq = 2447},
|
||||
{ .hw_value = 9, .center_freq = 2452},
|
||||
{ .hw_value = 10, .center_freq = 2457},
|
||||
{ .hw_value = 11, .center_freq = 2462},
|
||||
{ .hw_value = 12, .center_freq = 2467},
|
||||
{ .hw_value = 13, .center_freq = 2472},
|
||||
{ .hw_value = 1, .center_freq = 2412, .max_power = 25 },
|
||||
{ .hw_value = 2, .center_freq = 2417, .max_power = 25 },
|
||||
{ .hw_value = 3, .center_freq = 2422, .max_power = 25 },
|
||||
{ .hw_value = 4, .center_freq = 2427, .max_power = 25 },
|
||||
{ .hw_value = 5, .center_freq = 2432, .max_power = 25 },
|
||||
{ .hw_value = 6, .center_freq = 2437, .max_power = 25 },
|
||||
{ .hw_value = 7, .center_freq = 2442, .max_power = 25 },
|
||||
{ .hw_value = 8, .center_freq = 2447, .max_power = 25 },
|
||||
{ .hw_value = 9, .center_freq = 2452, .max_power = 25 },
|
||||
{ .hw_value = 10, .center_freq = 2457, .max_power = 25 },
|
||||
{ .hw_value = 11, .center_freq = 2462, .max_power = 25 },
|
||||
{ .hw_value = 12, .center_freq = 2467, .max_power = 25 },
|
||||
{ .hw_value = 13, .center_freq = 2472, .max_power = 25 },
|
||||
};
|
||||
|
||||
/* can't be const, mac80211 writes to this */
|
||||
@ -1757,7 +1889,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
||||
IEEE80211_HW_BEACON_FILTER |
|
||||
IEEE80211_HW_SUPPORTS_PS;
|
||||
|
||||
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
wl->hw->wiphy->max_scan_ssids = 1;
|
||||
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
|
||||
|
||||
@ -1818,21 +1951,18 @@ static int __devinit wl1271_probe(struct spi_device *spi)
|
||||
|
||||
INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
|
||||
wl->channel = WL1271_DEFAULT_CHANNEL;
|
||||
wl->scanning = false;
|
||||
wl->default_key = 0;
|
||||
wl->rx_counter = 0;
|
||||
wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
|
||||
wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
|
||||
wl->elp = false;
|
||||
wl->psm = 0;
|
||||
wl->psm_requested = false;
|
||||
wl->psm_entry_retry = 0;
|
||||
wl->tx_queue_stopped = false;
|
||||
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
|
||||
wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
|
||||
wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
|
||||
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
|
||||
wl->sta_rate_set = 0;
|
||||
wl->band = IEEE80211_BAND_2GHZ;
|
||||
wl->vif = NULL;
|
||||
wl->joined = false;
|
||||
wl->flags = 0;
|
||||
|
||||
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
|
||||
wl->tx_frames[i] = NULL;
|
||||
|
@ -39,12 +39,13 @@ void wl1271_elp_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->elp || !wl->psm)
|
||||
if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
|
||||
!test_bit(WL1271_FLAG_PSM, &wl->flags))
|
||||
goto out;
|
||||
|
||||
wl1271_debug(DEBUG_PSM, "chip to elp");
|
||||
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
|
||||
wl->elp = true;
|
||||
set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
@ -55,7 +56,7 @@ out:
|
||||
/* Routines to toggle sleep mode while in ELP */
|
||||
void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
||||
{
|
||||
if (wl->psm) {
|
||||
if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||
cancel_delayed_work(&wl->elp_work);
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
||||
msecs_to_jiffies(ELP_ENTRY_DELAY));
|
||||
@ -70,7 +71,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
|
||||
u32 start_time = jiffies;
|
||||
bool pending = false;
|
||||
|
||||
if (!wl->elp)
|
||||
if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
|
||||
return 0;
|
||||
|
||||
wl1271_debug(DEBUG_PSM, "waking up chip from elp");
|
||||
@ -101,7 +102,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
|
||||
}
|
||||
}
|
||||
|
||||
wl->elp = false;
|
||||
clear_bit(WL1271_FLAG_IN_ELP, &wl->flags);
|
||||
|
||||
wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
|
||||
jiffies_to_msecs(jiffies - start_time));
|
||||
@ -143,7 +144,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wl->psm = 1;
|
||||
set_bit(WL1271_FLAG_PSM, &wl->flags);
|
||||
break;
|
||||
case STATION_ACTIVE_MODE:
|
||||
default:
|
||||
@ -166,7 +167,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wl->psm = 0;
|
||||
clear_bit(WL1271_FLAG_PSM, &wl->flags);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
|
||||
pad = pad - skb->len;
|
||||
tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
|
||||
|
||||
/* if the packets are destined for AP (have a STA entry) send them
|
||||
with AP rate policies, otherwise use default basic rates */
|
||||
if (control->control.sta)
|
||||
tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY;
|
||||
|
||||
desc->tx_attr = cpu_to_le16(tx_attr);
|
||||
|
||||
wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
|
||||
@ -214,18 +219,50 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
|
||||
{
|
||||
struct ieee80211_supported_band *band;
|
||||
u32 enabled_rates = 0;
|
||||
int bit;
|
||||
|
||||
band = wl->hw->wiphy->bands[wl->band];
|
||||
for (bit = 0; bit < band->n_bitrates; bit++) {
|
||||
if (rate_set & 0x1)
|
||||
enabled_rates |= band->bitrates[bit].hw_value;
|
||||
rate_set >>= 1;
|
||||
}
|
||||
|
||||
return enabled_rates;
|
||||
}
|
||||
|
||||
void wl1271_tx_work(struct work_struct *work)
|
||||
{
|
||||
struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
|
||||
struct sk_buff *skb;
|
||||
bool woken_up = false;
|
||||
u32 sta_rates = 0;
|
||||
int ret;
|
||||
|
||||
/* check if the rates supported by the AP have changed */
|
||||
if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED,
|
||||
&wl->flags))) {
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
sta_rates = wl->sta_rate_set;
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
goto out;
|
||||
|
||||
/* if rates have changed, re-configure the rate policy */
|
||||
if (unlikely(sta_rates)) {
|
||||
wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
|
||||
wl1271_acx_rate_policies(wl);
|
||||
}
|
||||
|
||||
while ((skb = skb_dequeue(&wl->tx_queue))) {
|
||||
if (!woken_up) {
|
||||
ret = wl1271_ps_elp_wakeup(wl, false);
|
||||
@ -240,18 +277,18 @@ void wl1271_tx_work(struct work_struct *work)
|
||||
wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, "
|
||||
"stop queues");
|
||||
ieee80211_stop_queues(wl->hw);
|
||||
wl->tx_queue_stopped = true;
|
||||
set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
|
||||
skb_queue_head(&wl->tx_queue, skb);
|
||||
goto out;
|
||||
} else if (ret < 0) {
|
||||
dev_kfree_skb(skb);
|
||||
goto out;
|
||||
} else if (wl->tx_queue_stopped) {
|
||||
} else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED,
|
||||
&wl->flags)) {
|
||||
/* firmware buffer has space, restart queues */
|
||||
wl1271_debug(DEBUG_TX,
|
||||
"complete_packet: waking queues");
|
||||
ieee80211_wake_queues(wl->hw);
|
||||
wl->tx_queue_stopped = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1325,151 +1325,11 @@ int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size)
|
||||
{
|
||||
static const u16 constants[] = {
|
||||
715, 655, 585, 540, 470, 410, 360, 315,
|
||||
270, 235, 205, 175, 150, 125, 105, 85,
|
||||
65, 50, 40, 25, 15
|
||||
};
|
||||
|
||||
int i;
|
||||
u32 x;
|
||||
|
||||
/* It seems that their quality parameter is somehow per signal
|
||||
* and is now transferred per bit.
|
||||
*/
|
||||
switch (zd_rate) {
|
||||
case ZD_OFDM_RATE_6M:
|
||||
case ZD_OFDM_RATE_12M:
|
||||
case ZD_OFDM_RATE_24M:
|
||||
size *= 2;
|
||||
break;
|
||||
case ZD_OFDM_RATE_9M:
|
||||
case ZD_OFDM_RATE_18M:
|
||||
case ZD_OFDM_RATE_36M:
|
||||
case ZD_OFDM_RATE_54M:
|
||||
size *= 4;
|
||||
size /= 3;
|
||||
break;
|
||||
case ZD_OFDM_RATE_48M:
|
||||
size *= 3;
|
||||
size /= 2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
x = (10000 * status_quality)/size;
|
||||
for (i = 0; i < ARRAY_SIZE(constants); i++) {
|
||||
if (x > constants[i])
|
||||
break;
|
||||
}
|
||||
|
||||
switch (zd_rate) {
|
||||
case ZD_OFDM_RATE_6M:
|
||||
case ZD_OFDM_RATE_9M:
|
||||
i += 3;
|
||||
break;
|
||||
case ZD_OFDM_RATE_12M:
|
||||
case ZD_OFDM_RATE_18M:
|
||||
i += 5;
|
||||
break;
|
||||
case ZD_OFDM_RATE_24M:
|
||||
case ZD_OFDM_RATE_36M:
|
||||
i += 9;
|
||||
break;
|
||||
case ZD_OFDM_RATE_48M:
|
||||
case ZD_OFDM_RATE_54M:
|
||||
i += 15;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int ofdm_qual_percent(u8 status_quality, u8 zd_rate, unsigned int size)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = ofdm_qual_db(status_quality, zd_rate, size);
|
||||
ZD_ASSERT(r >= 0);
|
||||
if (r < 0)
|
||||
r = 0;
|
||||
|
||||
r = (r * 100)/29;
|
||||
return r <= 100 ? r : 100;
|
||||
}
|
||||
|
||||
static unsigned int log10times100(unsigned int x)
|
||||
{
|
||||
static const u8 log10[] = {
|
||||
0,
|
||||
0, 30, 47, 60, 69, 77, 84, 90, 95, 100,
|
||||
104, 107, 111, 114, 117, 120, 123, 125, 127, 130,
|
||||
132, 134, 136, 138, 139, 141, 143, 144, 146, 147,
|
||||
149, 150, 151, 153, 154, 155, 156, 157, 159, 160,
|
||||
161, 162, 163, 164, 165, 166, 167, 168, 169, 169,
|
||||
170, 171, 172, 173, 174, 174, 175, 176, 177, 177,
|
||||
178, 179, 179, 180, 181, 181, 182, 183, 183, 184,
|
||||
185, 185, 186, 186, 187, 188, 188, 189, 189, 190,
|
||||
190, 191, 191, 192, 192, 193, 193, 194, 194, 195,
|
||||
195, 196, 196, 197, 197, 198, 198, 199, 199, 200,
|
||||
200, 200, 201, 201, 202, 202, 202, 203, 203, 204,
|
||||
204, 204, 205, 205, 206, 206, 206, 207, 207, 207,
|
||||
208, 208, 208, 209, 209, 210, 210, 210, 211, 211,
|
||||
211, 212, 212, 212, 213, 213, 213, 213, 214, 214,
|
||||
214, 215, 215, 215, 216, 216, 216, 217, 217, 217,
|
||||
217, 218, 218, 218, 219, 219, 219, 219, 220, 220,
|
||||
220, 220, 221, 221, 221, 222, 222, 222, 222, 223,
|
||||
223, 223, 223, 224, 224, 224, 224,
|
||||
};
|
||||
|
||||
return x < ARRAY_SIZE(log10) ? log10[x] : 225;
|
||||
}
|
||||
|
||||
enum {
|
||||
MAX_CCK_EVM_DB = 45,
|
||||
};
|
||||
|
||||
static int cck_evm_db(u8 status_quality)
|
||||
{
|
||||
return (20 * log10times100(status_quality)) / 100;
|
||||
}
|
||||
|
||||
static int cck_snr_db(u8 status_quality)
|
||||
{
|
||||
int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality);
|
||||
ZD_ASSERT(r >= 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int cck_qual_percent(u8 status_quality)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = cck_snr_db(status_quality);
|
||||
r = (100*r)/17;
|
||||
return r <= 100 ? r : 100;
|
||||
}
|
||||
|
||||
static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame)
|
||||
{
|
||||
return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame);
|
||||
}
|
||||
|
||||
u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
|
||||
const struct rx_status *status)
|
||||
{
|
||||
return (status->frame_status&ZD_RX_OFDM) ?
|
||||
ofdm_qual_percent(status->signal_quality_ofdm,
|
||||
zd_rate_from_ofdm_plcp_header(rx_frame),
|
||||
size) :
|
||||
cck_qual_percent(status->signal_quality_cck);
|
||||
}
|
||||
|
||||
/**
|
||||
* zd_rx_rate - report zd-rate
|
||||
* @rx_frame - received frame
|
||||
|
@ -929,9 +929,6 @@ static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
|
||||
|
||||
struct rx_status;
|
||||
|
||||
u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
|
||||
const struct rx_status *status);
|
||||
|
||||
u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
|
||||
|
||||
struct zd_mc_hash {
|
||||
|
@ -828,9 +828,6 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
|
||||
stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
|
||||
stats.band = IEEE80211_BAND_2GHZ;
|
||||
stats.signal = status->signal_strength;
|
||||
stats.qual = zd_rx_qual_percent(buffer,
|
||||
length - sizeof(struct rx_status),
|
||||
status);
|
||||
|
||||
rate = zd_rx_rate(buffer, status);
|
||||
|
||||
@ -872,7 +869,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
|
||||
}
|
||||
|
||||
static int zd_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct zd_mac *mac = zd_hw_mac(hw);
|
||||
|
||||
@ -880,22 +877,22 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
|
||||
if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (conf->type) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
mac->type = conf->type;
|
||||
mac->type = vif->type;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return zd_write_mac_addr(&mac->chip, conf->mac_addr);
|
||||
return zd_write_mac_addr(&mac->chip, vif->addr);
|
||||
}
|
||||
|
||||
static void zd_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct zd_mac *mac = zd_hw_mac(hw);
|
||||
mac->type = NL80211_IFTYPE_UNSPECIFIED;
|
||||
|
@ -1085,12 +1085,12 @@ enum ieee80211_eid {
|
||||
WLAN_EID_TIM = 5,
|
||||
WLAN_EID_IBSS_PARAMS = 6,
|
||||
WLAN_EID_CHALLENGE = 16,
|
||||
/* 802.11d */
|
||||
|
||||
WLAN_EID_COUNTRY = 7,
|
||||
WLAN_EID_HP_PARAMS = 8,
|
||||
WLAN_EID_HP_TABLE = 9,
|
||||
WLAN_EID_REQUEST = 10,
|
||||
/* 802.11e */
|
||||
|
||||
WLAN_EID_QBSS_LOAD = 11,
|
||||
WLAN_EID_EDCA_PARAM_SET = 12,
|
||||
WLAN_EID_TSPEC = 13,
|
||||
@ -1113,7 +1113,7 @@ enum ieee80211_eid {
|
||||
WLAN_EID_PREP = 69,
|
||||
WLAN_EID_PERR = 70,
|
||||
WLAN_EID_RANN = 49, /* compatible with FreeBSD */
|
||||
/* 802.11h */
|
||||
|
||||
WLAN_EID_PWR_CONSTRAINT = 32,
|
||||
WLAN_EID_PWR_CAPABILITY = 33,
|
||||
WLAN_EID_TPC_REQUEST = 34,
|
||||
@ -1124,20 +1124,41 @@ enum ieee80211_eid {
|
||||
WLAN_EID_MEASURE_REPORT = 39,
|
||||
WLAN_EID_QUIET = 40,
|
||||
WLAN_EID_IBSS_DFS = 41,
|
||||
/* 802.11g */
|
||||
|
||||
WLAN_EID_ERP_INFO = 42,
|
||||
WLAN_EID_EXT_SUPP_RATES = 50,
|
||||
/* 802.11n */
|
||||
|
||||
WLAN_EID_HT_CAPABILITY = 45,
|
||||
WLAN_EID_HT_INFORMATION = 61,
|
||||
/* 802.11i */
|
||||
|
||||
WLAN_EID_RSN = 48,
|
||||
WLAN_EID_TIMEOUT_INTERVAL = 56,
|
||||
WLAN_EID_MMIE = 76 /* 802.11w */,
|
||||
WLAN_EID_MMIE = 76,
|
||||
WLAN_EID_WPA = 221,
|
||||
WLAN_EID_GENERIC = 221,
|
||||
WLAN_EID_VENDOR_SPECIFIC = 221,
|
||||
WLAN_EID_QOS_PARAMETER = 222
|
||||
WLAN_EID_QOS_PARAMETER = 222,
|
||||
|
||||
WLAN_EID_AP_CHAN_REPORT = 51,
|
||||
WLAN_EID_NEIGHBOR_REPORT = 52,
|
||||
WLAN_EID_RCPI = 53,
|
||||
WLAN_EID_BSS_AVG_ACCESS_DELAY = 63,
|
||||
WLAN_EID_ANTENNA_INFO = 64,
|
||||
WLAN_EID_RSNI = 65,
|
||||
WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66,
|
||||
WLAN_EID_BSS_AVAILABLE_CAPACITY = 67,
|
||||
WLAN_EID_BSS_AC_ACCESS_DELAY = 68,
|
||||
WLAN_EID_RRM_ENABLED_CAPABILITIES = 70,
|
||||
WLAN_EID_MULTIPLE_BSSID = 71,
|
||||
|
||||
WLAN_EID_MOBILITY_DOMAIN = 54,
|
||||
WLAN_EID_FAST_BSS_TRANSITION = 55,
|
||||
WLAN_EID_TIMEOUT_INTERVAL = 56,
|
||||
WLAN_EID_RIC_DATA = 57,
|
||||
WLAN_EID_RIC_DESCRIPTOR = 75,
|
||||
|
||||
WLAN_EID_DSE_REGISTERED_LOCATION = 58,
|
||||
WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
|
||||
WLAN_EID_EXT_CHANSWITCH_ANN = 60,
|
||||
};
|
||||
|
||||
/* Action category code */
|
||||
|
@ -270,6 +270,31 @@
|
||||
* @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
|
||||
* associated with this wiphy must be down and will follow.
|
||||
*
|
||||
* @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified
|
||||
* channel for the specified amount of time. This can be used to do
|
||||
* off-channel operations like transmit a Public Action frame and wait for
|
||||
* a response while being associated to an AP on another channel.
|
||||
* %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify which
|
||||
* radio is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
|
||||
* frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
|
||||
* optionally used to specify additional channel parameters.
|
||||
* %NL80211_ATTR_DURATION is used to specify the duration in milliseconds
|
||||
* to remain on the channel. This command is also used as an event to
|
||||
* notify when the requested duration starts (it may take a while for the
|
||||
* driver to schedule this time due to other concurrent needs for the
|
||||
* radio).
|
||||
* When called, this operation returns a cookie (%NL80211_ATTR_COOKIE)
|
||||
* that will be included with any events pertaining to this request;
|
||||
* the cookie is also used to cancel the request.
|
||||
* @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a
|
||||
* pending remain-on-channel duration if the desired operation has been
|
||||
* completed prior to expiration of the originally requested duration.
|
||||
* %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the
|
||||
* radio. The %NL80211_ATTR_COOKIE attribute must be given as well to
|
||||
* uniquely identify the request.
|
||||
* This command is also used as an event to notify when a requested
|
||||
* remain-on-channel duration has expired.
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
@ -353,6 +378,9 @@ enum nl80211_commands {
|
||||
NL80211_CMD_DEL_PMKSA,
|
||||
NL80211_CMD_FLUSH_PMKSA,
|
||||
|
||||
NL80211_CMD_REMAIN_ON_CHANNEL,
|
||||
NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
@ -606,6 +634,10 @@ enum nl80211_commands {
|
||||
* @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
|
||||
* cache, a wiphy attribute.
|
||||
*
|
||||
* @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32.
|
||||
*
|
||||
* @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects.
|
||||
*
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
*/
|
||||
@ -743,6 +775,10 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_PMKID,
|
||||
NL80211_ATTR_MAX_NUM_PMKIDS,
|
||||
|
||||
NL80211_ATTR_DURATION,
|
||||
|
||||
NL80211_ATTR_COOKIE,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -988,6 +988,15 @@ struct cfg80211_pmksa {
|
||||
*
|
||||
* @dump_survey: get site survey information.
|
||||
*
|
||||
* @remain_on_channel: Request the driver to remain awake on the specified
|
||||
* channel for the specified duration to complete an off-channel
|
||||
* operation (e.g., public action frame exchange). When the driver is
|
||||
* ready on the requested channel, it must indicate this with an event
|
||||
* notification by calling cfg80211_ready_on_channel().
|
||||
* @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation.
|
||||
* This allows the operation to be terminated prior to timeout based on
|
||||
* the duration value.
|
||||
*
|
||||
* @testmode_cmd: run a test mode command
|
||||
*
|
||||
* @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac
|
||||
@ -1123,6 +1132,16 @@ struct cfg80211_ops {
|
||||
struct cfg80211_pmksa *pmksa);
|
||||
int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
|
||||
|
||||
int (*remain_on_channel)(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration,
|
||||
u64 *cookie);
|
||||
int (*cancel_remain_on_channel)(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
u64 cookie);
|
||||
|
||||
/* some temporary stuff to finish wext */
|
||||
int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
|
||||
bool enabled, int timeout);
|
||||
@ -2147,5 +2166,45 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
|
||||
void cfg80211_disconnected(struct net_device *dev, u16 reason,
|
||||
u8 *ie, size_t ie_len, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_ready_on_channel - notification of remain_on_channel start
|
||||
* @dev: network device
|
||||
* @cookie: the request cookie
|
||||
* @chan: The current channel (from remain_on_channel request)
|
||||
* @channel_type: Channel type
|
||||
* @duration: Duration in milliseconds that the driver intents to remain on the
|
||||
* channel
|
||||
* @gfp: allocation flags
|
||||
*/
|
||||
void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_remain_on_channel_expired - remain_on_channel duration expired
|
||||
* @dev: network device
|
||||
* @cookie: the request cookie
|
||||
* @chan: The current channel (from remain_on_channel request)
|
||||
* @channel_type: Channel type
|
||||
* @gfp: allocation flags
|
||||
*/
|
||||
void cfg80211_remain_on_channel_expired(struct net_device *dev,
|
||||
u64 cookie,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
gfp_t gfp);
|
||||
|
||||
|
||||
/**
|
||||
* cfg80211_new_sta - notify userspace about station
|
||||
*
|
||||
* @dev: the netdev
|
||||
* @mac_addr: the station's address
|
||||
* @sinfo: the station information
|
||||
* @gfp: allocation flags
|
||||
*/
|
||||
void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp);
|
||||
|
||||
#endif /* __NET_CFG80211_H */
|
||||
|
@ -547,7 +547,6 @@ enum mac80211_rx_flags {
|
||||
* unspecified depending on the hardware capabilities flags
|
||||
* @IEEE80211_HW_SIGNAL_*
|
||||
* @noise: noise when receiving this frame, in dBm.
|
||||
* @qual: overall signal quality indication, in percent (0-100).
|
||||
* @antenna: antenna used
|
||||
* @rate_idx: index of data rate into band's supported rates or MCS index if
|
||||
* HT rates are use (RX_FLAG_HT)
|
||||
@ -559,7 +558,6 @@ struct ieee80211_rx_status {
|
||||
int freq;
|
||||
int signal;
|
||||
int noise;
|
||||
int __deprecated qual;
|
||||
int antenna;
|
||||
int rate_idx;
|
||||
int flag;
|
||||
@ -701,33 +699,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct ieee80211_if_init_conf - initial configuration of an interface
|
||||
*
|
||||
* @vif: pointer to a driver-use per-interface structure. The pointer
|
||||
* itself is also used for various functions including
|
||||
* ieee80211_beacon_get() and ieee80211_get_buffered_bc().
|
||||
* @type: one of &enum nl80211_iftype constants. Determines the type of
|
||||
* added/removed interface.
|
||||
* @mac_addr: pointer to MAC address of the interface. This pointer is valid
|
||||
* until the interface is removed (i.e. it cannot be used after
|
||||
* remove_interface() callback was called for this interface).
|
||||
*
|
||||
* This structure is used in add_interface() and remove_interface()
|
||||
* callbacks of &struct ieee80211_hw.
|
||||
*
|
||||
* When you allow multiple interfaces to be added to your PHY, take care
|
||||
* that the hardware can actually handle multiple MAC addresses. However,
|
||||
* also take care that when there's no interface left with mac_addr != %NULL
|
||||
* you remove the MAC address from the device to avoid acknowledging packets
|
||||
* in pure monitor mode.
|
||||
*/
|
||||
struct ieee80211_if_init_conf {
|
||||
enum nl80211_iftype type;
|
||||
struct ieee80211_vif *vif;
|
||||
void *mac_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ieee80211_key_alg - key algorithm
|
||||
* @ALG_WEP: WEP40 or WEP104
|
||||
@ -1410,7 +1381,7 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* When the device is started it should not have a MAC address
|
||||
* to avoid acknowledging frames before a non-monitor device
|
||||
* is added.
|
||||
* Must be implemented.
|
||||
* Must be implemented and can sleep.
|
||||
*
|
||||
* @stop: Called after last netdevice attached to the hardware
|
||||
* is disabled. This should turn off the hardware (at least
|
||||
@ -1418,7 +1389,7 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* May be called right after add_interface if that rejects
|
||||
* an interface. If you added any work onto the mac80211 workqueue
|
||||
* you should ensure to cancel it on this callback.
|
||||
* Must be implemented.
|
||||
* Must be implemented and can sleep.
|
||||
*
|
||||
* @add_interface: Called when a netdevice attached to the hardware is
|
||||
* enabled. Because it is not called for monitor mode devices, @start
|
||||
@ -1428,7 +1399,7 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* interface is given in the conf parameter.
|
||||
* The callback may refuse to add an interface by returning a
|
||||
* negative error code (which will be seen in userspace.)
|
||||
* Must be implemented.
|
||||
* Must be implemented and can sleep.
|
||||
*
|
||||
* @remove_interface: Notifies a driver that an interface is going down.
|
||||
* The @stop callback is called after this if it is the last interface
|
||||
@ -1437,19 +1408,20 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* must be cleared so the device no longer acknowledges packets,
|
||||
* the mac_addr member of the conf structure is, however, set to the
|
||||
* MAC address of the device going away.
|
||||
* Hence, this callback must be implemented.
|
||||
* Hence, this callback must be implemented. It can sleep.
|
||||
*
|
||||
* @config: Handler for configuration requests. IEEE 802.11 code calls this
|
||||
* function to change hardware configuration, e.g., channel.
|
||||
* This function should never fail but returns a negative error code
|
||||
* if it does.
|
||||
* if it does. The callback can sleep.
|
||||
*
|
||||
* @bss_info_changed: Handler for configuration requests related to BSS
|
||||
* parameters that may vary during BSS's lifespan, and may affect low
|
||||
* level driver (e.g. assoc/disassoc status, erp parameters).
|
||||
* This function should not be used if no BSS has been set, unless
|
||||
* for association indication. The @changed parameter indicates which
|
||||
* of the bss parameters has changed when a call is made.
|
||||
* of the bss parameters has changed when a call is made. The callback
|
||||
* can sleep.
|
||||
*
|
||||
* @prepare_multicast: Prepare for multicast filter configuration.
|
||||
* This callback is optional, and its return value is passed
|
||||
@ -1457,20 +1429,22 @@ enum ieee80211_ampdu_mlme_action {
|
||||
*
|
||||
* @configure_filter: Configure the device's RX filter.
|
||||
* See the section "Frame filtering" for more information.
|
||||
* This callback must be implemented.
|
||||
* This callback must be implemented and can sleep.
|
||||
*
|
||||
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
|
||||
* must be set or cleared for a given STA. Must be atomic.
|
||||
*
|
||||
* @set_key: See the section "Hardware crypto acceleration"
|
||||
* This callback can sleep, and is only called between add_interface
|
||||
* and remove_interface calls, i.e. while the given virtual interface
|
||||
* This callback is only called between add_interface and
|
||||
* remove_interface calls, i.e. while the given virtual interface
|
||||
* is enabled.
|
||||
* Returns a negative error code if the key can't be added.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @update_tkip_key: See the section "Hardware crypto acceleration"
|
||||
* This callback will be called in the context of Rx. Called for drivers
|
||||
* which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @hw_scan: Ask the hardware to service the scan request, no need to start
|
||||
* the scan state machine in stack. The scan must honour the channel
|
||||
@ -1484,21 +1458,28 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* When the scan finishes, ieee80211_scan_completed() must be called;
|
||||
* note that it also must be called when the scan cannot finish due to
|
||||
* any error unless this callback returned a negative error code.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @sw_scan_start: Notifier function that is called just before a software scan
|
||||
* is started. Can be NULL, if the driver doesn't need this notification.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @sw_scan_complete: Notifier function that is called just after a software scan
|
||||
* finished. Can be NULL, if the driver doesn't need this notification.
|
||||
* @sw_scan_complete: Notifier function that is called just after a
|
||||
* software scan finished. Can be NULL, if the driver doesn't need
|
||||
* this notification.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @get_stats: Return low-level statistics.
|
||||
* Returns zero if statistics are available.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @get_tkip_seq: If your device implements TKIP encryption in hardware this
|
||||
* callback should be provided to read the TKIP transmit IVs (both IV32
|
||||
* and IV16) for the given key from hardware.
|
||||
* The callback must be atomic.
|
||||
*
|
||||
* @set_rts_threshold: Configuration of RTS threshold (if device needs it)
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @sta_notify: Notifies low level driver about addition, removal or power
|
||||
* state transition of an associated station, AP, IBSS/WDS/mesh peer etc.
|
||||
@ -1507,30 +1488,36 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
|
||||
* bursting) for a hardware TX queue.
|
||||
* Returns a negative error code on failure.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @get_tx_stats: Get statistics of the current TX queue status. This is used
|
||||
* to get number of currently queued packets (queue length), maximum queue
|
||||
* size (limit), and total number of packets sent using each TX queue
|
||||
* (count). The 'stats' pointer points to an array that has hw->queues
|
||||
* items.
|
||||
* The callback must be atomic.
|
||||
*
|
||||
* @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
|
||||
* this is only used for IBSS mode BSSID merging and debugging. Is not a
|
||||
* required function.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @set_tsf: Set the TSF timer to the specified value in the firmware/hardware.
|
||||
* Currently, this is only used for IBSS mode debugging. Is not a
|
||||
* required function.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
|
||||
* with other STAs in the IBSS. This is only used in IBSS mode. This
|
||||
* function is optional if the firmware/hardware takes full care of
|
||||
* TSF synchronization.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
|
||||
* This is needed only for IBSS mode and the result of this function is
|
||||
* used to determine whether to reply to Probe Requests.
|
||||
* Returns non-zero if this device sent the last beacon.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @ampdu_action: Perform a certain A-MPDU action
|
||||
* The RA/TID combination determines the destination and TID we want
|
||||
@ -1539,21 +1526,28 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* is the first frame we expect to perform the action on. Notice
|
||||
* that TX/RX_STOP can pass NULL for this parameter.
|
||||
* Returns a negative error code on failure.
|
||||
* The callback must be atomic.
|
||||
*
|
||||
* @rfkill_poll: Poll rfkill hardware state. If you need this, you also
|
||||
* need to set wiphy->rfkill_poll to %true before registration,
|
||||
* and need to call wiphy_rfkill_set_hw_state() in the callback.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @testmode_cmd: Implement a cfg80211 test mode command.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @flush: Flush all pending frames from the hardware queue, making sure
|
||||
* that the hardware queues are empty. If the parameter @drop is set
|
||||
* to %true, pending frames may be dropped. The callback can sleep.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int (*start)(struct ieee80211_hw *hw);
|
||||
void (*stop)(struct ieee80211_hw *hw);
|
||||
int (*add_interface)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
struct ieee80211_vif *vif);
|
||||
void (*remove_interface)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
struct ieee80211_vif *vif);
|
||||
int (*config)(struct ieee80211_hw *hw, u32 changed);
|
||||
void (*bss_info_changed)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
@ -1601,6 +1595,7 @@ struct ieee80211_ops {
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
|
||||
#endif
|
||||
void (*flush)(struct ieee80211_hw *hw, bool drop);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1840,7 +1835,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
||||
/**
|
||||
* ieee80211_beacon_get_tim - beacon generation function
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @tim_offset: pointer to variable that will receive the TIM IE offset.
|
||||
* Set to 0 if invalid (in non-AP modes).
|
||||
* @tim_length: pointer to variable that will receive the TIM IE length,
|
||||
@ -1868,7 +1863,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
||||
/**
|
||||
* ieee80211_beacon_get - beacon generation function
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* See ieee80211_beacon_get_tim().
|
||||
*/
|
||||
@ -1881,7 +1876,7 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
/**
|
||||
* ieee80211_rts_get - RTS frame generation function
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @frame: pointer to the frame that is going to be protected by the RTS.
|
||||
* @frame_len: the frame length (in octets).
|
||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
||||
@ -1900,7 +1895,7 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
/**
|
||||
* ieee80211_rts_duration - Get the duration field for an RTS frame
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @frame_len: the length of the frame that is going to be protected by the RTS.
|
||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
||||
*
|
||||
@ -1915,7 +1910,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
|
||||
/**
|
||||
* ieee80211_ctstoself_get - CTS-to-self frame generation function
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @frame: pointer to the frame that is going to be protected by the CTS-to-self.
|
||||
* @frame_len: the frame length (in octets).
|
||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
||||
@ -1935,7 +1930,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
|
||||
/**
|
||||
* ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
|
||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
||||
*
|
||||
@ -1951,7 +1946,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
|
||||
/**
|
||||
* ieee80211_generic_frame_duration - Calculate the duration field for a frame
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @frame_len: the length of the frame.
|
||||
* @rate: the rate at which the frame is going to be transmitted.
|
||||
*
|
||||
@ -1966,7 +1961,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
|
||||
/**
|
||||
* ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* Function for accessing buffered broadcast and multicast frames. If
|
||||
* hardware/firmware does not implement buffering of broadcast/multicast
|
||||
@ -2134,7 +2129,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid);
|
||||
|
||||
/**
|
||||
* ieee80211_start_tx_ba_cb - low level driver ready to aggregate.
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback
|
||||
* @ra: receiver address of the BA session recipient.
|
||||
* @tid: the TID to BA on.
|
||||
*
|
||||
@ -2145,7 +2140,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid);
|
||||
|
||||
/**
|
||||
* ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate.
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback
|
||||
* @ra: receiver address of the BA session recipient.
|
||||
* @tid: the TID to BA on.
|
||||
*
|
||||
@ -2173,7 +2168,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid,
|
||||
|
||||
/**
|
||||
* ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate.
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback
|
||||
* @ra: receiver address of the BA session recipient.
|
||||
* @tid: the desired TID to BA on.
|
||||
*
|
||||
@ -2184,7 +2179,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid);
|
||||
|
||||
/**
|
||||
* ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate.
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback
|
||||
* @ra: receiver address of the BA session recipient.
|
||||
* @tid: the desired TID to BA on.
|
||||
*
|
||||
@ -2263,7 +2258,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
|
||||
/**
|
||||
* ieee80211_beacon_loss - inform hardware does not receive beacons
|
||||
*
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and
|
||||
* IEEE80211_CONF_PS is set, the driver needs to inform whenever the
|
||||
|
@ -6,10 +6,10 @@ mac80211-y := \
|
||||
sta_info.o \
|
||||
wep.o \
|
||||
wpa.o \
|
||||
scan.o \
|
||||
scan.o offchannel.o \
|
||||
ht.o agg-tx.o agg-rx.o \
|
||||
ibss.o \
|
||||
mlme.o \
|
||||
mlme.o work.o \
|
||||
iface.o \
|
||||
rate.o \
|
||||
michael.o \
|
||||
|
@ -78,17 +78,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
|
||||
enum nl80211_iftype type, u32 *flags,
|
||||
struct vif_params *params)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
int ret;
|
||||
|
||||
if (netif_running(dev))
|
||||
if (ieee80211_sdata_running(sdata))
|
||||
return -EBUSY;
|
||||
|
||||
if (!nl80211_params_check(type, params))
|
||||
return -EINVAL;
|
||||
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
ret = ieee80211_if_change_type(sdata, type);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1345,7 +1343,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
|
||||
return 0;
|
||||
}
|
||||
|
||||
ap = sdata->u.mgd.associated->cbss.bssid;
|
||||
ap = sdata->u.mgd.associated->bssid;
|
||||
|
||||
if (smps_mode == IEEE80211_SMPS_AUTOMATIC) {
|
||||
if (sdata->u.mgd.powersave)
|
||||
@ -1443,6 +1441,28 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ieee80211_remain_on_channel(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration,
|
||||
u64 *cookie)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
return ieee80211_wk_remain_on_channel(sdata, chan, channel_type,
|
||||
duration, cookie);
|
||||
}
|
||||
|
||||
static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
u64 cookie)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
|
||||
}
|
||||
|
||||
struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
@ -1489,4 +1509,6 @@ struct cfg80211_ops mac80211_config_ops = {
|
||||
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
|
||||
.set_power_mgmt = ieee80211_set_power_mgmt,
|
||||
.set_bitrate_mask = ieee80211_set_bitrate_mask,
|
||||
.remain_on_channel = ieee80211_remain_on_channel,
|
||||
.cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
|
||||
};
|
||||
|
@ -133,7 +133,6 @@ IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC);
|
||||
/* STA attributes */
|
||||
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
|
||||
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
|
||||
IEEE80211_IF_FILE(capab, u.mgd.capab, HEX);
|
||||
|
||||
static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
||||
enum ieee80211_smps_mode smps_mode)
|
||||
@ -270,7 +269,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
DEBUGFS_ADD(bssid, sta);
|
||||
DEBUGFS_ADD(aid, sta);
|
||||
DEBUGFS_ADD(capab, sta);
|
||||
DEBUGFS_ADD_MODE(smps, 0600);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@ static inline int drv_start(struct ieee80211_local *local)
|
||||
{
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
local->started = true;
|
||||
smp_mb();
|
||||
ret = local->ops->start(&local->hw);
|
||||
@ -23,6 +25,8 @@ static inline int drv_start(struct ieee80211_local *local)
|
||||
|
||||
static inline void drv_stop(struct ieee80211_local *local)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
local->ops->stop(&local->hw);
|
||||
trace_drv_stop(local);
|
||||
|
||||
@ -36,23 +40,33 @@ static inline void drv_stop(struct ieee80211_local *local)
|
||||
}
|
||||
|
||||
static inline int drv_add_interface(struct ieee80211_local *local,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
int ret = local->ops->add_interface(&local->hw, conf);
|
||||
trace_drv_add_interface(local, vif_to_sdata(conf->vif), ret);
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
ret = local->ops->add_interface(&local->hw, vif);
|
||||
trace_drv_add_interface(local, vif_to_sdata(vif), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void drv_remove_interface(struct ieee80211_local *local,
|
||||
struct ieee80211_if_init_conf *conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
local->ops->remove_interface(&local->hw, conf);
|
||||
trace_drv_remove_interface(local, vif_to_sdata(conf->vif));
|
||||
might_sleep();
|
||||
|
||||
local->ops->remove_interface(&local->hw, vif);
|
||||
trace_drv_remove_interface(local, vif_to_sdata(vif));
|
||||
}
|
||||
|
||||
static inline int drv_config(struct ieee80211_local *local, u32 changed)
|
||||
{
|
||||
int ret = local->ops->config(&local->hw, changed);
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
ret = local->ops->config(&local->hw, changed);
|
||||
trace_drv_config(local, changed, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -62,6 +76,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
|
||||
struct ieee80211_bss_conf *info,
|
||||
u32 changed)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->bss_info_changed)
|
||||
local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
|
||||
trace_drv_bss_info_changed(local, sdata, info, changed);
|
||||
@ -111,7 +127,11 @@ static inline int drv_set_key(struct ieee80211_local *local,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
int ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
|
||||
trace_drv_set_key(local, cmd, sdata, sta, key, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -121,6 +141,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local,
|
||||
const u8 *address, u32 iv32,
|
||||
u16 *phase1key)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->update_tkip_key)
|
||||
local->ops->update_tkip_key(&local->hw, conf, address,
|
||||
iv32, phase1key);
|
||||
@ -130,13 +152,19 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local,
|
||||
static inline int drv_hw_scan(struct ieee80211_local *local,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
int ret = local->ops->hw_scan(&local->hw, req);
|
||||
int ret;
|
||||
|
||||
might_sleep();
|
||||
|
||||
ret = local->ops->hw_scan(&local->hw, req);
|
||||
trace_drv_hw_scan(local, req, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void drv_sw_scan_start(struct ieee80211_local *local)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->sw_scan_start)
|
||||
local->ops->sw_scan_start(&local->hw);
|
||||
trace_drv_sw_scan_start(local);
|
||||
@ -144,6 +172,8 @@ static inline void drv_sw_scan_start(struct ieee80211_local *local)
|
||||
|
||||
static inline void drv_sw_scan_complete(struct ieee80211_local *local)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->sw_scan_complete)
|
||||
local->ops->sw_scan_complete(&local->hw);
|
||||
trace_drv_sw_scan_complete(local);
|
||||
@ -154,6 +184,8 @@ static inline int drv_get_stats(struct ieee80211_local *local,
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->get_stats)
|
||||
ret = local->ops->get_stats(&local->hw, stats);
|
||||
trace_drv_get_stats(local, stats, ret);
|
||||
@ -173,6 +205,9 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local,
|
||||
u32 value)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->set_rts_threshold)
|
||||
ret = local->ops->set_rts_threshold(&local->hw, value);
|
||||
trace_drv_set_rts_threshold(local, value, ret);
|
||||
@ -193,6 +228,9 @@ static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->conf_tx)
|
||||
ret = local->ops->conf_tx(&local->hw, queue, params);
|
||||
trace_drv_conf_tx(local, queue, params, ret);
|
||||
@ -210,6 +248,9 @@ static inline int drv_get_tx_stats(struct ieee80211_local *local,
|
||||
static inline u64 drv_get_tsf(struct ieee80211_local *local)
|
||||
{
|
||||
u64 ret = -1ULL;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->get_tsf)
|
||||
ret = local->ops->get_tsf(&local->hw);
|
||||
trace_drv_get_tsf(local, ret);
|
||||
@ -218,6 +259,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local)
|
||||
|
||||
static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->set_tsf)
|
||||
local->ops->set_tsf(&local->hw, tsf);
|
||||
trace_drv_set_tsf(local, tsf);
|
||||
@ -225,6 +268,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf)
|
||||
|
||||
static inline void drv_reset_tsf(struct ieee80211_local *local)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->reset_tsf)
|
||||
local->ops->reset_tsf(&local->hw);
|
||||
trace_drv_reset_tsf(local);
|
||||
@ -233,6 +278,9 @@ static inline void drv_reset_tsf(struct ieee80211_local *local)
|
||||
static inline int drv_tx_last_beacon(struct ieee80211_local *local)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->tx_last_beacon)
|
||||
ret = local->ops->tx_last_beacon(&local->hw);
|
||||
trace_drv_tx_last_beacon(local, ret);
|
||||
@ -256,7 +304,18 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
|
||||
|
||||
static inline void drv_rfkill_poll(struct ieee80211_local *local)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (local->ops->rfkill_poll)
|
||||
local->ops->rfkill_poll(&local->hw);
|
||||
}
|
||||
|
||||
static inline void drv_flush(struct ieee80211_local *local, bool drop)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
trace_drv_flush(local, drop);
|
||||
if (local->ops->flush)
|
||||
local->ops->flush(&local->hw, drop);
|
||||
}
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
|
@ -690,6 +690,27 @@ TRACE_EVENT(drv_ampdu_action,
|
||||
LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_flush,
|
||||
TP_PROTO(struct ieee80211_local *local, bool drop),
|
||||
|
||||
TP_ARGS(local, drop),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(bool, drop)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->drop = drop;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT " drop:%d",
|
||||
LOCAL_PR_ARG, __entry->drop
|
||||
)
|
||||
);
|
||||
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
@ -187,15 +187,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||
static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_bss *bss)
|
||||
{
|
||||
struct cfg80211_bss *cbss =
|
||||
container_of((void *)bss, struct cfg80211_bss, priv);
|
||||
struct ieee80211_supported_band *sband;
|
||||
u32 basic_rates;
|
||||
int i, j;
|
||||
u16 beacon_int = bss->cbss.beacon_interval;
|
||||
u16 beacon_int = cbss->beacon_interval;
|
||||
|
||||
if (beacon_int < 10)
|
||||
beacon_int = 10;
|
||||
|
||||
sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band];
|
||||
sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
|
||||
|
||||
basic_rates = 0;
|
||||
|
||||
@ -212,12 +214,12 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
}
|
||||
|
||||
__ieee80211_sta_join_ibss(sdata, bss->cbss.bssid,
|
||||
__ieee80211_sta_join_ibss(sdata, cbss->bssid,
|
||||
beacon_int,
|
||||
bss->cbss.channel,
|
||||
cbss->channel,
|
||||
basic_rates,
|
||||
bss->cbss.capability,
|
||||
bss->cbss.tsf);
|
||||
cbss->capability,
|
||||
cbss->tsf);
|
||||
}
|
||||
|
||||
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
@ -229,6 +231,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int freq;
|
||||
struct cfg80211_bss *cbss;
|
||||
struct ieee80211_bss *bss;
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_channel *channel;
|
||||
@ -283,8 +286,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
if (!bss)
|
||||
return;
|
||||
|
||||
cbss = container_of((void *)bss, struct cfg80211_bss, priv);
|
||||
|
||||
/* was just updated in ieee80211_bss_info_update */
|
||||
beacon_timestamp = bss->cbss.tsf;
|
||||
beacon_timestamp = cbss->tsf;
|
||||
|
||||
/* check if we need to merge IBSS */
|
||||
|
||||
@ -297,11 +302,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
goto put_bss;
|
||||
|
||||
/* not an IBSS */
|
||||
if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS))
|
||||
if (!(cbss->capability & WLAN_CAPABILITY_IBSS))
|
||||
goto put_bss;
|
||||
|
||||
/* different channel */
|
||||
if (bss->cbss.channel != local->oper_channel)
|
||||
if (cbss->channel != local->oper_channel)
|
||||
goto put_bss;
|
||||
|
||||
/* different SSID */
|
||||
@ -311,7 +316,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
goto put_bss;
|
||||
|
||||
/* same BSSID */
|
||||
if (memcmp(bss->cbss.bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0)
|
||||
if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0)
|
||||
goto put_bss;
|
||||
|
||||
if (rx_status->flag & RX_FLAG_TSFT) {
|
||||
@ -382,6 +387,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
|
||||
u8 *bssid,u8 *addr, u32 supp_rates)
|
||||
{
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
int band = local->hw.conf.channel->band;
|
||||
@ -397,6 +403,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH)
|
||||
return NULL;
|
||||
|
||||
if (compare_ether_addr(bssid, sdata->u.ibss.bssid))
|
||||
return NULL;
|
||||
|
||||
@ -514,7 +523,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_bss *bss;
|
||||
struct cfg80211_bss *cbss;
|
||||
struct ieee80211_channel *chan = NULL;
|
||||
const u8 *bssid = NULL;
|
||||
int active_ibss;
|
||||
@ -538,21 +547,23 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
|
||||
chan = ifibss->channel;
|
||||
if (!is_zero_ether_addr(ifibss->bssid))
|
||||
bssid = ifibss->bssid;
|
||||
bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid,
|
||||
ifibss->ssid, ifibss->ssid_len,
|
||||
WLAN_CAPABILITY_IBSS |
|
||||
WLAN_CAPABILITY_PRIVACY,
|
||||
capability);
|
||||
cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
|
||||
ifibss->ssid, ifibss->ssid_len,
|
||||
WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY,
|
||||
capability);
|
||||
|
||||
if (bss) {
|
||||
if (cbss) {
|
||||
struct ieee80211_bss *bss;
|
||||
|
||||
bss = (void *)cbss->priv;
|
||||
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
||||
printk(KERN_DEBUG " sta_find_ibss: selected %pM current "
|
||||
"%pM\n", bss->cbss.bssid, ifibss->bssid);
|
||||
"%pM\n", cbss->bssid, ifibss->bssid);
|
||||
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
||||
|
||||
printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
|
||||
" based on configured SSID\n",
|
||||
sdata->name, bss->cbss.bssid);
|
||||
sdata->name, cbss->bssid);
|
||||
|
||||
ieee80211_sta_join_ibss(sdata, bss);
|
||||
ieee80211_rx_bss_put(local, bss);
|
||||
@ -744,7 +755,7 @@ static void ieee80211_ibss_work(struct work_struct *work)
|
||||
if (WARN_ON(local->suspended))
|
||||
return;
|
||||
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
return;
|
||||
|
||||
if (local->scanning)
|
||||
@ -827,7 +838,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
|
||||
continue;
|
||||
|
@ -71,9 +71,6 @@ struct ieee80211_fragment_entry {
|
||||
|
||||
|
||||
struct ieee80211_bss {
|
||||
/* Yes, this is a hack */
|
||||
struct cfg80211_bss cbss;
|
||||
|
||||
/* don't want to look up all the time */
|
||||
size_t ssid_len;
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
@ -227,31 +224,78 @@ struct mesh_preq_queue {
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
enum ieee80211_mgd_state {
|
||||
IEEE80211_MGD_STATE_IDLE,
|
||||
IEEE80211_MGD_STATE_PROBE,
|
||||
IEEE80211_MGD_STATE_AUTH,
|
||||
IEEE80211_MGD_STATE_ASSOC,
|
||||
enum ieee80211_work_type {
|
||||
IEEE80211_WORK_ABORT,
|
||||
IEEE80211_WORK_DIRECT_PROBE,
|
||||
IEEE80211_WORK_AUTH,
|
||||
IEEE80211_WORK_ASSOC,
|
||||
IEEE80211_WORK_REMAIN_ON_CHANNEL,
|
||||
};
|
||||
|
||||
struct ieee80211_mgd_work {
|
||||
/**
|
||||
* enum work_done_result - indicates what to do after work was done
|
||||
*
|
||||
* @WORK_DONE_DESTROY: This work item is no longer needed, destroy.
|
||||
* @WORK_DONE_REQUEUE: This work item was reset to be reused, and
|
||||
* should be requeued.
|
||||
*/
|
||||
enum work_done_result {
|
||||
WORK_DONE_DESTROY,
|
||||
WORK_DONE_REQUEUE,
|
||||
};
|
||||
|
||||
struct ieee80211_work {
|
||||
struct list_head list;
|
||||
struct ieee80211_bss *bss;
|
||||
int ie_len;
|
||||
u8 prev_bssid[ETH_ALEN];
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 ssid_len;
|
||||
|
||||
struct rcu_head rcu_head;
|
||||
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
enum work_done_result (*done)(struct ieee80211_work *wk,
|
||||
struct sk_buff *skb);
|
||||
|
||||
struct ieee80211_channel *chan;
|
||||
enum nl80211_channel_type chan_type;
|
||||
|
||||
unsigned long timeout;
|
||||
enum ieee80211_mgd_state state;
|
||||
u16 auth_alg, auth_transaction;
|
||||
enum ieee80211_work_type type;
|
||||
|
||||
int tries;
|
||||
u8 filter_ta[ETH_ALEN];
|
||||
|
||||
u8 key[WLAN_KEY_LEN_WEP104];
|
||||
u8 key_len, key_idx;
|
||||
bool started;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int tries;
|
||||
u16 algorithm, transaction;
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 ssid_len;
|
||||
u8 key[WLAN_KEY_LEN_WEP104];
|
||||
u8 key_len, key_idx;
|
||||
bool privacy;
|
||||
} probe_auth;
|
||||
struct {
|
||||
struct cfg80211_bss *bss;
|
||||
const u8 *supp_rates;
|
||||
const u8 *ht_information_ie;
|
||||
enum ieee80211_smps_mode smps;
|
||||
int tries;
|
||||
u16 capability;
|
||||
u8 prev_bssid[ETH_ALEN];
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 ssid_len;
|
||||
u8 supp_rates_len;
|
||||
bool wmm_used, use_11n;
|
||||
} assoc;
|
||||
struct {
|
||||
u32 duration;
|
||||
bool started;
|
||||
} remain;
|
||||
};
|
||||
|
||||
int ie_len;
|
||||
/* must be last */
|
||||
u8 ie[0]; /* for auth or assoc frame, not probe */
|
||||
u8 ie[0];
|
||||
};
|
||||
|
||||
/* flags used in struct ieee80211_if_managed.flags */
|
||||
@ -259,17 +303,11 @@ enum ieee80211_sta_flags {
|
||||
IEEE80211_STA_BEACON_POLL = BIT(0),
|
||||
IEEE80211_STA_CONNECTION_POLL = BIT(1),
|
||||
IEEE80211_STA_CONTROL_PORT = BIT(2),
|
||||
IEEE80211_STA_WMM_ENABLED = BIT(3),
|
||||
IEEE80211_STA_DISABLE_11N = BIT(4),
|
||||
IEEE80211_STA_CSA_RECEIVED = BIT(5),
|
||||
IEEE80211_STA_MFP_ENABLED = BIT(6),
|
||||
};
|
||||
|
||||
/* flags for MLME request */
|
||||
enum ieee80211_sta_request {
|
||||
IEEE80211_STA_REQ_SCAN,
|
||||
};
|
||||
|
||||
struct ieee80211_if_managed {
|
||||
struct timer_list timer;
|
||||
struct timer_list conn_mon_timer;
|
||||
@ -284,14 +322,11 @@ struct ieee80211_if_managed {
|
||||
int probe_send_count;
|
||||
|
||||
struct mutex mtx;
|
||||
struct ieee80211_bss *associated;
|
||||
struct ieee80211_mgd_work *old_associate_work;
|
||||
struct list_head work_list;
|
||||
struct cfg80211_bss *associated;
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
u16 aid;
|
||||
u16 capab;
|
||||
|
||||
struct sk_buff_head skb_queue;
|
||||
|
||||
@ -300,8 +335,6 @@ struct ieee80211_if_managed {
|
||||
enum ieee80211_smps_mode req_smps, /* requested smps mode */
|
||||
ap_smps; /* smps mode AP thinks we're in */
|
||||
|
||||
unsigned long request;
|
||||
|
||||
unsigned int flags;
|
||||
|
||||
u32 beacon_crc;
|
||||
@ -567,6 +600,15 @@ struct ieee80211_local {
|
||||
|
||||
const struct ieee80211_ops *ops;
|
||||
|
||||
/*
|
||||
* work stuff, potentially off-channel (in the future)
|
||||
*/
|
||||
struct mutex work_mtx;
|
||||
struct list_head work_list;
|
||||
struct timer_list work_timer;
|
||||
struct work_struct work_work;
|
||||
struct sk_buff_head work_skb_queue;
|
||||
|
||||
/*
|
||||
* private workqueue to mac80211. mac80211 makes this accessible
|
||||
* via ieee80211_queue_work()
|
||||
@ -695,6 +737,10 @@ struct ieee80211_local {
|
||||
enum nl80211_channel_type oper_channel_type;
|
||||
struct ieee80211_channel *oper_channel, *csa_channel;
|
||||
|
||||
/* Temporary remain-on-channel for off-channel operations */
|
||||
struct ieee80211_channel *tmp_channel;
|
||||
enum nl80211_channel_type tmp_channel_type;
|
||||
|
||||
/* SNMP counters */
|
||||
/* dot11CountersTable */
|
||||
u32 dot11TransmittedFragmentCount;
|
||||
@ -752,7 +798,7 @@ struct ieee80211_local {
|
||||
unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
|
||||
|
||||
bool pspolling;
|
||||
bool scan_ps_enabled;
|
||||
bool offchannel_ps_enabled;
|
||||
/*
|
||||
* PS can only be enabled when we have exactly one managed
|
||||
* interface (and monitors) in PS, this then points there.
|
||||
@ -947,6 +993,12 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
|
||||
void ieee80211_rx_bss_put(struct ieee80211_local *local,
|
||||
struct ieee80211_bss *bss);
|
||||
|
||||
/* off-channel helpers */
|
||||
void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local);
|
||||
void ieee80211_offchannel_stop_station(struct ieee80211_local *local);
|
||||
void ieee80211_offchannel_return(struct ieee80211_local *local,
|
||||
bool enable_beaconing);
|
||||
|
||||
/* interface handling */
|
||||
int ieee80211_iface_init(void);
|
||||
void ieee80211_iface_exit(void);
|
||||
@ -960,6 +1012,11 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local);
|
||||
u32 __ieee80211_recalc_idle(struct ieee80211_local *local);
|
||||
void ieee80211_recalc_idle(struct ieee80211_local *local);
|
||||
|
||||
static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
return netif_running(sdata->dev);
|
||||
}
|
||||
|
||||
/* tx handling */
|
||||
void ieee80211_clear_tx_pending(struct ieee80211_local *local);
|
||||
void ieee80211_tx_pending(unsigned long data);
|
||||
@ -1106,6 +1163,24 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
|
||||
void ieee80211_recalc_smps(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *forsdata);
|
||||
|
||||
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
|
||||
const u8 *ids, int n_ids, size_t offset);
|
||||
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
|
||||
|
||||
/* internal work items */
|
||||
void ieee80211_work_init(struct ieee80211_local *local);
|
||||
void ieee80211_add_work(struct ieee80211_work *wk);
|
||||
void free_work(struct ieee80211_work *wk);
|
||||
void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata);
|
||||
ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb);
|
||||
int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration, u64 *cookie);
|
||||
int ieee80211_wk_cancel_remain_on_channel(
|
||||
struct ieee80211_sub_if_data *sdata, u64 cookie);
|
||||
|
||||
#ifdef CONFIG_MAC80211_NOINLINE
|
||||
#define debug_noinline noinline
|
||||
#else
|
||||
|
@ -65,7 +65,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
int ret;
|
||||
|
||||
if (netif_running(dev))
|
||||
if (ieee80211_sdata_running(sdata))
|
||||
return -EBUSY;
|
||||
|
||||
ret = eth_mac_addr(dev, addr);
|
||||
@ -96,7 +96,6 @@ static int ieee80211_open(struct net_device *dev)
|
||||
struct ieee80211_sub_if_data *nsdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_if_init_conf conf;
|
||||
u32 changed = 0;
|
||||
int res;
|
||||
u32 hw_reconf_flags = 0;
|
||||
@ -111,7 +110,7 @@ static int ieee80211_open(struct net_device *dev)
|
||||
list_for_each_entry(nsdata, &local->interfaces, list) {
|
||||
struct net_device *ndev = nsdata->dev;
|
||||
|
||||
if (ndev != dev && netif_running(ndev)) {
|
||||
if (ndev != dev && ieee80211_sdata_running(nsdata)) {
|
||||
/*
|
||||
* Allow only a single IBSS interface to be up at any
|
||||
* time. This is restricted because beacon distribution
|
||||
@ -197,7 +196,7 @@ static int ieee80211_open(struct net_device *dev)
|
||||
struct net_device *ndev = nsdata->dev;
|
||||
|
||||
/*
|
||||
* No need to check netif_running since we do not allow
|
||||
* No need to check running since we do not allow
|
||||
* it to start up with this invalid address.
|
||||
*/
|
||||
if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) {
|
||||
@ -248,10 +247,7 @@ static int ieee80211_open(struct net_device *dev)
|
||||
ieee80211_configure_filter(local);
|
||||
break;
|
||||
default:
|
||||
conf.vif = &sdata->vif;
|
||||
conf.type = sdata->vif.type;
|
||||
conf.mac_addr = sdata->vif.addr;
|
||||
res = drv_add_interface(local, &conf);
|
||||
res = drv_add_interface(local, &sdata->vif);
|
||||
if (res)
|
||||
goto err_stop;
|
||||
|
||||
@ -334,7 +330,7 @@ static int ieee80211_open(struct net_device *dev)
|
||||
|
||||
return 0;
|
||||
err_del_interface:
|
||||
drv_remove_interface(local, &conf);
|
||||
drv_remove_interface(local, &sdata->vif);
|
||||
err_stop:
|
||||
if (!local->open_count)
|
||||
drv_stop(local);
|
||||
@ -349,7 +345,6 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_init_conf conf;
|
||||
struct sta_info *sta;
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb, *tmp;
|
||||
@ -361,6 +356,11 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
*/
|
||||
netif_stop_queue(dev);
|
||||
|
||||
/*
|
||||
* Purge work for this interface.
|
||||
*/
|
||||
ieee80211_work_purge(sdata);
|
||||
|
||||
/*
|
||||
* Now delete all active aggregation sessions.
|
||||
*/
|
||||
@ -528,12 +528,9 @@ static int ieee80211_stop(struct net_device *dev)
|
||||
BSS_CHANGED_BEACON_ENABLED);
|
||||
}
|
||||
|
||||
conf.vif = &sdata->vif;
|
||||
conf.type = sdata->vif.type;
|
||||
conf.mac_addr = sdata->vif.addr;
|
||||
/* disable all keys for as long as this netdev is down */
|
||||
ieee80211_disable_keys(sdata);
|
||||
drv_remove_interface(local, &conf);
|
||||
drv_remove_interface(local, &sdata->vif);
|
||||
}
|
||||
|
||||
sdata->bss = NULL;
|
||||
@ -756,7 +753,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
|
||||
* and goes into the requested mode.
|
||||
*/
|
||||
|
||||
if (netif_running(sdata->dev))
|
||||
if (ieee80211_sdata_running(sdata))
|
||||
return -EBUSY;
|
||||
|
||||
/* Purge and reset type-dependent state. */
|
||||
@ -917,6 +914,8 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
|
||||
wiphy_name(local->hw.wiphy));
|
||||
#endif
|
||||
|
||||
drv_flush(local, false);
|
||||
|
||||
local->hw.conf.flags |= IEEE80211_CONF_IDLE;
|
||||
return IEEE80211_CONF_CHANGE_IDLE;
|
||||
}
|
||||
@ -926,16 +925,18 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
int count = 0;
|
||||
|
||||
if (!list_empty(&local->work_list))
|
||||
return ieee80211_idle_off(local, "working");
|
||||
|
||||
if (local->scanning)
|
||||
return ieee80211_idle_off(local, "scanning");
|
||||
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
/* do not count disabled managed interfaces */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
!sdata->u.mgd.associated &&
|
||||
list_empty(&sdata->u.mgd.work_list))
|
||||
!sdata->u.mgd.associated)
|
||||
continue;
|
||||
/* do not count unused IBSS interfaces */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
|
||||
|
@ -443,7 +443,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
|
||||
add_todo(old_key, KEY_FLAG_TODO_DELETE);
|
||||
|
||||
add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
|
||||
if (netif_running(sdata->dev))
|
||||
if (ieee80211_sdata_running(sdata))
|
||||
add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
|
||||
|
||||
spin_unlock_irqrestore(&sdata->local->key_lock, flags);
|
||||
@ -509,7 +509,7 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (WARN_ON(!netif_running(sdata->dev)))
|
||||
if (WARN_ON(!ieee80211_sdata_running(sdata)))
|
||||
return;
|
||||
|
||||
ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
|
||||
|
@ -107,6 +107,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
|
||||
if (scan_chan) {
|
||||
chan = scan_chan;
|
||||
channel_type = NL80211_CHAN_NO_HT;
|
||||
} else if (local->tmp_channel) {
|
||||
chan = scan_chan = local->tmp_channel;
|
||||
channel_type = local->tmp_channel_type;
|
||||
} else {
|
||||
chan = local->oper_channel;
|
||||
channel_type = local->oper_channel_type;
|
||||
@ -212,7 +215,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (local->quiescing || !netif_running(sdata->dev) ||
|
||||
if (local->quiescing || !ieee80211_sdata_running(sdata) ||
|
||||
test_bit(SCAN_SW_SCANNING, &local->scanning)) {
|
||||
sdata->vif.bss_conf.enable_beacon = false;
|
||||
} else {
|
||||
@ -359,9 +362,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
||||
WIPHY_FLAG_4ADDR_STATION;
|
||||
wiphy->privid = mac80211_wiphy_privid;
|
||||
|
||||
/* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
|
||||
wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
|
||||
sizeof(struct cfg80211_bss);
|
||||
wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
|
||||
|
||||
local = wiphy_priv(wiphy);
|
||||
|
||||
@ -395,6 +396,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
||||
|
||||
INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
|
||||
|
||||
ieee80211_work_init(local);
|
||||
|
||||
INIT_WORK(&local->restart_work, ieee80211_restart_work);
|
||||
|
||||
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
|
||||
|
@ -645,7 +645,7 @@ static void ieee80211_mesh_work(struct work_struct *work)
|
||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
return;
|
||||
|
||||
if (local->scanning)
|
||||
|
1087
net/mac80211/mlme.c
1087
net/mac80211/mlme.c
File diff suppressed because it is too large
Load Diff
168
net/mac80211/offchannel.c
Normal file
168
net/mac80211/offchannel.c
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Off-channel operation helpers
|
||||
*
|
||||
* Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
|
||||
* Copyright 2004, Instant802 Networks, Inc.
|
||||
* Copyright 2005, Devicescape Software, Inc.
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <net/mac80211.h>
|
||||
#include "ieee80211_i.h"
|
||||
|
||||
/*
|
||||
* inform AP that we will go to sleep so that it will buffer the frames
|
||||
* while we scan
|
||||
*/
|
||||
static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
local->offchannel_ps_enabled = false;
|
||||
|
||||
/* FIXME: what to do when local->pspolling is true? */
|
||||
|
||||
del_timer_sync(&local->dynamic_ps_timer);
|
||||
cancel_work_sync(&local->dynamic_ps_enable_work);
|
||||
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
||||
local->offchannel_ps_enabled = true;
|
||||
local->hw.conf.flags &= ~IEEE80211_CONF_PS;
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
|
||||
}
|
||||
|
||||
if (!(local->offchannel_ps_enabled) ||
|
||||
!(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
|
||||
/*
|
||||
* If power save was enabled, no need to send a nullfunc
|
||||
* frame because AP knows that we are sleeping. But if the
|
||||
* hardware is creating the nullfunc frame for power save
|
||||
* status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
|
||||
* enabled) and power save was enabled, the firmware just
|
||||
* sent a null frame with power save disabled. So we need
|
||||
* to send a new nullfunc frame to inform the AP that we
|
||||
* are again sleeping.
|
||||
*/
|
||||
ieee80211_send_nullfunc(local, sdata, 1);
|
||||
}
|
||||
|
||||
/* inform AP that we are awake again, unless power save is enabled */
|
||||
static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
if (!local->ps_sdata)
|
||||
ieee80211_send_nullfunc(local, sdata, 0);
|
||||
else if (local->offchannel_ps_enabled) {
|
||||
/*
|
||||
* In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
|
||||
* will send a nullfunc frame with the powersave bit set
|
||||
* even though the AP already knows that we are sleeping.
|
||||
* This could be avoided by sending a null frame with power
|
||||
* save bit disabled before enabling the power save, but
|
||||
* this doesn't gain anything.
|
||||
*
|
||||
* When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
|
||||
* to send a nullfunc frame because AP already knows that
|
||||
* we are sleeping, let's just enable power save mode in
|
||||
* hardware.
|
||||
*/
|
||||
local->hw.conf.flags |= IEEE80211_CONF_PS;
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
|
||||
} else if (local->hw.conf.dynamic_ps_timeout > 0) {
|
||||
/*
|
||||
* If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
|
||||
* had been running before leaving the operating channel,
|
||||
* restart the timer now and send a nullfunc frame to inform
|
||||
* the AP that we are awake.
|
||||
*/
|
||||
ieee80211_send_nullfunc(local, sdata, 0);
|
||||
mod_timer(&local->dynamic_ps_timer, jiffies +
|
||||
msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
/* disable beaconing */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC ||
|
||||
sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
|
||||
ieee80211_bss_info_change_notify(
|
||||
sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
|
||||
/*
|
||||
* only handle non-STA interfaces here, STA interfaces
|
||||
* are handled in ieee80211_offchannel_stop_station(),
|
||||
* e.g., from the background scan state machine.
|
||||
*
|
||||
* In addition, do not stop monitor interface to allow it to be
|
||||
* used from user space controlled off-channel operations.
|
||||
*/
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
|
||||
sdata->vif.type != NL80211_IFTYPE_MONITOR)
|
||||
netif_stop_queue(sdata->dev);
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
|
||||
void ieee80211_offchannel_stop_station(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
/*
|
||||
* notify the AP about us leaving the channel and stop all STA interfaces
|
||||
*/
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
netif_stop_queue(sdata->dev);
|
||||
if (sdata->u.mgd.associated)
|
||||
ieee80211_offchannel_ps_enable(sdata);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
|
||||
void ieee80211_offchannel_return(struct ieee80211_local *local,
|
||||
bool enable_beaconing)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
/* Tell AP we're back */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
if (sdata->u.mgd.associated)
|
||||
ieee80211_offchannel_ps_disable(sdata);
|
||||
netif_wake_queue(sdata->dev);
|
||||
}
|
||||
|
||||
/* re-enable beaconing */
|
||||
if (enable_beaconing &&
|
||||
(sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC ||
|
||||
sdata->vif.type == NL80211_IFTYPE_MESH_POINT))
|
||||
ieee80211_bss_info_change_notify(
|
||||
sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
@ -10,7 +10,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_if_init_conf conf;
|
||||
struct sta_info *sta;
|
||||
unsigned long flags;
|
||||
|
||||
@ -93,17 +92,14 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
/* disable beaconing */
|
||||
ieee80211_bss_info_change_notify(sdata,
|
||||
BSS_CHANGED_BEACON_ENABLED);
|
||||
|
||||
conf.vif = &sdata->vif;
|
||||
conf.type = sdata->vif.type;
|
||||
conf.mac_addr = sdata->vif.addr;
|
||||
drv_remove_interface(local, &conf);
|
||||
drv_remove_interface(local, &sdata->vif);
|
||||
}
|
||||
|
||||
/* stop hardware - this must stop RX */
|
||||
|
@ -289,7 +289,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
||||
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
|
||||
continue;
|
||||
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (prev_dev) {
|
||||
@ -1945,6 +1945,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||
ieee80211_rx_result rxs;
|
||||
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_DROP_MONITOR;
|
||||
@ -1952,6 +1953,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
||||
if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
|
||||
if (rxs != RX_CONTINUE)
|
||||
return rxs;
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif))
|
||||
return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
|
||||
|
||||
@ -2056,7 +2061,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
||||
skb->protocol = htons(ETH_P_802_2);
|
||||
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
|
||||
@ -2318,7 +2323,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||
}
|
||||
if (!found_sta) {
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
||||
|
@ -29,16 +29,19 @@ struct ieee80211_bss *
|
||||
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
|
||||
u8 *ssid, u8 ssid_len)
|
||||
{
|
||||
return (void *)cfg80211_get_bss(local->hw.wiphy,
|
||||
ieee80211_get_channel(local->hw.wiphy,
|
||||
freq),
|
||||
bssid, ssid, ssid_len,
|
||||
0, 0);
|
||||
struct cfg80211_bss *cbss;
|
||||
|
||||
cbss = cfg80211_get_bss(local->hw.wiphy,
|
||||
ieee80211_get_channel(local->hw.wiphy, freq),
|
||||
bssid, ssid, ssid_len, 0, 0);
|
||||
if (!cbss)
|
||||
return NULL;
|
||||
return (void *)cbss->priv;
|
||||
}
|
||||
|
||||
static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
|
||||
{
|
||||
struct ieee80211_bss *bss = (void *)cbss;
|
||||
struct ieee80211_bss *bss = (void *)cbss->priv;
|
||||
|
||||
kfree(bss_mesh_id(bss));
|
||||
kfree(bss_mesh_cfg(bss));
|
||||
@ -47,7 +50,9 @@ static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
|
||||
void ieee80211_rx_bss_put(struct ieee80211_local *local,
|
||||
struct ieee80211_bss *bss)
|
||||
{
|
||||
cfg80211_put_bss((struct cfg80211_bss *)bss);
|
||||
if (!bss)
|
||||
return;
|
||||
cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv));
|
||||
}
|
||||
|
||||
struct ieee80211_bss *
|
||||
@ -59,6 +64,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||
struct ieee80211_channel *channel,
|
||||
bool beacon)
|
||||
{
|
||||
struct cfg80211_bss *cbss;
|
||||
struct ieee80211_bss *bss;
|
||||
int clen;
|
||||
s32 signal = 0;
|
||||
@ -68,13 +74,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||
else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
|
||||
signal = (rx_status->signal * 100) / local->hw.max_signal;
|
||||
|
||||
bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel,
|
||||
mgmt, len, signal, GFP_ATOMIC);
|
||||
cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
|
||||
mgmt, len, signal, GFP_ATOMIC);
|
||||
|
||||
if (!bss)
|
||||
if (!cbss)
|
||||
return NULL;
|
||||
|
||||
bss->cbss.free_priv = ieee80211_rx_bss_free;
|
||||
cbss->free_priv = ieee80211_rx_bss_free;
|
||||
bss = (void *)cbss->priv;
|
||||
|
||||
/* save the ERP value so that it is available at association time */
|
||||
if (elems->erp_info && elems->erp_info_len >= 1) {
|
||||
@ -220,82 +227,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* inform AP that we will go to sleep so that it will buffer the frames
|
||||
* while we scan
|
||||
*/
|
||||
static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
local->scan_ps_enabled = false;
|
||||
|
||||
/* FIXME: what to do when local->pspolling is true? */
|
||||
|
||||
del_timer_sync(&local->dynamic_ps_timer);
|
||||
cancel_work_sync(&local->dynamic_ps_enable_work);
|
||||
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
||||
local->scan_ps_enabled = true;
|
||||
local->hw.conf.flags &= ~IEEE80211_CONF_PS;
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
|
||||
}
|
||||
|
||||
if (!(local->scan_ps_enabled) ||
|
||||
!(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
|
||||
/*
|
||||
* If power save was enabled, no need to send a nullfunc
|
||||
* frame because AP knows that we are sleeping. But if the
|
||||
* hardware is creating the nullfunc frame for power save
|
||||
* status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
|
||||
* enabled) and power save was enabled, the firmware just
|
||||
* sent a null frame with power save disabled. So we need
|
||||
* to send a new nullfunc frame to inform the AP that we
|
||||
* are again sleeping.
|
||||
*/
|
||||
ieee80211_send_nullfunc(local, sdata, 1);
|
||||
}
|
||||
|
||||
/* inform AP that we are awake again, unless power save is enabled */
|
||||
static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
if (!local->ps_sdata)
|
||||
ieee80211_send_nullfunc(local, sdata, 0);
|
||||
else if (local->scan_ps_enabled) {
|
||||
/*
|
||||
* In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
|
||||
* will send a nullfunc frame with the powersave bit set
|
||||
* even though the AP already knows that we are sleeping.
|
||||
* This could be avoided by sending a null frame with power
|
||||
* save bit disabled before enabling the power save, but
|
||||
* this doesn't gain anything.
|
||||
*
|
||||
* When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
|
||||
* to send a nullfunc frame because AP already knows that
|
||||
* we are sleeping, let's just enable power save mode in
|
||||
* hardware.
|
||||
*/
|
||||
local->hw.conf.flags |= IEEE80211_CONF_PS;
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
|
||||
} else if (local->hw.conf.dynamic_ps_timeout > 0) {
|
||||
/*
|
||||
* If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
|
||||
* had been running before leaving the operating channel,
|
||||
* restart the timer now and send a nullfunc frame to inform
|
||||
* the AP that we are awake.
|
||||
*/
|
||||
ieee80211_send_nullfunc(local, sdata, 0);
|
||||
mod_timer(&local->dynamic_ps_timer, jiffies +
|
||||
msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
bool was_hw_scan;
|
||||
|
||||
mutex_lock(&local->scan_mtx);
|
||||
@ -344,28 +278,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
|
||||
drv_sw_scan_complete(local);
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
continue;
|
||||
|
||||
/* Tell AP we're back */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
if (sdata->u.mgd.associated) {
|
||||
ieee80211_scan_ps_disable(sdata);
|
||||
netif_wake_queue(sdata->dev);
|
||||
}
|
||||
} else
|
||||
netif_wake_queue(sdata->dev);
|
||||
|
||||
/* re-enable beaconing */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC ||
|
||||
sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
|
||||
ieee80211_bss_info_change_notify(
|
||||
sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
ieee80211_offchannel_return(local, true);
|
||||
|
||||
done:
|
||||
ieee80211_recalc_idle(local);
|
||||
@ -377,8 +290,6 @@ EXPORT_SYMBOL(ieee80211_scan_completed);
|
||||
|
||||
static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
/*
|
||||
* Hardware/driver doesn't support hw_scan, so use software
|
||||
* scanning instead. First send a nullfunc frame with power save
|
||||
@ -394,33 +305,15 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
||||
*/
|
||||
drv_sw_scan_start(local);
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
continue;
|
||||
|
||||
/* disable beaconing */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_ADHOC ||
|
||||
sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
|
||||
ieee80211_bss_info_change_notify(
|
||||
sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
|
||||
/*
|
||||
* only handle non-STA interfaces here, STA interfaces
|
||||
* are handled in the scan state machine
|
||||
*/
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
netif_stop_queue(sdata->dev);
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
ieee80211_offchannel_stop_beaconing(local);
|
||||
|
||||
local->next_scan_state = SCAN_DECISION;
|
||||
local->scan_channel_idx = 0;
|
||||
|
||||
drv_flush(local, false);
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
/* TODO: start scan as soon as all nullfunc frames are ACKed */
|
||||
ieee80211_queue_delayed_work(&local->hw,
|
||||
&local->scan_work,
|
||||
IEEE80211_CHANNEL_TIME);
|
||||
@ -433,7 +326,6 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
int rc;
|
||||
|
||||
if (local->scan_req)
|
||||
@ -463,11 +355,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
local->scan_req = req;
|
||||
local->scan_sdata = sdata;
|
||||
|
||||
if (req != local->int_scan_req &&
|
||||
sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
!list_empty(&ifmgd->work_list)) {
|
||||
/* actually wait for the work it's doing to finish/time out */
|
||||
set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
|
||||
if (!list_empty(&local->work_list)) {
|
||||
/* wait for the work to finish/time out */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -526,7 +415,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
/* check if at least one STA interface is associated */
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
@ -564,56 +453,35 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
|
||||
static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
|
||||
unsigned long *next_delay)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
/*
|
||||
* notify the AP about us leaving the channel and stop all STA interfaces
|
||||
*/
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
continue;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
netif_stop_queue(sdata->dev);
|
||||
if (sdata->u.mgd.associated)
|
||||
ieee80211_scan_ps_enable(sdata);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
ieee80211_offchannel_stop_station(local);
|
||||
|
||||
__set_bit(SCAN_OFF_CHANNEL, &local->scanning);
|
||||
|
||||
/*
|
||||
* What if the nullfunc frames didn't arrive?
|
||||
*/
|
||||
drv_flush(local, false);
|
||||
if (local->ops->flush)
|
||||
*next_delay = 0;
|
||||
else
|
||||
*next_delay = HZ / 10;
|
||||
|
||||
/* advance to the next channel to be scanned */
|
||||
*next_delay = HZ / 10;
|
||||
local->next_scan_state = SCAN_SET_CHANNEL;
|
||||
}
|
||||
|
||||
static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
|
||||
unsigned long *next_delay)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = local->scan_sdata;
|
||||
|
||||
/* switch back to the operating channel */
|
||||
local->scan_channel = NULL;
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
|
||||
/*
|
||||
* notify the AP about us being back and restart all STA interfaces
|
||||
* Only re-enable station mode interface now; beaconing will be
|
||||
* re-enabled once the full scan has been completed.
|
||||
*/
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!netif_running(sdata->dev))
|
||||
continue;
|
||||
|
||||
/* Tell AP we're back */
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
if (sdata->u.mgd.associated)
|
||||
ieee80211_scan_ps_disable(sdata);
|
||||
netif_wake_queue(sdata->dev);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
ieee80211_offchannel_return(local, false);
|
||||
|
||||
__clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
|
||||
|
||||
@ -727,7 +595,7 @@ void ieee80211_scan_work(struct work_struct *work)
|
||||
/*
|
||||
* Avoid re-scheduling when the sdata is going away.
|
||||
*/
|
||||
if (!netif_running(sdata->dev)) {
|
||||
if (!ieee80211_sdata_running(sdata)) {
|
||||
ieee80211_scan_completed(&local->hw, true);
|
||||
return;
|
||||
}
|
||||
|
@ -359,6 +359,7 @@ int sta_info_insert(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_local *local = sta->local;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct station_info sinfo;
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
|
||||
@ -367,7 +368,7 @@ int sta_info_insert(struct sta_info *sta)
|
||||
* something inserts a STA (on one CPU) without holding the RTNL
|
||||
* and another CPU turns off the net device.
|
||||
*/
|
||||
if (unlikely(!netif_running(sdata->dev))) {
|
||||
if (unlikely(!ieee80211_sdata_running(sdata))) {
|
||||
err = -ENETDOWN;
|
||||
goto out_free;
|
||||
}
|
||||
@ -408,6 +409,10 @@ int sta_info_insert(struct sta_info *sta)
|
||||
|
||||
spin_unlock_irqrestore(&local->sta_lock, flags);
|
||||
|
||||
sinfo.filled = 0;
|
||||
sinfo.generation = local->sta_generation;
|
||||
cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_ATOMIC);
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
/*
|
||||
* Debugfs entry adding might sleep, so schedule process
|
||||
|
@ -351,7 +351,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
|
||||
|
@ -1418,6 +1418,10 @@ static bool need_dynamic_ps(struct ieee80211_local *local)
|
||||
if (!local->ps_sdata)
|
||||
return false;
|
||||
|
||||
/* No point if we're going to suspend */
|
||||
if (local->quiescing)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1469,7 +1473,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
list_for_each_entry_rcu(tmp_sdata, &local->interfaces,
|
||||
list) {
|
||||
if (!netif_running(tmp_sdata->dev))
|
||||
if (!ieee80211_sdata_running(tmp_sdata))
|
||||
continue;
|
||||
if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
|
||||
continue;
|
||||
|
@ -468,7 +468,7 @@ void ieee80211_iterate_active_interfaces(
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
break;
|
||||
}
|
||||
if (netif_running(sdata->dev))
|
||||
if (ieee80211_sdata_running(sdata))
|
||||
iterator(data, sdata->vif.addr,
|
||||
&sdata->vif);
|
||||
}
|
||||
@ -502,7 +502,7 @@ void ieee80211_iterate_active_interfaces_atomic(
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
break;
|
||||
}
|
||||
if (netif_running(sdata->dev))
|
||||
if (ieee80211_sdata_running(sdata))
|
||||
iterator(data, sdata->vif.addr,
|
||||
&sdata->vif);
|
||||
}
|
||||
@ -881,30 +881,66 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
u8 *pos, *supp_rates_len, *esupp_rates_len = NULL;
|
||||
int i;
|
||||
u8 *pos;
|
||||
size_t offset = 0, noffset;
|
||||
int supp_rates_len, i;
|
||||
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
|
||||
pos = buffer;
|
||||
|
||||
supp_rates_len = min_t(int, sband->n_bitrates, 8);
|
||||
|
||||
*pos++ = WLAN_EID_SUPP_RATES;
|
||||
supp_rates_len = pos;
|
||||
*pos++ = 0;
|
||||
*pos++ = supp_rates_len;
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
struct ieee80211_rate *rate = &sband->bitrates[i];
|
||||
for (i = 0; i < supp_rates_len; i++) {
|
||||
int rate = sband->bitrates[i].bitrate;
|
||||
*pos++ = (u8) (rate / 5);
|
||||
}
|
||||
|
||||
if (esupp_rates_len) {
|
||||
*esupp_rates_len += 1;
|
||||
} else if (*supp_rates_len == 8) {
|
||||
*pos++ = WLAN_EID_EXT_SUPP_RATES;
|
||||
esupp_rates_len = pos;
|
||||
*pos++ = 1;
|
||||
} else
|
||||
*supp_rates_len += 1;
|
||||
/* insert "request information" if in custom IEs */
|
||||
if (ie && ie_len) {
|
||||
static const u8 before_extrates[] = {
|
||||
WLAN_EID_SSID,
|
||||
WLAN_EID_SUPP_RATES,
|
||||
WLAN_EID_REQUEST,
|
||||
};
|
||||
noffset = ieee80211_ie_split(ie, ie_len,
|
||||
before_extrates,
|
||||
ARRAY_SIZE(before_extrates),
|
||||
offset);
|
||||
memcpy(pos, ie + offset, noffset - offset);
|
||||
pos += noffset - offset;
|
||||
offset = noffset;
|
||||
}
|
||||
|
||||
*pos++ = rate->bitrate / 5;
|
||||
if (sband->n_bitrates > i) {
|
||||
*pos++ = WLAN_EID_EXT_SUPP_RATES;
|
||||
*pos++ = sband->n_bitrates - i;
|
||||
|
||||
for (; i < sband->n_bitrates; i++) {
|
||||
int rate = sband->bitrates[i].bitrate;
|
||||
*pos++ = (u8) (rate / 5);
|
||||
}
|
||||
}
|
||||
|
||||
/* insert custom IEs that go before HT */
|
||||
if (ie && ie_len) {
|
||||
static const u8 before_ht[] = {
|
||||
WLAN_EID_SSID,
|
||||
WLAN_EID_SUPP_RATES,
|
||||
WLAN_EID_REQUEST,
|
||||
WLAN_EID_EXT_SUPP_RATES,
|
||||
WLAN_EID_DS_PARAMS,
|
||||
WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
|
||||
};
|
||||
noffset = ieee80211_ie_split(ie, ie_len,
|
||||
before_ht, ARRAY_SIZE(before_ht),
|
||||
offset);
|
||||
memcpy(pos, ie + offset, noffset - offset);
|
||||
pos += noffset - offset;
|
||||
offset = noffset;
|
||||
}
|
||||
|
||||
if (sband->ht_cap.ht_supported) {
|
||||
@ -936,9 +972,11 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
|
||||
* that calculates local->scan_ies_len.
|
||||
*/
|
||||
|
||||
if (ie) {
|
||||
memcpy(pos, ie, ie_len);
|
||||
pos += ie_len;
|
||||
/* add any remaining custom IEs */
|
||||
if (ie && ie_len) {
|
||||
noffset = ie_len;
|
||||
memcpy(pos, ie + offset, noffset - offset);
|
||||
pos += noffset - offset;
|
||||
}
|
||||
|
||||
return pos - buffer;
|
||||
@ -1037,7 +1075,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_if_init_conf conf;
|
||||
struct sta_info *sta;
|
||||
unsigned long flags;
|
||||
int res;
|
||||
@ -1047,7 +1084,19 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
|
||||
/* restart hardware */
|
||||
if (local->open_count) {
|
||||
/*
|
||||
* Upon resume hardware can sometimes be goofy due to
|
||||
* various platform / driver / bus issues, so restarting
|
||||
* the device may at times not work immediately. Propagate
|
||||
* the error.
|
||||
*/
|
||||
res = drv_start(local);
|
||||
if (res) {
|
||||
WARN(local->suspended, "Harware became unavailable "
|
||||
"upon resume. This is could be a software issue"
|
||||
"prior to suspend or a harware issue\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
ieee80211_led_radio(local, true);
|
||||
}
|
||||
@ -1056,12 +1105,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
|
||||
sdata->vif.type != NL80211_IFTYPE_MONITOR &&
|
||||
netif_running(sdata->dev)) {
|
||||
conf.vif = &sdata->vif;
|
||||
conf.type = sdata->vif.type;
|
||||
conf.mac_addr = sdata->vif.addr;
|
||||
res = drv_add_interface(local, &conf);
|
||||
}
|
||||
ieee80211_sdata_running(sdata))
|
||||
res = drv_add_interface(local, &sdata->vif);
|
||||
}
|
||||
|
||||
/* add STAs back */
|
||||
@ -1103,7 +1148,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
/* Finally also reconfigure all the BSS information */
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
u32 changed = ~0;
|
||||
if (!netif_running(sdata->dev))
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
@ -1131,7 +1176,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
|
||||
/* add back keys */
|
||||
list_for_each_entry(sdata, &local->interfaces, list)
|
||||
if (netif_running(sdata->dev))
|
||||
if (ieee80211_sdata_running(sdata))
|
||||
ieee80211_enable_keys(sdata);
|
||||
|
||||
ieee80211_wake_queues_by_reason(hw,
|
||||
@ -1252,3 +1297,59 @@ void ieee80211_recalc_smps(struct ieee80211_local *local,
|
||||
/* changed flag is auto-detected for this */
|
||||
ieee80211_hw_config(local, 0);
|
||||
}
|
||||
|
||||
static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_ids; i++)
|
||||
if (ids[i] == id)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee80211_ie_split - split an IE buffer according to ordering
|
||||
*
|
||||
* @ies: the IE buffer
|
||||
* @ielen: the length of the IE buffer
|
||||
* @ids: an array with element IDs that are allowed before
|
||||
* the split
|
||||
* @n_ids: the size of the element ID array
|
||||
* @offset: offset where to start splitting in the buffer
|
||||
*
|
||||
* This function splits an IE buffer by updating the @offset
|
||||
* variable to point to the location where the buffer should be
|
||||
* split.
|
||||
*
|
||||
* It assumes that the given IE buffer is well-formed, this
|
||||
* has to be guaranteed by the caller!
|
||||
*
|
||||
* It also assumes that the IEs in the buffer are ordered
|
||||
* correctly, if not the result of using this function will not
|
||||
* be ordered correctly either, i.e. it does no reordering.
|
||||
*
|
||||
* The function returns the offset where the next part of the
|
||||
* buffer starts, which may be @ielen if the entire (remainder)
|
||||
* of the buffer should be used.
|
||||
*/
|
||||
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
|
||||
const u8 *ids, int n_ids, size_t offset)
|
||||
{
|
||||
size_t pos = offset;
|
||||
|
||||
while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
|
||||
pos += 2 + ies[pos + 1];
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
|
||||
{
|
||||
size_t pos = offset;
|
||||
|
||||
while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC)
|
||||
pos += 2 + ies[pos + 1];
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
1086
net/mac80211/work.c
Normal file
1086
net/mac80211/work.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -94,21 +94,6 @@ config CFG80211_DEBUGFS
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config WIRELESS_OLD_REGULATORY
|
||||
bool "Old wireless static regulatory definitions"
|
||||
default n
|
||||
depends on CFG80211
|
||||
---help---
|
||||
This option enables the old static regulatory information
|
||||
and uses it within the new framework. This option is available
|
||||
for historical reasons and it is advised to leave it off.
|
||||
|
||||
For details see:
|
||||
|
||||
http://wireless.kernel.org/en/developers/Regulatory
|
||||
|
||||
Say N and if you say Y, please tell us why. The default is N.
|
||||
|
||||
config CFG80211_INTERNAL_REGDB
|
||||
bool "use statically compiled regulatory rules database" if EMBEDDED
|
||||
default n
|
||||
|
@ -41,12 +41,45 @@ rdev_fixed_channel(struct cfg80211_registered_device *rdev,
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ieee80211_channel *
|
||||
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
|
||||
int freq, enum nl80211_channel_type channel_type)
|
||||
{
|
||||
struct ieee80211_channel *chan;
|
||||
struct ieee80211_sta_ht_cap *ht_cap;
|
||||
|
||||
chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
||||
|
||||
/* Primary channel not allowed */
|
||||
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
|
||||
return NULL;
|
||||
|
||||
if (channel_type == NL80211_CHAN_HT40MINUS &&
|
||||
chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
|
||||
return NULL;
|
||||
else if (channel_type == NL80211_CHAN_HT40PLUS &&
|
||||
chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
|
||||
return NULL;
|
||||
|
||||
ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
|
||||
|
||||
if (channel_type != NL80211_CHAN_NO_HT) {
|
||||
if (!ht_cap->ht_supported)
|
||||
return NULL;
|
||||
|
||||
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
|
||||
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
int rdev_set_freq(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *for_wdev,
|
||||
int freq, enum nl80211_channel_type channel_type)
|
||||
{
|
||||
struct ieee80211_channel *chan;
|
||||
struct ieee80211_sta_ht_cap *ht_cap;
|
||||
int result;
|
||||
|
||||
if (rdev_fixed_channel(rdev, for_wdev))
|
||||
@ -55,30 +88,10 @@ int rdev_set_freq(struct cfg80211_registered_device *rdev,
|
||||
if (!rdev->ops->set_channel)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
||||
|
||||
/* Primary channel not allowed */
|
||||
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
|
||||
chan = rdev_freq_to_chan(rdev, freq, channel_type);
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
if (channel_type == NL80211_CHAN_HT40MINUS &&
|
||||
chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
|
||||
return -EINVAL;
|
||||
else if (channel_type == NL80211_CHAN_HT40PLUS &&
|
||||
chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
|
||||
return -EINVAL;
|
||||
|
||||
ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
|
||||
|
||||
if (channel_type != NL80211_CHAN_NO_HT) {
|
||||
if (!ht_cap->ht_supported)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
|
||||
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
|
||||
if (result)
|
||||
return result;
|
||||
|
@ -374,6 +374,9 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
|
||||
struct ieee80211_channel *
|
||||
rdev_fixed_channel(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *for_wdev);
|
||||
struct ieee80211_channel *
|
||||
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
|
||||
int freq, enum nl80211_channel_type channel_type);
|
||||
int rdev_set_freq(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *for_wdev,
|
||||
int freq, enum nl80211_channel_type channel_type);
|
||||
|
@ -93,7 +93,18 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON(!bss);
|
||||
/*
|
||||
* We might be coming here because the driver reported
|
||||
* a successful association at the same time as the
|
||||
* user requested a deauth. In that case, we will have
|
||||
* removed the BSS from the auth_bsses list due to the
|
||||
* deauth request when the assoc response makes it. If
|
||||
* the two code paths acquire the lock the other way
|
||||
* around, that's just the standard situation of a
|
||||
* deauth being requested while connected.
|
||||
*/
|
||||
if (!bss)
|
||||
goto out;
|
||||
} else if (wdev->conn) {
|
||||
cfg80211_sme_failed_assoc(wdev);
|
||||
/*
|
||||
@ -680,3 +691,40 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration, gfp_t gfp)
|
||||
{
|
||||
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
||||
nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type,
|
||||
duration, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_ready_on_channel);
|
||||
|
||||
void cfg80211_remain_on_channel_expired(struct net_device *dev,
|
||||
u64 cookie,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
gfp_t gfp)
|
||||
{
|
||||
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
||||
nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan,
|
||||
channel_type, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
|
||||
|
||||
void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp)
|
||||
{
|
||||
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
||||
nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_new_sta);
|
||||
|
@ -141,6 +141,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
|
||||
[NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
|
||||
.len = WLAN_PMKID_LEN },
|
||||
[NL80211_ATTR_DURATION] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
|
||||
};
|
||||
|
||||
/* policy for the attributes */
|
||||
@ -569,6 +571,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
||||
CMD(set_pmksa, SET_PMKSA);
|
||||
CMD(del_pmksa, DEL_PMKSA);
|
||||
CMD(flush_pmksa, FLUSH_PMKSA);
|
||||
CMD(remain_on_channel, REMAIN_ON_CHANNEL);
|
||||
if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
|
||||
i++;
|
||||
NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
|
||||
@ -1639,7 +1642,7 @@ static int parse_station_flags(struct genl_info *info,
|
||||
|
||||
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
|
||||
int flags, struct net_device *dev,
|
||||
u8 *mac_addr, struct station_info *sinfo)
|
||||
const u8 *mac_addr, struct station_info *sinfo)
|
||||
{
|
||||
void *hdr;
|
||||
struct nlattr *sinfoattr, *txrate;
|
||||
@ -2550,12 +2553,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
|
||||
/* We ignore world regdom requests with the old regdom setup */
|
||||
if (is_world_regdom(data))
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
r = regulatory_hint_user(data);
|
||||
|
||||
return r;
|
||||
@ -4289,6 +4286,143 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
}
|
||||
|
||||
static int nl80211_remain_on_channel(struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct net_device *dev;
|
||||
struct ieee80211_channel *chan;
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
u64 cookie;
|
||||
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
|
||||
u32 freq, duration;
|
||||
int err;
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
|
||||
!info->attrs[NL80211_ATTR_DURATION])
|
||||
return -EINVAL;
|
||||
|
||||
duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
|
||||
|
||||
/*
|
||||
* We should be on that channel for at least one jiffie,
|
||||
* and more than 5 seconds seems excessive.
|
||||
*/
|
||||
if (!duration || !msecs_to_jiffies(duration) || duration > 5000)
|
||||
return -EINVAL;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
|
||||
if (err)
|
||||
goto unlock_rtnl;
|
||||
|
||||
if (!rdev->ops->remain_on_channel) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!netif_running(dev)) {
|
||||
err = -ENETDOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
|
||||
channel_type = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
|
||||
if (channel_type != NL80211_CHAN_NO_HT &&
|
||||
channel_type != NL80211_CHAN_HT20 &&
|
||||
channel_type != NL80211_CHAN_HT40PLUS &&
|
||||
channel_type != NL80211_CHAN_HT40MINUS)
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
|
||||
chan = rdev_freq_to_chan(rdev, freq, channel_type);
|
||||
if (chan == NULL) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
|
||||
NL80211_CMD_REMAIN_ON_CHANNEL);
|
||||
|
||||
if (IS_ERR(hdr)) {
|
||||
err = PTR_ERR(hdr);
|
||||
goto free_msg;
|
||||
}
|
||||
|
||||
err = rdev->ops->remain_on_channel(&rdev->wiphy, dev, chan,
|
||||
channel_type, duration, &cookie);
|
||||
|
||||
if (err)
|
||||
goto free_msg;
|
||||
|
||||
NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
err = genlmsg_reply(msg, info);
|
||||
goto out;
|
||||
|
||||
nla_put_failure:
|
||||
err = -ENOBUFS;
|
||||
free_msg:
|
||||
nlmsg_free(msg);
|
||||
out:
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
dev_put(dev);
|
||||
unlock_rtnl:
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct net_device *dev;
|
||||
u64 cookie;
|
||||
int err;
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_COOKIE])
|
||||
return -EINVAL;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
|
||||
if (err)
|
||||
goto unlock_rtnl;
|
||||
|
||||
if (!rdev->ops->cancel_remain_on_channel) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!netif_running(dev)) {
|
||||
err = -ENETDOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
|
||||
|
||||
err = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie);
|
||||
|
||||
out:
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
dev_put(dev);
|
||||
unlock_rtnl:
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct genl_ops nl80211_ops[] = {
|
||||
{
|
||||
.cmd = NL80211_CMD_GET_WIPHY,
|
||||
@ -4551,8 +4685,20 @@ static struct genl_ops nl80211_ops[] = {
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
},
|
||||
|
||||
{
|
||||
.cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
|
||||
.doit = nl80211_remain_on_channel,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
|
||||
.doit = nl80211_cancel_remain_on_channel,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_multicast_group nl80211_mlme_mcgrp = {
|
||||
.name = "mlme",
|
||||
};
|
||||
@ -5140,6 +5286,89 @@ nla_put_failure:
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
|
||||
static void nl80211_send_remain_on_chan_event(
|
||||
int cmd, struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, u64 cookie,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration, gfp_t gfp)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
|
||||
if (!hdr) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type);
|
||||
NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
|
||||
|
||||
if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL)
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);
|
||||
|
||||
if (genlmsg_end(msg, hdr) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
|
||||
nl80211_mlme_mcgrp.id, gfp);
|
||||
return;
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
|
||||
void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, u64 cookie,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration, gfp_t gfp)
|
||||
{
|
||||
nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
|
||||
rdev, netdev, cookie, chan,
|
||||
channel_type, duration, gfp);
|
||||
}
|
||||
|
||||
void nl80211_send_remain_on_channel_cancel(
|
||||
struct cfg80211_registered_device *rdev, struct net_device *netdev,
|
||||
u64 cookie, struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type, gfp_t gfp)
|
||||
{
|
||||
nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
|
||||
rdev, netdev, cookie, chan,
|
||||
channel_type, 0, gfp);
|
||||
}
|
||||
|
||||
void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
|
||||
msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
if (nl80211_send_station(msg, 0, 0, 0, dev, mac_addr, sinfo) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
|
||||
nl80211_mlme_mcgrp.id, gfp);
|
||||
}
|
||||
|
||||
/* initialisation/exit functions */
|
||||
|
||||
int nl80211_init(void)
|
||||
|
@ -59,4 +59,19 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, const u8 *bssid,
|
||||
gfp_t gfp);
|
||||
|
||||
void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
u64 cookie,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
unsigned int duration, gfp_t gfp);
|
||||
void nl80211_send_remain_on_channel_cancel(
|
||||
struct cfg80211_registered_device *rdev, struct net_device *netdev,
|
||||
u64 cookie, struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type, gfp_t gfp);
|
||||
|
||||
void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp);
|
||||
|
||||
#endif /* __NET_WIRELESS_NL80211_H */
|
||||
|
@ -129,78 +129,6 @@ static char *ieee80211_regdom = "00";
|
||||
module_param(ieee80211_regdom, charp, 0444);
|
||||
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
|
||||
|
||||
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
|
||||
/*
|
||||
* We assume 40 MHz bandwidth for the old regulatory work.
|
||||
* We make emphasis we are using the exact same frequencies
|
||||
* as before
|
||||
*/
|
||||
|
||||
static const struct ieee80211_regdomain us_regdom = {
|
||||
.n_reg_rules = 6,
|
||||
.alpha2 = "US",
|
||||
.reg_rules = {
|
||||
/* IEEE 802.11b/g, channels 1..11 */
|
||||
REG_RULE(2412-10, 2462+10, 40, 6, 27, 0),
|
||||
/* IEEE 802.11a, channel 36..48 */
|
||||
REG_RULE(5180-10, 5240+10, 40, 6, 17, 0),
|
||||
/* IEEE 802.11a, channels 48..64 */
|
||||
REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS),
|
||||
/* IEEE 802.11a, channels 100..124 */
|
||||
REG_RULE(5500-10, 5590+10, 40, 6, 20, NL80211_RRF_DFS),
|
||||
/* IEEE 802.11a, channels 132..144 */
|
||||
REG_RULE(5660-10, 5700+10, 40, 6, 20, NL80211_RRF_DFS),
|
||||
/* IEEE 802.11a, channels 149..165, outdoor */
|
||||
REG_RULE(5745-10, 5825+10, 40, 6, 30, 0),
|
||||
}
|
||||
};
|
||||
|
||||
static const struct ieee80211_regdomain jp_regdom = {
|
||||
.n_reg_rules = 6,
|
||||
.alpha2 = "JP",
|
||||
.reg_rules = {
|
||||
/* IEEE 802.11b/g, channels 1..11 */
|
||||
REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
|
||||
/* IEEE 802.11b/g, channels 12..13 */
|
||||
REG_RULE(2467-10, 2472+10, 20, 6, 20, 0),
|
||||
/* IEEE 802.11b/g, channel 14 */
|
||||
REG_RULE(2484-10, 2484+10, 20, 6, 20, NL80211_RRF_NO_OFDM),
|
||||
/* IEEE 802.11a, channels 36..48 */
|
||||
REG_RULE(5180-10, 5240+10, 40, 6, 20, 0),
|
||||
/* IEEE 802.11a, channels 52..64 */
|
||||
REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS),
|
||||
/* IEEE 802.11a, channels 100..144 */
|
||||
REG_RULE(5500-10, 5700+10, 40, 6, 23, NL80211_RRF_DFS),
|
||||
}
|
||||
};
|
||||
|
||||
static const struct ieee80211_regdomain *static_regdom(char *alpha2)
|
||||
{
|
||||
if (alpha2[0] == 'U' && alpha2[1] == 'S')
|
||||
return &us_regdom;
|
||||
if (alpha2[0] == 'J' && alpha2[1] == 'P')
|
||||
return &jp_regdom;
|
||||
/* Use world roaming rules for "EU", since it was a pseudo
|
||||
domain anyway... */
|
||||
if (alpha2[0] == 'E' && alpha2[1] == 'U')
|
||||
return &world_regdom;
|
||||
/* Default, world roaming rules */
|
||||
return &world_regdom;
|
||||
}
|
||||
|
||||
static bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
|
||||
{
|
||||
if (rd == &us_regdom || rd == &jp_regdom || rd == &world_regdom)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void reset_regdomains(void)
|
||||
{
|
||||
/* avoid freeing static information or freeing something twice */
|
||||
@ -210,8 +138,6 @@ static void reset_regdomains(void)
|
||||
cfg80211_world_regdom = NULL;
|
||||
if (cfg80211_regdomain == &world_regdom)
|
||||
cfg80211_regdomain = NULL;
|
||||
if (is_old_static_regdom(cfg80211_regdomain))
|
||||
cfg80211_regdomain = NULL;
|
||||
|
||||
kfree(cfg80211_regdomain);
|
||||
kfree(cfg80211_world_regdom);
|
||||
@ -1490,8 +1416,6 @@ static int ignore_request(struct wiphy *wiphy,
|
||||
return REG_INTERSECT;
|
||||
case NL80211_REGDOM_SET_BY_DRIVER:
|
||||
if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
|
||||
if (is_old_static_regdom(cfg80211_regdomain))
|
||||
return 0;
|
||||
if (regdom_changes(pending_request->alpha2))
|
||||
return 0;
|
||||
return -EALREADY;
|
||||
@ -1528,8 +1452,7 @@ static int ignore_request(struct wiphy *wiphy,
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (!is_old_static_regdom(cfg80211_regdomain) &&
|
||||
!regdom_changes(pending_request->alpha2))
|
||||
if (!regdom_changes(pending_request->alpha2))
|
||||
return -EALREADY;
|
||||
|
||||
return 0;
|
||||
@ -2111,8 +2034,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
|
||||
* If someone else asked us to change the rd lets only bother
|
||||
* checking if the alpha2 changes if CRDA was already called
|
||||
*/
|
||||
if (!is_old_static_regdom(cfg80211_regdomain) &&
|
||||
!regdom_changes(rd->alpha2))
|
||||
if (!regdom_changes(rd->alpha2))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -2311,15 +2233,8 @@ int regulatory_init(void)
|
||||
spin_lock_init(®_requests_lock);
|
||||
spin_lock_init(®_pending_beacons_lock);
|
||||
|
||||
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
|
||||
cfg80211_regdomain = static_regdom(ieee80211_regdom);
|
||||
|
||||
printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
|
||||
print_regdomain_info(cfg80211_regdomain);
|
||||
#else
|
||||
cfg80211_regdomain = cfg80211_world_regdom;
|
||||
|
||||
#endif
|
||||
/* We always try to get an update for the static regdomain */
|
||||
err = regulatory_hint_core(cfg80211_regdomain->alpha2);
|
||||
if (err) {
|
||||
|
@ -601,7 +601,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy;
|
||||
struct iw_scan_req *wreq = NULL;
|
||||
struct cfg80211_scan_request *creq;
|
||||
struct cfg80211_scan_request *creq = NULL;
|
||||
int i, err, n_channels = 0;
|
||||
enum ieee80211_band band;
|
||||
|
||||
@ -694,8 +694,10 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
/* translate "Scan for SSID" request */
|
||||
if (wreq) {
|
||||
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
|
||||
if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
|
||||
return -EINVAL;
|
||||
if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
|
||||
creq->ssids[0].ssid_len = wreq->essid_len;
|
||||
}
|
||||
@ -707,12 +709,15 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
err = rdev->ops->scan(wiphy, dev, creq);
|
||||
if (err) {
|
||||
rdev->scan_req = NULL;
|
||||
kfree(creq);
|
||||
/* creq will be freed below */
|
||||
} else {
|
||||
nl80211_send_scan_start(rdev, dev);
|
||||
/* creq now owned by driver */
|
||||
creq = NULL;
|
||||
dev_hold(dev);
|
||||
}
|
||||
out:
|
||||
kfree(creq);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
return err;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user