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
|
What: dev->power.power_state
|
||||||
When: July 2007
|
When: July 2007
|
||||||
Why: Broken design for runtime control over driver power states, confusing
|
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,
|
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;
|
struct adm8211_priv *priv = dev->priv;
|
||||||
if (priv->mode != NL80211_IFTYPE_MONITOR)
|
if (priv->mode != NL80211_IFTYPE_MONITOR)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
priv->mode = conf->type;
|
priv->mode = vif->type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@ -1416,8 +1416,8 @@ static int adm8211_add_interface(struct ieee80211_hw *dev,
|
|||||||
|
|
||||||
ADM8211_IDLE();
|
ADM8211_IDLE();
|
||||||
|
|
||||||
ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr));
|
ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr));
|
||||||
ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
|
ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4)));
|
||||||
|
|
||||||
adm8211_update_mode(dev);
|
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,
|
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;
|
struct adm8211_priv *priv = dev->priv;
|
||||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
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,
|
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;
|
struct at76_priv *priv = hw->priv;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -1798,7 +1798,7 @@ static int at76_add_interface(struct ieee80211_hw *hw,
|
|||||||
|
|
||||||
mutex_lock(&priv->mtx);
|
mutex_lock(&priv->mtx);
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
priv->iw_mode = IW_MODE_INFRA;
|
priv->iw_mode = IW_MODE_INFRA;
|
||||||
break;
|
break;
|
||||||
@ -1814,7 +1814,7 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void at76_remove_interface(struct ieee80211_hw *hw,
|
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__);
|
at76_dbg(DBG_MAC80211, "%s()", __func__);
|
||||||
}
|
}
|
||||||
|
@ -1939,7 +1939,7 @@ err_free:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ar9170_op_add_interface(struct ieee80211_hw *hw,
|
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 ar9170 *ar = hw->priv;
|
||||||
struct ath_common *common = &ar->common;
|
struct ath_common *common = &ar->common;
|
||||||
@ -1952,8 +1952,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw,
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
ar->vif = conf->vif;
|
ar->vif = vif;
|
||||||
memcpy(common->macaddr, conf->mac_addr, ETH_ALEN);
|
memcpy(common->macaddr, vif->addr, ETH_ALEN);
|
||||||
|
|
||||||
if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
|
if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
|
||||||
ar->rx_software_decryption = true;
|
ar->rx_software_decryption = true;
|
||||||
@ -1973,7 +1973,7 @@ unlock:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
|
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;
|
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 int ath5k_start(struct ieee80211_hw *hw);
|
||||||
static void ath5k_stop(struct ieee80211_hw *hw);
|
static void ath5k_stop(struct ieee80211_hw *hw);
|
||||||
static int ath5k_add_interface(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,
|
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 int ath5k_config(struct ieee80211_hw *hw, u32 changed);
|
||||||
static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
|
static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
|
||||||
int mc_count, struct dev_addr_list *mc_list);
|
int mc_count, struct dev_addr_list *mc_list);
|
||||||
@ -1903,17 +1903,6 @@ accept:
|
|||||||
rxs->noise = sc->ah->ah_noise_floor;
|
rxs->noise = sc->ah->ah_noise_floor;
|
||||||
rxs->signal = rxs->noise + rs.rs_rssi;
|
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->antenna = rs.rs_antenna;
|
||||||
rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
|
rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
|
||||||
rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
|
rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
|
||||||
@ -2381,6 +2370,9 @@ ath5k_init(struct ath5k_softc *sc)
|
|||||||
*/
|
*/
|
||||||
ath5k_stop_locked(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
|
* The basic interface to setting the hardware in a good
|
||||||
* state is ``reset''. On return the hardware is known to
|
* 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 */
|
/* Set ack to be sent at low bit-rates */
|
||||||
ath5k_hw_set_ack_bitrate_high(ah, false);
|
ath5k_hw_set_ack_bitrate_high(ah, false);
|
||||||
|
|
||||||
/* Set PHY calibration inteval */
|
|
||||||
ah->ah_cal_intval = ath5k_calinterval;
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
done:
|
done:
|
||||||
mmiowb();
|
mmiowb();
|
||||||
@ -2785,7 +2773,7 @@ static void ath5k_stop(struct ieee80211_hw *hw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ath5k_add_interface(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;
|
struct ath5k_softc *sc = hw->priv;
|
||||||
int ret;
|
int ret;
|
||||||
@ -2796,22 +2784,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc->vif = conf->vif;
|
sc->vif = vif;
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
case NL80211_IFTYPE_ADHOC:
|
case NL80211_IFTYPE_ADHOC:
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
case NL80211_IFTYPE_MONITOR:
|
case NL80211_IFTYPE_MONITOR:
|
||||||
sc->opmode = conf->type;
|
sc->opmode = vif->type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EOPNOTSUPP;
|
ret = -EOPNOTSUPP;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
|
ath5k_hw_set_lladdr(sc->ah, vif->addr);
|
||||||
ath5k_mode_setup(sc);
|
ath5k_mode_setup(sc);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -2822,13 +2810,13 @@ end:
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
ath5k_remove_interface(struct ieee80211_hw *hw,
|
ath5k_remove_interface(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_if_init_conf *conf)
|
struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
struct ath5k_softc *sc = hw->priv;
|
struct ath5k_softc *sc = hw->priv;
|
||||||
u8 mac[ETH_ALEN] = {};
|
u8 mac[ETH_ALEN] = {};
|
||||||
|
|
||||||
mutex_lock(&sc->lock);
|
mutex_lock(&sc->lock);
|
||||||
if (sc->vif != conf->vif)
|
if (sc->vif != vif)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
ath5k_hw_set_lladdr(sc->ah, mac);
|
ath5k_hw_set_lladdr(sc->ah, mac);
|
||||||
|
@ -77,6 +77,9 @@
|
|||||||
#define ATH9K_TXERR_XTXOP 0x08
|
#define ATH9K_TXERR_XTXOP 0x08
|
||||||
#define ATH9K_TXERR_TIMER_EXPIRED 0x10
|
#define ATH9K_TXERR_TIMER_EXPIRED 0x10
|
||||||
#define ATH9K_TX_ACKED 0x20
|
#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_BA 0x01
|
||||||
#define ATH9K_TX_PWRMGMT 0x02
|
#define ATH9K_TX_PWRMGMT 0x02
|
||||||
|
@ -2504,6 +2504,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
|||||||
return; /* another wiphy still in use */
|
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) {
|
if (ah->btcoex_hw.enabled) {
|
||||||
ath9k_hw_btcoex_disable(ah);
|
ath9k_hw_btcoex_disable(ah);
|
||||||
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
|
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 */
|
/* disable HAL and put h/w to sleep */
|
||||||
ath9k_hw_disable(ah);
|
ath9k_hw_disable(ah);
|
||||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
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);
|
ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
|
||||||
|
|
||||||
sc->sc_flags |= SC_OP_INVALID;
|
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,
|
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_wiphy *aphy = hw->priv;
|
||||||
struct ath_softc *sc = aphy->sc;
|
struct ath_softc *sc = aphy->sc;
|
||||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
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;
|
enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -2551,7 +2557,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
ic_opmode = NL80211_IFTYPE_STATION;
|
ic_opmode = NL80211_IFTYPE_STATION;
|
||||||
break;
|
break;
|
||||||
@ -2562,11 +2568,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
|||||||
ret = -ENOBUFS;
|
ret = -ENOBUFS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ic_opmode = conf->type;
|
ic_opmode = vif->type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ath_print(common, ATH_DBG_FATAL,
|
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;
|
ret = -EOPNOTSUPP;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -2598,18 +2604,18 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
|||||||
* Enable MIB interrupts when there are hardware phy counters.
|
* Enable MIB interrupts when there are hardware phy counters.
|
||||||
* Note we only do this (at the moment) for station mode.
|
* Note we only do this (at the moment) for station mode.
|
||||||
*/
|
*/
|
||||||
if ((conf->type == NL80211_IFTYPE_STATION) ||
|
if ((vif->type == NL80211_IFTYPE_STATION) ||
|
||||||
(conf->type == NL80211_IFTYPE_ADHOC) ||
|
(vif->type == NL80211_IFTYPE_ADHOC) ||
|
||||||
(conf->type == NL80211_IFTYPE_MESH_POINT)) {
|
(vif->type == NL80211_IFTYPE_MESH_POINT)) {
|
||||||
sc->imask |= ATH9K_INT_MIB;
|
sc->imask |= ATH9K_INT_MIB;
|
||||||
sc->imask |= ATH9K_INT_TSFOOR;
|
sc->imask |= ATH9K_INT_TSFOOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
|
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
|
||||||
|
|
||||||
if (conf->type == NL80211_IFTYPE_AP ||
|
if (vif->type == NL80211_IFTYPE_AP ||
|
||||||
conf->type == NL80211_IFTYPE_ADHOC ||
|
vif->type == NL80211_IFTYPE_ADHOC ||
|
||||||
conf->type == NL80211_IFTYPE_MONITOR)
|
vif->type == NL80211_IFTYPE_MONITOR)
|
||||||
ath_start_ani(common);
|
ath_start_ani(common);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -2618,12 +2624,12 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
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_wiphy *aphy = hw->priv;
|
||||||
struct ath_softc *sc = aphy->sc;
|
struct ath_softc *sc = aphy->sc;
|
||||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
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;
|
int i;
|
||||||
|
|
||||||
ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
|
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) ||
|
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
|
||||||
(sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
|
(sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
|
||||||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
|
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
|
||||||
|
ath9k_ps_wakeup(sc);
|
||||||
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
||||||
ath_beacon_return(sc, avp);
|
ath_beacon_return(sc, avp);
|
||||||
|
ath9k_ps_restore(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc->sc_flags &= ~SC_OP_BEACONS;
|
sc->sc_flags &= ~SC_OP_BEACONS;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
|
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 "
|
printk(KERN_DEBUG "%s: vif had allocated beacon "
|
||||||
"slot\n", __func__);
|
"slot\n", __func__);
|
||||||
sc->beacon.bslot[i] = NULL;
|
sc->beacon.bslot[i] = NULL;
|
||||||
@ -3087,15 +3095,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
|||||||
case IEEE80211_AMPDU_RX_STOP:
|
case IEEE80211_AMPDU_RX_STOP:
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_START:
|
case IEEE80211_AMPDU_TX_START:
|
||||||
|
ath9k_ps_wakeup(sc);
|
||||||
ath_tx_aggr_start(sc, sta, tid, ssn);
|
ath_tx_aggr_start(sc, sta, tid, ssn);
|
||||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||||
|
ath9k_ps_restore(sc);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_STOP:
|
case IEEE80211_AMPDU_TX_STOP:
|
||||||
|
ath9k_ps_wakeup(sc);
|
||||||
ath_tx_aggr_stop(sc, sta, tid);
|
ath_tx_aggr_stop(sc, sta, tid);
|
||||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||||
|
ath9k_ps_restore(sc);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||||
|
ath9k_ps_wakeup(sc);
|
||||||
ath_tx_aggr_resume(sc, sta, tid);
|
ath_tx_aggr_resume(sc, sta, tid);
|
||||||
|
ath9k_ps_restore(sc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
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);
|
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,
|
.read_cachesize = ath_pci_read_cachesize,
|
||||||
.cleanup = ath_pci_cleanup,
|
.cleanup = ath_pci_cleanup,
|
||||||
.eeprom_read = ath_pci_eeprom_read,
|
.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_q, lastbf->list.prev);
|
||||||
|
|
||||||
txq->axq_depth--;
|
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;
|
txq->axq_tx_inprogress = false;
|
||||||
spin_unlock_bh(&txq->axq_lock);
|
spin_unlock_bh(&txq->axq_lock);
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ config B43
|
|||||||
depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
|
depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
|
||||||
select SSB
|
select SSB
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
|
select SSB_BLOCKIO
|
||||||
---help---
|
---help---
|
||||||
b43 is a driver for the Broadcom 43xx series wireless devices.
|
b43 is a driver for the Broadcom 43xx series wireless devices.
|
||||||
|
|
||||||
@ -78,14 +79,6 @@ config B43_SDIO
|
|||||||
|
|
||||||
If unsure, say N.
|
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
|
config B43_NPHY
|
||||||
bool "Pre IEEE 802.11n support (BROKEN)"
|
bool "Pre IEEE 802.11n support (BROKEN)"
|
||||||
depends on B43 && EXPERIMENTAL && BROKEN
|
depends on B43 && EXPERIMENTAL && BROKEN
|
||||||
@ -137,12 +130,4 @@ config B43_DEBUG
|
|||||||
for production use.
|
for production use.
|
||||||
Only say Y, if you are debugging a problem in the b43 driver sourcecode.
|
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 += lo.o
|
||||||
b43-y += wa.o
|
b43-y += wa.o
|
||||||
b43-y += dma.o
|
b43-y += dma.o
|
||||||
b43-$(CONFIG_B43_PIO) += pio.o
|
b43-y += pio.o
|
||||||
b43-y += rfkill.o
|
b43-y += rfkill.o
|
||||||
b43-$(CONFIG_B43_LEDS) += leds.o
|
b43-$(CONFIG_B43_LEDS) += leds.o
|
||||||
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
|
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
|
||||||
|
@ -821,11 +821,9 @@ struct b43_wl {
|
|||||||
/* The device LEDs. */
|
/* The device LEDs. */
|
||||||
struct b43_leds leds;
|
struct b43_leds leds;
|
||||||
|
|
||||||
#ifdef CONFIG_B43_PIO
|
|
||||||
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
|
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
|
||||||
u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
|
u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
|
||||||
u8 pio_tailspace[4] __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)
|
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)
|
static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_B43_PIO
|
|
||||||
return dev->__using_pio_transfers;
|
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 */
|
/* Message printing */
|
||||||
void b43info(struct b43_wl *wl, const char *fmt, ...)
|
void b43info(struct b43_wl *wl, const char *fmt, ...)
|
||||||
__attribute__ ((format(printf, 2, 3)));
|
__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)
|
static int alloc_ringmemory(struct b43_dmaring *ring)
|
||||||
{
|
{
|
||||||
unsigned int required;
|
gfp_t flags = GFP_KERNEL;
|
||||||
void *base;
|
|
||||||
dma_addr_t dmaaddr;
|
|
||||||
|
|
||||||
/* There are several requirements to the descriptor ring memory:
|
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
|
||||||
* - The memory region needs to fit the address constraints for the
|
* alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing
|
||||||
* device (same as for frame buffers).
|
* has shown that 4K is sufficient for the latter as long as the buffer
|
||||||
* - For 30/32bit DMA devices, the descriptor ring must be 4k aligned.
|
* does not cross an 8K boundary.
|
||||||
* - For 64bit DMA devices, the descriptor ring must be 8k aligned.
|
*
|
||||||
|
* 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)
|
if (ring->type == B43_DMA_64BIT)
|
||||||
required = ring->nr_slots * sizeof(struct b43_dmadesc64);
|
flags |= GFP_DMA;
|
||||||
else
|
ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
|
||||||
required = ring->nr_slots * sizeof(struct b43_dmadesc32);
|
B43_DMA_RINGMEMSIZE,
|
||||||
if (B43_WARN_ON(required > 0x1000))
|
&(ring->dmabase), flags);
|
||||||
|
if (!ring->descbase) {
|
||||||
|
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
|
||||||
return -ENOMEM;
|
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);
|
memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE);
|
||||||
|
|
||||||
/* 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));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_ringmemory(struct b43_dmaring *ring)
|
static void free_ringmemory(struct b43_dmaring *ring)
|
||||||
{
|
{
|
||||||
b43_unmap_and_free_ringmem(ring, ring->alloc_descbase,
|
gfp_t flags = GFP_KERNEL;
|
||||||
ring->alloc_dmabase, ring->alloc_descsize);
|
|
||||||
|
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 */
|
/* 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)))
|
if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!b43_dma_address_ok(ring, addr, buffersize)) {
|
switch (ring->type) {
|
||||||
/* We can't support this address. Unmap it again. */
|
case B43_DMA_30BIT:
|
||||||
unmap_descbuffer(ring, addr, buffersize, dma_to_device);
|
if ((u64)addr + buffersize > (1ULL << 30))
|
||||||
return 1;
|
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. */
|
/* The address is OK. */
|
||||||
return 0;
|
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)
|
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;
|
meta->dmaaddr = dmaaddr;
|
||||||
ring->ops->fill_descriptor(ring, desc, dmaaddr,
|
ring->ops->fill_descriptor(ring, desc, dmaaddr,
|
||||||
ring->rx_buffersize, 0, 0, 0);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1354,9 +1250,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
|||||||
}
|
}
|
||||||
/* Now transfer the whole frame. */
|
/* Now transfer the whole frame. */
|
||||||
wmb();
|
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));
|
ops->poke_tx(ring, next_slot(ring, slot));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1760,7 +1653,6 @@ void b43_dma_tx_resume(struct b43_wldev *dev)
|
|||||||
b43_power_saving_ctl_bits(dev, 0);
|
b43_power_saving_ctl_bits(dev, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_B43_PIO
|
|
||||||
static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
|
static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
|
||||||
u16 mmio_base, bool enable)
|
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);
|
mmio_base = b43_dmacontroller_base(type, engine_index);
|
||||||
direct_fifo_rx(dev, type, mmio_base, enable);
|
direct_fifo_rx(dev, type, mmio_base, enable);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_B43_PIO */
|
|
||||||
|
@ -157,6 +157,7 @@ struct b43_dmadesc_generic {
|
|||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
/* Misc DMA constants */
|
/* Misc DMA constants */
|
||||||
|
#define B43_DMA_RINGMEMSIZE PAGE_SIZE
|
||||||
#define B43_DMA0_RX_FRAMEOFFSET 30
|
#define B43_DMA0_RX_FRAMEOFFSET 30
|
||||||
|
|
||||||
/* DMA engine tuning knobs */
|
/* DMA engine tuning knobs */
|
||||||
@ -246,12 +247,6 @@ struct b43_dmaring {
|
|||||||
/* The QOS priority assigned to this ring. Only used for TX rings.
|
/* The QOS priority assigned to this ring. Only used for TX rings.
|
||||||
* This is the mac80211 "queue" value. */
|
* This is the mac80211 "queue" value. */
|
||||||
u8 queue_prio;
|
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;
|
struct b43_wldev *dev;
|
||||||
#ifdef CONFIG_B43_DEBUG
|
#ifdef CONFIG_B43_DEBUG
|
||||||
/* Maximum number of used slots. */
|
/* 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_param_named(verbose, b43_modparam_verbose, int, 0644);
|
||||||
MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
|
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[] = {
|
static const struct ssb_device_id b43_ssb_tbl[] = {
|
||||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
|
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]);
|
dma_reason[4], dma_reason[5]);
|
||||||
b43err(dev->wl, "This device does not support DMA "
|
b43err(dev->wl, "This device does not support DMA "
|
||||||
"on your system. Please use PIO instead.\n");
|
"on your system. Please use PIO instead.\n");
|
||||||
b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in "
|
b43err(dev->wl, "Unload the b43 module and reload "
|
||||||
"your kernel configuration.\n");
|
"with 'pio=1'\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
|
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) ||
|
if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
|
||||||
(dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
|
(dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
|
||||||
B43_FORCE_PIO) {
|
modparam_pio) {
|
||||||
dev->__using_pio_transfers = 1;
|
dev->__using_pio_transfers = 1;
|
||||||
err = b43_pio_init(dev);
|
err = b43_pio_init(dev);
|
||||||
} else {
|
} else {
|
||||||
@ -4388,7 +4391,7 @@ err_busdown:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int b43_op_add_interface(struct ieee80211_hw *hw,
|
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_wl *wl = hw_to_b43_wl(hw);
|
||||||
struct b43_wldev *dev;
|
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 */
|
/* TODO: allow WDS/AP devices to coexist */
|
||||||
|
|
||||||
if (conf->type != NL80211_IFTYPE_AP &&
|
if (vif->type != NL80211_IFTYPE_AP &&
|
||||||
conf->type != NL80211_IFTYPE_MESH_POINT &&
|
vif->type != NL80211_IFTYPE_MESH_POINT &&
|
||||||
conf->type != NL80211_IFTYPE_STATION &&
|
vif->type != NL80211_IFTYPE_STATION &&
|
||||||
conf->type != NL80211_IFTYPE_WDS &&
|
vif->type != NL80211_IFTYPE_WDS &&
|
||||||
conf->type != NL80211_IFTYPE_ADHOC)
|
vif->type != NL80211_IFTYPE_ADHOC)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
if (wl->operating)
|
if (wl->operating)
|
||||||
goto out_mutex_unlock;
|
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;
|
dev = wl->current_dev;
|
||||||
wl->operating = 1;
|
wl->operating = 1;
|
||||||
wl->vif = conf->vif;
|
wl->vif = vif;
|
||||||
wl->if_type = conf->type;
|
wl->if_type = vif->type;
|
||||||
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
|
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
|
||||||
|
|
||||||
b43_adjust_opmode(dev);
|
b43_adjust_opmode(dev);
|
||||||
b43_set_pretbtt(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,
|
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_wl *wl = hw_to_b43_wl(hw);
|
||||||
struct b43_wldev *dev = wl->current_dev;
|
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);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
B43_WARN_ON(!wl->operating);
|
B43_WARN_ON(!wl->operating);
|
||||||
B43_WARN_ON(wl->vif != conf->vif);
|
B43_WARN_ON(wl->vif != vif);
|
||||||
wl->vif = NULL;
|
wl->vif = NULL;
|
||||||
|
|
||||||
wl->operating = 0;
|
wl->operating = 0;
|
||||||
|
@ -55,8 +55,6 @@
|
|||||||
#define B43_PIO_MAX_NR_TXPACKETS 32
|
#define B43_PIO_MAX_NR_TXPACKETS 32
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_B43_PIO
|
|
||||||
|
|
||||||
struct b43_pio_txpacket {
|
struct b43_pio_txpacket {
|
||||||
/* Pointer to the TX queue we belong to. */
|
/* Pointer to the TX queue we belong to. */
|
||||||
struct b43_pio_txqueue *queue;
|
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_suspend(struct b43_wldev *dev);
|
||||||
void b43_pio_tx_resume(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_ */
|
#endif /* B43_PIO_H_ */
|
||||||
|
@ -3361,7 +3361,7 @@ err_kfree_lo_control:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
|
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_wl *wl = hw_to_b43legacy_wl(hw);
|
||||||
struct b43legacy_wldev *dev;
|
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 */
|
/* TODO: allow WDS/AP devices to coexist */
|
||||||
|
|
||||||
if (conf->type != NL80211_IFTYPE_AP &&
|
if (vif->type != NL80211_IFTYPE_AP &&
|
||||||
conf->type != NL80211_IFTYPE_STATION &&
|
vif->type != NL80211_IFTYPE_STATION &&
|
||||||
conf->type != NL80211_IFTYPE_WDS &&
|
vif->type != NL80211_IFTYPE_WDS &&
|
||||||
conf->type != NL80211_IFTYPE_ADHOC)
|
vif->type != NL80211_IFTYPE_ADHOC)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
if (wl->operating)
|
if (wl->operating)
|
||||||
goto out_mutex_unlock;
|
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;
|
dev = wl->current_dev;
|
||||||
wl->operating = 1;
|
wl->operating = 1;
|
||||||
wl->vif = conf->vif;
|
wl->vif = vif;
|
||||||
wl->if_type = conf->type;
|
wl->if_type = vif->type;
|
||||||
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
|
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
|
||||||
|
|
||||||
spin_lock_irqsave(&wl->irq_lock, flags);
|
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||||
b43legacy_adjust_opmode(dev);
|
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,
|
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_wl *wl = hw_to_b43legacy_wl(hw);
|
||||||
struct b43legacy_wldev *dev = wl->current_dev;
|
struct b43legacy_wldev *dev = wl->current_dev;
|
||||||
unsigned long flags;
|
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);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
B43legacy_WARN_ON(!wl->operating);
|
B43legacy_WARN_ON(!wl->operating);
|
||||||
B43legacy_WARN_ON(wl->vif != conf->vif);
|
B43legacy_WARN_ON(wl->vif != vif);
|
||||||
wl->vif = NULL;
|
wl->vif = NULL;
|
||||||
|
|
||||||
wl->operating = 0;
|
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;
|
snr = rx_stats_sig_avg / rx_stats_noise_diff;
|
||||||
rx_status.noise = rx_status.signal -
|
rx_status.noise = rx_status.signal -
|
||||||
iwl3945_calc_db_from_ratio(snr);
|
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 {
|
} else {
|
||||||
rx_status.noise = priv->last_rx_noise;
|
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",
|
IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n",
|
||||||
rx_status.signal, rx_status.noise, rx_status.qual,
|
rx_status.signal, rx_status.noise,
|
||||||
rx_stats_sig_avg, rx_stats_noise_diff);
|
rx_stats_sig_avg, rx_stats_noise_diff);
|
||||||
|
|
||||||
header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
|
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_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_replenish(void *data);
|
||||||
extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
|
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,
|
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 */
|
/* 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"},
|
{ "1", "BPSK DSSS"},
|
||||||
{ "2", "QPSK DSSS"},
|
{ "2", "QPSK DSSS"},
|
||||||
{"5.5", "BPSK CCK"},
|
{"5.5", "BPSK CCK"},
|
||||||
|
@ -2584,12 +2584,12 @@ int iwl_set_mode(struct iwl_priv *priv, int mode)
|
|||||||
EXPORT_SYMBOL(iwl_set_mode);
|
EXPORT_SYMBOL(iwl_set_mode);
|
||||||
|
|
||||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
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;
|
struct iwl_priv *priv = hw->priv;
|
||||||
unsigned long flags;
|
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) {
|
if (priv->vif) {
|
||||||
IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
|
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);
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
priv->vif = conf->vif;
|
priv->vif = vif;
|
||||||
priv->iw_mode = conf->type;
|
priv->iw_mode = vif->type;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
mutex_lock(&priv->mutex);
|
mutex_lock(&priv->mutex);
|
||||||
|
|
||||||
if (conf->mac_addr) {
|
if (vif->addr) {
|
||||||
IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr);
|
IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
|
||||||
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
|
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 */
|
/* we are not ready, will run again when ready */
|
||||||
set_bit(STATUS_MODE_PENDING, &priv->status);
|
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);
|
EXPORT_SYMBOL(iwl_mac_add_interface);
|
||||||
|
|
||||||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
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;
|
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;
|
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||||
iwlcore_commit_rxon(priv);
|
iwlcore_commit_rxon(priv);
|
||||||
}
|
}
|
||||||
if (priv->vif == conf->vif) {
|
if (priv->vif == vif) {
|
||||||
priv->vif = NULL;
|
priv->vif = NULL;
|
||||||
memset(priv->bssid, 0, ETH_ALEN);
|
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_commit_rxon(struct iwl_priv *priv);
|
||||||
int iwl_set_mode(struct iwl_priv *priv, int mode);
|
int iwl_set_mode(struct iwl_priv *priv, int mode);
|
||||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
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,
|
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);
|
int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||||
void iwl_config_ap(struct iwl_priv *priv);
|
void iwl_config_ap(struct iwl_priv *priv);
|
||||||
int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
|
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);
|
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 */
|
/* Calc max signal level (dBm) among 3 possible receivers */
|
||||||
static inline int iwl_calc_rssi(struct iwl_priv *priv,
|
static inline int iwl_calc_rssi(struct iwl_priv *priv,
|
||||||
struct iwl_rx_phy_res *rx_resp)
|
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) &&
|
if (iwl_is_associated(priv) &&
|
||||||
!test_bit(STATUS_SCANNING, &priv->status)) {
|
!test_bit(STATUS_SCANNING, &priv->status)) {
|
||||||
rx_status.noise = priv->last_rx_noise;
|
rx_status.noise = priv->last_rx_noise;
|
||||||
rx_status.qual = iwl_calc_sig_qual(rx_status.signal,
|
|
||||||
rx_status.noise);
|
|
||||||
} else {
|
} else {
|
||||||
rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
|
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. */
|
/* 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);
|
iwl_dbg_report_frame(priv, phy_res, len, header, 1);
|
||||||
#endif
|
#endif
|
||||||
iwl_dbg_log_rx_data_frame(priv, len, header);
|
iwl_dbg_log_rx_data_frame(priv, len, header);
|
||||||
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
|
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n",
|
||||||
rx_status.signal, rx_status.noise, rx_status.qual,
|
rx_status.signal, rx_status.noise,
|
||||||
(unsigned long long)rx_status.mactime);
|
(unsigned long long)rx_status.mactime);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1299,47 +1299,6 @@ int iwl3945_calc_db_from_ratio(int sig_ratio)
|
|||||||
return (int)ratio2dB[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
|
* 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 sk_buff_head rx_list;
|
||||||
struct list_head rx_tickets;
|
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 workqueue_struct *rx_wq;
|
||||||
struct work_struct rx_worker;
|
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);
|
chan_count = lbs_scan_create_channel_list(priv, chan_list);
|
||||||
|
|
||||||
netif_stop_queue(priv->dev);
|
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_stop_queue(priv->mesh_dev);
|
||||||
netif_carrier_off(priv->mesh_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare to continue an interrupted scan */
|
/* Prepare to continue an interrupted scan */
|
||||||
lbs_deb_scan("chan_count %d, scan_channel %d\n",
|
lbs_deb_scan("chan_count %d, scan_channel %d\n",
|
||||||
@ -635,16 +632,13 @@ out2:
|
|||||||
priv->scan_channel = 0;
|
priv->scan_channel = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (priv->connect_status == LBS_CONNECTED) {
|
if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
|
||||||
netif_carrier_on(priv->dev);
|
netif_wake_queue(priv->dev);
|
||||||
if (!priv->tx_pending_len)
|
|
||||||
netif_wake_queue(priv->dev);
|
if (priv->mesh_dev && lbs_mesh_connected(priv) &&
|
||||||
}
|
!priv->tx_pending_len)
|
||||||
if (priv->mesh_dev && lbs_mesh_connected(priv)) {
|
netif_wake_queue(priv->mesh_dev);
|
||||||
netif_carrier_on(priv->mesh_dev);
|
|
||||||
if (!priv->tx_pending_len)
|
|
||||||
netif_wake_queue(priv->mesh_dev);
|
|
||||||
}
|
|
||||||
kfree(chan_list);
|
kfree(chan_list);
|
||||||
|
|
||||||
lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
|
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,
|
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;
|
struct lbtf_private *priv = hw->priv;
|
||||||
if (priv->vif != NULL)
|
if (priv->vif != NULL)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
priv->vif = conf->vif;
|
priv->vif = vif;
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
lbtf_set_mode(priv, LBTF_AP_MODE);
|
lbtf_set_mode(priv, LBTF_AP_MODE);
|
||||||
@ -337,12 +337,12 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,
|
|||||||
priv->vif = NULL;
|
priv->vif = NULL;
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
lbtf_set_mac_address(priv, (u8 *) conf->mac_addr);
|
lbtf_set_mac_address(priv, (u8 *) vif->addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
|
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;
|
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.band = IEEE80211_BAND_2GHZ;
|
||||||
stats.signal = prxpd->snr;
|
stats.signal = prxpd->snr;
|
||||||
stats.noise = prxpd->nf;
|
stats.noise = prxpd->nf;
|
||||||
stats.qual = prxpd->snr - prxpd->nf;
|
|
||||||
/* Marvell rate index has a hole at value 4 */
|
/* Marvell rate index has a hole at value 4 */
|
||||||
if (prxpd->rx_rate > 4)
|
if (prxpd->rx_rate > 4)
|
||||||
--prxpd->rx_rate;
|
--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,
|
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",
|
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
|
||||||
wiphy_name(hw->wiphy), __func__, conf->type,
|
wiphy_name(hw->wiphy), __func__, vif->type,
|
||||||
conf->mac_addr);
|
vif->addr);
|
||||||
hwsim_set_magic(conf->vif);
|
hwsim_set_magic(vif);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void mac80211_hwsim_remove_interface(
|
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",
|
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
|
||||||
wiphy_name(hw->wiphy), __func__, conf->type,
|
wiphy_name(hw->wiphy), __func__, vif->type,
|
||||||
conf->mac_addr);
|
vif->addr);
|
||||||
hwsim_check_magic(conf->vif);
|
hwsim_check_magic(vif);
|
||||||
hwsim_clear_magic(conf->vif);
|
hwsim_clear_magic(vif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -896,6 +896,16 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
|
|||||||
return 0;
|
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 =
|
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,
|
.conf_tx = mac80211_hwsim_conf_tx,
|
||||||
CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
|
CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
|
||||||
.ampdu_action = mac80211_hwsim_ampdu_action,
|
.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
|
#define MAX_RID_LEN 1024
|
||||||
|
|
||||||
/* Helper routine to record keys
|
/* 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,
|
static int orinoco_set_key(struct orinoco_private *priv, int index,
|
||||||
enum orinoco_alg alg, const u8 *key, int key_len,
|
enum orinoco_alg alg, const u8 *key, int key_len,
|
||||||
const u8 *seq, int seq_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);
|
kzfree(priv->keys[index].seq);
|
||||||
|
|
||||||
if (key_len) {
|
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)
|
if (!priv->keys[index].key)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
} else
|
} else
|
||||||
priv->keys[index].key = NULL;
|
priv->keys[index].key = NULL;
|
||||||
|
|
||||||
if (seq_len) {
|
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)
|
if (!priv->keys[index].seq)
|
||||||
goto free_key;
|
goto free_key;
|
||||||
} else
|
} else
|
||||||
|
@ -216,7 +216,7 @@ static void p54_stop(struct ieee80211_hw *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int p54_add_interface(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;
|
struct p54_common *priv = dev->priv;
|
||||||
|
|
||||||
@ -226,28 +226,28 @@ static int p54_add_interface(struct ieee80211_hw *dev,
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->vif = conf->vif;
|
priv->vif = vif;
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
case NL80211_IFTYPE_ADHOC:
|
case NL80211_IFTYPE_ADHOC:
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
priv->mode = conf->type;
|
priv->mode = vif->type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mutex_unlock(&priv->conf_mutex);
|
mutex_unlock(&priv->conf_mutex);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
|
memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
|
||||||
p54_setup_mac(priv);
|
p54_setup_mac(priv);
|
||||||
mutex_unlock(&priv->conf_mutex);
|
mutex_unlock(&priv->conf_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void p54_remove_interface(struct ieee80211_hw *dev,
|
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;
|
struct p54_common *priv = dev->priv;
|
||||||
|
|
||||||
|
@ -54,12 +54,12 @@ config RT61PCI
|
|||||||
When compiled as a module, this driver will be called rt61pci.
|
When compiled as a module, this driver will be called rt61pci.
|
||||||
|
|
||||||
config RT2800PCI_PCI
|
config RT2800PCI_PCI
|
||||||
tristate
|
boolean
|
||||||
depends on PCI
|
depends on PCI
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config RT2800PCI_SOC
|
config RT2800PCI_SOC
|
||||||
tristate
|
boolean
|
||||||
depends on RALINK_RT288X || RALINK_RT305X
|
depends on RALINK_RT288X || RALINK_RT305X
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
@ -451,7 +451,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
|||||||
/*
|
/*
|
||||||
* RF2420 chipset don't need any additional actions.
|
* RF2420 chipset don't need any additional actions.
|
||||||
*/
|
*/
|
||||||
if (rt2x00_rf(&rt2x00dev->chip, RF2420))
|
if (rt2x00_rf(rt2x00dev, RF2420))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1343,8 +1343,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||||
rt2x00_print_chip(rt2x00dev);
|
rt2x00_print_chip(rt2x00dev);
|
||||||
|
|
||||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
|
if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2421)) {
|
|
||||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -440,8 +440,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
|
|||||||
/*
|
/*
|
||||||
* RT2525E and RT5222 need to flip TX I/Q
|
* RT2525E and RT5222 need to flip TX I/Q
|
||||||
*/
|
*/
|
||||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
|
if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
|
||||||
rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
|
rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
|
||||||
rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1);
|
rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1);
|
||||||
rt2x00_set_field32(®, BBPCSR1_OFDM_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.
|
* 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);
|
rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
|
||||||
} else {
|
} else {
|
||||||
rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0);
|
rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0);
|
||||||
@ -475,14 +474,14 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
|||||||
* Switch on tuning bits.
|
* Switch on tuning bits.
|
||||||
* For RT2523 devices we do not need to update the R1 register.
|
* 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->rf1, RF1_TUNER, 1);
|
||||||
rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
|
rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For RT2525 we should first set the channel to half band higher.
|
* 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[] = {
|
static const u32 vals[] = {
|
||||||
0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a,
|
0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a,
|
||||||
0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a,
|
0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a,
|
||||||
@ -516,7 +515,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
|
|||||||
* Switch off tuning bits.
|
* Switch off tuning bits.
|
||||||
* For RT2523 devices we do not need to update the R1 register.
|
* 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);
|
rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
|
||||||
rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
|
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
|
* up to version C the link tuning should halt after 20
|
||||||
* seconds while being associated.
|
* seconds while being associated.
|
||||||
*/
|
*/
|
||||||
if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
|
if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D &&
|
||||||
rt2x00dev->intf_associated && count > 20)
|
rt2x00dev->intf_associated && count > 20)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -650,7 +649,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
|
|||||||
* should go straight to dynamic CCA tuning when they
|
* should go straight to dynamic CCA tuning when they
|
||||||
* are not associated.
|
* are not associated.
|
||||||
*/
|
*/
|
||||||
if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D ||
|
if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D ||
|
||||||
!rt2x00dev->intf_associated)
|
!rt2x00dev->intf_associated)
|
||||||
goto dynamic_cca_tune;
|
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_set_chip_rf(rt2x00dev, value, reg);
|
||||||
rt2x00_print_chip(rt2x00dev);
|
rt2x00_print_chip(rt2x00dev);
|
||||||
|
|
||||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
|
if (!rt2x00_rf(rt2x00dev, RF2522) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2523) &&
|
!rt2x00_rf(rt2x00dev, RF2523) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2524) &&
|
!rt2x00_rf(rt2x00dev, RF2524) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2525) &&
|
!rt2x00_rf(rt2x00dev, RF2525) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2525E) &&
|
!rt2x00_rf(rt2x00dev, RF2525E) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
!rt2x00_rf(rt2x00dev, RF5222)) {
|
||||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@ -1744,22 +1743,22 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
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->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
|
||||||
spec->channels = 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->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
|
||||||
spec->channels = 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->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
|
||||||
spec->channels = 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->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
|
||||||
spec->channels = 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->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
|
||||||
spec->channels = 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->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||||
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
|
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
|
||||||
spec->channels = 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
|
* RT2525E and RT5222 need to flip TX I/Q
|
||||||
*/
|
*/
|
||||||
if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
|
if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
|
||||||
rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
|
rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
|
||||||
rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1);
|
rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1);
|
||||||
rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_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.
|
* 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);
|
rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
|
||||||
} else {
|
} else {
|
||||||
rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0);
|
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.
|
* 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[] = {
|
static const u32 vals[] = {
|
||||||
0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
|
0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
|
||||||
0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
|
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);
|
rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1);
|
||||||
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
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, ®);
|
rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®);
|
||||||
rt2x00_set_field16(®, PHY_CSR2_LNA, 0);
|
rt2x00_set_field16(®, PHY_CSR2_LNA, 0);
|
||||||
} else {
|
} else {
|
||||||
@ -1411,19 +1410,18 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||||||
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
|
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
|
||||||
rt2x00_print_chip(rt2x00dev);
|
rt2x00_print_chip(rt2x00dev);
|
||||||
|
|
||||||
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) ||
|
if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) ||
|
||||||
rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
|
rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) {
|
||||||
|
|
||||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
|
if (!rt2x00_rf(rt2x00dev, RF2522) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2523) &&
|
!rt2x00_rf(rt2x00dev, RF2523) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2524) &&
|
!rt2x00_rf(rt2x00dev, RF2524) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2525) &&
|
!rt2x00_rf(rt2x00dev, RF2525) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2525E) &&
|
!rt2x00_rf(rt2x00dev, RF2525E) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF5222)) {
|
!rt2x00_rf(rt2x00dev, RF5222)) {
|
||||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@ -1667,22 +1665,22 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
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->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
|
||||||
spec->channels = 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->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
|
||||||
spec->channels = 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->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
|
||||||
spec->channels = 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->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
|
||||||
spec->channels = 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->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
|
||||||
spec->channels = 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->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||||
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
|
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
|
||||||
spec->channels = rf_vals_5222;
|
spec->channels = rf_vals_5222;
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
#include "rt2x00.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"
|
#include "rt2x00usb.h"
|
||||||
#endif
|
#endif
|
||||||
#include "rt2800lib.h"
|
#include "rt2800lib.h"
|
||||||
@ -220,8 +220,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
|
|||||||
/*
|
/*
|
||||||
* RT2880 and RT3052 don't support MCU requests.
|
* RT2880 and RT3052 don't support MCU requests.
|
||||||
*/
|
*/
|
||||||
if (rt2x00_rt(&rt2x00dev->chip, RT2880) ||
|
if (rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT3052))
|
||||||
rt2x00_rt(&rt2x00dev->chip, RT3052))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&rt2x00dev->csr_mutex);
|
mutex_lock(&rt2x00dev->csr_mutex);
|
||||||
@ -806,12 +805,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
|
|||||||
unsigned int tx_pin;
|
unsigned int tx_pin;
|
||||||
u8 bbp;
|
u8 bbp;
|
||||||
|
|
||||||
if ((rt2x00_rt(&rt2x00dev->chip, RT3070) ||
|
if ((rt2x00_rt(rt2x00dev, RT3070) ||
|
||||||
rt2x00_rt(&rt2x00dev->chip, RT3090)) &&
|
rt2x00_rt(rt2x00dev, RT3090)) &&
|
||||||
(rt2x00_rf(&rt2x00dev->chip, RF2020) ||
|
(rt2x00_rf(rt2x00dev, RF2020) ||
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF3020) ||
|
rt2x00_rf(rt2x00dev, RF3020) ||
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF3021) ||
|
rt2x00_rf(rt2x00dev, RF3021) ||
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF3022)))
|
rt2x00_rf(rt2x00dev, RF3022)))
|
||||||
rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
|
rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
|
||||||
else
|
else
|
||||||
rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
|
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));
|
rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
|
||||||
rt2800_bbp_write(rt2x00dev, 3, bbp);
|
rt2800_bbp_write(rt2x00dev, 3, bbp);
|
||||||
|
|
||||||
if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
|
if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) {
|
||||||
if (conf_is_ht40(conf)) {
|
if (conf_is_ht40(conf)) {
|
||||||
rt2800_bbp_write(rt2x00dev, 69, 0x1a);
|
rt2800_bbp_write(rt2x00dev, 69, 0x1a);
|
||||||
rt2800_bbp_write(rt2x00dev, 70, 0x0a);
|
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 (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
|
||||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||||
rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION)
|
rt2x00_rev(rt2x00dev) == RT3070_VERSION)
|
||||||
return 0x1c + (2 * rt2x00dev->lna_gain);
|
return 0x1c + (2 * rt2x00dev->lna_gain);
|
||||||
else
|
else
|
||||||
return 0x2e + rt2x00dev->lna_gain;
|
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,
|
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
|
||||||
const u32 count)
|
const u32 count)
|
||||||
{
|
{
|
||||||
if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION)
|
if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1121,7 +1120,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||||||
|
|
||||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||||
rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
|
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,
|
rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
|
||||||
USB_MODE_RESET, REGISTER_TIMEOUT);
|
USB_MODE_RESET, REGISTER_TIMEOUT);
|
||||||
#endif
|
#endif
|
||||||
@ -1158,7 +1157,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||||||
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
|
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
|
||||||
|
|
||||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
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_CFG0, 0x00000400);
|
||||||
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
|
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
|
||||||
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 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, ®);
|
rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®);
|
||||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
|
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
|
||||||
if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION &&
|
if (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION &&
|
||||||
rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION)
|
rt2x00_rev(rt2x00dev) < RT3070_VERSION)
|
||||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2);
|
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2);
|
||||||
else
|
else
|
||||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1);
|
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, 103, 0x00);
|
||||||
rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
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, 69, 0x16);
|
||||||
rt2800_bbp_write(rt2x00dev, 73, 0x12);
|
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);
|
rt2800_bbp_write(rt2x00dev, 84, 0x19);
|
||||||
|
|
||||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
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, 70, 0x0a);
|
||||||
rt2800_bbp_write(rt2x00dev, 84, 0x99);
|
rt2800_bbp_write(rt2x00dev, 84, 0x99);
|
||||||
rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
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, 31, 0x08);
|
||||||
rt2800_bbp_write(rt2x00dev, 78, 0x0e);
|
rt2800_bbp_write(rt2x00dev, 78, 0x0e);
|
||||||
rt2800_bbp_write(rt2x00dev, 80, 0x08);
|
rt2800_bbp_write(rt2x00dev, 80, 0x08);
|
||||||
@ -1566,13 +1565,13 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
|||||||
u8 bbp;
|
u8 bbp;
|
||||||
|
|
||||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||||
rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
|
rt2x00_rev(rt2x00dev) != RT3070_VERSION)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (rt2x00_intf_is_pci(rt2x00dev)) {
|
if (rt2x00_intf_is_pci(rt2x00dev)) {
|
||||||
if (!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
if (!rt2x00_rf(rt2x00dev, RF3020) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF3021) &&
|
!rt2x00_rf(rt2x00dev, RF3021) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF3022))
|
!rt2x00_rf(rt2x00dev, RF3022))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1737,7 +1736,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
|
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
|
||||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||||
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", 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
|
* 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);
|
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||||
|
|
||||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||||
struct rt2x00_chip *chip = &rt2x00dev->chip;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The check for rt2860 is not a typo, some rt2870 hardware
|
* The check for rt2860 is not a typo, some rt2870 hardware
|
||||||
* identifies itself as rt2860 in the CSR register.
|
* identifies itself as rt2860 in the CSR register.
|
||||||
*/
|
*/
|
||||||
if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) ||
|
if (rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28600000) ||
|
||||||
rt2x00_check_rev(chip, 0xfff00000, 0x28700000) ||
|
rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28700000) ||
|
||||||
rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) {
|
rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28800000)) {
|
||||||
rt2x00_set_chip_rt(rt2x00dev, RT2870);
|
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);
|
rt2x00_set_chip_rt(rt2x00dev, RT3070);
|
||||||
} else {
|
} else {
|
||||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||||
@ -1858,14 +1855,14 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||||||
}
|
}
|
||||||
rt2x00_print_chip(rt2x00dev);
|
rt2x00_print_chip(rt2x00dev);
|
||||||
|
|
||||||
if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
|
if (!rt2x00_rf(rt2x00dev, RF2820) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2850) &&
|
!rt2x00_rf(rt2x00dev, RF2850) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2720) &&
|
!rt2x00_rf(rt2x00dev, RF2720) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2750) &&
|
!rt2x00_rf(rt2x00dev, RF2750) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
|
!rt2x00_rf(rt2x00dev, RF3020) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2020) &&
|
!rt2x00_rf(rt2x00dev, RF2020) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF3021) &&
|
!rt2x00_rf(rt2x00dev, RF3021) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF3022)) {
|
!rt2x00_rf(rt2x00dev, RF3022)) {
|
||||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@ -2013,7 +2010,6 @@ static const struct rf_channel rf_vals_302x[] = {
|
|||||||
|
|
||||||
int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||||
{
|
{
|
||||||
struct rt2x00_chip *chip = &rt2x00dev->chip;
|
|
||||||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||||
struct channel_info *info;
|
struct channel_info *info;
|
||||||
char *tx_power1;
|
char *tx_power1;
|
||||||
@ -2049,19 +2045,19 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
||||||
|
|
||||||
if (rt2x00_rf(chip, RF2820) ||
|
if (rt2x00_rf(rt2x00dev, RF2820) ||
|
||||||
rt2x00_rf(chip, RF2720) ||
|
rt2x00_rf(rt2x00dev, RF2720) ||
|
||||||
(rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) {
|
(rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(rt2x00dev, RF3052))) {
|
||||||
spec->num_channels = 14;
|
spec->num_channels = 14;
|
||||||
spec->channels = rf_vals;
|
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->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||||
spec->num_channels = ARRAY_SIZE(rf_vals);
|
spec->num_channels = ARRAY_SIZE(rf_vals);
|
||||||
spec->channels = rf_vals;
|
spec->channels = rf_vals;
|
||||||
} else if (rt2x00_rf(chip, RF3020) ||
|
} else if (rt2x00_rf(rt2x00dev, RF3020) ||
|
||||||
rt2x00_rf(chip, RF2020) ||
|
rt2x00_rf(rt2x00dev, RF2020) ||
|
||||||
rt2x00_rf(chip, RF3021) ||
|
rt2x00_rf(rt2x00dev, RF3021) ||
|
||||||
rt2x00_rf(chip, RF3022)) {
|
rt2x00_rf(rt2x00dev, RF3022)) {
|
||||||
spec->num_channels = ARRAY_SIZE(rf_vals_302x);
|
spec->num_channels = ARRAY_SIZE(rf_vals_302x);
|
||||||
spec->channels = rf_vals_302x;
|
spec->channels = rf_vals_302x;
|
||||||
}
|
}
|
||||||
@ -2069,7 +2065,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||||||
/*
|
/*
|
||||||
* Initialize HT information.
|
* Initialize HT information.
|
||||||
*/
|
*/
|
||||||
if (!rt2x00_rf(chip, RF2020))
|
if (!rt2x00_rf(rt2x00dev, RF2020))
|
||||||
spec->ht.ht_supported = true;
|
spec->ht.ht_supported = true;
|
||||||
else
|
else
|
||||||
spec->ht.ht_supported = false;
|
spec->ht.ht_supported = false;
|
||||||
|
@ -48,14 +48,6 @@
|
|||||||
#include "rt2800.h"
|
#include "rt2800.h"
|
||||||
#include "rt2800pci.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.
|
* 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);
|
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)
|
static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
|
||||||
{
|
{
|
||||||
u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */
|
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)
|
static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_RT2800PCI_WISOC */
|
#endif /* CONFIG_RT2800PCI_SOC */
|
||||||
|
|
||||||
#ifdef CONFIG_RT2800PCI_PCI
|
#ifdef CONFIG_RT2800PCI_PCI
|
||||||
static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
|
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.
|
* This device requires firmware.
|
||||||
*/
|
*/
|
||||||
if (!rt2x00_rt(&rt2x00dev->chip, RT2880) &&
|
if (!rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT3052))
|
||||||
!rt2x00_rt(&rt2x00dev->chip, RT3052))
|
|
||||||
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||||||
__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
|
__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
|
||||||
__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
|
__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
|
||||||
@ -1251,7 +1242,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
|
|||||||
#endif /* CONFIG_RT2800PCI_PCI */
|
#endif /* CONFIG_RT2800PCI_PCI */
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
#ifdef CONFIG_RT2800PCI_WISOC
|
#ifdef CONFIG_RT2800PCI_SOC
|
||||||
#if defined(CONFIG_RALINK_RT288X)
|
#if defined(CONFIG_RALINK_RT288X)
|
||||||
__rt2x00soc_probe(RT2880, &rt2800pci_ops);
|
__rt2x00soc_probe(RT2880, &rt2800pci_ops);
|
||||||
#elif defined(CONFIG_RALINK_RT305X)
|
#elif defined(CONFIG_RALINK_RT305X)
|
||||||
@ -1269,7 +1260,7 @@ static struct platform_driver rt2800soc_driver = {
|
|||||||
.suspend = rt2x00soc_suspend,
|
.suspend = rt2x00soc_suspend,
|
||||||
.resume = rt2x00soc_resume,
|
.resume = rt2x00soc_resume,
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_RT2800PCI_WISOC */
|
#endif /* CONFIG_RT2800PCI_SOC */
|
||||||
|
|
||||||
#ifdef CONFIG_RT2800PCI_PCI
|
#ifdef CONFIG_RT2800PCI_PCI
|
||||||
static struct pci_driver rt2800pci_driver = {
|
static struct pci_driver rt2800pci_driver = {
|
||||||
@ -1286,7 +1277,7 @@ static int __init rt2800pci_init(void)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_RT2800PCI_WISOC
|
#ifdef CONFIG_RT2800PCI_SOC
|
||||||
ret = platform_driver_register(&rt2800soc_driver);
|
ret = platform_driver_register(&rt2800soc_driver);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -1294,7 +1285,7 @@ static int __init rt2800pci_init(void)
|
|||||||
#ifdef CONFIG_RT2800PCI_PCI
|
#ifdef CONFIG_RT2800PCI_PCI
|
||||||
ret = pci_register_driver(&rt2800pci_driver);
|
ret = pci_register_driver(&rt2800pci_driver);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
#ifdef CONFIG_RT2800PCI_WISOC
|
#ifdef CONFIG_RT2800PCI_SOC
|
||||||
platform_driver_unregister(&rt2800soc_driver);
|
platform_driver_unregister(&rt2800soc_driver);
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
@ -1309,7 +1300,7 @@ static void __exit rt2800pci_exit(void)
|
|||||||
#ifdef CONFIG_RT2800PCI_PCI
|
#ifdef CONFIG_RT2800PCI_PCI
|
||||||
pci_unregister_driver(&rt2800pci_driver);
|
pci_unregister_driver(&rt2800pci_driver);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_RT2800PCI_WISOC
|
#ifdef CONFIG_RT2800PCI_SOC
|
||||||
platform_driver_unregister(&rt2800soc_driver);
|
platform_driver_unregister(&rt2800soc_driver);
|
||||||
#endif
|
#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,
|
static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
|
||||||
const u8 *data, const size_t len)
|
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;
|
size_t offset = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -138,7 +138,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
|
|||||||
u32 reg;
|
u32 reg;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 length;
|
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.
|
* 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, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||||
{ USB_DEVICE(0x1737, 0x0071), 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, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||||
|
{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||||
/* Logitec */
|
/* Logitec */
|
||||||
{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
|
{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||||
{ USB_DEVICE(0x0789, 0x0163), 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);
|
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)
|
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,
|
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;
|
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)
|
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)
|
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)
|
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);
|
int rt2x00mac_start(struct ieee80211_hw *hw);
|
||||||
void rt2x00mac_stop(struct ieee80211_hw *hw);
|
void rt2x00mac_stop(struct ieee80211_hw *hw);
|
||||||
int rt2x00mac_add_interface(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,
|
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);
|
int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||||
void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
|
void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
|
||||||
unsigned int changed_flags,
|
unsigned int changed_flags,
|
||||||
|
@ -187,10 +187,10 @@ void rt2x00mac_stop(struct ieee80211_hw *hw)
|
|||||||
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
|
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
|
||||||
|
|
||||||
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
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_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 data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
|
||||||
struct queue_entry *entry = NULL;
|
struct queue_entry *entry = NULL;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -203,7 +203,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
|||||||
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
/*
|
/*
|
||||||
* We don't support mixed combinations of
|
* 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.
|
* increase interface count and start initialization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (conf->type == NL80211_IFTYPE_AP)
|
if (vif->type == NL80211_IFTYPE_AP)
|
||||||
rt2x00dev->intf_ap_count++;
|
rt2x00dev->intf_ap_count++;
|
||||||
else
|
else
|
||||||
rt2x00dev->intf_sta_count++;
|
rt2x00dev->intf_sta_count++;
|
||||||
@ -273,16 +273,16 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
|||||||
mutex_init(&intf->beacon_skb_mutex);
|
mutex_init(&intf->beacon_skb_mutex);
|
||||||
intf->beacon = entry;
|
intf->beacon = entry;
|
||||||
|
|
||||||
if (conf->type == NL80211_IFTYPE_AP)
|
if (vif->type == NL80211_IFTYPE_AP)
|
||||||
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
|
memcpy(&intf->bssid, vif->addr, ETH_ALEN);
|
||||||
memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
|
memcpy(&intf->mac, vif->addr, ETH_ALEN);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The MAC adddress must be configured after the device
|
* The MAC adddress must be configured after the device
|
||||||
* has been initialized. Otherwise the device can reset
|
* has been initialized. Otherwise the device can reset
|
||||||
* the MAC registers.
|
* 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
|
* 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);
|
EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
|
||||||
|
|
||||||
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
|
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_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
|
* Don't allow interfaces to be remove while
|
||||||
@ -307,11 +307,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
|
|||||||
* no interface is present.
|
* no interface is present.
|
||||||
*/
|
*/
|
||||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
|
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
|
||||||
(conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
|
(vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
|
||||||
(conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
|
(vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (conf->type == NL80211_IFTYPE_AP)
|
if (vif->type == NL80211_IFTYPE_AP)
|
||||||
rt2x00dev->intf_ap_count--;
|
rt2x00dev->intf_ap_count--;
|
||||||
else
|
else
|
||||||
rt2x00dev->intf_sta_count--;
|
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, 4, &r4);
|
||||||
rt61pci_bbp_read(rt2x00dev, 77, &r77);
|
rt61pci_bbp_read(rt2x00dev, 77, &r77);
|
||||||
|
|
||||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
|
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325));
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF5325));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure the RX antenna.
|
* 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, 4, &r4);
|
||||||
rt61pci_bbp_read(rt2x00dev, 77, &r77);
|
rt61pci_bbp_read(rt2x00dev, 77, &r77);
|
||||||
|
|
||||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
|
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF2529));
|
|
||||||
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
|
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
|
||||||
!test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
|
!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);
|
rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
|
||||||
|
|
||||||
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF5325))
|
|
||||||
rt61pci_config_antenna_5x(rt2x00dev, ant);
|
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);
|
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))
|
if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
|
||||||
rt61pci_config_antenna_2x(rt2x00dev, ant);
|
rt61pci_config_antenna_2x(rt2x00dev, ant);
|
||||||
else
|
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->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
|
||||||
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
|
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
|
||||||
|
|
||||||
smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF2527));
|
|
||||||
|
|
||||||
rt61pci_bbp_read(rt2x00dev, 3, &r3);
|
rt61pci_bbp_read(rt2x00dev, 3, &r3);
|
||||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
|
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_set_chip_rf(rt2x00dev, value, reg);
|
||||||
rt2x00_print_chip(rt2x00dev);
|
rt2x00_print_chip(rt2x00dev);
|
||||||
|
|
||||||
if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
|
if (!rt2x00_rf(rt2x00dev, RF5225) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF5325) &&
|
!rt2x00_rf(rt2x00dev, RF5325) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2527) &&
|
!rt2x00_rf(rt2x00dev, RF2527) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2529)) {
|
!rt2x00_rf(rt2x00dev, RF2529)) {
|
||||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@ -2360,7 +2356,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||||||
* the antenna settings should be gathered from the NIC
|
* the antenna settings should be gathered from the NIC
|
||||||
* eeprom word.
|
* eeprom word.
|
||||||
*/
|
*/
|
||||||
if (rt2x00_rf(&rt2x00dev->chip, RF2529) &&
|
if (rt2x00_rf(rt2x00dev, RF2529) &&
|
||||||
!test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
|
!test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
|
||||||
rt2x00dev->default_ant.rx =
|
rt2x00dev->default_ant.rx =
|
||||||
ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
|
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;
|
spec->channels = rf_vals_seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) {
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF5325)) {
|
|
||||||
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
spec->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||||
spec->num_channels = ARRAY_SIZE(rf_vals_seq);
|
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.
|
* all others contain 20 bits.
|
||||||
*/
|
*/
|
||||||
rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS,
|
rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS,
|
||||||
20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
20 + (rt2x00_rf(rt2x00dev, RF5225) ||
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF2527)));
|
rt2x00_rf(rt2x00dev, RF2527)));
|
||||||
rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
|
rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
|
||||||
rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
|
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);
|
rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
|
||||||
|
|
||||||
if (rt2x00_rf(&rt2x00dev->chip, RF5226) ||
|
if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225))
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF5225))
|
|
||||||
rt73usb_config_antenna_5x(rt2x00dev, ant);
|
rt73usb_config_antenna_5x(rt2x00dev, ant);
|
||||||
else if (rt2x00_rf(&rt2x00dev->chip, RF2528) ||
|
else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527))
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF2527))
|
|
||||||
rt73usb_config_antenna_2x(rt2x00dev, ant);
|
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->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
|
||||||
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
|
rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
|
||||||
|
|
||||||
smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF2527));
|
|
||||||
|
|
||||||
rt73usb_bbp_read(rt2x00dev, 3, &r3);
|
rt73usb_bbp_read(rt2x00dev, 3, &r3);
|
||||||
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
|
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);
|
rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
|
||||||
|
|
||||||
reg = 0x000023b0;
|
reg = 0x000023b0;
|
||||||
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
|
if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527))
|
||||||
rt2x00_rf(&rt2x00dev->chip, RF2527))
|
|
||||||
rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1);
|
rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1);
|
||||||
rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
|
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_set_chip(rt2x00dev, RT2571, value, reg);
|
||||||
rt2x00_print_chip(rt2x00dev);
|
rt2x00_print_chip(rt2x00dev);
|
||||||
|
|
||||||
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) ||
|
if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) ||
|
||||||
rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
|
rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) {
|
||||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rt2x00_rf(&rt2x00dev->chip, RF5226) &&
|
if (!rt2x00_rf(rt2x00dev, RF5226) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2528) &&
|
!rt2x00_rf(rt2x00dev, RF2528) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
|
!rt2x00_rf(rt2x00dev, RF5225) &&
|
||||||
!rt2x00_rf(&rt2x00dev->chip, RF2527)) {
|
!rt2x00_rf(rt2x00dev, RF2527)) {
|
||||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@ -2081,17 +2077,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
|||||||
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
spec->supported_bands = SUPPORT_BAND_2GHZ;
|
||||||
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
|
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->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
|
||||||
spec->channels = 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->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||||
spec->num_channels = ARRAY_SIZE(rf_vals_5226);
|
spec->num_channels = ARRAY_SIZE(rf_vals_5226);
|
||||||
spec->channels = 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->num_channels = 14;
|
||||||
spec->channels = rf_vals_5225_2527;
|
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->supported_bands |= SUPPORT_BAND_5GHZ;
|
||||||
spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
|
spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
|
||||||
spec->channels = rf_vals_5225_2527;
|
spec->channels = rf_vals_5225_2527;
|
||||||
|
@ -60,7 +60,6 @@ struct rtl8180_priv {
|
|||||||
struct rtl818x_csr __iomem *map;
|
struct rtl818x_csr __iomem *map;
|
||||||
const struct rtl818x_rf_ops *rf;
|
const struct rtl818x_rf_ops *rf;
|
||||||
struct ieee80211_vif *vif;
|
struct ieee80211_vif *vif;
|
||||||
int mode;
|
|
||||||
|
|
||||||
/* rtl8180 driver specific */
|
/* rtl8180 driver specific */
|
||||||
spinlock_t lock;
|
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)
|
void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
|
||||||
{
|
{
|
||||||
struct rtl8180_priv *priv = dev->priv;
|
struct rtl8180_priv *priv = dev->priv;
|
||||||
@ -615,7 +613,6 @@ static int rtl8180_start(struct ieee80211_hw *dev)
|
|||||||
reg |= RTL818X_CMD_TX_ENABLE;
|
reg |= RTL818X_CMD_TX_ENABLE;
|
||||||
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
|
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
|
||||||
|
|
||||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_free_rings:
|
err_free_rings:
|
||||||
@ -633,8 +630,6 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
|
|||||||
u8 reg;
|
u8 reg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
|
|
||||||
|
|
||||||
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
|
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
|
||||||
|
|
||||||
reg = rtl818x_ioread8(priv, &priv->map->CMD);
|
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,
|
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;
|
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:
|
case NL80211_IFTYPE_STATION:
|
||||||
priv->mode = conf->type;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->vif = conf->vif;
|
priv->vif = vif;
|
||||||
|
|
||||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
|
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
|
||||||
rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
|
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],
|
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);
|
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtl8180_remove_interface(struct ieee80211_hw *dev,
|
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;
|
struct rtl8180_priv *priv = dev->priv;
|
||||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
|
||||||
priv->vif = NULL;
|
priv->vif = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ struct rtl8187_priv {
|
|||||||
struct rtl818x_csr *map;
|
struct rtl818x_csr *map;
|
||||||
const struct rtl818x_rf_ops *rf;
|
const struct rtl818x_rf_ops *rf;
|
||||||
struct ieee80211_vif *vif;
|
struct ieee80211_vif *vif;
|
||||||
int mode;
|
|
||||||
/* The mutex protects the TX loopback state.
|
/* The mutex protects the TX loopback state.
|
||||||
* Any attempt to set channels concurrently locks the device.
|
* 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,
|
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;
|
struct rtl8187_priv *priv = dev->priv;
|
||||||
int i;
|
int i;
|
||||||
int ret = -EOPNOTSUPP;
|
int ret = -EOPNOTSUPP;
|
||||||
|
|
||||||
mutex_lock(&priv->conf_mutex);
|
mutex_lock(&priv->conf_mutex);
|
||||||
if (priv->mode != NL80211_IFTYPE_MONITOR)
|
if (priv->vif)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
priv->mode = conf->type;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
priv->vif = conf->vif;
|
priv->vif = vif;
|
||||||
|
|
||||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
|
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
|
||||||
for (i = 0; i < ETH_ALEN; i++)
|
for (i = 0; i < ETH_ALEN; i++)
|
||||||
rtl818x_iowrite8(priv, &priv->map->MAC[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);
|
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -1051,11 +1050,10 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void rtl8187_remove_interface(struct ieee80211_hw *dev,
|
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;
|
struct rtl8187_priv *priv = dev->priv;
|
||||||
mutex_lock(&priv->conf_mutex);
|
mutex_lock(&priv->conf_mutex);
|
||||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
|
||||||
priv->vif = NULL;
|
priv->vif = NULL;
|
||||||
mutex_unlock(&priv->conf_mutex);
|
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;
|
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
|
||||||
|
|
||||||
|
|
||||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
|
||||||
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||||
IEEE80211_HW_SIGNAL_DBM |
|
IEEE80211_HW_SIGNAL_DBM |
|
||||||
IEEE80211_HW_RX_INCLUDES_FCS;
|
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;
|
struct rtl8187_led *led = &priv->led_tx;
|
||||||
|
|
||||||
/* Don't change the LED, when the device is down. */
|
/* 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 ;
|
return ;
|
||||||
|
|
||||||
/* Skip if the LED is not registered. */
|
/* 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;
|
struct rtl8187_led *led = &priv->led_tx;
|
||||||
|
|
||||||
/* Don't change the LED, when the device is down. */
|
/* 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 ;
|
return ;
|
||||||
|
|
||||||
/* Skip if the LED is not registered. */
|
/* 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 "
|
wl1251_error("timeout waiting for the hardware to "
|
||||||
"complete initialization");
|
"complete initialization");
|
||||||
return -EIO;
|
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,
|
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;
|
struct wl1251 *wl = hw->priv;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
||||||
conf->type, conf->mac_addr);
|
vif->type, vif->addr);
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
if (wl->vif) {
|
if (wl->vif) {
|
||||||
@ -525,9 +525,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl->vif = conf->vif;
|
wl->vif = vif;
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
wl->bss_type = BSS_TYPE_STA_BSS;
|
wl->bss_type = BSS_TYPE_STA_BSS;
|
||||||
break;
|
break;
|
||||||
@ -539,8 +539,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) {
|
if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) {
|
||||||
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
|
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
|
||||||
SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
|
SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
|
||||||
ret = wl1251_acx_station_id(wl);
|
ret = wl1251_acx_station_id(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -553,7 +553,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
|
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;
|
struct wl1251 *wl = hw->priv;
|
||||||
|
|
||||||
|
@ -107,10 +107,9 @@ enum {
|
|||||||
CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
|
CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
|
||||||
CFG_RX_AUTH_EN | CFG_RX_ASSOC_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_FW_NAME "wl1271-fw.bin"
|
||||||
#define WL1271_NVS_NAME "wl1271-nvs.bin"
|
#define WL1271_NVS_NAME "wl1271-nvs.bin"
|
||||||
|
#define WL1271_NVS_LEN 468
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable/disable 802.11a support for WL1273
|
* Enable/disable 802.11a support for WL1273
|
||||||
@ -276,6 +275,7 @@ struct wl1271_debugfs {
|
|||||||
|
|
||||||
struct dentry *retry_count;
|
struct dentry *retry_count;
|
||||||
struct dentry *excessive_retries;
|
struct dentry *excessive_retries;
|
||||||
|
struct dentry *gpio_power;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_TX_QUEUES 4
|
#define NUM_TX_QUEUES 4
|
||||||
@ -322,6 +322,17 @@ struct wl1271 {
|
|||||||
enum wl1271_state state;
|
enum wl1271_state state;
|
||||||
struct mutex mutex;
|
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_partition_set part;
|
||||||
|
|
||||||
struct wl1271_chip chip;
|
struct wl1271_chip chip;
|
||||||
@ -359,7 +370,6 @@ struct wl1271 {
|
|||||||
|
|
||||||
/* Frames scheduled for transmission, not handled yet */
|
/* Frames scheduled for transmission, not handled yet */
|
||||||
struct sk_buff_head tx_queue;
|
struct sk_buff_head tx_queue;
|
||||||
bool tx_queue_stopped;
|
|
||||||
|
|
||||||
struct work_struct tx_work;
|
struct work_struct tx_work;
|
||||||
|
|
||||||
@ -387,14 +397,15 @@ struct wl1271 {
|
|||||||
u32 mbox_ptr[2];
|
u32 mbox_ptr[2];
|
||||||
|
|
||||||
/* Are we currently scanning */
|
/* Are we currently scanning */
|
||||||
bool scanning;
|
|
||||||
struct wl1271_scan scan;
|
struct wl1271_scan scan;
|
||||||
|
|
||||||
/* Our association ID */
|
/* Our association ID */
|
||||||
u16 aid;
|
u16 aid;
|
||||||
|
|
||||||
/* currently configured rate set */
|
/* currently configured rate set */
|
||||||
|
u32 sta_rate_set;
|
||||||
u32 basic_rate_set;
|
u32 basic_rate_set;
|
||||||
|
u32 rate_set;
|
||||||
|
|
||||||
/* The current band */
|
/* The current band */
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
@ -405,18 +416,9 @@ struct wl1271 {
|
|||||||
unsigned int rx_config;
|
unsigned int rx_config;
|
||||||
unsigned int rx_filter;
|
unsigned int rx_filter;
|
||||||
|
|
||||||
/* is firmware in elp mode */
|
|
||||||
bool elp;
|
|
||||||
|
|
||||||
struct completion *elp_compl;
|
struct completion *elp_compl;
|
||||||
struct delayed_work elp_work;
|
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 */
|
/* retry counter for PSM entries */
|
||||||
u8 psm_entry_retry;
|
u8 psm_entry_retry;
|
||||||
|
|
||||||
@ -435,9 +437,6 @@ struct wl1271 {
|
|||||||
|
|
||||||
struct ieee80211_vif *vif;
|
struct ieee80211_vif *vif;
|
||||||
|
|
||||||
/* Used for a workaround to send disconnect before rejoining */
|
|
||||||
bool joined;
|
|
||||||
|
|
||||||
/* Current chipset configuration */
|
/* Current chipset configuration */
|
||||||
struct conf_drv_settings conf;
|
struct conf_drv_settings conf;
|
||||||
|
|
||||||
@ -455,7 +454,9 @@ int wl1271_plt_stop(struct wl1271 *wl);
|
|||||||
|
|
||||||
#define WL1271_TX_QUEUE_MAX_LENGTH 20
|
#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 */
|
#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
|
||||||
|
|
||||||
static inline bool wl1271_11a_enabled(void)
|
static inline bool wl1271_11a_enabled(void)
|
||||||
|
@ -390,6 +390,35 @@ out:
|
|||||||
return ret;
|
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)
|
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
|
||||||
{
|
{
|
||||||
struct acx_beacon_filter_option *beacon_filter = NULL;
|
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;
|
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 acx_rate_policy *acx;
|
||||||
struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
|
struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
|
||||||
|
int idx = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
wl1271_debug(DEBUG_ACX, "acx rate policies");
|
wl1271_debug(DEBUG_ACX, "acx rate policies");
|
||||||
@ -773,12 +803,21 @@ int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* configure one default (one-size-fits-all) rate class */
|
/* configure one basic rate class */
|
||||||
acx->rate_class_cnt = cpu_to_le32(1);
|
idx = ACX_TX_BASIC_RATE;
|
||||||
acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates);
|
acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set);
|
||||||
acx->rate_class[0].short_retry_limit = c->short_retry_limit;
|
acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
|
||||||
acx->rate_class[0].long_retry_limit = c->long_retry_limit;
|
acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
|
||||||
acx->rate_class[0].aflags = c->aflags;
|
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));
|
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -1012,59 +1051,6 @@ out:
|
|||||||
return ret;
|
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)
|
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
|
||||||
{
|
{
|
||||||
struct wl1271_acx_bet_enable *acx = NULL;
|
struct wl1271_acx_bet_enable *acx = NULL;
|
||||||
@ -1132,3 +1118,31 @@ out:
|
|||||||
kfree(acx);
|
kfree(acx);
|
||||||
return ret;
|
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];
|
u8 pad[3];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct acx_smart_reflex_state {
|
struct acx_dco_itrim_params {
|
||||||
struct acx_header header;
|
struct acx_header header;
|
||||||
|
|
||||||
u8 enable;
|
u8 enable;
|
||||||
u8 padding[3];
|
u8 padding[3];
|
||||||
} __attribute__ ((packed));
|
__le32 timeout;
|
||||||
|
|
||||||
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];
|
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#define PTA_ANTENNA_TYPE_DEF (0)
|
#define PTA_ANTENNA_TYPE_DEF (0)
|
||||||
@ -837,6 +826,9 @@ struct acx_rate_class {
|
|||||||
u8 reserved;
|
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_rate_policy {
|
||||||
struct acx_header header;
|
struct acx_header header;
|
||||||
|
|
||||||
@ -877,8 +869,8 @@ struct acx_tx_config_options {
|
|||||||
__le16 tx_compl_threshold; /* number of packets */
|
__le16 tx_compl_threshold; /* number of packets */
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#define ACX_RX_MEM_BLOCKS 64
|
#define ACX_RX_MEM_BLOCKS 70
|
||||||
#define ACX_TX_MIN_MEM_BLOCKS 64
|
#define ACX_TX_MIN_MEM_BLOCKS 40
|
||||||
#define ACX_TX_DESCRIPTORS 32
|
#define ACX_TX_DESCRIPTORS 32
|
||||||
#define ACX_NUM_SSID_PROFILES 1
|
#define ACX_NUM_SSID_PROFILES 1
|
||||||
|
|
||||||
@ -969,6 +961,13 @@ struct wl1271_acx_arp_filter {
|
|||||||
used. */
|
used. */
|
||||||
} __attribute__((packed));
|
} __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 {
|
enum {
|
||||||
ACX_WAKE_UP_CONDITIONS = 0x0002,
|
ACX_WAKE_UP_CONDITIONS = 0x0002,
|
||||||
@ -1027,13 +1026,13 @@ enum {
|
|||||||
ACX_HT_BSS_OPERATION = 0x0058,
|
ACX_HT_BSS_OPERATION = 0x0058,
|
||||||
ACX_COEX_ACTIVITY = 0x0059,
|
ACX_COEX_ACTIVITY = 0x0059,
|
||||||
ACX_SET_SMART_REFLEX_DEBUG = 0x005A,
|
ACX_SET_SMART_REFLEX_DEBUG = 0x005A,
|
||||||
ACX_SET_SMART_REFLEX_STATE = 0x005B,
|
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
|
||||||
ACX_SET_SMART_REFLEX_PARAMS = 0x005F,
|
|
||||||
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
|
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
|
||||||
DOT11_CUR_TX_PWR = 0x100D,
|
DOT11_CUR_TX_PWR = 0x100D,
|
||||||
DOT11_RX_DOT11_MODE = 0x1012,
|
DOT11_RX_DOT11_MODE = 0x1012,
|
||||||
DOT11_RTS_THRESHOLD = 0x1013,
|
DOT11_RTS_THRESHOLD = 0x1013,
|
||||||
DOT11_GROUP_ADDRESS_TBL = 0x1014,
|
DOT11_GROUP_ADDRESS_TBL = 0x1014,
|
||||||
|
ACX_PM_CONFIG = 0x1016,
|
||||||
|
|
||||||
MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
|
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);
|
void *mc_list, u32 mc_list_len);
|
||||||
int wl1271_acx_service_period_timeout(struct wl1271 *wl);
|
int wl1271_acx_service_period_timeout(struct wl1271 *wl);
|
||||||
int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
|
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_opt(struct wl1271 *wl, bool enable_filter);
|
||||||
int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
|
int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
|
||||||
int wl1271_acx_conn_monit_params(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,
|
int wl1271_acx_cts_protect(struct wl1271 *wl,
|
||||||
enum acx_ctsprotect_type ctsprotect);
|
enum acx_ctsprotect_type ctsprotect);
|
||||||
int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
|
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_ac_cfg(struct wl1271 *wl);
|
||||||
int wl1271_acx_tid_cfg(struct wl1271 *wl);
|
int wl1271_acx_tid_cfg(struct wl1271 *wl);
|
||||||
int wl1271_acx_frag_threshold(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_bet_enable(struct wl1271 *wl, bool enable);
|
||||||
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
|
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
|
||||||
u8 version);
|
u8 version);
|
||||||
|
int wl1271_acx_pm_config(struct wl1271 *wl);
|
||||||
|
|
||||||
#endif /* __WL1271_ACX_H__ */
|
#endif /* __WL1271_ACX_H__ */
|
||||||
|
@ -225,9 +225,15 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
|||||||
if (nvs == NULL)
|
if (nvs == NULL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (wl->nvs_len < WL1271_NVS_LEN)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
nvs_ptr = nvs;
|
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 */
|
/* Update the device MAC address into the nvs */
|
||||||
nvs[11] = wl->mac_addr[0];
|
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->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer;
|
||||||
gen_parms->settings = g->settings;
|
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);
|
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
|
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);
|
CONF_NUMBER_OF_RATE_GROUPS);
|
||||||
memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
|
memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
|
||||||
CONF_NUMBER_OF_RATE_GROUPS);
|
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,
|
memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b,
|
||||||
CONF_NUMBER_OF_CHANNELS_2_4);
|
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);
|
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->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++)
|
for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++)
|
||||||
radio_parms->tx_ref_pd_voltage_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);
|
r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS);
|
||||||
memcpy(radio_parms->tx_rate_limits_degraded_5,
|
memcpy(radio_parms->tx_rate_limits_degraded_5,
|
||||||
r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS);
|
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,
|
memcpy(radio_parms->tx_channel_limits_ofdm_5,
|
||||||
r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_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,
|
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);
|
CONF_NUMBER_OF_RATE_GROUPS);
|
||||||
memcpy(radio_parms->rx_fem_insertion_loss_5,
|
memcpy(radio_parms->rx_fem_insertion_loss_5,
|
||||||
r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_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: ",
|
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
|
||||||
radio_parms, sizeof(*radio_parms));
|
radio_parms, sizeof(*radio_parms));
|
||||||
@ -311,19 +344,6 @@ int wl1271_cmd_join(struct wl1271 *wl)
|
|||||||
do_cal = false;
|
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);
|
join = kzalloc(sizeof(*join), GFP_KERNEL);
|
||||||
if (!join) {
|
if (!join) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
@ -388,8 +408,6 @@ int wl1271_cmd_join(struct wl1271 *wl)
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl->joined = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
|
* ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
|
||||||
* simplify locking we just sleep instead, for now
|
* 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;
|
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;
|
struct cmd_enabledisable_path *cmd;
|
||||||
int ret;
|
int ret;
|
||||||
@ -501,7 +519,8 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd->channel = channel;
|
/* the channel here is only used for calibration, so hardcoded to 1 */
|
||||||
|
cmd->channel = 1;
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
cmd_rx = CMD_ENABLE_RX;
|
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);
|
ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wl1271_error("rx %s cmd for channel %d failed",
|
wl1271_error("rx %s cmd for channel %d failed",
|
||||||
enable ? "start" : "stop", channel);
|
enable ? "start" : "stop", cmd->channel);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d",
|
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);
|
ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wl1271_error("tx %s cmd for channel %d failed",
|
wl1271_error("tx %s cmd for channel %d failed",
|
||||||
enable ? "start" : "stop", channel);
|
enable ? "start" : "stop", cmd->channel);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d",
|
wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d",
|
||||||
enable ? "start" : "stop", channel);
|
enable ? "start" : "stop", cmd->channel);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(cmd);
|
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;
|
channels = wl->hw->wiphy->bands[ieee_band]->channels;
|
||||||
n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels;
|
n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels;
|
||||||
|
|
||||||
if (wl->scanning)
|
if (test_bit(WL1271_FLAG_SCANNING, &wl->flags))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
params = kzalloc(sizeof(*params), GFP_KERNEL);
|
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));
|
wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
|
||||||
|
|
||||||
wl->scanning = true;
|
set_bit(WL1271_FLAG_SCANNING, &wl->flags);
|
||||||
if (wl1271_11a_enabled()) {
|
if (wl1271_11a_enabled()) {
|
||||||
wl->scan.state = band;
|
wl->scan.state = band;
|
||||||
if (band == WL1271_SCAN_BAND_DUAL) {
|
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);
|
ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wl1271_error("SCAN failed");
|
wl1271_error("SCAN failed");
|
||||||
wl->scanning = false;
|
clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,7 +796,7 @@ out:
|
|||||||
return ret;
|
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;
|
u8 index = 0;
|
||||||
|
|
||||||
@ -804,7 +823,7 @@ static int wl1271_build_basic_rates(char *rates, u8 band)
|
|||||||
return index;
|
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;
|
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_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_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_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_ps_mode(struct wl1271 *wl, u8 ps_mode);
|
||||||
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
|
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
|
||||||
size_t len);
|
size_t len);
|
||||||
@ -437,6 +437,21 @@ struct wl1271_general_parms_cmd {
|
|||||||
u8 tx_bip_fem_autodetect;
|
u8 tx_bip_fem_autodetect;
|
||||||
u8 tx_bip_fem_manufacturer;
|
u8 tx_bip_fem_manufacturer;
|
||||||
u8 settings;
|
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));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct wl1271_radio_parms_cmd {
|
struct wl1271_radio_parms_cmd {
|
||||||
@ -458,11 +473,12 @@ struct wl1271_radio_parms_cmd {
|
|||||||
/* Dynamic radio parameters */
|
/* Dynamic radio parameters */
|
||||||
/* 2.4GHz */
|
/* 2.4GHz */
|
||||||
__le16 tx_ref_pd_voltage;
|
__le16 tx_ref_pd_voltage;
|
||||||
s8 tx_ref_power;
|
u8 tx_ref_power;
|
||||||
s8 tx_offset_db;
|
s8 tx_offset_db;
|
||||||
|
|
||||||
s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
|
s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
|
||||||
s8 tx_rate_limits_degraded[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_11b[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||||
s8 tx_channel_limits_ofdm[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 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
|
||||||
u8 rx_fem_insertion_loss;
|
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 */
|
/* 5GHz */
|
||||||
__le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
__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_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||||
|
|
||||||
s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
|
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_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_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
|
||||||
s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
|
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 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||||
s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
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));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct wl1271_cmd_cal_channel_tune {
|
struct wl1271_cmd_cal_channel_tune {
|
||||||
|
@ -258,7 +258,8 @@ struct conf_rx_settings {
|
|||||||
#define CONF_TX_MAX_RATE_CLASSES 8
|
#define CONF_TX_MAX_RATE_CLASSES 8
|
||||||
|
|
||||||
#define CONF_TX_RATE_MASK_UNSPECIFIED 0
|
#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
|
#define CONF_TX_RATE_RETRY_LIMIT 10
|
||||||
|
|
||||||
struct conf_tx_rate_class {
|
struct conf_tx_rate_class {
|
||||||
@ -722,31 +723,6 @@ struct conf_conn_settings {
|
|||||||
u8 psm_entry_retries;
|
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 {
|
enum {
|
||||||
CONF_REF_CLK_19_2_E,
|
CONF_REF_CLK_19_2_E,
|
||||||
CONF_REF_CLK_26_E,
|
CONF_REF_CLK_26_E,
|
||||||
@ -759,6 +735,9 @@ enum single_dual_band_enum {
|
|||||||
CONF_DUAL_BAND
|
CONF_DUAL_BAND
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define CONF_MAX_SMART_REFLEX_PARAMS 16
|
||||||
|
|
||||||
struct conf_general_parms {
|
struct conf_general_parms {
|
||||||
/*
|
/*
|
||||||
* RF Reference Clock type / speed
|
* RF Reference Clock type / speed
|
||||||
@ -815,6 +794,20 @@ struct conf_general_parms {
|
|||||||
* Range: Unknown
|
* Range: Unknown
|
||||||
*/
|
*/
|
||||||
u8 settings;
|
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
|
#define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15
|
||||||
@ -847,12 +840,13 @@ struct conf_radio_parms {
|
|||||||
*
|
*
|
||||||
* Range: unknown
|
* Range: unknown
|
||||||
*/
|
*/
|
||||||
s16 tx_ref_pd_voltage;
|
u16 tx_ref_pd_voltage;
|
||||||
s8 tx_ref_power;
|
u8 tx_ref_power;
|
||||||
s8 tx_offset_db;
|
s8 tx_offset_db;
|
||||||
|
|
||||||
s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
|
s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
|
||||||
s8 tx_rate_limits_degraded[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_11b[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||||
s8 tx_channel_limits_ofdm[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 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
|
||||||
u8 rx_fem_insertion_loss;
|
u8 rx_fem_insertion_loss;
|
||||||
|
|
||||||
|
u8 degraded_low_to_normal_threshold;
|
||||||
|
u8 degraded_normal_to_high_threshold;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dynamic radio parameters for 5GHz
|
* Dynamic radio parameters for 5GHz
|
||||||
*
|
*
|
||||||
* Range: unknown
|
* Range: unknown
|
||||||
*/
|
*/
|
||||||
s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
u16 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_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||||
|
|
||||||
s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
|
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_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_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
|
||||||
s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
|
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 */
|
/* FIXME: this is inconsistent with the types for 2.4GHz */
|
||||||
s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
|
s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||||
s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
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 {
|
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.
|
* 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_drv_settings {
|
||||||
struct conf_sg_settings sg;
|
struct conf_sg_settings sg;
|
||||||
struct conf_rx_settings rx;
|
struct conf_rx_settings rx;
|
||||||
struct conf_tx_settings tx;
|
struct conf_tx_settings tx;
|
||||||
struct conf_conn_settings conn;
|
struct conf_conn_settings conn;
|
||||||
struct conf_init_settings init;
|
struct conf_init_settings init;
|
||||||
|
struct conf_itrim_settings itrim;
|
||||||
|
struct conf_pm_config_settings pm_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -237,6 +237,64 @@ static const struct file_operations tx_queue_len_ops = {
|
|||||||
.open = wl1271_open_file_generic,
|
.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)
|
static void wl1271_debugfs_delete_files(struct wl1271 *wl)
|
||||||
{
|
{
|
||||||
DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
|
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(tx_queue_len);
|
||||||
DEBUGFS_DEL(retry_count);
|
DEBUGFS_DEL(retry_count);
|
||||||
DEBUGFS_DEL(excessive_retries);
|
DEBUGFS_DEL(excessive_retries);
|
||||||
|
|
||||||
|
DEBUGFS_DEL(gpio_power);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wl1271_debugfs_add_files(struct wl1271 *wl)
|
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(retry_count, wl->debugfs.rootdir);
|
||||||
DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
|
DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
|
||||||
|
|
||||||
|
DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
wl1271_debugfs_delete_files(wl);
|
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",
|
wl1271_debug(DEBUG_EVENT, "status: 0x%x",
|
||||||
mbox->scheduled_scan_status);
|
mbox->scheduled_scan_status);
|
||||||
|
|
||||||
if (wl->scanning) {
|
if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) {
|
||||||
if (wl->scan.state == WL1271_SCAN_BAND_DUAL) {
|
if (wl->scan.state == WL1271_SCAN_BAND_DUAL) {
|
||||||
wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
||||||
NULL, size);
|
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
|
* to the wl1271_cmd_scan function that we are not
|
||||||
* scanning as it checks that.
|
* 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,
|
wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len,
|
||||||
wl->scan.active,
|
wl->scan.active,
|
||||||
wl->scan.high_prio,
|
wl->scan.high_prio,
|
||||||
@ -62,7 +62,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
|
|||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
ieee80211_scan_completed(wl->hw, false);
|
ieee80211_scan_completed(wl->hw, false);
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
wl->scanning = false;
|
clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -78,7 +78,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
|||||||
|
|
||||||
switch (mbox->ps_status) {
|
switch (mbox->ps_status) {
|
||||||
case EVENT_ENTER_POWER_SAVE_FAIL:
|
case EVENT_ENTER_POWER_SAVE_FAIL:
|
||||||
if (!wl->psm) {
|
if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||||
wl->psm_entry_retry = 0;
|
wl->psm_entry_retry = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -89,7 +89,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
|||||||
} else {
|
} else {
|
||||||
wl1271_error("PSM entry failed, giving up.\n");
|
wl1271_error("PSM entry failed, giving up.\n");
|
||||||
wl->psm_entry_retry = 0;
|
wl->psm_entry_retry = 0;
|
||||||
*beacon_loss = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_ENTER_POWER_SAVE_SUCCESS:
|
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
|
* filtering) is enabled. Without PSM, the stack will receive all
|
||||||
* beacons and can detect beacon loss by itself.
|
* 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");
|
wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
|
||||||
|
|
||||||
/* indicate to the stack, that beacons have been lost */
|
/* 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (beacon_loss) {
|
if (wl->vif && beacon_loss) {
|
||||||
/* Obviously, it's dangerous to release the mutex while
|
/* Obviously, it's dangerous to release the mutex while
|
||||||
we are holding many of the variables in the wl struct.
|
we are holding many of the variables in the wl struct.
|
||||||
That's why it's done last in the function, and care must
|
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]);
|
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;
|
struct event_mailbox mbox;
|
||||||
int ret;
|
int ret;
|
||||||
@ -204,9 +204,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* then we let the firmware know it can go on...*/
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,6 @@ struct event_mailbox {
|
|||||||
|
|
||||||
int wl1271_event_unmask(struct wl1271 *wl);
|
int wl1271_event_unmask(struct wl1271 *wl);
|
||||||
void wl1271_event_mbox_config(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
|
#endif
|
||||||
|
@ -229,6 +229,10 @@ int wl1271_hw_init(struct wl1271 *wl)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_free_memmap;
|
goto out_free_memmap;
|
||||||
|
|
||||||
|
ret = wl1271_acx_dco_itrim_params(wl);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out_free_memmap;
|
||||||
|
|
||||||
/* Initialize connection monitoring thresholds */
|
/* Initialize connection monitoring thresholds */
|
||||||
ret = wl1271_acx_conn_monit_params(wl);
|
ret = wl1271_acx_conn_monit_params(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -280,12 +284,12 @@ int wl1271_hw_init(struct wl1271 *wl)
|
|||||||
goto out_free_memmap;
|
goto out_free_memmap;
|
||||||
|
|
||||||
/* Configure TX rate classes */
|
/* Configure TX rate classes */
|
||||||
ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL);
|
ret = wl1271_acx_rate_policies(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_free_memmap;
|
goto out_free_memmap;
|
||||||
|
|
||||||
/* Enable data path */
|
/* Enable data path */
|
||||||
ret = wl1271_cmd_data_path(wl, wl->channel, 1);
|
ret = wl1271_cmd_data_path(wl, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_free_memmap;
|
goto out_free_memmap;
|
||||||
|
|
||||||
@ -299,8 +303,8 @@ int wl1271_hw_init(struct wl1271 *wl)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_free_memmap;
|
goto out_free_memmap;
|
||||||
|
|
||||||
/* Configure smart reflex */
|
/* configure PM */
|
||||||
ret = wl1271_acx_smart_reflex(wl);
|
ret = wl1271_acx_pm_config(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_free_memmap;
|
goto out_free_memmap;
|
||||||
|
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
#include "wl1271_cmd.h"
|
#include "wl1271_cmd.h"
|
||||||
#include "wl1271_boot.h"
|
#include "wl1271_boot.h"
|
||||||
|
|
||||||
|
#define WL1271_BOOT_RETRIES 3
|
||||||
|
|
||||||
static struct conf_drv_settings default_conf = {
|
static struct conf_drv_settings default_conf = {
|
||||||
.sg = {
|
.sg = {
|
||||||
.per_threshold = 7500,
|
.per_threshold = 7500,
|
||||||
@ -67,16 +69,17 @@ static struct conf_drv_settings default_conf = {
|
|||||||
.ps_poll_timeout = 15,
|
.ps_poll_timeout = 15,
|
||||||
.upsd_timeout = 15,
|
.upsd_timeout = 15,
|
||||||
.rts_threshold = 2347,
|
.rts_threshold = 2347,
|
||||||
.rx_cca_threshold = 0xFFEF,
|
.rx_cca_threshold = 0,
|
||||||
.irq_blk_threshold = 0,
|
.irq_blk_threshold = 0xFFFF,
|
||||||
.irq_pkt_threshold = USHORT_MAX,
|
.irq_pkt_threshold = 0,
|
||||||
.irq_timeout = 5,
|
.irq_timeout = 600,
|
||||||
.queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
|
.queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
|
||||||
},
|
},
|
||||||
.tx = {
|
.tx = {
|
||||||
.tx_energy_detection = 0,
|
.tx_energy_detection = 0,
|
||||||
.rc_conf = {
|
.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,
|
.short_retry_limit = 10,
|
||||||
.long_retry_limit = 10,
|
.long_retry_limit = 10,
|
||||||
.aflags = 0
|
.aflags = 0
|
||||||
@ -172,8 +175,8 @@ static struct conf_drv_settings default_conf = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
|
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
|
||||||
.tx_compl_timeout = 5,
|
.tx_compl_timeout = 700,
|
||||||
.tx_compl_threshold = 5
|
.tx_compl_threshold = 4
|
||||||
},
|
},
|
||||||
.conn = {
|
.conn = {
|
||||||
.wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
|
.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,
|
.rule = CONF_BCN_RULE_PASS_ON_APPEARANCE,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.synch_fail_thold = 5,
|
.synch_fail_thold = 10,
|
||||||
.bss_lose_timeout = 100,
|
.bss_lose_timeout = 100,
|
||||||
.beacon_rx_timeout = 10000,
|
.beacon_rx_timeout = 10000,
|
||||||
.broadcast_timeout = 20000,
|
.broadcast_timeout = 20000,
|
||||||
.rx_broadcast_in_ps = 1,
|
.rx_broadcast_in_ps = 1,
|
||||||
.ps_poll_threshold = 4,
|
.ps_poll_threshold = 20,
|
||||||
.sig_trigger_count = 2,
|
.sig_trigger_count = 2,
|
||||||
.sig_trigger = {
|
.sig_trigger = {
|
||||||
[0] = {
|
[0] = {
|
||||||
@ -226,46 +229,35 @@ static struct conf_drv_settings default_conf = {
|
|||||||
.psm_entry_retries = 3
|
.psm_entry_retries = 3
|
||||||
},
|
},
|
||||||
.init = {
|
.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 = {
|
.genparam = {
|
||||||
.ref_clk = CONF_REF_CLK_38_4_E,
|
.ref_clk = CONF_REF_CLK_38_4_E,
|
||||||
.settling_time = 5,
|
.settling_time = 5,
|
||||||
.clk_valid_on_wakeup = 0,
|
.clk_valid_on_wakeup = 0,
|
||||||
.dc2dcmode = 0,
|
.dc2dcmode = 0,
|
||||||
.single_dual_band = CONF_SINGLE_BAND,
|
.single_dual_band = CONF_SINGLE_BAND,
|
||||||
.tx_bip_fem_autodetect = 0,
|
.tx_bip_fem_autodetect = 1,
|
||||||
.tx_bip_fem_manufacturer = 1,
|
.tx_bip_fem_manufacturer = 1,
|
||||||
.settings = 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 = {
|
.radioparam = {
|
||||||
.rx_trace_loss = 10,
|
.rx_trace_loss = 0x24,
|
||||||
.tx_trace_loss = 10,
|
.tx_trace_loss = 0x0,
|
||||||
.rx_rssi_and_proc_compens = {
|
.rx_rssi_and_proc_compens = {
|
||||||
0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
|
0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
|
||||||
0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8,
|
0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8,
|
||||||
0x00, 0x0a, 0x14 },
|
0x00, 0x0a, 0x14 },
|
||||||
.rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
|
.rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
|
||||||
.tx_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, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00 },
|
0x00, 0x00, 0x00 },
|
||||||
.tx_ref_pd_voltage = 0x24e,
|
.tx_ref_pd_voltage = 0x1a9,
|
||||||
.tx_ref_power = 0x78,
|
.tx_ref_power = 0x80,
|
||||||
.tx_offset_db = 0x0,
|
.tx_offset_db = 0x0,
|
||||||
.tx_rate_limits_normal = {
|
.tx_rate_limits_normal = {
|
||||||
0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 },
|
0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 },
|
||||||
.tx_rate_limits_degraded = {
|
.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 = {
|
.tx_channel_limits_11b = {
|
||||||
0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
|
0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
|
0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
|
||||||
@ -289,10 +283,12 @@ static struct conf_drv_settings default_conf = {
|
|||||||
0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
|
0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
|
||||||
0x20, 0x50 },
|
0x20, 0x50 },
|
||||||
.tx_pdv_rate_offsets = {
|
.tx_pdv_rate_offsets = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
0x07, 0x08, 0x04, 0x02, 0x02, 0x00 },
|
||||||
.tx_ibias = {
|
.tx_ibias = {
|
||||||
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 },
|
0x11, 0x11, 0x15, 0x11, 0x15, 0x0f },
|
||||||
.rx_fem_insertion_loss = 0x14,
|
.rx_fem_insertion_loss = 0x0e,
|
||||||
|
.degraded_low_to_normal_threshold = 0x1e,
|
||||||
|
.degraded_normal_to_high_threshold = 0x2d,
|
||||||
.tx_ref_pd_voltage_5 = {
|
.tx_ref_pd_voltage_5 = {
|
||||||
0x0190, 0x01a4, 0x01c3, 0x01d8,
|
0x0190, 0x01a4, 0x01c3, 0x01d8,
|
||||||
0x020a, 0x021c },
|
0x020a, 0x021c },
|
||||||
@ -304,6 +300,8 @@ static struct conf_drv_settings default_conf = {
|
|||||||
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||||
.tx_rate_limits_degraded_5 = {
|
.tx_rate_limits_degraded_5 = {
|
||||||
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||||
|
.tx_rate_limits_extreme_5 = {
|
||||||
|
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||||
.tx_channel_limits_ofdm_5 = {
|
.tx_channel_limits_ofdm_5 = {
|
||||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
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 = {
|
.tx_ibias_5 = {
|
||||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
|
0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
|
||||||
.rx_fem_insertion_loss_5 = {
|
.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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = wl1271_cmd_data_path(wl, wl->channel, 1);
|
ret = wl1271_cmd_data_path(wl, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -374,11 +382,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl)
|
|||||||
static void wl1271_power_off(struct wl1271 *wl)
|
static void wl1271_power_off(struct wl1271 *wl)
|
||||||
{
|
{
|
||||||
wl->set_power(false);
|
wl->set_power(false);
|
||||||
|
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wl1271_power_on(struct wl1271 *wl)
|
static void wl1271_power_on(struct wl1271 *wl)
|
||||||
{
|
{
|
||||||
wl->set_power(true);
|
wl->set_power(true);
|
||||||
|
set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wl1271_fw_status(struct wl1271 *wl,
|
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;
|
intr &= WL1271_INTR_MASK;
|
||||||
|
|
||||||
if (intr & WL1271_ACX_INTR_EVENT_A) {
|
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_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) {
|
if (intr & WL1271_ACX_INTR_EVENT_B) {
|
||||||
wl1271_debug(DEBUG_IRQ, "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)
|
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
|
||||||
@ -614,6 +623,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
|
|||||||
struct wl1271_partition_set partition;
|
struct wl1271_partition_set partition;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
msleep(WL1271_PRE_POWER_ON_SLEEP);
|
||||||
wl1271_power_on(wl);
|
wl1271_power_on(wl);
|
||||||
msleep(WL1271_POWER_ON_SLEEP);
|
msleep(WL1271_POWER_ON_SLEEP);
|
||||||
wl1271_spi_reset(wl);
|
wl1271_spi_reset(wl);
|
||||||
@ -643,7 +653,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
|
|||||||
|
|
||||||
ret = wl1271_setup(wl);
|
ret = wl1271_setup(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_power_off;
|
goto out;
|
||||||
break;
|
break;
|
||||||
case CHIP_ID_1271_PG20:
|
case CHIP_ID_1271_PG20:
|
||||||
wl1271_debug(DEBUG_BOOT, "chip id 0x%x (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);
|
ret = wl1271_setup(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_power_off;
|
goto out;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
|
wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto out_power_off;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl->fw == NULL) {
|
if (wl->fw == NULL) {
|
||||||
ret = wl1271_fetch_firmware(wl);
|
ret = wl1271_fetch_firmware(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_power_off;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No NVS from netlink, try to get it from the filesystem */
|
/* No NVS from netlink, try to get it from the filesystem */
|
||||||
if (wl->nvs == NULL) {
|
if (wl->nvs == NULL) {
|
||||||
ret = wl1271_fetch_nvs(wl);
|
ret = wl1271_fetch_nvs(wl);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_power_off;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
out_power_off:
|
|
||||||
wl1271_power_off(wl);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wl1271_plt_start(struct wl1271 *wl)
|
int wl1271_plt_start(struct wl1271 *wl)
|
||||||
{
|
{
|
||||||
|
int retries = WL1271_BOOT_RETRIES;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
@ -696,35 +702,48 @@ int wl1271_plt_start(struct wl1271 *wl)
|
|||||||
goto out;
|
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);
|
ret = wl1271_boot(wl);
|
||||||
if (ret < 0)
|
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;
|
goto out;
|
||||||
|
|
||||||
ret = wl1271_boot(wl);
|
irq_disable:
|
||||||
if (ret < 0)
|
wl1271_disable_interrupts(wl);
|
||||||
goto out_power_off;
|
mutex_unlock(&wl->mutex);
|
||||||
|
/* Unlocking the mutex in the middle of handling is
|
||||||
wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
|
inherently unsafe. In this case we deem it safe to do,
|
||||||
|
because we need to let any possibly pending IRQ out of
|
||||||
ret = wl1271_plt_init(wl);
|
the system (and while we are WL1271_STATE_OFF the IRQ
|
||||||
if (ret < 0)
|
work function will not do anything.) Also, any other
|
||||||
goto out_irq_disable;
|
possible concurrent operations will fail due to the
|
||||||
|
current state, hence the wl1271 struct should be safe. */
|
||||||
/* Make sure power saving is disabled */
|
cancel_work_sync(&wl->irq_work);
|
||||||
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
|
mutex_lock(&wl->mutex);
|
||||||
if (ret < 0)
|
power_off:
|
||||||
goto out_irq_disable;
|
wl1271_power_off(wl);
|
||||||
|
}
|
||||||
goto out;
|
|
||||||
|
|
||||||
out_irq_disable:
|
|
||||||
wl1271_disable_interrupts(wl);
|
|
||||||
|
|
||||||
out_power_off:
|
|
||||||
wl1271_power_off(wl);
|
|
||||||
|
|
||||||
|
wl1271_error("firmware boot in PLT mode failed despite %d retries",
|
||||||
|
WL1271_BOOT_RETRIES);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
|
|
||||||
@ -762,7 +781,20 @@ out:
|
|||||||
static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct wl1271 *wl = hw->priv;
|
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);
|
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
|
* protected. Maybe fix this by removing the stupid
|
||||||
* variable altogether and checking the real queue state?
|
* 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;
|
return NETDEV_TX_OK;
|
||||||
@ -880,6 +912,7 @@ static struct notifier_block wl1271_dev_notifier = {
|
|||||||
static int wl1271_op_start(struct ieee80211_hw *hw)
|
static int wl1271_op_start(struct ieee80211_hw *hw)
|
||||||
{
|
{
|
||||||
struct wl1271 *wl = hw->priv;
|
struct wl1271 *wl = hw->priv;
|
||||||
|
int retries = WL1271_BOOT_RETRIES;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
wl1271_debug(DEBUG_MAC80211, "mac80211 start");
|
wl1271_debug(DEBUG_MAC80211, "mac80211 start");
|
||||||
@ -893,30 +926,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = wl1271_chip_wakeup(wl);
|
while (retries) {
|
||||||
if (ret < 0)
|
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;
|
goto out;
|
||||||
|
|
||||||
ret = wl1271_boot(wl);
|
irq_disable:
|
||||||
if (ret < 0)
|
wl1271_disable_interrupts(wl);
|
||||||
goto out_power_off;
|
mutex_unlock(&wl->mutex);
|
||||||
|
/* Unlocking the mutex in the middle of handling is
|
||||||
ret = wl1271_hw_init(wl);
|
inherently unsafe. In this case we deem it safe to do,
|
||||||
if (ret < 0)
|
because we need to let any possibly pending IRQ out of
|
||||||
goto out_irq_disable;
|
the system (and while we are WL1271_STATE_OFF the IRQ
|
||||||
|
work function will not do anything.) Also, any other
|
||||||
wl->state = WL1271_STATE_ON;
|
possible concurrent operations will fail due to the
|
||||||
|
current state, hence the wl1271 struct should be safe. */
|
||||||
wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
|
cancel_work_sync(&wl->irq_work);
|
||||||
|
mutex_lock(&wl->mutex);
|
||||||
goto out;
|
power_off:
|
||||||
|
wl1271_power_off(wl);
|
||||||
out_irq_disable:
|
}
|
||||||
wl1271_disable_interrupts(wl);
|
|
||||||
|
|
||||||
out_power_off:
|
|
||||||
wl1271_power_off(wl);
|
|
||||||
|
|
||||||
|
wl1271_error("firmware boot failed despite %d retries",
|
||||||
|
WL1271_BOOT_RETRIES);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
|
|
||||||
@ -944,11 +989,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|||||||
|
|
||||||
WARN_ON(wl->state != WL1271_STATE_ON);
|
WARN_ON(wl->state != WL1271_STATE_ON);
|
||||||
|
|
||||||
if (wl->scanning) {
|
if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) {
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
ieee80211_scan_completed(wl->hw, true);
|
ieee80211_scan_completed(wl->hw, true);
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
wl->scanning = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wl->state = WL1271_STATE_OFF;
|
wl->state = WL1271_STATE_OFF;
|
||||||
@ -973,10 +1017,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|||||||
wl->band = IEEE80211_BAND_2GHZ;
|
wl->band = IEEE80211_BAND_2GHZ;
|
||||||
|
|
||||||
wl->rx_counter = 0;
|
wl->rx_counter = 0;
|
||||||
wl->elp = false;
|
|
||||||
wl->psm = 0;
|
|
||||||
wl->psm_entry_retry = 0;
|
wl->psm_entry_retry = 0;
|
||||||
wl->tx_queue_stopped = false;
|
|
||||||
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
|
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
|
||||||
wl->tx_blocks_available = 0;
|
wl->tx_blocks_available = 0;
|
||||||
wl->tx_results_count = 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->tx_security_seq_32 = 0;
|
||||||
wl->time_offset = 0;
|
wl->time_offset = 0;
|
||||||
wl->session_counter = 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++)
|
for (i = 0; i < NUM_TX_QUEUES; i++)
|
||||||
wl->tx_blocks_freed[i] = 0;
|
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,
|
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;
|
struct wl1271 *wl = hw->priv;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
|
||||||
conf->type, conf->mac_addr);
|
vif->type, vif->addr);
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
if (wl->vif) {
|
if (wl->vif) {
|
||||||
@ -1010,9 +1053,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl->vif = conf->vif;
|
wl->vif = vif;
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
wl->bss_type = BSS_TYPE_STA_BSS;
|
wl->bss_type = BSS_TYPE_STA_BSS;
|
||||||
break;
|
break;
|
||||||
@ -1032,7 +1075,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
|
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;
|
struct wl1271 *wl = hw->priv;
|
||||||
|
|
||||||
@ -1109,6 +1152,51 @@ out:
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||||
{
|
{
|
||||||
struct wl1271 *wl = hw->priv;
|
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);
|
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,
|
channel,
|
||||||
conf->flags & IEEE80211_CONF_PS ? "on" : "off",
|
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);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
@ -1130,34 +1219,44 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (channel != wl->channel) {
|
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||||
/*
|
if (conf->flags & IEEE80211_CONF_IDLE &&
|
||||||
* We assume that the stack will configure the right channel
|
test_bit(WL1271_FLAG_JOINED, &wl->flags))
|
||||||
* before associating, so we don't need to send a join
|
wl1271_unjoin_channel(wl);
|
||||||
* command here. We will join the right channel when the
|
else if (!(conf->flags & IEEE80211_CONF_IDLE))
|
||||||
* BSSID changes
|
wl1271_join_channel(wl, channel);
|
||||||
*/
|
|
||||||
wl->channel = 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) {
|
/* if the channel changes while joined, join again */
|
||||||
wl1271_info("psm enabled");
|
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.
|
* We enter PSM only if we're already associated.
|
||||||
* If we're not, we'll enter it when joining an SSID,
|
* If we're not, we'll enter it when joining an SSID,
|
||||||
* through the bss_info_changed() hook.
|
* 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) &&
|
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
|
||||||
wl->psm_requested) {
|
test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
|
||||||
wl1271_info("psm disabled");
|
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);
|
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1440,22 +1539,6 @@ out:
|
|||||||
return ret;
|
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,
|
static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_bss_conf *bss_conf,
|
struct ieee80211_bss_conf *bss_conf,
|
||||||
@ -1473,9 +1556,68 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
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 (changed & BSS_CHANGED_ASSOC) {
|
||||||
if (bss_conf->assoc) {
|
if (bss_conf->assoc) {
|
||||||
wl->aid = bss_conf->aid;
|
wl->aid = bss_conf->aid;
|
||||||
|
set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* with wl1271, we don't need to update the
|
* 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;
|
goto out_sleep;
|
||||||
|
|
||||||
/* If we want to go in PSM but we're not there yet */
|
/* 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;
|
mode = STATION_POWER_SAVE_MODE;
|
||||||
ret = wl1271_ps_set_mode(wl, mode);
|
ret = wl1271_ps_set_mode(wl, mode);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1500,7 +1643,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* use defaults when not associated */
|
/* 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;
|
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:
|
out_sleep:
|
||||||
wl1271_ps_elp_sleep(wl);
|
wl1271_ps_elp_sleep(wl);
|
||||||
|
|
||||||
@ -1599,19 +1731,19 @@ static struct ieee80211_rate wl1271_rates[] = {
|
|||||||
|
|
||||||
/* can't be const, mac80211 writes to this */
|
/* can't be const, mac80211 writes to this */
|
||||||
static struct ieee80211_channel wl1271_channels[] = {
|
static struct ieee80211_channel wl1271_channels[] = {
|
||||||
{ .hw_value = 1, .center_freq = 2412},
|
{ .hw_value = 1, .center_freq = 2412, .max_power = 25 },
|
||||||
{ .hw_value = 2, .center_freq = 2417},
|
{ .hw_value = 2, .center_freq = 2417, .max_power = 25 },
|
||||||
{ .hw_value = 3, .center_freq = 2422},
|
{ .hw_value = 3, .center_freq = 2422, .max_power = 25 },
|
||||||
{ .hw_value = 4, .center_freq = 2427},
|
{ .hw_value = 4, .center_freq = 2427, .max_power = 25 },
|
||||||
{ .hw_value = 5, .center_freq = 2432},
|
{ .hw_value = 5, .center_freq = 2432, .max_power = 25 },
|
||||||
{ .hw_value = 6, .center_freq = 2437},
|
{ .hw_value = 6, .center_freq = 2437, .max_power = 25 },
|
||||||
{ .hw_value = 7, .center_freq = 2442},
|
{ .hw_value = 7, .center_freq = 2442, .max_power = 25 },
|
||||||
{ .hw_value = 8, .center_freq = 2447},
|
{ .hw_value = 8, .center_freq = 2447, .max_power = 25 },
|
||||||
{ .hw_value = 9, .center_freq = 2452},
|
{ .hw_value = 9, .center_freq = 2452, .max_power = 25 },
|
||||||
{ .hw_value = 10, .center_freq = 2457},
|
{ .hw_value = 10, .center_freq = 2457, .max_power = 25 },
|
||||||
{ .hw_value = 11, .center_freq = 2462},
|
{ .hw_value = 11, .center_freq = 2462, .max_power = 25 },
|
||||||
{ .hw_value = 12, .center_freq = 2467},
|
{ .hw_value = 12, .center_freq = 2467, .max_power = 25 },
|
||||||
{ .hw_value = 13, .center_freq = 2472},
|
{ .hw_value = 13, .center_freq = 2472, .max_power = 25 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* can't be const, mac80211 writes to this */
|
/* 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_BEACON_FILTER |
|
||||||
IEEE80211_HW_SUPPORTS_PS;
|
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->max_scan_ssids = 1;
|
||||||
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
|
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);
|
INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
|
||||||
wl->channel = WL1271_DEFAULT_CHANNEL;
|
wl->channel = WL1271_DEFAULT_CHANNEL;
|
||||||
wl->scanning = false;
|
|
||||||
wl->default_key = 0;
|
wl->default_key = 0;
|
||||||
wl->rx_counter = 0;
|
wl->rx_counter = 0;
|
||||||
wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
|
wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
|
||||||
wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
|
wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
|
||||||
wl->elp = false;
|
|
||||||
wl->psm = 0;
|
|
||||||
wl->psm_requested = false;
|
|
||||||
wl->psm_entry_retry = 0;
|
wl->psm_entry_retry = 0;
|
||||||
wl->tx_queue_stopped = false;
|
|
||||||
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
|
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->band = IEEE80211_BAND_2GHZ;
|
||||||
wl->vif = NULL;
|
wl->vif = NULL;
|
||||||
wl->joined = false;
|
wl->flags = 0;
|
||||||
|
|
||||||
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
|
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
|
||||||
wl->tx_frames[i] = NULL;
|
wl->tx_frames[i] = NULL;
|
||||||
|
@ -39,12 +39,13 @@ void wl1271_elp_work(struct work_struct *work)
|
|||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
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;
|
goto out;
|
||||||
|
|
||||||
wl1271_debug(DEBUG_PSM, "chip to elp");
|
wl1271_debug(DEBUG_PSM, "chip to elp");
|
||||||
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
|
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
|
||||||
wl->elp = true;
|
set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
@ -55,7 +56,7 @@ out:
|
|||||||
/* Routines to toggle sleep mode while in ELP */
|
/* Routines to toggle sleep mode while in ELP */
|
||||||
void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
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);
|
cancel_delayed_work(&wl->elp_work);
|
||||||
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
||||||
msecs_to_jiffies(ELP_ENTRY_DELAY));
|
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;
|
u32 start_time = jiffies;
|
||||||
bool pending = false;
|
bool pending = false;
|
||||||
|
|
||||||
if (!wl->elp)
|
if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wl1271_debug(DEBUG_PSM, "waking up chip from elp");
|
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",
|
wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
|
||||||
jiffies_to_msecs(jiffies - start_time));
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
wl->psm = 1;
|
set_bit(WL1271_FLAG_PSM, &wl->flags);
|
||||||
break;
|
break;
|
||||||
case STATION_ACTIVE_MODE:
|
case STATION_ACTIVE_MODE:
|
||||||
default:
|
default:
|
||||||
@ -166,7 +167,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
wl->psm = 0;
|
clear_bit(WL1271_FLAG_PSM, &wl->flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +121,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
|
|||||||
pad = pad - skb->len;
|
pad = pad - skb->len;
|
||||||
tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
|
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);
|
desc->tx_attr = cpu_to_le16(tx_attr);
|
||||||
|
|
||||||
wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
|
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;
|
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)
|
void wl1271_tx_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
|
struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
bool woken_up = false;
|
bool woken_up = false;
|
||||||
|
u32 sta_rates = 0;
|
||||||
int ret;
|
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);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||||
goto out;
|
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))) {
|
while ((skb = skb_dequeue(&wl->tx_queue))) {
|
||||||
if (!woken_up) {
|
if (!woken_up) {
|
||||||
ret = wl1271_ps_elp_wakeup(wl, false);
|
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, "
|
wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, "
|
||||||
"stop queues");
|
"stop queues");
|
||||||
ieee80211_stop_queues(wl->hw);
|
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);
|
skb_queue_head(&wl->tx_queue, skb);
|
||||||
goto out;
|
goto out;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
goto out;
|
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 */
|
/* firmware buffer has space, restart queues */
|
||||||
wl1271_debug(DEBUG_TX,
|
wl1271_debug(DEBUG_TX,
|
||||||
"complete_packet: waking queues");
|
"complete_packet: waking queues");
|
||||||
ieee80211_wake_queues(wl->hw);
|
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;
|
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)
|
static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame)
|
||||||
{
|
{
|
||||||
return ZD_OFDM | zd_ofdm_plcp_header_rate(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
|
* zd_rx_rate - report zd-rate
|
||||||
* @rx_frame - received frame
|
* @rx_frame - received frame
|
||||||
|
@ -929,9 +929,6 @@ static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
|
|||||||
|
|
||||||
struct rx_status;
|
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);
|
u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
|
||||||
|
|
||||||
struct zd_mc_hash {
|
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.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
|
||||||
stats.band = IEEE80211_BAND_2GHZ;
|
stats.band = IEEE80211_BAND_2GHZ;
|
||||||
stats.signal = status->signal_strength;
|
stats.signal = status->signal_strength;
|
||||||
stats.qual = zd_rx_qual_percent(buffer,
|
|
||||||
length - sizeof(struct rx_status),
|
|
||||||
status);
|
|
||||||
|
|
||||||
rate = zd_rx_rate(buffer, 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,
|
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);
|
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)
|
if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
switch (conf->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_MONITOR:
|
case NL80211_IFTYPE_MONITOR:
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
case NL80211_IFTYPE_ADHOC:
|
case NL80211_IFTYPE_ADHOC:
|
||||||
mac->type = conf->type;
|
mac->type = vif->type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
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,
|
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);
|
struct zd_mac *mac = zd_hw_mac(hw);
|
||||||
mac->type = NL80211_IFTYPE_UNSPECIFIED;
|
mac->type = NL80211_IFTYPE_UNSPECIFIED;
|
||||||
|
@ -1085,12 +1085,12 @@ enum ieee80211_eid {
|
|||||||
WLAN_EID_TIM = 5,
|
WLAN_EID_TIM = 5,
|
||||||
WLAN_EID_IBSS_PARAMS = 6,
|
WLAN_EID_IBSS_PARAMS = 6,
|
||||||
WLAN_EID_CHALLENGE = 16,
|
WLAN_EID_CHALLENGE = 16,
|
||||||
/* 802.11d */
|
|
||||||
WLAN_EID_COUNTRY = 7,
|
WLAN_EID_COUNTRY = 7,
|
||||||
WLAN_EID_HP_PARAMS = 8,
|
WLAN_EID_HP_PARAMS = 8,
|
||||||
WLAN_EID_HP_TABLE = 9,
|
WLAN_EID_HP_TABLE = 9,
|
||||||
WLAN_EID_REQUEST = 10,
|
WLAN_EID_REQUEST = 10,
|
||||||
/* 802.11e */
|
|
||||||
WLAN_EID_QBSS_LOAD = 11,
|
WLAN_EID_QBSS_LOAD = 11,
|
||||||
WLAN_EID_EDCA_PARAM_SET = 12,
|
WLAN_EID_EDCA_PARAM_SET = 12,
|
||||||
WLAN_EID_TSPEC = 13,
|
WLAN_EID_TSPEC = 13,
|
||||||
@ -1113,7 +1113,7 @@ enum ieee80211_eid {
|
|||||||
WLAN_EID_PREP = 69,
|
WLAN_EID_PREP = 69,
|
||||||
WLAN_EID_PERR = 70,
|
WLAN_EID_PERR = 70,
|
||||||
WLAN_EID_RANN = 49, /* compatible with FreeBSD */
|
WLAN_EID_RANN = 49, /* compatible with FreeBSD */
|
||||||
/* 802.11h */
|
|
||||||
WLAN_EID_PWR_CONSTRAINT = 32,
|
WLAN_EID_PWR_CONSTRAINT = 32,
|
||||||
WLAN_EID_PWR_CAPABILITY = 33,
|
WLAN_EID_PWR_CAPABILITY = 33,
|
||||||
WLAN_EID_TPC_REQUEST = 34,
|
WLAN_EID_TPC_REQUEST = 34,
|
||||||
@ -1124,20 +1124,41 @@ enum ieee80211_eid {
|
|||||||
WLAN_EID_MEASURE_REPORT = 39,
|
WLAN_EID_MEASURE_REPORT = 39,
|
||||||
WLAN_EID_QUIET = 40,
|
WLAN_EID_QUIET = 40,
|
||||||
WLAN_EID_IBSS_DFS = 41,
|
WLAN_EID_IBSS_DFS = 41,
|
||||||
/* 802.11g */
|
|
||||||
WLAN_EID_ERP_INFO = 42,
|
WLAN_EID_ERP_INFO = 42,
|
||||||
WLAN_EID_EXT_SUPP_RATES = 50,
|
WLAN_EID_EXT_SUPP_RATES = 50,
|
||||||
/* 802.11n */
|
|
||||||
WLAN_EID_HT_CAPABILITY = 45,
|
WLAN_EID_HT_CAPABILITY = 45,
|
||||||
WLAN_EID_HT_INFORMATION = 61,
|
WLAN_EID_HT_INFORMATION = 61,
|
||||||
/* 802.11i */
|
|
||||||
WLAN_EID_RSN = 48,
|
WLAN_EID_RSN = 48,
|
||||||
WLAN_EID_TIMEOUT_INTERVAL = 56,
|
WLAN_EID_MMIE = 76,
|
||||||
WLAN_EID_MMIE = 76 /* 802.11w */,
|
|
||||||
WLAN_EID_WPA = 221,
|
WLAN_EID_WPA = 221,
|
||||||
WLAN_EID_GENERIC = 221,
|
WLAN_EID_GENERIC = 221,
|
||||||
WLAN_EID_VENDOR_SPECIFIC = 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 */
|
/* Action category code */
|
||||||
|
@ -270,6 +270,31 @@
|
|||||||
* @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
|
* @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
|
||||||
* associated with this wiphy must be down and will follow.
|
* 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_MAX: highest used command number
|
||||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||||
*/
|
*/
|
||||||
@ -353,6 +378,9 @@ enum nl80211_commands {
|
|||||||
NL80211_CMD_DEL_PMKSA,
|
NL80211_CMD_DEL_PMKSA,
|
||||||
NL80211_CMD_FLUSH_PMKSA,
|
NL80211_CMD_FLUSH_PMKSA,
|
||||||
|
|
||||||
|
NL80211_CMD_REMAIN_ON_CHANNEL,
|
||||||
|
NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
|
||||||
|
|
||||||
/* add new commands above here */
|
/* add new commands above here */
|
||||||
|
|
||||||
/* used to define NL80211_CMD_MAX below */
|
/* 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
|
* @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
|
||||||
* cache, a wiphy attribute.
|
* 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_MAX: highest attribute number currently defined
|
||||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||||
*/
|
*/
|
||||||
@ -743,6 +775,10 @@ enum nl80211_attrs {
|
|||||||
NL80211_ATTR_PMKID,
|
NL80211_ATTR_PMKID,
|
||||||
NL80211_ATTR_MAX_NUM_PMKIDS,
|
NL80211_ATTR_MAX_NUM_PMKIDS,
|
||||||
|
|
||||||
|
NL80211_ATTR_DURATION,
|
||||||
|
|
||||||
|
NL80211_ATTR_COOKIE,
|
||||||
|
|
||||||
/* add attributes here, update the policy in nl80211.c */
|
/* add attributes here, update the policy in nl80211.c */
|
||||||
|
|
||||||
__NL80211_ATTR_AFTER_LAST,
|
__NL80211_ATTR_AFTER_LAST,
|
||||||
|
@ -988,6 +988,15 @@ struct cfg80211_pmksa {
|
|||||||
*
|
*
|
||||||
* @dump_survey: get site survey information.
|
* @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
|
* @testmode_cmd: run a test mode command
|
||||||
*
|
*
|
||||||
* @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac
|
* @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);
|
struct cfg80211_pmksa *pmksa);
|
||||||
int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
|
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 */
|
/* some temporary stuff to finish wext */
|
||||||
int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
|
int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
|
||||||
bool enabled, int timeout);
|
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,
|
void cfg80211_disconnected(struct net_device *dev, u16 reason,
|
||||||
u8 *ie, size_t ie_len, gfp_t gfp);
|
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 */
|
#endif /* __NET_CFG80211_H */
|
||||||
|
@ -547,7 +547,6 @@ enum mac80211_rx_flags {
|
|||||||
* unspecified depending on the hardware capabilities flags
|
* unspecified depending on the hardware capabilities flags
|
||||||
* @IEEE80211_HW_SIGNAL_*
|
* @IEEE80211_HW_SIGNAL_*
|
||||||
* @noise: noise when receiving this frame, in dBm.
|
* @noise: noise when receiving this frame, in dBm.
|
||||||
* @qual: overall signal quality indication, in percent (0-100).
|
|
||||||
* @antenna: antenna used
|
* @antenna: antenna used
|
||||||
* @rate_idx: index of data rate into band's supported rates or MCS index if
|
* @rate_idx: index of data rate into band's supported rates or MCS index if
|
||||||
* HT rates are use (RX_FLAG_HT)
|
* HT rates are use (RX_FLAG_HT)
|
||||||
@ -559,7 +558,6 @@ struct ieee80211_rx_status {
|
|||||||
int freq;
|
int freq;
|
||||||
int signal;
|
int signal;
|
||||||
int noise;
|
int noise;
|
||||||
int __deprecated qual;
|
|
||||||
int antenna;
|
int antenna;
|
||||||
int rate_idx;
|
int rate_idx;
|
||||||
int flag;
|
int flag;
|
||||||
@ -701,33 +699,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
|
|||||||
return false;
|
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
|
* enum ieee80211_key_alg - key algorithm
|
||||||
* @ALG_WEP: WEP40 or WEP104
|
* @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
|
* When the device is started it should not have a MAC address
|
||||||
* to avoid acknowledging frames before a non-monitor device
|
* to avoid acknowledging frames before a non-monitor device
|
||||||
* is added.
|
* is added.
|
||||||
* Must be implemented.
|
* Must be implemented and can sleep.
|
||||||
*
|
*
|
||||||
* @stop: Called after last netdevice attached to the hardware
|
* @stop: Called after last netdevice attached to the hardware
|
||||||
* is disabled. This should turn off the hardware (at least
|
* 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
|
* May be called right after add_interface if that rejects
|
||||||
* an interface. If you added any work onto the mac80211 workqueue
|
* an interface. If you added any work onto the mac80211 workqueue
|
||||||
* you should ensure to cancel it on this callback.
|
* 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
|
* @add_interface: Called when a netdevice attached to the hardware is
|
||||||
* enabled. Because it is not called for monitor mode devices, @start
|
* 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.
|
* interface is given in the conf parameter.
|
||||||
* The callback may refuse to add an interface by returning a
|
* The callback may refuse to add an interface by returning a
|
||||||
* negative error code (which will be seen in userspace.)
|
* 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.
|
* @remove_interface: Notifies a driver that an interface is going down.
|
||||||
* The @stop callback is called after this if it is the last interface
|
* 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,
|
* must be cleared so the device no longer acknowledges packets,
|
||||||
* the mac_addr member of the conf structure is, however, set to the
|
* the mac_addr member of the conf structure is, however, set to the
|
||||||
* MAC address of the device going away.
|
* 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
|
* @config: Handler for configuration requests. IEEE 802.11 code calls this
|
||||||
* function to change hardware configuration, e.g., channel.
|
* function to change hardware configuration, e.g., channel.
|
||||||
* This function should never fail but returns a negative error code
|
* 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
|
* @bss_info_changed: Handler for configuration requests related to BSS
|
||||||
* parameters that may vary during BSS's lifespan, and may affect low
|
* parameters that may vary during BSS's lifespan, and may affect low
|
||||||
* level driver (e.g. assoc/disassoc status, erp parameters).
|
* level driver (e.g. assoc/disassoc status, erp parameters).
|
||||||
* This function should not be used if no BSS has been set, unless
|
* This function should not be used if no BSS has been set, unless
|
||||||
* for association indication. The @changed parameter indicates which
|
* 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.
|
* @prepare_multicast: Prepare for multicast filter configuration.
|
||||||
* This callback is optional, and its return value is passed
|
* 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.
|
* @configure_filter: Configure the device's RX filter.
|
||||||
* See the section "Frame filtering" for more information.
|
* 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
|
* @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.
|
* must be set or cleared for a given STA. Must be atomic.
|
||||||
*
|
*
|
||||||
* @set_key: See the section "Hardware crypto acceleration"
|
* @set_key: See the section "Hardware crypto acceleration"
|
||||||
* This callback can sleep, and is only called between add_interface
|
* This callback is only called between add_interface and
|
||||||
* and remove_interface calls, i.e. while the given virtual interface
|
* remove_interface calls, i.e. while the given virtual interface
|
||||||
* is enabled.
|
* is enabled.
|
||||||
* Returns a negative error code if the key can't be added.
|
* 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"
|
* @update_tkip_key: See the section "Hardware crypto acceleration"
|
||||||
* This callback will be called in the context of Rx. Called for drivers
|
* This callback will be called in the context of Rx. Called for drivers
|
||||||
* which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
|
* 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
|
* @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
|
* 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;
|
* When the scan finishes, ieee80211_scan_completed() must be called;
|
||||||
* note that it also must be called when the scan cannot finish due to
|
* note that it also must be called when the scan cannot finish due to
|
||||||
* any error unless this callback returned a negative error code.
|
* 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
|
* @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.
|
* 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
|
* @sw_scan_complete: Notifier function that is called just after a
|
||||||
* finished. Can be NULL, if the driver doesn't need this notification.
|
* software scan finished. Can be NULL, if the driver doesn't need
|
||||||
|
* this notification.
|
||||||
|
* The callback can sleep.
|
||||||
*
|
*
|
||||||
* @get_stats: Return low-level statistics.
|
* @get_stats: Return low-level statistics.
|
||||||
* Returns zero if statistics are available.
|
* Returns zero if statistics are available.
|
||||||
|
* The callback can sleep.
|
||||||
*
|
*
|
||||||
* @get_tkip_seq: If your device implements TKIP encryption in hardware this
|
* @get_tkip_seq: If your device implements TKIP encryption in hardware this
|
||||||
* callback should be provided to read the TKIP transmit IVs (both IV32
|
* callback should be provided to read the TKIP transmit IVs (both IV32
|
||||||
* and IV16) for the given key from hardware.
|
* and IV16) for the given key from hardware.
|
||||||
|
* The callback must be atomic.
|
||||||
*
|
*
|
||||||
* @set_rts_threshold: Configuration of RTS threshold (if device needs it)
|
* @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
|
* @sta_notify: Notifies low level driver about addition, removal or power
|
||||||
* state transition of an associated station, AP, IBSS/WDS/mesh peer etc.
|
* 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),
|
* @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
|
||||||
* bursting) for a hardware TX queue.
|
* bursting) for a hardware TX queue.
|
||||||
* Returns a negative error code on failure.
|
* 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
|
* @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
|
* to get number of currently queued packets (queue length), maximum queue
|
||||||
* size (limit), and total number of packets sent using each TX 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
|
* (count). The 'stats' pointer points to an array that has hw->queues
|
||||||
* items.
|
* items.
|
||||||
|
* The callback must be atomic.
|
||||||
*
|
*
|
||||||
* @get_tsf: Get the current TSF timer value from firmware/hardware. Currently,
|
* @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
|
* this is only used for IBSS mode BSSID merging and debugging. Is not a
|
||||||
* required function.
|
* required function.
|
||||||
|
* The callback can sleep.
|
||||||
*
|
*
|
||||||
* @set_tsf: Set the TSF timer to the specified value in the firmware/hardware.
|
* @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
|
* Currently, this is only used for IBSS mode debugging. Is not a
|
||||||
* required function.
|
* required function.
|
||||||
|
* The callback can sleep.
|
||||||
*
|
*
|
||||||
* @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
|
* @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
|
* 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
|
* function is optional if the firmware/hardware takes full care of
|
||||||
* TSF synchronization.
|
* TSF synchronization.
|
||||||
|
* The callback can sleep.
|
||||||
*
|
*
|
||||||
* @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
|
* @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
|
* This is needed only for IBSS mode and the result of this function is
|
||||||
* used to determine whether to reply to Probe Requests.
|
* used to determine whether to reply to Probe Requests.
|
||||||
* Returns non-zero if this device sent the last beacon.
|
* Returns non-zero if this device sent the last beacon.
|
||||||
|
* The callback can sleep.
|
||||||
*
|
*
|
||||||
* @ampdu_action: Perform a certain A-MPDU action
|
* @ampdu_action: Perform a certain A-MPDU action
|
||||||
* The RA/TID combination determines the destination and TID we want
|
* 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
|
* is the first frame we expect to perform the action on. Notice
|
||||||
* that TX/RX_STOP can pass NULL for this parameter.
|
* that TX/RX_STOP can pass NULL for this parameter.
|
||||||
* Returns a negative error code on failure.
|
* Returns a negative error code on failure.
|
||||||
|
* The callback must be atomic.
|
||||||
*
|
*
|
||||||
* @rfkill_poll: Poll rfkill hardware state. If you need this, you also
|
* @rfkill_poll: Poll rfkill hardware state. If you need this, you also
|
||||||
* need to set wiphy->rfkill_poll to %true before registration,
|
* need to set wiphy->rfkill_poll to %true before registration,
|
||||||
* and need to call wiphy_rfkill_set_hw_state() in the callback.
|
* and need to call wiphy_rfkill_set_hw_state() in the callback.
|
||||||
|
* The callback can sleep.
|
||||||
*
|
*
|
||||||
* @testmode_cmd: Implement a cfg80211 test mode command.
|
* @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 {
|
struct ieee80211_ops {
|
||||||
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
|
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||||
int (*start)(struct ieee80211_hw *hw);
|
int (*start)(struct ieee80211_hw *hw);
|
||||||
void (*stop)(struct ieee80211_hw *hw);
|
void (*stop)(struct ieee80211_hw *hw);
|
||||||
int (*add_interface)(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,
|
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);
|
int (*config)(struct ieee80211_hw *hw, u32 changed);
|
||||||
void (*bss_info_changed)(struct ieee80211_hw *hw,
|
void (*bss_info_changed)(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
@ -1601,6 +1595,7 @@ struct ieee80211_ops {
|
|||||||
#ifdef CONFIG_NL80211_TESTMODE
|
#ifdef CONFIG_NL80211_TESTMODE
|
||||||
int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
|
int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
|
||||||
#endif
|
#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
|
* ieee80211_beacon_get_tim - beacon generation function
|
||||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
* @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.
|
* @tim_offset: pointer to variable that will receive the TIM IE offset.
|
||||||
* Set to 0 if invalid (in non-AP modes).
|
* Set to 0 if invalid (in non-AP modes).
|
||||||
* @tim_length: pointer to variable that will receive the TIM IE length,
|
* @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
|
* ieee80211_beacon_get - beacon generation function
|
||||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
* @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().
|
* 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
|
* ieee80211_rts_get - RTS frame generation function
|
||||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
* @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: pointer to the frame that is going to be protected by the RTS.
|
||||||
* @frame_len: the frame length (in octets).
|
* @frame_len: the frame length (in octets).
|
||||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
* @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
|
* ieee80211_rts_duration - Get the duration field for an RTS frame
|
||||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
* @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_len: the length of the frame that is going to be protected by the RTS.
|
||||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
* @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
|
* ieee80211_ctstoself_get - CTS-to-self frame generation function
|
||||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
* @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: pointer to the frame that is going to be protected by the CTS-to-self.
|
||||||
* @frame_len: the frame length (in octets).
|
* @frame_len: the frame length (in octets).
|
||||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
* @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
|
* ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
|
||||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
* @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_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.
|
* @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
|
* ieee80211_generic_frame_duration - Calculate the duration field for a frame
|
||||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
* @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.
|
* @frame_len: the length of the frame.
|
||||||
* @rate: the rate at which the frame is going to be transmitted.
|
* @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
|
* ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
|
||||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
* @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
|
* Function for accessing buffered broadcast and multicast frames. If
|
||||||
* hardware/firmware does not implement buffering of broadcast/multicast
|
* 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.
|
* 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.
|
* @ra: receiver address of the BA session recipient.
|
||||||
* @tid: the TID to BA on.
|
* @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.
|
* 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.
|
* @ra: receiver address of the BA session recipient.
|
||||||
* @tid: the TID to BA on.
|
* @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.
|
* 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.
|
* @ra: receiver address of the BA session recipient.
|
||||||
* @tid: the desired TID to BA on.
|
* @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.
|
* 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.
|
* @ra: receiver address of the BA session recipient.
|
||||||
* @tid: the desired TID to BA on.
|
* @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
|
* 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
|
* When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and
|
||||||
* IEEE80211_CONF_PS is set, the driver needs to inform whenever the
|
* IEEE80211_CONF_PS is set, the driver needs to inform whenever the
|
||||||
|
@ -6,10 +6,10 @@ mac80211-y := \
|
|||||||
sta_info.o \
|
sta_info.o \
|
||||||
wep.o \
|
wep.o \
|
||||||
wpa.o \
|
wpa.o \
|
||||||
scan.o \
|
scan.o offchannel.o \
|
||||||
ht.o agg-tx.o agg-rx.o \
|
ht.o agg-tx.o agg-rx.o \
|
||||||
ibss.o \
|
ibss.o \
|
||||||
mlme.o \
|
mlme.o work.o \
|
||||||
iface.o \
|
iface.o \
|
||||||
rate.o \
|
rate.o \
|
||||||
michael.o \
|
michael.o \
|
||||||
|
@ -78,17 +78,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
|
|||||||
enum nl80211_iftype type, u32 *flags,
|
enum nl80211_iftype type, u32 *flags,
|
||||||
struct vif_params *params)
|
struct vif_params *params)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (netif_running(dev))
|
if (ieee80211_sdata_running(sdata))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
if (!nl80211_params_check(type, params))
|
if (!nl80211_params_check(type, params))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
||||||
|
|
||||||
ret = ieee80211_if_change_type(sdata, type);
|
ret = ieee80211_if_change_type(sdata, type);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -1345,7 +1343,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ap = sdata->u.mgd.associated->cbss.bssid;
|
ap = sdata->u.mgd.associated->bssid;
|
||||||
|
|
||||||
if (smps_mode == IEEE80211_SMPS_AUTOMATIC) {
|
if (smps_mode == IEEE80211_SMPS_AUTOMATIC) {
|
||||||
if (sdata->u.mgd.powersave)
|
if (sdata->u.mgd.powersave)
|
||||||
@ -1443,6 +1441,28 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
|
|||||||
return -EINVAL;
|
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 = {
|
struct cfg80211_ops mac80211_config_ops = {
|
||||||
.add_virtual_intf = ieee80211_add_iface,
|
.add_virtual_intf = ieee80211_add_iface,
|
||||||
.del_virtual_intf = ieee80211_del_iface,
|
.del_virtual_intf = ieee80211_del_iface,
|
||||||
@ -1489,4 +1509,6 @@ struct cfg80211_ops mac80211_config_ops = {
|
|||||||
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
|
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
|
||||||
.set_power_mgmt = ieee80211_set_power_mgmt,
|
.set_power_mgmt = ieee80211_set_power_mgmt,
|
||||||
.set_bitrate_mask = ieee80211_set_bitrate_mask,
|
.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 */
|
/* STA attributes */
|
||||||
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
|
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
|
||||||
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
|
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,
|
static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
||||||
enum ieee80211_smps_mode smps_mode)
|
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(bssid, sta);
|
||||||
DEBUGFS_ADD(aid, sta);
|
DEBUGFS_ADD(aid, sta);
|
||||||
DEBUGFS_ADD(capab, sta);
|
|
||||||
DEBUGFS_ADD_MODE(smps, 0600);
|
DEBUGFS_ADD_MODE(smps, 0600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@ static inline int drv_start(struct ieee80211_local *local)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
local->started = true;
|
local->started = true;
|
||||||
smp_mb();
|
smp_mb();
|
||||||
ret = local->ops->start(&local->hw);
|
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)
|
static inline void drv_stop(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
local->ops->stop(&local->hw);
|
local->ops->stop(&local->hw);
|
||||||
trace_drv_stop(local);
|
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,
|
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);
|
int ret;
|
||||||
trace_drv_add_interface(local, vif_to_sdata(conf->vif), ret);
|
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
|
ret = local->ops->add_interface(&local->hw, vif);
|
||||||
|
trace_drv_add_interface(local, vif_to_sdata(vif), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void drv_remove_interface(struct ieee80211_local *local,
|
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);
|
might_sleep();
|
||||||
trace_drv_remove_interface(local, vif_to_sdata(conf->vif));
|
|
||||||
|
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)
|
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);
|
trace_drv_config(local, changed, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -62,6 +76,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
|
|||||||
struct ieee80211_bss_conf *info,
|
struct ieee80211_bss_conf *info,
|
||||||
u32 changed)
|
u32 changed)
|
||||||
{
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->bss_info_changed)
|
if (local->ops->bss_info_changed)
|
||||||
local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
|
local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
|
||||||
trace_drv_bss_info_changed(local, sdata, 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_sta *sta,
|
||||||
struct ieee80211_key_conf *key)
|
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);
|
trace_drv_set_key(local, cmd, sdata, sta, key, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -121,6 +141,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local,
|
|||||||
const u8 *address, u32 iv32,
|
const u8 *address, u32 iv32,
|
||||||
u16 *phase1key)
|
u16 *phase1key)
|
||||||
{
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->update_tkip_key)
|
if (local->ops->update_tkip_key)
|
||||||
local->ops->update_tkip_key(&local->hw, conf, address,
|
local->ops->update_tkip_key(&local->hw, conf, address,
|
||||||
iv32, phase1key);
|
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,
|
static inline int drv_hw_scan(struct ieee80211_local *local,
|
||||||
struct cfg80211_scan_request *req)
|
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);
|
trace_drv_hw_scan(local, req, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void drv_sw_scan_start(struct ieee80211_local *local)
|
static inline void drv_sw_scan_start(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->sw_scan_start)
|
if (local->ops->sw_scan_start)
|
||||||
local->ops->sw_scan_start(&local->hw);
|
local->ops->sw_scan_start(&local->hw);
|
||||||
trace_drv_sw_scan_start(local);
|
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)
|
static inline void drv_sw_scan_complete(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->sw_scan_complete)
|
if (local->ops->sw_scan_complete)
|
||||||
local->ops->sw_scan_complete(&local->hw);
|
local->ops->sw_scan_complete(&local->hw);
|
||||||
trace_drv_sw_scan_complete(local);
|
trace_drv_sw_scan_complete(local);
|
||||||
@ -154,6 +184,8 @@ static inline int drv_get_stats(struct ieee80211_local *local,
|
|||||||
{
|
{
|
||||||
int ret = -EOPNOTSUPP;
|
int ret = -EOPNOTSUPP;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->get_stats)
|
if (local->ops->get_stats)
|
||||||
ret = local->ops->get_stats(&local->hw, stats);
|
ret = local->ops->get_stats(&local->hw, stats);
|
||||||
trace_drv_get_stats(local, stats, ret);
|
trace_drv_get_stats(local, stats, ret);
|
||||||
@ -173,6 +205,9 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local,
|
|||||||
u32 value)
|
u32 value)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->set_rts_threshold)
|
if (local->ops->set_rts_threshold)
|
||||||
ret = local->ops->set_rts_threshold(&local->hw, value);
|
ret = local->ops->set_rts_threshold(&local->hw, value);
|
||||||
trace_drv_set_rts_threshold(local, value, ret);
|
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)
|
const struct ieee80211_tx_queue_params *params)
|
||||||
{
|
{
|
||||||
int ret = -EOPNOTSUPP;
|
int ret = -EOPNOTSUPP;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->conf_tx)
|
if (local->ops->conf_tx)
|
||||||
ret = local->ops->conf_tx(&local->hw, queue, params);
|
ret = local->ops->conf_tx(&local->hw, queue, params);
|
||||||
trace_drv_conf_tx(local, queue, params, ret);
|
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)
|
static inline u64 drv_get_tsf(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
u64 ret = -1ULL;
|
u64 ret = -1ULL;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->get_tsf)
|
if (local->ops->get_tsf)
|
||||||
ret = local->ops->get_tsf(&local->hw);
|
ret = local->ops->get_tsf(&local->hw);
|
||||||
trace_drv_get_tsf(local, ret);
|
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)
|
static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf)
|
||||||
{
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->set_tsf)
|
if (local->ops->set_tsf)
|
||||||
local->ops->set_tsf(&local->hw, tsf);
|
local->ops->set_tsf(&local->hw, tsf);
|
||||||
trace_drv_set_tsf(local, 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)
|
static inline void drv_reset_tsf(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->reset_tsf)
|
if (local->ops->reset_tsf)
|
||||||
local->ops->reset_tsf(&local->hw);
|
local->ops->reset_tsf(&local->hw);
|
||||||
trace_drv_reset_tsf(local);
|
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)
|
static inline int drv_tx_last_beacon(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->tx_last_beacon)
|
if (local->ops->tx_last_beacon)
|
||||||
ret = local->ops->tx_last_beacon(&local->hw);
|
ret = local->ops->tx_last_beacon(&local->hw);
|
||||||
trace_drv_tx_last_beacon(local, ret);
|
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)
|
static inline void drv_rfkill_poll(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
|
might_sleep();
|
||||||
|
|
||||||
if (local->ops->rfkill_poll)
|
if (local->ops->rfkill_poll)
|
||||||
local->ops->rfkill_poll(&local->hw);
|
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 */
|
#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
|
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 */
|
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
|
||||||
|
|
||||||
#undef TRACE_INCLUDE_PATH
|
#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,
|
static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_bss *bss)
|
struct ieee80211_bss *bss)
|
||||||
{
|
{
|
||||||
|
struct cfg80211_bss *cbss =
|
||||||
|
container_of((void *)bss, struct cfg80211_bss, priv);
|
||||||
struct ieee80211_supported_band *sband;
|
struct ieee80211_supported_band *sband;
|
||||||
u32 basic_rates;
|
u32 basic_rates;
|
||||||
int i, j;
|
int i, j;
|
||||||
u16 beacon_int = bss->cbss.beacon_interval;
|
u16 beacon_int = cbss->beacon_interval;
|
||||||
|
|
||||||
if (beacon_int < 10)
|
if (beacon_int < 10)
|
||||||
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;
|
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,
|
beacon_int,
|
||||||
bss->cbss.channel,
|
cbss->channel,
|
||||||
basic_rates,
|
basic_rates,
|
||||||
bss->cbss.capability,
|
cbss->capability,
|
||||||
bss->cbss.tsf);
|
cbss->tsf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
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;
|
struct ieee80211_local *local = sdata->local;
|
||||||
int freq;
|
int freq;
|
||||||
|
struct cfg80211_bss *cbss;
|
||||||
struct ieee80211_bss *bss;
|
struct ieee80211_bss *bss;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
struct ieee80211_channel *channel;
|
struct ieee80211_channel *channel;
|
||||||
@ -283,8 +286,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|||||||
if (!bss)
|
if (!bss)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
cbss = container_of((void *)bss, struct cfg80211_bss, priv);
|
||||||
|
|
||||||
/* was just updated in ieee80211_bss_info_update */
|
/* was just updated in ieee80211_bss_info_update */
|
||||||
beacon_timestamp = bss->cbss.tsf;
|
beacon_timestamp = cbss->tsf;
|
||||||
|
|
||||||
/* check if we need to merge IBSS */
|
/* 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;
|
goto put_bss;
|
||||||
|
|
||||||
/* not an IBSS */
|
/* not an IBSS */
|
||||||
if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS))
|
if (!(cbss->capability & WLAN_CAPABILITY_IBSS))
|
||||||
goto put_bss;
|
goto put_bss;
|
||||||
|
|
||||||
/* different channel */
|
/* different channel */
|
||||||
if (bss->cbss.channel != local->oper_channel)
|
if (cbss->channel != local->oper_channel)
|
||||||
goto put_bss;
|
goto put_bss;
|
||||||
|
|
||||||
/* different SSID */
|
/* different SSID */
|
||||||
@ -311,7 +316,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|||||||
goto put_bss;
|
goto put_bss;
|
||||||
|
|
||||||
/* same BSSID */
|
/* 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;
|
goto put_bss;
|
||||||
|
|
||||||
if (rx_status->flag & RX_FLAG_TSFT) {
|
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,
|
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
|
||||||
u8 *bssid,u8 *addr, u32 supp_rates)
|
u8 *bssid,u8 *addr, u32 supp_rates)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
int band = local->hw.conf.channel->band;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (compare_ether_addr(bssid, sdata->u.ibss.bssid))
|
if (compare_ether_addr(bssid, sdata->u.ibss.bssid))
|
||||||
return NULL;
|
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_if_ibss *ifibss = &sdata->u.ibss;
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct ieee80211_bss *bss;
|
struct cfg80211_bss *cbss;
|
||||||
struct ieee80211_channel *chan = NULL;
|
struct ieee80211_channel *chan = NULL;
|
||||||
const u8 *bssid = NULL;
|
const u8 *bssid = NULL;
|
||||||
int active_ibss;
|
int active_ibss;
|
||||||
@ -538,21 +547,23 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
|
|||||||
chan = ifibss->channel;
|
chan = ifibss->channel;
|
||||||
if (!is_zero_ether_addr(ifibss->bssid))
|
if (!is_zero_ether_addr(ifibss->bssid))
|
||||||
bssid = ifibss->bssid;
|
bssid = ifibss->bssid;
|
||||||
bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid,
|
cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
|
||||||
ifibss->ssid, ifibss->ssid_len,
|
ifibss->ssid, ifibss->ssid_len,
|
||||||
WLAN_CAPABILITY_IBSS |
|
WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY,
|
||||||
WLAN_CAPABILITY_PRIVACY,
|
capability);
|
||||||
capability);
|
|
||||||
|
|
||||||
if (bss) {
|
if (cbss) {
|
||||||
|
struct ieee80211_bss *bss;
|
||||||
|
|
||||||
|
bss = (void *)cbss->priv;
|
||||||
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
||||||
printk(KERN_DEBUG " sta_find_ibss: selected %pM current "
|
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 */
|
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
||||||
|
|
||||||
printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
|
printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
|
||||||
" based on configured SSID\n",
|
" based on configured SSID\n",
|
||||||
sdata->name, bss->cbss.bssid);
|
sdata->name, cbss->bssid);
|
||||||
|
|
||||||
ieee80211_sta_join_ibss(sdata, bss);
|
ieee80211_sta_join_ibss(sdata, bss);
|
||||||
ieee80211_rx_bss_put(local, 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))
|
if (WARN_ON(local->suspended))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (local->scanning)
|
if (local->scanning)
|
||||||
@ -827,7 +838,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
|
|||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
|
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
|
||||||
continue;
|
continue;
|
||||||
|
@ -71,9 +71,6 @@ struct ieee80211_fragment_entry {
|
|||||||
|
|
||||||
|
|
||||||
struct ieee80211_bss {
|
struct ieee80211_bss {
|
||||||
/* Yes, this is a hack */
|
|
||||||
struct cfg80211_bss cbss;
|
|
||||||
|
|
||||||
/* don't want to look up all the time */
|
/* don't want to look up all the time */
|
||||||
size_t ssid_len;
|
size_t ssid_len;
|
||||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||||
@ -227,31 +224,78 @@ struct mesh_preq_queue {
|
|||||||
u8 flags;
|
u8 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ieee80211_mgd_state {
|
enum ieee80211_work_type {
|
||||||
IEEE80211_MGD_STATE_IDLE,
|
IEEE80211_WORK_ABORT,
|
||||||
IEEE80211_MGD_STATE_PROBE,
|
IEEE80211_WORK_DIRECT_PROBE,
|
||||||
IEEE80211_MGD_STATE_AUTH,
|
IEEE80211_WORK_AUTH,
|
||||||
IEEE80211_MGD_STATE_ASSOC,
|
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 list_head list;
|
||||||
struct ieee80211_bss *bss;
|
|
||||||
int ie_len;
|
struct rcu_head rcu_head;
|
||||||
u8 prev_bssid[ETH_ALEN];
|
|
||||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
struct ieee80211_sub_if_data *sdata;
|
||||||
u8 ssid_len;
|
|
||||||
|
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;
|
unsigned long timeout;
|
||||||
enum ieee80211_mgd_state state;
|
enum ieee80211_work_type type;
|
||||||
u16 auth_alg, auth_transaction;
|
|
||||||
|
|
||||||
int tries;
|
u8 filter_ta[ETH_ALEN];
|
||||||
|
|
||||||
u8 key[WLAN_KEY_LEN_WEP104];
|
bool started;
|
||||||
u8 key_len, key_idx;
|
|
||||||
|
|
||||||
|
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 */
|
/* must be last */
|
||||||
u8 ie[0]; /* for auth or assoc frame, not probe */
|
u8 ie[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* flags used in struct ieee80211_if_managed.flags */
|
/* flags used in struct ieee80211_if_managed.flags */
|
||||||
@ -259,17 +303,11 @@ enum ieee80211_sta_flags {
|
|||||||
IEEE80211_STA_BEACON_POLL = BIT(0),
|
IEEE80211_STA_BEACON_POLL = BIT(0),
|
||||||
IEEE80211_STA_CONNECTION_POLL = BIT(1),
|
IEEE80211_STA_CONNECTION_POLL = BIT(1),
|
||||||
IEEE80211_STA_CONTROL_PORT = BIT(2),
|
IEEE80211_STA_CONTROL_PORT = BIT(2),
|
||||||
IEEE80211_STA_WMM_ENABLED = BIT(3),
|
|
||||||
IEEE80211_STA_DISABLE_11N = BIT(4),
|
IEEE80211_STA_DISABLE_11N = BIT(4),
|
||||||
IEEE80211_STA_CSA_RECEIVED = BIT(5),
|
IEEE80211_STA_CSA_RECEIVED = BIT(5),
|
||||||
IEEE80211_STA_MFP_ENABLED = BIT(6),
|
IEEE80211_STA_MFP_ENABLED = BIT(6),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* flags for MLME request */
|
|
||||||
enum ieee80211_sta_request {
|
|
||||||
IEEE80211_STA_REQ_SCAN,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ieee80211_if_managed {
|
struct ieee80211_if_managed {
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
struct timer_list conn_mon_timer;
|
struct timer_list conn_mon_timer;
|
||||||
@ -284,14 +322,11 @@ struct ieee80211_if_managed {
|
|||||||
int probe_send_count;
|
int probe_send_count;
|
||||||
|
|
||||||
struct mutex mtx;
|
struct mutex mtx;
|
||||||
struct ieee80211_bss *associated;
|
struct cfg80211_bss *associated;
|
||||||
struct ieee80211_mgd_work *old_associate_work;
|
|
||||||
struct list_head work_list;
|
|
||||||
|
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
|
|
||||||
u16 aid;
|
u16 aid;
|
||||||
u16 capab;
|
|
||||||
|
|
||||||
struct sk_buff_head skb_queue;
|
struct sk_buff_head skb_queue;
|
||||||
|
|
||||||
@ -300,8 +335,6 @@ struct ieee80211_if_managed {
|
|||||||
enum ieee80211_smps_mode req_smps, /* requested smps mode */
|
enum ieee80211_smps_mode req_smps, /* requested smps mode */
|
||||||
ap_smps; /* smps mode AP thinks we're in */
|
ap_smps; /* smps mode AP thinks we're in */
|
||||||
|
|
||||||
unsigned long request;
|
|
||||||
|
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
u32 beacon_crc;
|
u32 beacon_crc;
|
||||||
@ -567,6 +600,15 @@ struct ieee80211_local {
|
|||||||
|
|
||||||
const struct ieee80211_ops *ops;
|
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
|
* private workqueue to mac80211. mac80211 makes this accessible
|
||||||
* via ieee80211_queue_work()
|
* via ieee80211_queue_work()
|
||||||
@ -695,6 +737,10 @@ struct ieee80211_local {
|
|||||||
enum nl80211_channel_type oper_channel_type;
|
enum nl80211_channel_type oper_channel_type;
|
||||||
struct ieee80211_channel *oper_channel, *csa_channel;
|
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 */
|
/* SNMP counters */
|
||||||
/* dot11CountersTable */
|
/* dot11CountersTable */
|
||||||
u32 dot11TransmittedFragmentCount;
|
u32 dot11TransmittedFragmentCount;
|
||||||
@ -752,7 +798,7 @@ struct ieee80211_local {
|
|||||||
unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
|
unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
|
||||||
|
|
||||||
bool pspolling;
|
bool pspolling;
|
||||||
bool scan_ps_enabled;
|
bool offchannel_ps_enabled;
|
||||||
/*
|
/*
|
||||||
* PS can only be enabled when we have exactly one managed
|
* PS can only be enabled when we have exactly one managed
|
||||||
* interface (and monitors) in PS, this then points there.
|
* 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,
|
void ieee80211_rx_bss_put(struct ieee80211_local *local,
|
||||||
struct ieee80211_bss *bss);
|
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 */
|
/* interface handling */
|
||||||
int ieee80211_iface_init(void);
|
int ieee80211_iface_init(void);
|
||||||
void ieee80211_iface_exit(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);
|
u32 __ieee80211_recalc_idle(struct ieee80211_local *local);
|
||||||
void 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 */
|
/* tx handling */
|
||||||
void ieee80211_clear_tx_pending(struct ieee80211_local *local);
|
void ieee80211_clear_tx_pending(struct ieee80211_local *local);
|
||||||
void ieee80211_tx_pending(unsigned long data);
|
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,
|
void ieee80211_recalc_smps(struct ieee80211_local *local,
|
||||||
struct ieee80211_sub_if_data *forsdata);
|
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
|
#ifdef CONFIG_MAC80211_NOINLINE
|
||||||
#define debug_noinline noinline
|
#define debug_noinline noinline
|
||||||
#else
|
#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);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (netif_running(dev))
|
if (ieee80211_sdata_running(sdata))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
ret = eth_mac_addr(dev, addr);
|
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_sub_if_data *nsdata;
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
struct ieee80211_if_init_conf conf;
|
|
||||||
u32 changed = 0;
|
u32 changed = 0;
|
||||||
int res;
|
int res;
|
||||||
u32 hw_reconf_flags = 0;
|
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) {
|
list_for_each_entry(nsdata, &local->interfaces, list) {
|
||||||
struct net_device *ndev = nsdata->dev;
|
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
|
* Allow only a single IBSS interface to be up at any
|
||||||
* time. This is restricted because beacon distribution
|
* 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;
|
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.
|
* it to start up with this invalid address.
|
||||||
*/
|
*/
|
||||||
if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) {
|
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);
|
ieee80211_configure_filter(local);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
conf.vif = &sdata->vif;
|
res = drv_add_interface(local, &sdata->vif);
|
||||||
conf.type = sdata->vif.type;
|
|
||||||
conf.mac_addr = sdata->vif.addr;
|
|
||||||
res = drv_add_interface(local, &conf);
|
|
||||||
if (res)
|
if (res)
|
||||||
goto err_stop;
|
goto err_stop;
|
||||||
|
|
||||||
@ -334,7 +330,7 @@ static int ieee80211_open(struct net_device *dev)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_del_interface:
|
err_del_interface:
|
||||||
drv_remove_interface(local, &conf);
|
drv_remove_interface(local, &sdata->vif);
|
||||||
err_stop:
|
err_stop:
|
||||||
if (!local->open_count)
|
if (!local->open_count)
|
||||||
drv_stop(local);
|
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_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct ieee80211_if_init_conf conf;
|
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct sk_buff *skb, *tmp;
|
struct sk_buff *skb, *tmp;
|
||||||
@ -361,6 +356,11 @@ static int ieee80211_stop(struct net_device *dev)
|
|||||||
*/
|
*/
|
||||||
netif_stop_queue(dev);
|
netif_stop_queue(dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Purge work for this interface.
|
||||||
|
*/
|
||||||
|
ieee80211_work_purge(sdata);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now delete all active aggregation sessions.
|
* Now delete all active aggregation sessions.
|
||||||
*/
|
*/
|
||||||
@ -528,12 +528,9 @@ static int ieee80211_stop(struct net_device *dev)
|
|||||||
BSS_CHANGED_BEACON_ENABLED);
|
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 */
|
/* disable all keys for as long as this netdev is down */
|
||||||
ieee80211_disable_keys(sdata);
|
ieee80211_disable_keys(sdata);
|
||||||
drv_remove_interface(local, &conf);
|
drv_remove_interface(local, &sdata->vif);
|
||||||
}
|
}
|
||||||
|
|
||||||
sdata->bss = NULL;
|
sdata->bss = NULL;
|
||||||
@ -756,7 +753,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
|
|||||||
* and goes into the requested mode.
|
* and goes into the requested mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (netif_running(sdata->dev))
|
if (ieee80211_sdata_running(sdata))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
/* Purge and reset type-dependent state. */
|
/* Purge and reset type-dependent state. */
|
||||||
@ -917,6 +914,8 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local)
|
|||||||
wiphy_name(local->hw.wiphy));
|
wiphy_name(local->hw.wiphy));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
drv_flush(local, false);
|
||||||
|
|
||||||
local->hw.conf.flags |= IEEE80211_CONF_IDLE;
|
local->hw.conf.flags |= IEEE80211_CONF_IDLE;
|
||||||
return IEEE80211_CONF_CHANGE_IDLE;
|
return IEEE80211_CONF_CHANGE_IDLE;
|
||||||
}
|
}
|
||||||
@ -926,16 +925,18 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
|
|||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
if (!list_empty(&local->work_list))
|
||||||
|
return ieee80211_idle_off(local, "working");
|
||||||
|
|
||||||
if (local->scanning)
|
if (local->scanning)
|
||||||
return ieee80211_idle_off(local, "scanning");
|
return ieee80211_idle_off(local, "scanning");
|
||||||
|
|
||||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
/* do not count disabled managed interfaces */
|
/* do not count disabled managed interfaces */
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||||
!sdata->u.mgd.associated &&
|
!sdata->u.mgd.associated)
|
||||||
list_empty(&sdata->u.mgd.work_list))
|
|
||||||
continue;
|
continue;
|
||||||
/* do not count unused IBSS interfaces */
|
/* do not count unused IBSS interfaces */
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
|
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(old_key, KEY_FLAG_TODO_DELETE);
|
||||||
|
|
||||||
add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
|
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);
|
add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&sdata->local->key_lock, flags);
|
spin_unlock_irqrestore(&sdata->local->key_lock, flags);
|
||||||
@ -509,7 +509,7 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
|
|||||||
{
|
{
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
if (WARN_ON(!netif_running(sdata->dev)))
|
if (WARN_ON(!ieee80211_sdata_running(sdata)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
|
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) {
|
if (scan_chan) {
|
||||||
chan = scan_chan;
|
chan = scan_chan;
|
||||||
channel_type = NL80211_CHAN_NO_HT;
|
channel_type = NL80211_CHAN_NO_HT;
|
||||||
|
} else if (local->tmp_channel) {
|
||||||
|
chan = scan_chan = local->tmp_channel;
|
||||||
|
channel_type = local->tmp_channel_type;
|
||||||
} else {
|
} else {
|
||||||
chan = local->oper_channel;
|
chan = local->oper_channel;
|
||||||
channel_type = local->oper_channel_type;
|
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 (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)) {
|
test_bit(SCAN_SW_SCANNING, &local->scanning)) {
|
||||||
sdata->vif.bss_conf.enable_beacon = false;
|
sdata->vif.bss_conf.enable_beacon = false;
|
||||||
} else {
|
} else {
|
||||||
@ -359,9 +362,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
|||||||
WIPHY_FLAG_4ADDR_STATION;
|
WIPHY_FLAG_4ADDR_STATION;
|
||||||
wiphy->privid = mac80211_wiphy_privid;
|
wiphy->privid = mac80211_wiphy_privid;
|
||||||
|
|
||||||
/* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
|
wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
|
||||||
wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
|
|
||||||
sizeof(struct cfg80211_bss);
|
|
||||||
|
|
||||||
local = wiphy_priv(wiphy);
|
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);
|
INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
|
||||||
|
|
||||||
|
ieee80211_work_init(local);
|
||||||
|
|
||||||
INIT_WORK(&local->restart_work, ieee80211_restart_work);
|
INIT_WORK(&local->restart_work, ieee80211_restart_work);
|
||||||
|
|
||||||
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
|
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 ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (local->scanning)
|
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_local *local = hw_to_local(hw);
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
struct ieee80211_if_init_conf conf;
|
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
@ -93,17 +92,14 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* disable beaconing */
|
/* disable beaconing */
|
||||||
ieee80211_bss_info_change_notify(sdata,
|
ieee80211_bss_info_change_notify(sdata,
|
||||||
BSS_CHANGED_BEACON_ENABLED);
|
BSS_CHANGED_BEACON_ENABLED);
|
||||||
|
|
||||||
conf.vif = &sdata->vif;
|
drv_remove_interface(local, &sdata->vif);
|
||||||
conf.type = sdata->vif.type;
|
|
||||||
conf.mac_addr = sdata->vif.addr;
|
|
||||||
drv_remove_interface(local, &conf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stop hardware - this must stop RX */
|
/* 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)
|
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (prev_dev) {
|
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_sub_if_data *sdata = rx->sdata;
|
||||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||||
|
ieee80211_rx_result rxs;
|
||||||
|
|
||||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||||
return RX_DROP_MONITOR;
|
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))
|
if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
|
||||||
return RX_DROP_MONITOR;
|
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))
|
if (ieee80211_vif_is_mesh(&sdata->vif))
|
||||||
return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
|
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);
|
skb->protocol = htons(ETH_P_802_2);
|
||||||
|
|
||||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
|
if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
|
||||||
@ -2318,7 +2323,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
if (!found_sta) {
|
if (!found_sta) {
|
||||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
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,
|
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
|
||||||
u8 *ssid, u8 ssid_len)
|
u8 *ssid, u8 ssid_len)
|
||||||
{
|
{
|
||||||
return (void *)cfg80211_get_bss(local->hw.wiphy,
|
struct cfg80211_bss *cbss;
|
||||||
ieee80211_get_channel(local->hw.wiphy,
|
|
||||||
freq),
|
cbss = cfg80211_get_bss(local->hw.wiphy,
|
||||||
bssid, ssid, ssid_len,
|
ieee80211_get_channel(local->hw.wiphy, freq),
|
||||||
0, 0);
|
bssid, ssid, ssid_len, 0, 0);
|
||||||
|
if (!cbss)
|
||||||
|
return NULL;
|
||||||
|
return (void *)cbss->priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
|
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_id(bss));
|
||||||
kfree(bss_mesh_cfg(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,
|
void ieee80211_rx_bss_put(struct ieee80211_local *local,
|
||||||
struct ieee80211_bss *bss)
|
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 *
|
struct ieee80211_bss *
|
||||||
@ -59,6 +64,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
|||||||
struct ieee80211_channel *channel,
|
struct ieee80211_channel *channel,
|
||||||
bool beacon)
|
bool beacon)
|
||||||
{
|
{
|
||||||
|
struct cfg80211_bss *cbss;
|
||||||
struct ieee80211_bss *bss;
|
struct ieee80211_bss *bss;
|
||||||
int clen;
|
int clen;
|
||||||
s32 signal = 0;
|
s32 signal = 0;
|
||||||
@ -68,13 +74,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
|||||||
else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
|
else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
|
||||||
signal = (rx_status->signal * 100) / local->hw.max_signal;
|
signal = (rx_status->signal * 100) / local->hw.max_signal;
|
||||||
|
|
||||||
bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel,
|
cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
|
||||||
mgmt, len, signal, GFP_ATOMIC);
|
mgmt, len, signal, GFP_ATOMIC);
|
||||||
|
|
||||||
if (!bss)
|
if (!cbss)
|
||||||
return NULL;
|
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 */
|
/* save the ERP value so that it is available at association time */
|
||||||
if (elems->erp_info && elems->erp_info_len >= 1) {
|
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;
|
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)
|
void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = hw_to_local(hw);
|
struct ieee80211_local *local = hw_to_local(hw);
|
||||||
struct ieee80211_sub_if_data *sdata;
|
|
||||||
bool was_hw_scan;
|
bool was_hw_scan;
|
||||||
|
|
||||||
mutex_lock(&local->scan_mtx);
|
mutex_lock(&local->scan_mtx);
|
||||||
@ -344,28 +278,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
|||||||
|
|
||||||
drv_sw_scan_complete(local);
|
drv_sw_scan_complete(local);
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
ieee80211_offchannel_return(local, true);
|
||||||
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);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
ieee80211_recalc_idle(local);
|
ieee80211_recalc_idle(local);
|
||||||
@ -377,8 +290,6 @@ EXPORT_SYMBOL(ieee80211_scan_completed);
|
|||||||
|
|
||||||
static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
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
|
* Hardware/driver doesn't support hw_scan, so use software
|
||||||
* scanning instead. First send a nullfunc frame with power save
|
* 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);
|
drv_sw_scan_start(local);
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
ieee80211_offchannel_stop_beaconing(local);
|
||||||
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);
|
|
||||||
|
|
||||||
local->next_scan_state = SCAN_DECISION;
|
local->next_scan_state = SCAN_DECISION;
|
||||||
local->scan_channel_idx = 0;
|
local->scan_channel_idx = 0;
|
||||||
|
|
||||||
|
drv_flush(local, false);
|
||||||
|
|
||||||
ieee80211_configure_filter(local);
|
ieee80211_configure_filter(local);
|
||||||
|
|
||||||
/* TODO: start scan as soon as all nullfunc frames are ACKed */
|
|
||||||
ieee80211_queue_delayed_work(&local->hw,
|
ieee80211_queue_delayed_work(&local->hw,
|
||||||
&local->scan_work,
|
&local->scan_work,
|
||||||
IEEE80211_CHANNEL_TIME);
|
IEEE80211_CHANNEL_TIME);
|
||||||
@ -433,7 +326,6 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
|||||||
struct cfg80211_scan_request *req)
|
struct cfg80211_scan_request *req)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (local->scan_req)
|
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_req = req;
|
||||||
local->scan_sdata = sdata;
|
local->scan_sdata = sdata;
|
||||||
|
|
||||||
if (req != local->int_scan_req &&
|
if (!list_empty(&local->work_list)) {
|
||||||
sdata->vif.type == NL80211_IFTYPE_STATION &&
|
/* wait for the work to finish/time out */
|
||||||
!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);
|
|
||||||
return 0;
|
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 */
|
/* check if at least one STA interface is associated */
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
|
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,
|
static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
|
||||||
unsigned long *next_delay)
|
unsigned long *next_delay)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata;
|
ieee80211_offchannel_stop_station(local);
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
__set_bit(SCAN_OFF_CHANNEL, &local->scanning);
|
__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 */
|
/* advance to the next channel to be scanned */
|
||||||
*next_delay = HZ / 10;
|
|
||||||
local->next_scan_state = SCAN_SET_CHANNEL;
|
local->next_scan_state = SCAN_SET_CHANNEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
|
static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
|
||||||
unsigned long *next_delay)
|
unsigned long *next_delay)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = local->scan_sdata;
|
|
||||||
|
|
||||||
/* switch back to the operating channel */
|
/* switch back to the operating channel */
|
||||||
local->scan_channel = NULL;
|
local->scan_channel = NULL;
|
||||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
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);
|
ieee80211_offchannel_return(local, false);
|
||||||
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);
|
|
||||||
|
|
||||||
__clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
|
__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.
|
* 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);
|
ieee80211_scan_completed(&local->hw, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -359,6 +359,7 @@ int sta_info_insert(struct sta_info *sta)
|
|||||||
{
|
{
|
||||||
struct ieee80211_local *local = sta->local;
|
struct ieee80211_local *local = sta->local;
|
||||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||||
|
struct station_info sinfo;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int err = 0;
|
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
|
* something inserts a STA (on one CPU) without holding the RTNL
|
||||||
* and another CPU turns off the net device.
|
* and another CPU turns off the net device.
|
||||||
*/
|
*/
|
||||||
if (unlikely(!netif_running(sdata->dev))) {
|
if (unlikely(!ieee80211_sdata_running(sdata))) {
|
||||||
err = -ENETDOWN;
|
err = -ENETDOWN;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
@ -408,6 +409,10 @@ int sta_info_insert(struct sta_info *sta)
|
|||||||
|
|
||||||
spin_unlock_irqrestore(&local->sta_lock, flags);
|
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
|
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||||
/*
|
/*
|
||||||
* Debugfs entry adding might sleep, so schedule process
|
* 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();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
|
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)
|
if (!local->ps_sdata)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* No point if we're going to suspend */
|
||||||
|
if (local->quiescing)
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
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_for_each_entry_rcu(tmp_sdata, &local->interfaces,
|
||||||
list) {
|
list) {
|
||||||
if (!netif_running(tmp_sdata->dev))
|
if (!ieee80211_sdata_running(tmp_sdata))
|
||||||
continue;
|
continue;
|
||||||
if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
|
if (tmp_sdata->vif.type != NL80211_IFTYPE_AP)
|
||||||
continue;
|
continue;
|
||||||
|
@ -468,7 +468,7 @@ void ieee80211_iterate_active_interfaces(
|
|||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (netif_running(sdata->dev))
|
if (ieee80211_sdata_running(sdata))
|
||||||
iterator(data, sdata->vif.addr,
|
iterator(data, sdata->vif.addr,
|
||||||
&sdata->vif);
|
&sdata->vif);
|
||||||
}
|
}
|
||||||
@ -502,7 +502,7 @@ void ieee80211_iterate_active_interfaces_atomic(
|
|||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (netif_running(sdata->dev))
|
if (ieee80211_sdata_running(sdata))
|
||||||
iterator(data, sdata->vif.addr,
|
iterator(data, sdata->vif.addr,
|
||||||
&sdata->vif);
|
&sdata->vif);
|
||||||
}
|
}
|
||||||
@ -881,30 +881,66 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
|
|||||||
enum ieee80211_band band)
|
enum ieee80211_band band)
|
||||||
{
|
{
|
||||||
struct ieee80211_supported_band *sband;
|
struct ieee80211_supported_band *sband;
|
||||||
u8 *pos, *supp_rates_len, *esupp_rates_len = NULL;
|
u8 *pos;
|
||||||
int i;
|
size_t offset = 0, noffset;
|
||||||
|
int supp_rates_len, i;
|
||||||
|
|
||||||
sband = local->hw.wiphy->bands[band];
|
sband = local->hw.wiphy->bands[band];
|
||||||
|
|
||||||
pos = buffer;
|
pos = buffer;
|
||||||
|
|
||||||
|
supp_rates_len = min_t(int, sband->n_bitrates, 8);
|
||||||
|
|
||||||
*pos++ = WLAN_EID_SUPP_RATES;
|
*pos++ = WLAN_EID_SUPP_RATES;
|
||||||
supp_rates_len = pos;
|
*pos++ = supp_rates_len;
|
||||||
*pos++ = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < sband->n_bitrates; i++) {
|
for (i = 0; i < supp_rates_len; i++) {
|
||||||
struct ieee80211_rate *rate = &sband->bitrates[i];
|
int rate = sband->bitrates[i].bitrate;
|
||||||
|
*pos++ = (u8) (rate / 5);
|
||||||
|
}
|
||||||
|
|
||||||
if (esupp_rates_len) {
|
/* insert "request information" if in custom IEs */
|
||||||
*esupp_rates_len += 1;
|
if (ie && ie_len) {
|
||||||
} else if (*supp_rates_len == 8) {
|
static const u8 before_extrates[] = {
|
||||||
*pos++ = WLAN_EID_EXT_SUPP_RATES;
|
WLAN_EID_SSID,
|
||||||
esupp_rates_len = pos;
|
WLAN_EID_SUPP_RATES,
|
||||||
*pos++ = 1;
|
WLAN_EID_REQUEST,
|
||||||
} else
|
};
|
||||||
*supp_rates_len += 1;
|
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) {
|
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.
|
* that calculates local->scan_ies_len.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ie) {
|
/* add any remaining custom IEs */
|
||||||
memcpy(pos, ie, ie_len);
|
if (ie && ie_len) {
|
||||||
pos += ie_len;
|
noffset = ie_len;
|
||||||
|
memcpy(pos, ie + offset, noffset - offset);
|
||||||
|
pos += noffset - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos - buffer;
|
return pos - buffer;
|
||||||
@ -1037,7 +1075,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||||||
{
|
{
|
||||||
struct ieee80211_hw *hw = &local->hw;
|
struct ieee80211_hw *hw = &local->hw;
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
struct ieee80211_if_init_conf conf;
|
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int res;
|
int res;
|
||||||
@ -1047,7 +1084,19 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||||||
|
|
||||||
/* restart hardware */
|
/* restart hardware */
|
||||||
if (local->open_count) {
|
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);
|
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);
|
ieee80211_led_radio(local, true);
|
||||||
}
|
}
|
||||||
@ -1056,12 +1105,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
|
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
|
||||||
sdata->vif.type != NL80211_IFTYPE_MONITOR &&
|
sdata->vif.type != NL80211_IFTYPE_MONITOR &&
|
||||||
netif_running(sdata->dev)) {
|
ieee80211_sdata_running(sdata))
|
||||||
conf.vif = &sdata->vif;
|
res = drv_add_interface(local, &sdata->vif);
|
||||||
conf.type = sdata->vif.type;
|
|
||||||
conf.mac_addr = sdata->vif.addr;
|
|
||||||
res = drv_add_interface(local, &conf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add STAs back */
|
/* add STAs back */
|
||||||
@ -1103,7 +1148,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||||||
/* Finally also reconfigure all the BSS information */
|
/* Finally also reconfigure all the BSS information */
|
||||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
u32 changed = ~0;
|
u32 changed = ~0;
|
||||||
if (!netif_running(sdata->dev))
|
if (!ieee80211_sdata_running(sdata))
|
||||||
continue;
|
continue;
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
@ -1131,7 +1176,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||||||
|
|
||||||
/* add back keys */
|
/* add back keys */
|
||||||
list_for_each_entry(sdata, &local->interfaces, list)
|
list_for_each_entry(sdata, &local->interfaces, list)
|
||||||
if (netif_running(sdata->dev))
|
if (ieee80211_sdata_running(sdata))
|
||||||
ieee80211_enable_keys(sdata);
|
ieee80211_enable_keys(sdata);
|
||||||
|
|
||||||
ieee80211_wake_queues_by_reason(hw,
|
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 */
|
/* changed flag is auto-detected for this */
|
||||||
ieee80211_hw_config(local, 0);
|
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.
|
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
|
config CFG80211_INTERNAL_REGDB
|
||||||
bool "use statically compiled regulatory rules database" if EMBEDDED
|
bool "use statically compiled regulatory rules database" if EMBEDDED
|
||||||
default n
|
default n
|
||||||
|
@ -41,12 +41,45 @@ rdev_fixed_channel(struct cfg80211_registered_device *rdev,
|
|||||||
return result;
|
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,
|
int rdev_set_freq(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *for_wdev,
|
struct wireless_dev *for_wdev,
|
||||||
int freq, enum nl80211_channel_type channel_type)
|
int freq, enum nl80211_channel_type channel_type)
|
||||||
{
|
{
|
||||||
struct ieee80211_channel *chan;
|
struct ieee80211_channel *chan;
|
||||||
struct ieee80211_sta_ht_cap *ht_cap;
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (rdev_fixed_channel(rdev, for_wdev))
|
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)
|
if (!rdev->ops->set_channel)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
chan = rdev_freq_to_chan(rdev, freq, channel_type);
|
||||||
|
if (!chan)
|
||||||
/* Primary channel not allowed */
|
|
||||||
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
|
|
||||||
return -EINVAL;
|
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);
|
result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
@ -374,6 +374,9 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
|
|||||||
struct ieee80211_channel *
|
struct ieee80211_channel *
|
||||||
rdev_fixed_channel(struct cfg80211_registered_device *rdev,
|
rdev_fixed_channel(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *for_wdev);
|
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,
|
int rdev_set_freq(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *for_wdev,
|
struct wireless_dev *for_wdev,
|
||||||
int freq, enum nl80211_channel_type channel_type);
|
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) {
|
} else if (wdev->conn) {
|
||||||
cfg80211_sme_failed_assoc(wdev);
|
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_4ADDR] = { .type = NLA_U8 },
|
||||||
[NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
|
[NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
|
||||||
.len = WLAN_PMKID_LEN },
|
.len = WLAN_PMKID_LEN },
|
||||||
|
[NL80211_ATTR_DURATION] = { .type = NLA_U32 },
|
||||||
|
[NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* policy for the attributes */
|
/* 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(set_pmksa, SET_PMKSA);
|
||||||
CMD(del_pmksa, DEL_PMKSA);
|
CMD(del_pmksa, DEL_PMKSA);
|
||||||
CMD(flush_pmksa, FLUSH_PMKSA);
|
CMD(flush_pmksa, FLUSH_PMKSA);
|
||||||
|
CMD(remain_on_channel, REMAIN_ON_CHANNEL);
|
||||||
if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
|
if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
|
||||||
i++;
|
i++;
|
||||||
NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
|
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,
|
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
|
||||||
int flags, struct net_device *dev,
|
int flags, struct net_device *dev,
|
||||||
u8 *mac_addr, struct station_info *sinfo)
|
const u8 *mac_addr, struct station_info *sinfo)
|
||||||
{
|
{
|
||||||
void *hdr;
|
void *hdr;
|
||||||
struct nlattr *sinfoattr, *txrate;
|
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]);
|
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);
|
r = regulatory_hint_user(data);
|
||||||
|
|
||||||
return r;
|
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[] = {
|
static struct genl_ops nl80211_ops[] = {
|
||||||
{
|
{
|
||||||
.cmd = NL80211_CMD_GET_WIPHY,
|
.cmd = NL80211_CMD_GET_WIPHY,
|
||||||
@ -4551,8 +4685,20 @@ static struct genl_ops nl80211_ops[] = {
|
|||||||
.policy = nl80211_policy,
|
.policy = nl80211_policy,
|
||||||
.flags = GENL_ADMIN_PERM,
|
.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 = {
|
static struct genl_multicast_group nl80211_mlme_mcgrp = {
|
||||||
.name = "mlme",
|
.name = "mlme",
|
||||||
};
|
};
|
||||||
@ -5140,6 +5286,89 @@ nla_put_failure:
|
|||||||
nlmsg_free(msg);
|
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 */
|
/* initialisation/exit functions */
|
||||||
|
|
||||||
int nl80211_init(void)
|
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,
|
struct net_device *netdev, const u8 *bssid,
|
||||||
gfp_t gfp);
|
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 */
|
#endif /* __NET_WIRELESS_NL80211_H */
|
||||||
|
@ -129,78 +129,6 @@ static char *ieee80211_regdom = "00";
|
|||||||
module_param(ieee80211_regdom, charp, 0444);
|
module_param(ieee80211_regdom, charp, 0444);
|
||||||
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
|
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)
|
static void reset_regdomains(void)
|
||||||
{
|
{
|
||||||
/* avoid freeing static information or freeing something twice */
|
/* avoid freeing static information or freeing something twice */
|
||||||
@ -210,8 +138,6 @@ static void reset_regdomains(void)
|
|||||||
cfg80211_world_regdom = NULL;
|
cfg80211_world_regdom = NULL;
|
||||||
if (cfg80211_regdomain == &world_regdom)
|
if (cfg80211_regdomain == &world_regdom)
|
||||||
cfg80211_regdomain = NULL;
|
cfg80211_regdomain = NULL;
|
||||||
if (is_old_static_regdom(cfg80211_regdomain))
|
|
||||||
cfg80211_regdomain = NULL;
|
|
||||||
|
|
||||||
kfree(cfg80211_regdomain);
|
kfree(cfg80211_regdomain);
|
||||||
kfree(cfg80211_world_regdom);
|
kfree(cfg80211_world_regdom);
|
||||||
@ -1490,8 +1416,6 @@ static int ignore_request(struct wiphy *wiphy,
|
|||||||
return REG_INTERSECT;
|
return REG_INTERSECT;
|
||||||
case NL80211_REGDOM_SET_BY_DRIVER:
|
case NL80211_REGDOM_SET_BY_DRIVER:
|
||||||
if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
|
if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
|
||||||
if (is_old_static_regdom(cfg80211_regdomain))
|
|
||||||
return 0;
|
|
||||||
if (regdom_changes(pending_request->alpha2))
|
if (regdom_changes(pending_request->alpha2))
|
||||||
return 0;
|
return 0;
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
@ -1528,8 +1452,7 @@ static int ignore_request(struct wiphy *wiphy,
|
|||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_old_static_regdom(cfg80211_regdomain) &&
|
if (!regdom_changes(pending_request->alpha2))
|
||||||
!regdom_changes(pending_request->alpha2))
|
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
|
|
||||||
return 0;
|
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
|
* If someone else asked us to change the rd lets only bother
|
||||||
* checking if the alpha2 changes if CRDA was already called
|
* checking if the alpha2 changes if CRDA was already called
|
||||||
*/
|
*/
|
||||||
if (!is_old_static_regdom(cfg80211_regdomain) &&
|
if (!regdom_changes(rd->alpha2))
|
||||||
!regdom_changes(rd->alpha2))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2311,15 +2233,8 @@ int regulatory_init(void)
|
|||||||
spin_lock_init(®_requests_lock);
|
spin_lock_init(®_requests_lock);
|
||||||
spin_lock_init(®_pending_beacons_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;
|
cfg80211_regdomain = cfg80211_world_regdom;
|
||||||
|
|
||||||
#endif
|
|
||||||
/* We always try to get an update for the static regdomain */
|
/* We always try to get an update for the static regdomain */
|
||||||
err = regulatory_hint_core(cfg80211_regdomain->alpha2);
|
err = regulatory_hint_core(cfg80211_regdomain->alpha2);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -601,7 +601,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
|||||||
struct cfg80211_registered_device *rdev;
|
struct cfg80211_registered_device *rdev;
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
struct iw_scan_req *wreq = NULL;
|
struct iw_scan_req *wreq = NULL;
|
||||||
struct cfg80211_scan_request *creq;
|
struct cfg80211_scan_request *creq = NULL;
|
||||||
int i, err, n_channels = 0;
|
int i, err, n_channels = 0;
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
|
|
||||||
@ -694,8 +694,10 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
|||||||
/* translate "Scan for SSID" request */
|
/* translate "Scan for SSID" request */
|
||||||
if (wreq) {
|
if (wreq) {
|
||||||
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
|
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
|
||||||
if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
|
if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
|
memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
|
||||||
creq->ssids[0].ssid_len = 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);
|
err = rdev->ops->scan(wiphy, dev, creq);
|
||||||
if (err) {
|
if (err) {
|
||||||
rdev->scan_req = NULL;
|
rdev->scan_req = NULL;
|
||||||
kfree(creq);
|
/* creq will be freed below */
|
||||||
} else {
|
} else {
|
||||||
nl80211_send_scan_start(rdev, dev);
|
nl80211_send_scan_start(rdev, dev);
|
||||||
|
/* creq now owned by driver */
|
||||||
|
creq = NULL;
|
||||||
dev_hold(dev);
|
dev_hold(dev);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
kfree(creq);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user