Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

This commit is contained in:
David S. Miller 2008-09-19 16:17:12 -07:00
commit d950f264ff
108 changed files with 5451 additions and 3606 deletions

View File

@ -145,7 +145,6 @@ usage should require reading the full document.
this though and the recommendation to allow only a single
interface in STA mode at first!
</para>
!Finclude/net/mac80211.h ieee80211_if_types
!Finclude/net/mac80211.h ieee80211_if_init_conf
!Finclude/net/mac80211.h ieee80211_if_conf
</chapter>
@ -177,8 +176,7 @@ usage should require reading the full document.
<title>functions/definitions</title>
!Finclude/net/mac80211.h ieee80211_rx_status
!Finclude/net/mac80211.h mac80211_rx_flags
!Finclude/net/mac80211.h ieee80211_tx_control
!Finclude/net/mac80211.h ieee80211_tx_status_flags
!Finclude/net/mac80211.h ieee80211_tx_info
!Finclude/net/mac80211.h ieee80211_rx
!Finclude/net/mac80211.h ieee80211_rx_irqsafe
!Finclude/net/mac80211.h ieee80211_tx_status
@ -189,12 +187,11 @@ usage should require reading the full document.
!Finclude/net/mac80211.h ieee80211_ctstoself_duration
!Finclude/net/mac80211.h ieee80211_generic_frame_duration
!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb
!Finclude/net/mac80211.h ieee80211_get_hdrlen
!Finclude/net/mac80211.h ieee80211_hdrlen
!Finclude/net/mac80211.h ieee80211_wake_queue
!Finclude/net/mac80211.h ieee80211_stop_queue
!Finclude/net/mac80211.h ieee80211_start_queues
!Finclude/net/mac80211.h ieee80211_stop_queues
!Finclude/net/mac80211.h ieee80211_wake_queues
!Finclude/net/mac80211.h ieee80211_stop_queues
</sect1>
</chapter>
@ -230,8 +227,7 @@ usage should require reading the full document.
<title>Multiple queues and QoS support</title>
<para>TBD</para>
!Finclude/net/mac80211.h ieee80211_tx_queue_params
!Finclude/net/mac80211.h ieee80211_tx_queue_stats_data
!Finclude/net/mac80211.h ieee80211_tx_queue
!Finclude/net/mac80211.h ieee80211_tx_queue_stats
</chapter>
<chapter id="AP">

View File

@ -6,6 +6,24 @@ be removed from this file.
---------------------------
What: old static regulatory information and ieee80211_regdom module parameter
When: 2.6.29
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 also kept around the ieee80211_regdom module parameter in case
some applications were relying on it. Changing regulatory domains
can now be done instead by using nl80211, as is done with iw.
Who: Luis R. Rodriguez <lrodriguez@atheros.com>
---------------------------
What: dev->power.power_state
When: July 2007
Why: Broken design for runtime control over driver power states, confusing

View File

@ -0,0 +1,194 @@
Linux wireless regulatory documentation
---------------------------------------
This document gives a brief review over how the Linux wireless
regulatory infrastructure works.
More up to date information can be obtained at the project's web page:
http://wireless.kernel.org/en/developers/Regulatory
Keeping regulatory domains in userspace
---------------------------------------
Due to the dynamic nature of regulatory domains we keep them
in userspace and provide a framework for userspace to upload
to the kernel one regulatory domain to be used as the central
core regulatory domain all wireless devices should adhere to.
How to get regulatory domains to the kernel
-------------------------------------------
Userspace gets a regulatory domain in the kernel by having
a userspace agent build it and send it via nl80211. Only
expected regulatory domains will be respected by the kernel.
A currently available userspace agent which can accomplish this
is CRDA - central regulatory domain agent. Its documented here:
http://wireless.kernel.org/en/developers/Regulatory/CRDA
Essentially the kernel will send a udev event when it knows
it needs a new regulatory domain. A udev rule can be put in place
to trigger crda to send the respective regulatory domain for a
specific ISO/IEC 3166 alpha2.
Below is an example udev rule which can be used:
# Example file, should be put in /etc/udev/rules.d/regulatory.rules
KERNEL=="regulatory*", ACTION=="change", SUBSYSTEM=="platform", RUN+="/sbin/crda"
The alpha2 is passed as an environment variable under the variable COUNTRY.
Who asks for regulatory domains?
--------------------------------
* Users
Users can use iw:
http://wireless.kernel.org/en/users/Documentation/iw
An example:
# set regulatory domain to "Costa Rica"
iw reg set CR
This will request the kernel to set the regulatory domain to
the specificied alpha2. The kernel in turn will then ask userspace
to provide a regulatory domain for the alpha2 specified by the user
by sending a uevent.
* Wireless subsystems for Country Information elements
The kernel will send a uevent to inform userspace a new
regulatory domain is required. More on this to be added
as its integration is added.
* Drivers
If drivers determine they need a specific regulatory domain
set they can inform the wireless core using regulatory_hint().
They have two options -- they either provide an alpha2 so that
crda can provide back a regulatory domain for that country or
they can build their own regulatory domain based on internal
custom knowledge so the wireless core can respect it.
*Most* drivers will rely on the first mechanism of providing a
regulatory hint with an alpha2. For these drivers there is an additional
check that can be used to ensure compliance based on custom EEPROM
regulatory data. This additional check can be used by drivers by
registering on its struct wiphy a reg_notifier() callback. This notifier
is called when the core's regulatory domain has been changed. The driver
can use this to review the changes made and also review who made them
(driver, user, country IE) and determine what to allow based on its
internal EEPROM data. Devices drivers wishing to be capable of world
roaming should use this callback. More on world roaming will be
added to this document when its support is enabled.
Device drivers who provide their own built regulatory domain
do not need a callback as the channels registered by them are
the only ones that will be allowed and therefore *additional*
cannels cannot be enabled.
Example code - drivers hinting an alpha2:
------------------------------------------
This example comes from the zd1211rw device driver. You can start
by having a mapping of your device's EEPROM country/regulatory
domain value to to a specific alpha2 as follows:
static struct zd_reg_alpha2_map reg_alpha2_map[] = {
{ ZD_REGDOMAIN_FCC, "US" },
{ ZD_REGDOMAIN_IC, "CA" },
{ ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
{ ZD_REGDOMAIN_JAPAN, "JP" },
{ ZD_REGDOMAIN_JAPAN_ADD, "JP" },
{ ZD_REGDOMAIN_SPAIN, "ES" },
{ ZD_REGDOMAIN_FRANCE, "FR" },
Then you can define a routine to map your read EEPROM value to an alpha2,
as follows:
static int zd_reg2alpha2(u8 regdomain, char *alpha2)
{
unsigned int i;
struct zd_reg_alpha2_map *reg_map;
for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
reg_map = &reg_alpha2_map[i];
if (regdomain == reg_map->reg) {
alpha2[0] = reg_map->alpha2[0];
alpha2[1] = reg_map->alpha2[1];
return 0;
}
}
return 1;
}
Lastly, you can then hint to the core of your discovered alpha2, if a match
was found. You need to do this after you have registered your wiphy. You
are expected to do this during initialization.
r = zd_reg2alpha2(mac->regdomain, alpha2);
if (!r)
regulatory_hint(hw->wiphy, alpha2, NULL);
Example code - drivers providing a built in regulatory domain:
--------------------------------------------------------------
If you have regulatory information you can obtain from your
driver and you *need* to use this we let you build a regulatory domain
structure and pass it to the wireless core. To do this you should
kmalloc() a structure big enough to hold your regulatory domain
structure and you should then fill it with your data. Finally you simply
call regulatory_hint() with the regulatory domain structure in it.
Bellow is a simple example, with a regulatory domain cached using the stack.
Your implementation may vary (read EEPROM cache instead, for example).
Example cache of some regulatory domain
struct ieee80211_regdomain mydriver_jp_regdom = {
.n_reg_rules = 3,
.alpha2 = "JP",
//.alpha2 = "99", /* If I have no alpha2 to map it to */
.reg_rules = {
/* IEEE 802.11b/g, channels 1..14 */
REG_RULE(2412-20, 2484+20, 40, 6, 20, 0),
/* IEEE 802.11a, channels 34..48 */
REG_RULE(5170-20, 5240+20, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channels 52..64 */
REG_RULE(5260-20, 5320+20, 40, 6, 20,
NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
}
};
Then in some part of your code after your wiphy has been registered:
int r;
struct ieee80211_regdomain *rd;
int size_of_regd;
int num_rules = mydriver_jp_regdom.n_reg_rules;
unsigned int i;
size_of_regd = sizeof(struct ieee80211_regdomain) +
(num_rules * sizeof(struct ieee80211_reg_rule));
rd = kzalloc(size_of_regd, GFP_KERNEL);
if (!rd)
return -ENOMEM;
memcpy(rd, &mydriver_jp_regdom, sizeof(struct ieee80211_regdomain));
for (i=0; i < num_rules; i++) {
memcpy(&rd->reg_rules[i], &mydriver_jp_regdom.reg_rules[i],
sizeof(struct ieee80211_reg_rule));
}
r = regulatory_hint(hw->wiphy, NULL, rd);
if (r) {
kfree(rd);
return r;
}

View File

@ -341,6 +341,8 @@ key that does nothing by itself, as well as any hot key that is type-specific
3.1 Guidelines for wireless device drivers
------------------------------------------
(in this text, rfkill->foo means the foo field of struct rfkill).
1. Each independent transmitter in a wireless device (usually there is only one
transmitter per device) should have a SINGLE rfkill class attached to it.
@ -363,10 +365,32 @@ This rule exists because users of the rfkill subsystem expect to get (and set,
when possible) the overall transmitter rfkill state, not of a particular rfkill
line.
5. During suspend, the rfkill class will attempt to soft-block the radio
through a call to rfkill->toggle_radio, and will try to restore its previous
state during resume. After a rfkill class is suspended, it will *not* call
rfkill->toggle_radio until it is resumed.
5. The wireless device driver MUST NOT leave the transmitter enabled during
suspend and hibernation unless:
5.1. The transmitter has to be enabled for some sort of functionality
like wake-on-wireless-packet or autonomous packed forwarding in a mesh
network, and that functionality is enabled for this suspend/hibernation
cycle.
AND
5.2. The device was not on a user-requested BLOCKED state before
the suspend (i.e. the driver must NOT unblock a device, not even
to support wake-on-wireless-packet or remain in the mesh).
In other words, there is absolutely no allowed scenario where a driver can
automatically take action to unblock a rfkill controller (obviously, this deals
with scenarios where soft-blocking or both soft and hard blocking is happening.
Scenarios where hardware rfkill lines are the only ones blocking the
transmitter are outside of this rule, since the wireless device driver does not
control its input hardware rfkill lines in the first place).
6. During resume, rfkill will try to restore its previous state.
7. After a rfkill class is suspended, it will *not* call rfkill->toggle_radio
until it is resumed.
Example of a WLAN wireless driver connected to the rfkill subsystem:
--------------------------------------------------------------------

View File

@ -765,11 +765,11 @@ static void adm8211_update_mode(struct ieee80211_hw *dev)
priv->soft_rx_crc = 0;
switch (priv->mode) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
priv->nar &= ~(ADM8211_NAR_PR | ADM8211_NAR_EA);
priv->nar |= ADM8211_NAR_ST | ADM8211_NAR_SR;
break;
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
priv->nar &= ~ADM8211_NAR_PR;
priv->nar |= ADM8211_NAR_EA | ADM8211_NAR_ST | ADM8211_NAR_SR;
@ -777,7 +777,7 @@ static void adm8211_update_mode(struct ieee80211_hw *dev)
if (priv->pdev->revision >= ADM8211_REV_BA)
priv->soft_rx_crc = 1;
break;
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
priv->nar &= ~(ADM8211_NAR_EA | ADM8211_NAR_ST);
priv->nar |= ADM8211_NAR_PR | ADM8211_NAR_SR;
break;
@ -1410,11 +1410,11 @@ static int adm8211_add_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct adm8211_priv *priv = dev->priv;
if (priv->mode != IEEE80211_IF_TYPE_MNTR)
if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
@ -1437,7 +1437,7 @@ static void adm8211_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct adm8211_priv *priv = dev->priv;
priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->mode = NL80211_IFTYPE_MONITOR;
}
static int adm8211_init_rings(struct ieee80211_hw *dev)
@ -1556,7 +1556,7 @@ static int adm8211_start(struct ieee80211_hw *dev)
ADM8211_CSR_WRITE(IER, ADM8211_IER_NIE | ADM8211_IER_AIE |
ADM8211_IER_RCIE | ADM8211_IER_TCIE |
ADM8211_IER_TDUIE | ADM8211_IER_GPTIE);
priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->mode = NL80211_IFTYPE_MONITOR;
adm8211_update_mode(dev);
ADM8211_CSR_WRITE(RDR, 0);
@ -1571,7 +1571,7 @@ static void adm8211_stop(struct ieee80211_hw *dev)
{
struct adm8211_priv *priv = dev->priv;
priv->mode = IEEE80211_IF_TYPE_INVALID;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
priv->nar = 0;
ADM8211_CSR_WRITE(NAR, 0);
ADM8211_CSR_WRITE(IER, 0);
@ -1896,7 +1896,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
priv->tx_power = 0x40;
priv->lpf_cutoff = 0xFF;
priv->lnags_threshold = 0xFF;
priv->mode = IEEE80211_IF_TYPE_INVALID;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
/* Power-on issue. EEPROM won't read correctly without */
if (pdev->revision >= ADM8211_REV_BA) {
@ -1986,7 +1986,7 @@ static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state)
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct adm8211_priv *priv = dev->priv;
if (priv->mode != IEEE80211_IF_TYPE_INVALID) {
if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) {
ieee80211_stop_queues(dev);
adm8211_stop(dev);
}
@ -2004,7 +2004,7 @@ static int adm8211_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
if (priv->mode != IEEE80211_IF_TYPE_INVALID) {
if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) {
adm8211_start(dev);
ieee80211_wake_queues(dev);
}

View File

@ -1008,7 +1008,7 @@ struct ath5k_hw {
enum ath5k_int ah_imr;
enum ieee80211_if_types ah_op_mode;
enum nl80211_iftype ah_op_mode;
enum ath5k_power_mode ah_power_mode;
struct ieee80211_channel ah_current_channel;
bool ah_turbo;
@ -1117,7 +1117,7 @@ extern void ath5k_hw_detach(struct ath5k_hw *ah);
/* Reset Functions */
extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
extern int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel);
extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
/* Power management functions */
extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);

View File

@ -124,7 +124,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
/*
* HW information
*/
ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
ah->ah_op_mode = NL80211_IFTYPE_STATION;
ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
ah->ah_turbo = false;
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;

View File

@ -507,7 +507,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
sc->iobase = mem; /* So we can unmap it on detach */
sc->cachelsz = csz * sizeof(u32); /* convert to bytes */
sc->opmode = IEEE80211_IF_TYPE_STA;
sc->opmode = NL80211_IFTYPE_STATION;
mutex_init(&sc->lock);
spin_lock_init(&sc->rxbuflock);
spin_lock_init(&sc->txbuflock);
@ -1377,8 +1377,8 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
if (ret)
return ret;
if (sc->opmode == IEEE80211_IF_TYPE_AP ||
sc->opmode == IEEE80211_IF_TYPE_MESH_POINT) {
if (sc->opmode == NL80211_IFTYPE_AP ||
sc->opmode == NL80211_IFTYPE_MESH_POINT) {
/*
* Always burst out beacon and CAB traffic
* (aifs = cwmin = cwmax = 0)
@ -1386,7 +1386,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
qi.tqi_aifs = 0;
qi.tqi_cw_min = 0;
qi.tqi_cw_max = 0;
} else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
} else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/*
* Adhoc mode; backoff between 0 and (2 * cw_min).
*/
@ -1714,7 +1714,7 @@ ath5k_tasklet_rx(unsigned long data)
/* let crypto-error packets fall through in MNTR */
if ((rs.rs_status &
~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
sc->opmode != IEEE80211_IF_TYPE_MNTR)
sc->opmode != NL80211_IFTYPE_MONITOR)
goto next;
}
accept:
@ -1777,7 +1777,7 @@ accept:
ath5k_debug_dump_skb(sc, skb, "RX ", 0);
/* check beacons in IBSS mode */
if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
if (sc->opmode == NL80211_IFTYPE_ADHOC)
ath5k_check_ibss_tsf(sc, skb, &rxs);
__ieee80211_rx(sc->hw, skb, &rxs);
@ -1892,7 +1892,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ds = bf->desc;
flags = AR5K_TXDESC_NOACK;
if (sc->opmode == IEEE80211_IF_TYPE_IBSS && ath5k_hw_hasveol(ah)) {
if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
ds->ds_link = bf->daddr; /* self-linked */
flags |= AR5K_TXDESC_VEOL;
/*
@ -1941,8 +1941,8 @@ ath5k_beacon_send(struct ath5k_softc *sc)
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA ||
sc->opmode == IEEE80211_IF_TYPE_MNTR)) {
if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
sc->opmode == NL80211_IFTYPE_MONITOR)) {
ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
return;
}
@ -2116,9 +2116,9 @@ ath5k_beacon_config(struct ath5k_softc *sc)
sc->bmisscount = 0;
sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
if (sc->opmode == IEEE80211_IF_TYPE_STA) {
if (sc->opmode == NL80211_IFTYPE_STATION) {
sc->imask |= AR5K_INT_BMISS;
} else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
} else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/*
* In IBSS mode we use a self-linked tx descriptor and let the
* hardware send the beacons automatically. We have to load it
@ -2323,7 +2323,7 @@ ath5k_intr(int irq, void *dev_id)
* transmission time) in order to detect wether
* automatic TSF updates happened.
*/
if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/* XXX: only if VEOL suppported */
u64 tsf = ath5k_hw_get_tsf64(ah);
sc->nexttbtt += sc->bintval;
@ -2553,7 +2553,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
ath5k_debug_dump_skb(sc, skb, "TX ", 1);
if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
if (sc->opmode == NL80211_IFTYPE_MONITOR)
ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
/*
@ -2688,9 +2688,9 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
sc->vif = conf->vif;
switch (conf->type) {
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MONITOR:
sc->opmode = conf->type;
break;
default:
@ -2761,7 +2761,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (conf->changed & IEEE80211_IFCC_BEACON &&
vif->type == IEEE80211_IF_TYPE_IBSS) {
vif->type == NL80211_IFTYPE_ADHOC) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon) {
ret = -ENOMEM;
@ -2880,17 +2880,17 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
if (sc->opmode == NL80211_IFTYPE_MONITOR)
rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
if (sc->opmode != IEEE80211_IF_TYPE_STA)
if (sc->opmode != NL80211_IFTYPE_STATION)
rfilt |= AR5K_RX_FILTER_PROBEREQ;
if (sc->opmode != IEEE80211_IF_TYPE_AP &&
sc->opmode != IEEE80211_IF_TYPE_MESH_POINT &&
if (sc->opmode != NL80211_IFTYPE_AP &&
sc->opmode != NL80211_IFTYPE_MESH_POINT &&
test_bit(ATH_STAT_PROMISC, sc->status))
rfilt |= AR5K_RX_FILTER_PROM;
if (sc->opmode == IEEE80211_IF_TYPE_STA ||
sc->opmode == IEEE80211_IF_TYPE_IBSS) {
if (sc->opmode == NL80211_IFTYPE_STATION ||
sc->opmode == NL80211_IFTYPE_ADHOC) {
rfilt |= AR5K_RX_FILTER_BEACON;
}
@ -2995,7 +2995,7 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
* in IBSS mode we need to update the beacon timers too.
* this will also reset the TSF if we call it with 0
*/
if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
if (sc->opmode == NL80211_IFTYPE_ADHOC)
ath5k_beacon_update_timers(sc, 0);
else
ath5k_hw_reset_tsf(sc->ah);
@ -3010,7 +3010,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
ath5k_debug_dump_skb(sc, skb, "BC ", 1);
if (sc->opmode != IEEE80211_IF_TYPE_IBSS) {
if (sc->opmode != NL80211_IFTYPE_ADHOC) {
ret = -EIO;
goto end;
}

View File

@ -113,7 +113,7 @@ struct ath5k_softc {
struct ieee80211_channel channels[ATH_CHAN_MAX];
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
u8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
enum ieee80211_if_types opmode;
enum nl80211_iftype opmode;
struct ath5k_hw *ah; /* Atheros HW */
struct ieee80211_supported_band *curband;

View File

@ -52,26 +52,26 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
ATH5K_TRACE(ah->ah_sc);
switch (ah->ah_op_mode) {
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
(ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_NO_PSPOLL : 0);
beacon_reg |= AR5K_BCR_ADHOC;
break;
case IEEE80211_IF_TYPE_AP:
case IEEE80211_IF_TYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
(ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_NO_PSPOLL : 0);
beacon_reg |= AR5K_BCR_AP;
break;
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
(ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_PWR_SV : 0);
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
(ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_NO_PSPOLL : 0);
@ -649,7 +649,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
* Set the additional timers by mode
*/
switch (ah->ah_op_mode) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
if (ah->ah_version == AR5K_AR5210) {
timer1 = 0xffffffff;
timer2 = 0xffffffff;

View File

@ -399,7 +399,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
/*
* Main reset function
*/
int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
struct ieee80211_channel *channel, bool change_channel)
{
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;

View File

@ -798,10 +798,11 @@ struct ath_hal {
struct ath9k_channel *ah_curchan;
u32 ah_nchan;
u16 ah_rfsilent;
bool ah_rfkillEnabled;
bool ah_isPciExpress;
u16 ah_txTrigLevel;
u16 ah_rfsilent;
u32 ah_rfkill_gpio;
u32 ah_rfkill_polarity;
#ifndef ATH_NF_PER_CHAN
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
@ -1003,4 +1004,6 @@ bool ath9k_get_channel_edges(struct ath_hal *ah,
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
u32 ah_signal_type);
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
#endif

View File

@ -40,6 +40,7 @@
#include <asm/page.h>
#include <net/mac80211.h>
#include <linux/leds.h>
#include <linux/rfkill.h>
#include "ath9k.h"
#include "rc.h"
@ -823,6 +824,15 @@ struct ath_led {
bool registered;
};
/* Rfkill */
#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */
struct ath_rfkill {
struct rfkill *rfkill;
struct delayed_work rfkill_poll;
char rfkill_name[32];
};
/********************/
/* Main driver core */
/********************/
@ -906,6 +916,9 @@ struct ath_ht_info {
#define SC_OP_PROTECT_ENABLE BIT(8)
#define SC_OP_RXFLUSH BIT(9)
#define SC_OP_LED_ASSOCIATED BIT(10)
#define SC_OP_RFKILL_REGISTERED BIT(11)
#define SC_OP_RFKILL_SW_BLOCKED BIT(12)
#define SC_OP_RFKILL_HW_BLOCKED BIT(13)
struct ath_softc {
struct ieee80211_hw *hw;
@ -1015,6 +1028,9 @@ struct ath_softc {
struct ath_led assoc_led;
struct ath_led tx_led;
struct ath_led rx_led;
/* Rfkill */
struct ath_rfkill rf_kill;
};
int ath_init(u16 devid, struct ath_softc *sc);

View File

@ -2821,7 +2821,38 @@ void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
AR_GPIO_BIT(gpio));
}
static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
/*
* Configure GPIO Input lines
*/
void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio)
{
u32 gpio_shift;
ASSERT(gpio < ah->ah_caps.num_gpio_pins);
gpio_shift = gpio << 1;
REG_RMW(ah,
AR_GPIO_OE_OUT,
(AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
(AR_GPIO_OE_OUT_DRV << gpio_shift));
}
#ifdef CONFIG_RFKILL
static void ath9k_enable_rfkill(struct ath_hal *ah)
{
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
AR_GPIO_INPUT_MUX2_RFSILENT);
ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio);
REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
}
#endif
u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
{
if (gpio >= ah->ah_caps.num_gpio_pins)
return 0xffffffff;
@ -3034,17 +3065,17 @@ static bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
#ifdef CONFIG_RFKILL
ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT);
if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
ahp->ah_gpioSelect =
ah->ah_rfkill_gpio =
MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
ahp->ah_polarity =
ah->ah_rfkill_polarity =
MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
ath9k_hw_setcapability(ah, ATH9K_CAP_RFSILENT, 1, true,
NULL);
pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
}
#endif
if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
(ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
@ -5961,6 +5992,10 @@ bool ath9k_hw_reset(struct ath_hal *ah,
ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode);
ath9k_hw_init_qos(ah);
#ifdef CONFIG_RFKILL
if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
ath9k_enable_rfkill(ah);
#endif
ath9k_hw_init_user_settings(ah);
REG_WRITE(ah, AR_STA_ID1,
@ -6490,31 +6525,6 @@ ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask)
return true;
}
#ifdef CONFIG_ATH9K_RFKILL
static void ath9k_enable_rfkill(struct ath_hal *ah)
{
struct ath_hal_5416 *ahp = AH5416(ah);
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
AR_GPIO_INPUT_MUX2_RFSILENT);
ath9k_hw_cfg_gpio_input(ah, ahp->ah_gpioSelect);
REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
if (ahp->ah_gpioBit == ath9k_hw_gpio_get(ah, ahp->ah_gpioSelect)) {
ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect,
!ahp->ah_gpioBit);
} else {
ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect,
ahp->ah_gpioBit);
}
}
#endif
void
ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
u16 assocId)

File diff suppressed because it is too large Load Diff

View File

@ -1825,7 +1825,7 @@ static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta)
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
for (i = 0; i < sband->n_bitrates; i++) {
if (sta->supp_rates[local->hw.conf.channel->band] & BIT(i)) {
if (sta->sta.supp_rates[local->hw.conf.channel->band] & BIT(i)) {
rc_priv->neg_rates.rs_rates[j]
= (sband->bitrates[i].bitrate * 2) / 10;
j++;
@ -2039,7 +2039,6 @@ static void ath_rate_init(void *priv, void *priv_sta,
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
sta->txrate_idx = rate_lowest_index(local, sband, sta);
ath_setup_rates(local, sta);
if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {

View File

@ -569,7 +569,7 @@ struct b43_key {
#define B43_QOS_VOICE B43_QOS_PARAMS(3)
/* QOS parameter hardware data structure offsets. */
#define B43_NR_QOSPARAMS 22
#define B43_NR_QOSPARAMS 16
enum {
B43_QOSPARAM_TXOP = 0,
B43_QOSPARAM_CWMIN,

View File

@ -1244,13 +1244,13 @@ generate_new:
static void handle_irq_tbtt_indication(struct b43_wldev *dev)
{
if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) {
if (b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) {
///TODO: PS TBTT
} else {
if (1 /*FIXME: the last PSpoll frame was sent successfully */ )
b43_power_saving_ctl_bits(dev, 0);
}
if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
dev->dfq_valid = 1;
}
@ -1599,8 +1599,8 @@ static void handle_irq_beacon(struct b43_wldev *dev)
struct b43_wl *wl = dev->wl;
u32 cmd, beacon0_valid, beacon1_valid;
if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP) &&
!b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT))
if (!b43_is_mode(wl, NL80211_IFTYPE_AP) &&
!b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
return;
/* This is the bottom half of the asynchronous beacon update. */
@ -2568,10 +2568,10 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
ctl &= ~B43_MACCTL_BEACPROMISC;
ctl |= B43_MACCTL_INFRA;
if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT))
if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
ctl |= B43_MACCTL_AP;
else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC))
ctl &= ~B43_MACCTL_INFRA;
if (wl->filter_flags & FIF_CONTROL)
@ -3406,8 +3406,8 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
phy->ops->set_rx_antenna(dev, antenna);
/* Update templates for AP/mesh mode. */
if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT))
if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
b43_set_beacon_int(dev, conf->beacon_int);
if (!!conf->radio_enabled != phy->radio_on) {
@ -3595,14 +3595,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
else
memset(wl->bssid, 0, ETH_ALEN);
if (b43_status(dev) >= B43_STAT_INITIALIZED) {
if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) {
if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) {
B43_WARN_ON(vif->type != wl->if_type);
if (conf->changed & IEEE80211_IFCC_SSID)
b43_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->changed & IEEE80211_IFCC_BEACON)
b43_update_templates(wl);
} else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
} else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
if (conf->changed & IEEE80211_IFCC_BEACON)
b43_update_templates(wl);
}
@ -3903,7 +3903,7 @@ static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
pu_delay = 3700;
else
pu_delay = 1050;
if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle)
pu_delay = 500;
if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
pu_delay = max(pu_delay, (u16)2400);
@ -3917,7 +3917,7 @@ static void b43_set_pretbtt(struct b43_wldev *dev)
u16 pretbtt;
/* The time value is in microseconds. */
if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) {
if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) {
pretbtt = 2;
} else {
if (dev->phy.type == B43_PHYTYPE_A)
@ -4084,11 +4084,11 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
/* TODO: allow WDS/AP devices to coexist */
if (conf->type != IEEE80211_IF_TYPE_AP &&
conf->type != IEEE80211_IF_TYPE_MESH_POINT &&
conf->type != IEEE80211_IF_TYPE_STA &&
conf->type != IEEE80211_IF_TYPE_WDS &&
conf->type != IEEE80211_IF_TYPE_IBSS)
if (conf->type != NL80211_IFTYPE_AP &&
conf->type != NL80211_IFTYPE_MESH_POINT &&
conf->type != NL80211_IFTYPE_STATION &&
conf->type != NL80211_IFTYPE_WDS &&
conf->type != NL80211_IFTYPE_ADHOC)
return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
@ -4234,7 +4234,8 @@ out_unlock:
return err;
}
static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, bool set)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
unsigned long flags;
@ -4249,7 +4250,7 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
static void b43_op_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd notify_cmd,
const u8 *addr)
struct ieee80211_sta *sta)
{
struct b43_wl *wl = hw_to_b43_wl(hw);

View File

@ -162,7 +162,7 @@ void b43_phy_lock(struct b43_wldev *dev)
#endif
B43_WARN_ON(dev->dev->id.revision < 3);
if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
}
@ -174,7 +174,7 @@ void b43_phy_unlock(struct b43_wldev *dev)
#endif
B43_WARN_ON(dev->dev->id.revision < 3);
if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, 0);
}

View File

@ -888,13 +888,13 @@ generate_new:
static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev)
{
if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) {
if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) {
/* TODO: PS TBTT */
} else {
if (1/*FIXME: the last PSpoll frame was sent successfully */)
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
dev->dfq_valid = 1;
}
@ -1201,7 +1201,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
struct b43legacy_wl *wl = dev->wl;
u32 cmd;
if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
return;
/* This is the bottom half of the asynchronous beacon update. */
@ -1936,9 +1936,9 @@ static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev)
ctl &= ~B43legacy_MACCTL_BEACPROMISC;
ctl |= B43legacy_MACCTL_INFRA;
if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
ctl |= B43legacy_MACCTL_AP;
else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))
ctl &= ~B43legacy_MACCTL_INFRA;
if (wl->filter_flags & FIF_CONTROL)
@ -2646,7 +2646,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
b43legacy_mgmtframe_txantenna(dev, antenna_tx);
/* Update templates for AP mode. */
if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
b43legacy_set_beacon_int(dev, conf->beacon_int);
@ -2733,12 +2733,12 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
else
memset(wl->bssid, 0, ETH_ALEN);
if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
B43legacy_WARN_ON(vif->type != IEEE80211_IF_TYPE_AP);
if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) {
B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP);
b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->changed & IEEE80211_IFCC_BEACON)
b43legacy_update_templates(wl);
} else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
} else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
if (conf->changed & IEEE80211_IFCC_BEACON)
b43legacy_update_templates(wl);
}
@ -3020,7 +3020,7 @@ static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
bool idle) {
u16 pu_delay = 1050;
if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle)
pu_delay = 500;
if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
pu_delay = max(pu_delay, (u16)2400);
@ -3035,7 +3035,7 @@ static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
u16 pretbtt;
/* The time value is in microseconds. */
if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
pretbtt = 2;
else
pretbtt = 250;
@ -3259,10 +3259,10 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
/* TODO: allow WDS/AP devices to coexist */
if (conf->type != IEEE80211_IF_TYPE_AP &&
conf->type != IEEE80211_IF_TYPE_STA &&
conf->type != IEEE80211_IF_TYPE_WDS &&
conf->type != IEEE80211_IF_TYPE_IBSS)
if (conf->type != NL80211_IFTYPE_AP &&
conf->type != NL80211_IFTYPE_STATION &&
conf->type != NL80211_IFTYPE_WDS &&
conf->type != NL80211_IFTYPE_ADHOC)
return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
@ -3403,7 +3403,7 @@ out_unlock:
}
static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
int aid, int set)
struct ieee80211_sta *sta, bool set)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;

View File

@ -103,7 +103,7 @@ void b43legacy_phy_lock(struct b43legacy_wldev *dev)
if (dev->dev->id.revision < 3) {
b43legacy_mac_suspend(dev);
} else {
if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, 1);
}
}
@ -118,7 +118,7 @@ void b43legacy_phy_unlock(struct b43legacy_wldev *dev)
if (dev->dev->id.revision < 3) {
b43legacy_mac_enable(dev);
} else {
if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
}

View File

@ -65,6 +65,9 @@ struct iwl3945_rs_sta {
u8 ibss_sta_added;
struct timer_list rate_scale_flush;
struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
/* used to be in sta_info */
int last_txrate_idx;
};
static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = {
@ -319,6 +322,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
static void rs_rate_init(void *priv_rate, void *priv_sta,
struct ieee80211_local *local, struct sta_info *sta)
{
struct iwl3945_rs_sta *rs_sta = (void *)sta->rate_ctrl_priv;
int i;
IWL_DEBUG_RATE("enter\n");
@ -329,17 +333,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
* after assoc.. */
for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) {
sta->txrate_idx = i;
if (sta->sta.supp_rates[local->hw.conf.channel->band] & (1 << i)) {
rs_sta->last_txrate_idx = i;
break;
}
}
sta->last_txrate_idx = sta->txrate_idx;
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
IWL_DEBUG_RATE("leave\n");
}
@ -674,15 +676,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
return;
}
rate_mask = sta->supp_rates[sband->band];
index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
rs_sta = (void *)sta->rate_ctrl_priv;
rate_mask = sta->sta.supp_rates[sband->band];
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
if (sband->band == IEEE80211_BAND_5GHZ)
rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
rs_sta = (void *)sta->rate_ctrl_priv;
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!rs_sta->ibss_sta_added) {
u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
@ -803,17 +805,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
out:
sta->last_txrate_idx = index;
rs_sta->last_txrate_idx = index;
if (sband->band == IEEE80211_BAND_5GHZ)
sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
else
sta->txrate_idx = sta->last_txrate_idx;
sel->rate_idx = rs_sta->last_txrate_idx;
rcu_read_unlock();
IWL_DEBUG_RATE("leave: %d\n", index);
sel->rate_idx = sta->txrate_idx;
}
static struct rate_control_ops rs_ops = {

View File

@ -520,10 +520,10 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv,
/* Filter incoming packets to determine if they are targeted toward
* this network, discarding packets coming from ourselves */
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */
case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */
/* packets to our IBSS update information */
return !compare_ether_addr(header->addr3, priv->bssid);
case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
/* packets to our IBSS update information */
return !compare_ether_addr(header->addr2, priv->bssid);
default:
@ -807,7 +807,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
priv->stations[sta_id].current_rate.rate_n_flags = rate;
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
(sta_id != priv->hw_setting.bcast_sta_id) &&
(sta_id != IWL_MULTICAST_ID))
priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate;

View File

@ -851,7 +851,7 @@ struct iwl3945_priv {
/* eeprom */
struct iwl3945_eeprom eeprom;
enum ieee80211_if_types iw_mode;
enum nl80211_iftype iw_mode;
struct sk_buff *ibss_beacon;

View File

@ -1569,6 +1569,8 @@ struct iwl_cfg iwl5350_agn_cfg = {
.mod_params = &iwl50_mod_params,
};
MODULE_FIRMWARE("iwlwifi-5000" IWL5000_UCODE_API ".ucode");
module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
MODULE_PARM_DESC(disable50,
"manually disable the 50XX radio (default 0 [radio on])");

View File

@ -163,6 +163,9 @@ struct iwl_lq_sta {
u32 dbg_fixed_rate;
#endif
struct iwl_priv *drv;
/* used to be in sta_info */
int last_txrate_idx;
};
static void rs_rate_scale_perform(struct iwl_priv *priv,
@ -356,18 +359,12 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid,
struct sta_info *sta)
{
unsigned long state;
DECLARE_MAC_BUF(mac);
spin_lock_bh(&sta->lock);
state = sta->ampdu_mlme.tid_state_tx[tid];
spin_unlock_bh(&sta->lock);
if (state == HT_AGG_STATE_IDLE &&
rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
print_mac(mac, sta->addr), tid);
ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
print_mac(mac, sta->sta.addr), tid);
ieee80211_start_tx_ba_session(priv->hw, sta->sta.addr, tid);
}
}
@ -821,7 +818,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!lq_sta->ibss_sta_added)
goto out;
@ -1151,10 +1148,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
s8 is_green = lq_sta->is_green;
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
!sta->ht_info.ht_supported)
!sta->sta.ht_info.ht_supported)
return -1;
if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
if (((sta->sta.ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
== WLAN_HT_CAP_SM_PS_STATIC)
return -1;
@ -1219,7 +1216,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
s32 rate;
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
!sta->ht_info.ht_supported)
!sta->sta.ht_info.ht_supported)
return -1;
IWL_DEBUG_RATE("LQ: try to switch to SISO\n");
@ -1728,7 +1725,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
return;
lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
lq_sta->supp_rates = sta->sta.supp_rates[lq_sta->band];
tid = rs_tl_add_packet(lq_sta, hdr);
@ -1746,7 +1743,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
is_green = lq_sta->is_green;
/* current tx rate */
index = sta->last_txrate_idx;
index = lq_sta->last_txrate_idx;
IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index,
tbl->lq_type);
@ -2059,15 +2056,7 @@ lq_update:
out:
tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green);
i = index;
sta->last_txrate_idx = i;
/* sta->txrate_idx is an index to A mode rates which start
* at IWL_FIRST_OFDM_RATE
*/
if (lq_sta->band == IEEE80211_BAND_5GHZ)
sta->txrate_idx = i - IWL_FIRST_OFDM_RATE;
else
sta->txrate_idx = i;
lq_sta->last_txrate_idx = i;
return;
}
@ -2090,10 +2079,10 @@ static void rs_initialize_lq(struct iwl_priv *priv,
goto out;
lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
i = sta->last_txrate_idx;
i = lq_sta->last_txrate_idx;
if ((lq_sta->lq.sta_id == 0xff) &&
(priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
(priv->iw_mode == NL80211_IFTYPE_ADHOC))
goto out;
valid_tx_ant = priv->hw_params.valid_tx_ant;
@ -2161,9 +2150,9 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
}
lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
i = sta->last_txrate_idx;
i = lq_sta->last_txrate_idx;
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!lq_sta->ibss_sta_added) {
u8 sta_id = iwl_find_station(priv, hdr->addr1);
DECLARE_MAC_BUF(mac);
@ -2230,8 +2219,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
lq_sta->flush_timer = 0;
lq_sta->supp_rates = sta->supp_rates[sband->band];
sta->txrate_idx = 3;
lq_sta->supp_rates = sta->sta.supp_rates[sband->band];
for (j = 0; j < LQ_SIZE; j++)
for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
@ -2243,18 +2231,18 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
* after assoc.. */
lq_sta->ibss_sta_added = 0;
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
u8 sta_id = iwl_find_station(priv, sta->addr);
if (priv->iw_mode == NL80211_IFTYPE_AP) {
u8 sta_id = iwl_find_station(priv, sta->sta.addr);
DECLARE_MAC_BUF(mac);
/* for IBSS the call are from tasklet */
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, sta->addr));
print_mac(mac, sta->sta.addr));
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, sta->addr));
sta_id = iwl_add_station_flags(priv, sta->addr,
print_mac(mac, sta->sta.addr));
sta_id = iwl_add_station_flags(priv, sta->sta.addr,
0, CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
@ -2266,14 +2254,14 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
}
/* Find highest tx rate supported by hardware and destination station */
lq_sta->last_txrate_idx = 3;
for (i = 0; i < sband->n_bitrates; i++)
if (sta->supp_rates[sband->band] & BIT(i))
sta->txrate_idx = i;
if (sta->sta.supp_rates[sband->band] & BIT(i))
lq_sta->last_txrate_idx = i;
sta->last_txrate_idx = sta->txrate_idx;
/* For MODE_IEEE80211A, skip over cck rates in global rate table */
if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_dup = 0;
lq_sta->is_green = rs_use_green(priv, conf);

View File

@ -337,7 +337,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
/* If we have set the ASSOC_MSK and we are in BSS mode then
* add the IWL_AP_ID to the station rate table */
if (new_assoc) {
if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
if (priv->iw_mode == NL80211_IFTYPE_STATION) {
ret = iwl_rxon_add_station(priv,
priv->active_rxon.bssid_addr, 1);
if (ret == IWL_INVALID_STATION) {
@ -448,8 +448,8 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
const u8 *dest, int left)
{
if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
(priv->iw_mode != IEEE80211_IF_TYPE_AP)))
((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
(priv->iw_mode != NL80211_IFTYPE_AP)))
return 0;
if (priv->ibss_beacon->len > left)
@ -672,7 +672,7 @@ static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
beacon_int = priv->beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
if (priv->iw_mode == NL80211_IFTYPE_STATION) {
if (beacon_int == 0) {
priv->rxon_timing.beacon_interval = cpu_to_le16(100);
priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
@ -721,7 +721,7 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv,
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
@ -740,23 +740,23 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
break;
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
break;
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
RXON_FILTER_ACCEPT_GRP_MSK;
break;
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
@ -785,7 +785,7 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
* in some case A channels are all non IBSS
* in this case force B/G channel
*/
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!(is_channel_ibss(ch_info)))
ch_info = &priv->channel_info[0];
@ -1182,7 +1182,7 @@ static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
queue_work(priv->workqueue, &priv->beacon_update);
}
@ -2388,7 +2388,7 @@ static void iwl4965_bg_set_monitor(struct work_struct *work)
mutex_lock(&priv->mutex);
ret = iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR);
ret = iwl4965_set_mode(priv, NL80211_IFTYPE_MONITOR);
if (ret) {
if (ret == -EAGAIN)
@ -2469,7 +2469,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
DECLARE_MAC_BUF(mac);
unsigned long flags;
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
return;
}
@ -2524,7 +2524,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
}
@ -2532,10 +2532,10 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
iwl4965_commit_rxon(priv);
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
break;
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
/* assume default assoc id */
priv->assoc_id = 1;
@ -2551,7 +2551,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
break;
}
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->assoc_station_added = 1;
spin_lock_irqsave(&priv->lock, flags);
@ -2828,7 +2828,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
goto out;
}
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
!is_channel_ibss(ch_info)) {
IWL_ERROR("channel %d in band %d not IBSS channel\n",
conf->channel->hw_value, conf->channel->band);
@ -2943,7 +2943,7 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
}
@ -2982,7 +2982,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
return 0;
}
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
conf->changed & IEEE80211_IFCC_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
@ -2992,7 +2992,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
return rc;
}
if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
@ -3015,7 +3015,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
!(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
*/
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (!conf->bssid) {
conf->bssid = priv->mac_addr;
memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
@ -3050,11 +3050,11 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
* to verify) - jpk */
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl4965_config_ap(priv);
else {
rc = iwl4965_commit_rxon(priv);
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
iwl_rxon_add_station(
priv, priv->active_rxon.bssid_addr, 1);
}
@ -3090,7 +3090,7 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw,
if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
IEEE80211_IF_TYPE_MNTR,
NL80211_IFTYPE_MONITOR,
changed_flags, *total_flags);
/* queue work 'cuz mac80211 is holding a lock which
* prevents us from issuing (synchronous) f/w cmds */
@ -3204,7 +3204,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len)
goto out_unlock;
}
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { /* APs don't scan */
if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
ret = -EIO;
IWL_ERROR("ERROR: APs don't scan\n");
goto out_unlock;
@ -3329,7 +3329,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
* in 1X mode.
* In legacy wep mode, we use another host command to the uCode */
if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id &&
priv->iw_mode != IEEE80211_IF_TYPE_AP) {
priv->iw_mode != NL80211_IFTYPE_AP) {
if (cmd == SET_KEY)
is_default_wep_key = !priv->key_mapping_key;
else
@ -3400,7 +3400,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
priv->qos_data.qos_active = 1;
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl_activate_qos(priv, 1);
else if (priv->assoc_id && iwl_is_associated(priv))
iwl_activate_qos(priv, 0);
@ -3413,13 +3413,13 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 *ssn)
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
struct iwl_priv *priv = hw->priv;
DECLARE_MAC_BUF(mac);
IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
print_mac(mac, addr), tid);
print_mac(mac, sta->addr), tid);
if (!(priv->cfg->sku & IWL_SKU_N))
return -EACCES;
@ -3427,16 +3427,16 @@ static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
IWL_DEBUG_HT("start Rx\n");
return iwl_rx_agg_start(priv, addr, tid, *ssn);
return iwl_rx_agg_start(priv, sta->addr, tid, *ssn);
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT("stop Rx\n");
return iwl_rx_agg_stop(priv, addr, tid);
return iwl_rx_agg_stop(priv, sta->addr, tid);
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT("start Tx\n");
return iwl_tx_agg_start(priv, addr, tid, ssn);
return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT("stop Tx\n");
return iwl_tx_agg_stop(priv, addr, tid);
return iwl_tx_agg_stop(priv, sta->addr, tid);
default:
IWL_DEBUG_HT("unknown\n");
return -EINVAL;
@ -3518,7 +3518,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
priv->beacon_int = priv->hw->conf.beacon_int;
priv->timestamp = 0;
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
if ((priv->iw_mode == NL80211_IFTYPE_STATION))
priv->beacon_int = 0;
spin_unlock_irqrestore(&priv->lock, flags);
@ -3532,7 +3532,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode != NL80211_IFTYPE_AP) {
iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl4965_commit_rxon(priv);
@ -3541,7 +3541,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
iwl_power_update_mode(priv, 0);
/* Per mac80211.h: This is only used in IBSS mode... */
if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
/* switch to CAM during association period.
* the ucode will block any association/authentication
@ -3580,7 +3580,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
return -EIO;
}
if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not IBSS\n");
mutex_unlock(&priv->mutex);
return -EIO;
@ -4506,7 +4506,10 @@ static struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
{IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)},
{IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)},
{IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)},
/* 5350 WiFi/WiMax */
{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)},
{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)},
{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)},
#endif /* CONFIG_IWL5000 */
{0}
};

View File

@ -306,14 +306,14 @@ void iwl_reset_qos(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
if (!(priv->active_rate & 0xfff0)) {
cw_min = 31;
is_legacy = 1;
}
} else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
} else if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
@ -932,7 +932,7 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->ieee_rates = NULL;
priv->band = IEEE80211_BAND_2GHZ;
priv->iw_mode = IEEE80211_IF_TYPE_STA;
priv->iw_mode = NL80211_IFTYPE_STATION;
priv->use_ant_b_for_management_frame = 1; /* start with ant B */
priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
@ -1396,7 +1396,7 @@ void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
iwl_scan_cancel(priv);
/* FIXME: This is a workaround for AP */
if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode != NL80211_IFTYPE_AP) {
spin_lock_irqsave(&priv->lock, flags);
iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_SW_BIT_RFKILL);

View File

@ -954,7 +954,7 @@ struct iwl_priv {
u8 *eeprom;
struct iwl_eeprom_calib_info *calib_info;
enum ieee80211_if_types iw_mode;
enum nl80211_iftype iw_mode;
struct sk_buff *ibss_beacon;

View File

@ -290,7 +290,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
final_mode = setting->critical_power_setting;
/* driver only support CAM for non STA network */
if (priv->iw_mode != IEEE80211_IF_TYPE_STA)
if (priv->iw_mode != NL80211_IFTYPE_STATION)
final_mode = IWL_POWER_MODE_CAM;
if (!iwl_is_rfkill(priv) && !setting->power_disabled &&

View File

@ -1026,10 +1026,10 @@ static int iwl_is_network_packet(struct iwl_priv *priv,
/* Filter incoming packets to determine if they are targeted toward
* this network, discarding packets coming from ourselves */
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */
case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */
/* packets to our IBSS update information */
return !compare_ether_addr(header->addr3, priv->bssid);
case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
/* packets to our IBSS update information */
return !compare_ether_addr(header->addr2, priv->bssid);
default:
@ -1169,7 +1169,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
rx_status.flag |= RX_FLAG_SHORTPRE;
/* Take shortcut when only in monitor mode */
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
iwl_pass_packet_to_mac80211(priv, include_phy,
rxb, &rx_status);
return;
@ -1186,7 +1186,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
switch (fc & IEEE80211_FCTL_FTYPE) {
case IEEE80211_FTYPE_MGMT:
case IEEE80211_FTYPE_DATA:
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
header->addr2);
/* fall through */

View File

@ -463,7 +463,7 @@ void iwl_init_scan_params(struct iwl_priv *priv)
int iwl_scan_initiate(struct iwl_priv *priv)
{
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("APs don't scan.\n");
return 0;
}
@ -868,7 +868,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
scan->tx_cmd.len = cpu_to_le16(cmd_len);
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
scan->filter_flags = RXON_FILTER_PROMISC_MSK;
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |

View File

@ -47,8 +47,8 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
unsigned long flags;
DECLARE_MAC_BUF(mac);
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) ||
(priv->iw_mode == IEEE80211_IF_TYPE_AP))
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
(priv->iw_mode == NL80211_IFTYPE_AP))
start = IWL_STA_ID;
if (is_broadcast_ether_addr(addr))
@ -74,7 +74,7 @@ EXPORT_SYMBOL(iwl_find_station);
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
{
if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
if (priv->iw_mode == NL80211_IFTYPE_STATION) {
return IWL_AP_ID;
} else {
u8 *da = ieee80211_get_DA(hdr);
@ -286,7 +286,7 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
/* BCAST station and IBSS stations do not work in HT mode */
if (sta_id != priv->hw_params.bcast_sta_id &&
priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
priv->iw_mode != NL80211_IFTYPE_ADHOC)
iwl_set_ht_add_station(priv, sta_id, ht_info);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
@ -817,7 +817,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
};
if ((lq->sta_id == 0xFF) &&
(priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
(priv->iw_mode == NL80211_IFTYPE_ADHOC))
return -EINVAL;
if (lq->sta_id == 0xFF)
@ -904,7 +904,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
if ((is_ap) &&
(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
(priv->iw_mode == IEEE80211_IF_TYPE_STA))
(priv->iw_mode == NL80211_IFTYPE_STATION))
sta_id = iwl_add_station_flags(priv, addr, is_ap,
0, cur_ht_config);
else
@ -938,11 +938,11 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/* If we are a client station in a BSS network, use the special
* AP station entry (that's the only station we communicate with) */
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
return IWL_AP_ID;
/* If we are an AP, then find the station, or use BCAST */
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
sta_id = iwl_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
@ -950,7 +950,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/* If this frame is going out to an IBSS network, find the station,
* or create a new station table entry */
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
sta_id = iwl_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
@ -970,7 +970,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/* If we are in monitor mode, use BCAST. This is required for
* packet injection. */
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
return priv->hw_params.bcast_sta_id;
default:

View File

@ -814,10 +814,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* drop all data frame if we are not associated */
if (ieee80211_is_data(fc) &&
(priv->iw_mode != IEEE80211_IF_TYPE_MNTR ||
(priv->iw_mode != NL80211_IFTYPE_MONITOR ||
!(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */
(!iwl_is_associated(priv) ||
((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) ||
((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) ||
!priv->assoc_station_added)) {
IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
goto drop_unlock;

View File

@ -1160,7 +1160,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
/* If we have set the ASSOC_MSK and we are in BSS mode then
* add the IWL_AP_ID to the station rate table */
if (iwl3945_is_associated(priv) &&
(priv->iw_mode == IEEE80211_IF_TYPE_STA))
(priv->iw_mode == NL80211_IFTYPE_STATION))
if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0)
== IWL_INVALID_STATION) {
IWL_ERROR("Error adding AP address for transmit.\n");
@ -1447,8 +1447,8 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
{
if (!iwl3945_is_associated(priv) || !priv->ibss_beacon ||
((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
(priv->iw_mode != IEEE80211_IF_TYPE_AP)))
((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
(priv->iw_mode != NL80211_IFTYPE_AP)))
return 0;
if (priv->ibss_beacon->len > left)
@ -1746,14 +1746,14 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
if (!(priv->active_rate & 0xfff0)) {
cw_min = 31;
is_legacy = 1;
}
} else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
} else if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
@ -2120,7 +2120,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
beacon_int = priv->beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
if (priv->iw_mode == NL80211_IFTYPE_STATION) {
if (beacon_int == 0) {
priv->rxon_timing.beacon_interval = cpu_to_le16(100);
priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
@ -2156,7 +2156,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
{
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("APs don't scan.\n");
return 0;
}
@ -2218,7 +2218,7 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
@ -2237,23 +2237,23 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
break;
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
break;
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
RXON_FILTER_ACCEPT_GRP_MSK;
break;
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
@ -2282,7 +2282,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
* in some case A channels are all non IBSS
* in this case force B/G channel
*/
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!(is_channel_ibss(ch_info)))
ch_info = &priv->channel_info[0];
@ -2302,7 +2302,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
{
if (mode == IEEE80211_IF_TYPE_IBSS) {
if (mode == NL80211_IFTYPE_ADHOC) {
const struct iwl3945_channel_info *ch_info;
ch_info = iwl3945_get_channel_info(priv,
@ -2469,11 +2469,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
/* If we are a client station in a BSS network, use the special
* AP station entry (that's the only station we communicate with) */
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
return IWL_AP_ID;
/* If we are an AP, then find the station, or use BCAST */
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
@ -2481,7 +2481,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
/* If this frame is going out to an IBSS network, find the station,
* or create a new station table entry */
case IEEE80211_IF_TYPE_IBSS: {
case NL80211_IFTYPE_ADHOC: {
DECLARE_MAC_BUF(mac);
/* Create new station table entry */
@ -2502,7 +2502,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
}
/* If we are in monitor mode, use BCAST. This is required for
* packet injection. */
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
return priv->hw_setting.bcast_sta_id;
default:
@ -2565,9 +2565,9 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
/* drop all data frame if we are not associated */
if (ieee80211_is_data(fc) &&
(priv->iw_mode != IEEE80211_IF_TYPE_MNTR) && /* packet injection */
(priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */
(!iwl3945_is_associated(priv) ||
((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id))) {
((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
goto drop_unlock;
}
@ -2806,7 +2806,7 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
if (disable_radio) {
iwl3945_scan_cancel(priv);
/* FIXME: This is a workaround for AP */
if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode != NL80211_IFTYPE_AP) {
spin_lock_irqsave(&priv->lock, flags);
iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_SW_BIT_RFKILL);
@ -3161,7 +3161,7 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
queue_work(priv->workqueue, &priv->beacon_update);
}
@ -6059,7 +6059,7 @@ static void iwl3945_bg_set_monitor(struct work_struct *work)
if (!iwl3945_is_ready(priv))
IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
else
if (iwl3945_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0)
if (iwl3945_set_mode(priv, NL80211_IFTYPE_MONITOR) != 0)
IWL_ERROR("iwl3945_set_mode() failed\n");
mutex_unlock(&priv->mutex);
@ -6248,7 +6248,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
/* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv);
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
scan->filter_flags = RXON_FILTER_PROMISC_MSK;
scan->channel_count =
@ -6323,7 +6323,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
struct ieee80211_conf *conf = NULL;
DECLARE_MAC_BUF(mac);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
return;
}
@ -6372,7 +6372,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
else
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
}
@ -6380,11 +6380,11 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
iwl3945_commit_rxon(priv);
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
break;
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
/* clear out the station table */
iwl3945_clear_stations_table(priv);
@ -6754,7 +6754,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
priv->staging_rxon.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
}
@ -6791,7 +6791,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
}
/* handle this temporarily here */
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
conf->changed & IEEE80211_IFCC_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
@ -6803,7 +6803,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
/* XXX: this MUST use conf->mac_addr */
if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
@ -6826,7 +6826,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
!(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
*/
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (!conf->bssid) {
conf->bssid = priv->mac_addr;
memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
@ -6861,11 +6861,11 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
* to verify) - jpk */
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl3945_config_ap(priv);
else {
rc = iwl3945_commit_rxon(priv);
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
iwl3945_add_station(priv,
priv->active_rxon.bssid_addr, 1, 0);
}
@ -6901,7 +6901,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
IEEE80211_IF_TYPE_MNTR,
NL80211_IFTYPE_MONITOR,
changed_flags, *total_flags);
/* queue work 'cuz mac80211 is holding a lock which
* prevents us from issuing (synchronous) f/w cmds */
@ -7010,7 +7010,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
goto out_unlock;
}
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { /* APs don't scan */
if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
rc = -EIO;
IWL_ERROR("ERROR: APs don't scan\n");
goto out_unlock;
@ -7152,7 +7152,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
spin_unlock_irqrestore(&priv->lock, flags);
mutex_lock(&priv->mutex);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
if (priv->iw_mode == NL80211_IFTYPE_AP)
iwl3945_activate_qos(priv, 1);
else if (priv->assoc_id && iwl3945_is_associated(priv))
iwl3945_activate_qos(priv, 0);
@ -7239,7 +7239,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
priv->beacon_int = priv->hw->conf.beacon_int;
priv->timestamp1 = 0;
priv->timestamp0 = 0;
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
if ((priv->iw_mode == NL80211_IFTYPE_STATION))
priv->beacon_int = 0;
spin_unlock_irqrestore(&priv->lock, flags);
@ -7253,14 +7253,14 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
if (priv->iw_mode != NL80211_IFTYPE_AP) {
iwl3945_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwl3945_commit_rxon(priv);
}
/* Per mac80211.h: This is only used in IBSS mode... */
if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not in IBSS\n");
mutex_unlock(&priv->mutex);
@ -7289,7 +7289,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
return -EIO;
}
if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) {
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not IBSS\n");
mutex_unlock(&priv->mutex);
return -EIO;
@ -7996,7 +7996,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
IWL_DEBUG_INFO("Radio disabled.\n");
}
priv->iw_mode = IEEE80211_IF_TYPE_STA;
priv->iw_mode = NL80211_IFTYPE_STATION;
printk(KERN_INFO DRV_NAME
": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
@ -8376,6 +8376,8 @@ static void __exit iwl3945_exit(void)
iwl3945_rate_control_unregister();
}
MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode");
module_param_named(antenna, iwl3945_param_antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
module_param_named(disable, iwl3945_param_disable, int, 0444);

View File

@ -823,11 +823,7 @@ static int assoc_helper_mode(struct lbs_private *priv,
}
priv->mode = assoc_req->mode;
ret = lbs_prepare_and_send_command(priv,
CMD_802_11_SNMP_MIB,
0, CMD_OPTION_WAITFORRSP,
OID_802_11_INFRASTRUCTURE_MODE,
/* Shoot me now */ (void *) (size_t) assoc_req->mode);
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode);
done:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);

View File

@ -480,138 +480,103 @@ int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
return ret;
}
static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action)
/**
* @brief Set an SNMP MIB value
*
* @param priv A pointer to struct lbs_private structure
* @param oid The OID to set in the firmware
* @param val Value to set the OID to
*
* @return 0 on success, error on failure
*/
int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
{
struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
struct cmd_ds_802_11_snmp_mib cmd;
int ret;
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_802_11_RESET);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
reset->action = cpu_to_le16(cmd_action);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
struct cmd_ds_command *cmd,
int cmd_action,
int cmd_oid, void *pdata_buf)
{
struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib;
u8 ucTemp;
lbs_deb_enter(LBS_DEB_CMD);
lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
cmd->command = cpu_to_le16(CMD_802_11_SNMP_MIB);
cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
switch (cmd_oid) {
case OID_802_11_INFRASTRUCTURE_MODE:
{
u8 mode = (u8) (size_t) pdata_buf;
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
pSNMPMIB->bufsize = cpu_to_le16(sizeof(u8));
if (mode == IW_MODE_ADHOC) {
ucTemp = SNMP_MIB_VALUE_ADHOC;
} else {
/* Infra and Auto modes */
ucTemp = SNMP_MIB_VALUE_INFRA;
}
memmove(pSNMPMIB->value, &ucTemp, sizeof(u8));
memset(&cmd, 0, sizeof (cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
cmd.oid = cpu_to_le16((u16) oid);
switch (oid) {
case SNMP_MIB_OID_BSS_TYPE:
cmd.bufsize = cpu_to_le16(sizeof(u8));
cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1;
break;
}
case OID_802_11D_ENABLE:
{
u32 ulTemp;
pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
if (cmd_action == CMD_ACT_SET) {
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
ulTemp = *(u32 *)pdata_buf;
*((__le16 *)(pSNMPMIB->value)) =
cpu_to_le16((u16) ulTemp);
}
break;
}
case OID_802_11_FRAGMENTATION_THRESHOLD:
{
u32 ulTemp;
pSNMPMIB->oid = cpu_to_le16((u16) FRAGTHRESH_I);
if (cmd_action == CMD_ACT_GET) {
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
} else if (cmd_action == CMD_ACT_SET) {
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
ulTemp = *((u32 *) pdata_buf);
*((__le16 *)(pSNMPMIB->value)) =
cpu_to_le16((u16) ulTemp);
}
break;
}
case OID_802_11_RTS_THRESHOLD:
{
u32 ulTemp;
pSNMPMIB->oid = cpu_to_le16(RTSTHRESH_I);
if (cmd_action == CMD_ACT_GET) {
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
} else if (cmd_action == CMD_ACT_SET) {
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
ulTemp = *((u32 *)pdata_buf);
*(__le16 *)(pSNMPMIB->value) =
cpu_to_le16((u16) ulTemp);
}
break;
}
case OID_802_11_TX_RETRYCOUNT:
pSNMPMIB->oid = cpu_to_le16((u16) SHORT_RETRYLIM_I);
if (cmd_action == CMD_ACT_GET) {
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
} else if (cmd_action == CMD_ACT_SET) {
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
*((__le16 *)(pSNMPMIB->value)) =
cpu_to_le16((u16) priv->txretrycount);
}
case SNMP_MIB_OID_11D_ENABLE:
case SNMP_MIB_OID_FRAG_THRESHOLD:
case SNMP_MIB_OID_RTS_THRESHOLD:
case SNMP_MIB_OID_SHORT_RETRY_LIMIT:
case SNMP_MIB_OID_LONG_RETRY_LIMIT:
cmd.bufsize = cpu_to_le16(sizeof(u16));
*((__le16 *)(&cmd.value)) = cpu_to_le16(val);
break;
default:
lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid);
ret = -EINVAL;
goto out;
}
lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n",
le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val);
ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
out:
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
/**
* @brief Get an SNMP MIB value
*
* @param priv A pointer to struct lbs_private structure
* @param oid The OID to retrieve from the firmware
* @param out_val Location for the returned value
*
* @return 0 on success, error on failure
*/
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
{
struct cmd_ds_802_11_snmp_mib cmd;
int ret;
lbs_deb_enter(LBS_DEB_CMD);
memset(&cmd, 0, sizeof (cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_GET);
cmd.oid = cpu_to_le16(oid);
ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
if (ret)
goto out;
switch (le16_to_cpu(cmd.bufsize)) {
case sizeof(u8):
if (oid == SNMP_MIB_OID_BSS_TYPE) {
if (cmd.value[0] == 2)
*out_val = IW_MODE_ADHOC;
else
*out_val = IW_MODE_INFRA;
} else
*out_val = cmd.value[0];
break;
case sizeof(u16):
*out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
break;
default:
lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n",
oid, le16_to_cpu(cmd.bufsize));
break;
}
lbs_deb_cmd(
"SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
lbs_deb_cmd(
"SNMP_CMD: action 0x%x, oid 0x%x, oidsize 0x%x, value 0x%x\n",
le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
le16_to_cpu(pSNMPMIB->bufsize),
le16_to_cpu(*(__le16 *) pSNMPMIB->value));
lbs_deb_leave(LBS_DEB_CMD);
return 0;
out:
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
/**
@ -1419,19 +1384,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
break;
case CMD_802_11_RESET:
ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
break;
case CMD_802_11_AUTHENTICATE:
ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
break;
case CMD_802_11_SNMP_MIB:
ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
cmd_action, cmd_oid, pdata_buf);
break;
case CMD_MAC_REG_ACCESS:
case CMD_BBP_REG_ACCESS:
case CMD_RF_REG_ACCESS:

View File

@ -73,4 +73,8 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val);
#endif /* _LBS_CMD_H */

View File

@ -146,48 +146,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
return ret;
}
static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
u16 oid = le16_to_cpu(smib->oid);
u16 querytype = le16_to_cpu(smib->querytype);
lbs_deb_enter(LBS_DEB_CMD);
lbs_deb_cmd("SNMP_RESP: oid 0x%x, querytype 0x%x\n", oid,
querytype);
lbs_deb_cmd("SNMP_RESP: Buf size %d\n", le16_to_cpu(smib->bufsize));
if (querytype == CMD_ACT_GET) {
switch (oid) {
case FRAGTHRESH_I:
priv->fragthsd =
le16_to_cpu(*((__le16 *)(smib->value)));
lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
priv->fragthsd);
break;
case RTSTHRESH_I:
priv->rtsthsd =
le16_to_cpu(*((__le16 *)(smib->value)));
lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
priv->rtsthsd);
break;
case SHORT_RETRYLIM_I:
priv->txretrycount =
le16_to_cpu(*((__le16 *)(smib->value)));
lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
priv->rtsthsd);
break;
default:
break;
}
}
lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
static int lbs_ret_802_11_rssi(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
@ -258,10 +216,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
ret = lbs_ret_80211_associate(priv, resp);
break;
case CMD_RET(CMD_802_11_SNMP_MIB):
ret = lbs_ret_802_11_snmp_mib(priv, resp);
break;
case CMD_RET(CMD_802_11_SET_AFC):
case CMD_RET(CMD_802_11_GET_AFC):
spin_lock_irqsave(&priv->driver_lock, flags);
@ -271,7 +225,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
break;
case CMD_RET(CMD_802_11_RESET):
case CMD_RET(CMD_802_11_AUTHENTICATE):
case CMD_RET(CMD_802_11_BEACON_STOP):
break;

View File

@ -352,27 +352,6 @@ enum mv_ms_type {
MVMS_EVENT
};
/** SNMP_MIB_INDEX_e */
enum SNMP_MIB_INDEX_e {
DESIRED_BSSTYPE_I = 0,
OP_RATESET_I,
BCNPERIOD_I,
DTIMPERIOD_I,
ASSOCRSP_TIMEOUT_I,
RTSTHRESH_I,
SHORT_RETRYLIM_I,
LONG_RETRYLIM_I,
FRAGTHRESH_I,
DOT11D_I,
DOT11H_I,
MANUFID_I,
PRODID_I,
MANUF_OUI_I,
MANUF_NAME_I,
MANUF_PRODNAME_I,
MANUF_PRODVER_I,
};
/** KEY_TYPE_ID */
enum KEY_TYPE_ID {
KEY_TYPE_ID_WEP = 0,
@ -387,12 +366,6 @@ enum KEY_INFO_WPA {
KEY_INFO_WPA_ENABLED = 0x04
};
/** SNMP_MIB_VALUE_e */
enum SNMP_MIB_VALUE_e {
SNMP_MIB_VALUE_INFRA = 1,
SNMP_MIB_VALUE_ADHOC
};
/* Default values for fwt commands. */
#define FWT_DEFAULT_METRIC 0
#define FWT_DEFAULT_DIR 1

View File

@ -240,9 +240,6 @@ struct lbs_private {
uint16_t enablehwauto;
uint16_t ratebitmap;
u32 fragthsd;
u32 rtsthsd;
u8 txretrycount;
/** Tx-related variables (for single packet tx) */

View File

@ -9,17 +9,6 @@
#define DEFAULT_AD_HOC_CHANNEL 6
#define DEFAULT_AD_HOC_CHANNEL_A 36
/** IEEE 802.11 oids */
#define OID_802_11_SSID 0x00008002
#define OID_802_11_INFRASTRUCTURE_MODE 0x00008008
#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008009
#define OID_802_11_RTS_THRESHOLD 0x0000800A
#define OID_802_11_TX_ANTENNA_SELECTED 0x0000800D
#define OID_802_11_SUPPORTED_RATES 0x0000800E
#define OID_802_11_STATISTICS 0x00008012
#define OID_802_11_TX_RETRYCOUNT 0x0000801D
#define OID_802_11D_ENABLE 0x00008020
#define CMD_OPTION_WAITFORRSP 0x0002
/** Host command IDs */
@ -191,6 +180,19 @@
#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
#define CMD_WAKE_METHOD_GPIO 0x0002
/* Object IDs for CMD_802_11_SNMP_MIB */
#define SNMP_MIB_OID_BSS_TYPE 0x0000
#define SNMP_MIB_OID_OP_RATE_SET 0x0001
#define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */
#define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */
#define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */
#define SNMP_MIB_OID_RTS_THRESHOLD 0x0005
#define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006
#define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007
#define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008
#define SNMP_MIB_OID_11D_ENABLE 0x0009
#define SNMP_MIB_OID_11H_ENABLE 0x000A
/* Define action or option for CMD_BT_ACCESS */
enum cmd_bt_access_opts {
/* The bt commands start at 5 instead of 1 because the old dft commands

View File

@ -151,10 +151,6 @@ struct cmd_ds_get_hw_spec {
__le32 fwcapinfo;
} __attribute__ ((packed));
struct cmd_ds_802_11_reset {
__le16 action;
};
struct cmd_ds_802_11_subscribe_event {
struct cmd_header hdr;
@ -301,7 +297,9 @@ struct cmd_ds_802_11_get_stat {
};
struct cmd_ds_802_11_snmp_mib {
__le16 querytype;
struct cmd_header hdr;
__le16 action;
__le16 oid;
__le16 bufsize;
u8 value[128];
@ -717,11 +715,9 @@ struct cmd_ds_command {
union {
struct cmd_ds_802_11_ps_mode psmode;
struct cmd_ds_802_11_associate associate;
struct cmd_ds_802_11_reset reset;
struct cmd_ds_802_11_authenticate auth;
struct cmd_ds_802_11_get_stat gstat;
struct cmd_ds_802_3_get_stat gstat_8023;
struct cmd_ds_802_11_snmp_mib smib;
struct cmd_ds_802_11_rf_antenna rant;
struct cmd_ds_802_11_monitor_mode monitor;
struct cmd_ds_802_11_rssi rssi;

View File

@ -439,11 +439,10 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
cmd->command = cpu_to_le16(CMD_802_11_RESET);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
cmd->size = cpu_to_le16(sizeof(struct cmd_header));
cmd->result = cpu_to_le16(0);
cmd->seqnum = cpu_to_le16(0x5a5a);
cmd->params.reset.action = cpu_to_le16(CMD_ACT_HALT);
usb_tx_block(cardp, cardp->ep_out_buf, 4 + S_DS_GEN + sizeof(struct cmd_ds_802_11_reset));
usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header));
msleep(100);
ret = usb_reset_device(cardp->udev);

View File

@ -30,6 +30,14 @@ static inline void lbs_postpone_association_work(struct lbs_private *priv)
queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
}
static inline void lbs_do_association_work(struct lbs_private *priv)
{
if (priv->surpriseremoved)
return;
cancel_delayed_work(&priv->assoc_work);
queue_delayed_work(priv->work_thread, &priv->assoc_work, 0);
}
static inline void lbs_cancel_association_work(struct lbs_private *priv)
{
cancel_delayed_work(&priv->assoc_work);
@ -266,21 +274,17 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
{
int ret = 0;
struct lbs_private *priv = dev->priv;
u32 rthr = vwrq->value;
u32 val = vwrq->value;
lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
priv->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
} else {
if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE)
return -EINVAL;
priv->rtsthsd = rthr;
}
if (vwrq->disabled)
val = MRVDRV_RTS_MAX_VALUE;
ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
OID_802_11_RTS_THRESHOLD, &rthr);
if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */
return -EINVAL;
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val);
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
@ -289,21 +293,18 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
struct lbs_private *priv = dev->priv;
int ret = 0;
u16 val = 0;
lbs_deb_enter(LBS_DEB_WEXT);
priv->rtsthsd = 0;
ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
OID_802_11_RTS_THRESHOLD, NULL);
ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
if (ret)
goto out;
vwrq->value = priv->rtsthsd;
vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
|| (vwrq->value > MRVDRV_RTS_MAX_VALUE));
vwrq->value = val;
vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */
vwrq->fixed = 1;
out:
@ -314,24 +315,19 @@ out:
static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
u32 fthr = vwrq->value;
struct lbs_private *priv = dev->priv;
int ret = 0;
u32 val = vwrq->value;
lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
priv->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
} else {
if (fthr < MRVDRV_FRAG_MIN_VALUE
|| fthr > MRVDRV_FRAG_MAX_VALUE)
return -EINVAL;
priv->fragthsd = fthr;
}
if (vwrq->disabled)
val = MRVDRV_FRAG_MAX_VALUE;
ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
if (val < MRVDRV_FRAG_MIN_VALUE || val > MRVDRV_FRAG_MAX_VALUE)
return -EINVAL;
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, (u16) val);
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
@ -340,22 +336,19 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
struct lbs_private *priv = dev->priv;
int ret = 0;
u16 val = 0;
lbs_deb_enter(LBS_DEB_WEXT);
priv->fragthsd = 0;
ret = lbs_prepare_and_send_command(priv,
CMD_802_11_SNMP_MIB,
CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
if (ret)
goto out;
vwrq->value = priv->fragthsd;
vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
|| (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
vwrq->value = val;
vwrq->disabled = ((val < MRVDRV_FRAG_MIN_VALUE)
|| (val > MRVDRV_FRAG_MAX_VALUE));
vwrq->fixed = 1;
out:
@ -382,7 +375,7 @@ static int mesh_wlan_get_mode(struct net_device *dev,
{
lbs_deb_enter(LBS_DEB_WEXT);
*uwrq = IW_MODE_REPEAT ;
*uwrq = IW_MODE_REPEAT;
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
@ -425,31 +418,44 @@ out:
static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
struct lbs_private *priv = dev->priv;
int ret = 0;
u16 slimit = 0, llimit = 0;
lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->flags == IW_RETRY_LIMIT) {
/* The MAC has a 4-bit Total_Tx_Count register
Total_Tx_Count = 1 + Tx_Retry_Count */
if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
return -EOPNOTSUPP;
/* The MAC has a 4-bit Total_Tx_Count register
Total_Tx_Count = 1 + Tx_Retry_Count */
#define TX_RETRY_MIN 0
#define TX_RETRY_MAX 14
if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
return -EINVAL;
if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
return -EINVAL;
/* Adding 1 to convert retry count to try count */
priv->txretrycount = vwrq->value + 1;
ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
CMD_ACT_SET,
CMD_OPTION_WAITFORRSP,
OID_802_11_TX_RETRYCOUNT, NULL);
/* Add 1 to convert retry count to try count */
if (vwrq->flags & IW_RETRY_SHORT)
slimit = (u16) (vwrq->value + 1);
else if (vwrq->flags & IW_RETRY_LONG)
llimit = (u16) (vwrq->value + 1);
else
slimit = llimit = (u16) (vwrq->value + 1); /* set both */
if (llimit) {
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT,
llimit);
if (ret)
goto out;
}
if (slimit) {
/* txretrycount follows the short retry limit */
priv->txretrycount = slimit;
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT,
slimit);
if (ret)
goto out;
} else {
return -EOPNOTSUPP;
}
out:
@ -462,22 +468,30 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
{
struct lbs_private *priv = dev->priv;
int ret = 0;
u16 val = 0;
lbs_deb_enter(LBS_DEB_WEXT);
priv->txretrycount = 0;
ret = lbs_prepare_and_send_command(priv,
CMD_802_11_SNMP_MIB,
CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
OID_802_11_TX_RETRYCOUNT, NULL);
if (ret)
goto out;
vwrq->disabled = 0;
if (!vwrq->flags) {
vwrq->flags = IW_RETRY_LIMIT;
if (vwrq->flags & IW_RETRY_LONG) {
ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, &val);
if (ret)
goto out;
/* Subtract 1 to convert try count to retry count */
vwrq->value = priv->txretrycount - 1;
vwrq->value = val - 1;
vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
} else {
ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, &val);
if (ret)
goto out;
/* txretry count follows the short retry limit */
priv->txretrycount = val;
/* Subtract 1 to convert try count to retry count */
vwrq->value = val - 1;
vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
}
out:
@ -1578,12 +1592,14 @@ static int lbs_set_encodeext(struct net_device *dev,
set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
}
disable_wep (assoc_req);
/* Only disable wep if necessary: can't waste time here. */
if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE)
disable_wep(assoc_req);
}
out:
if (ret == 0) {
lbs_postpone_association_work(priv);
if (ret == 0) { /* key installation is time critical: postpone not! */
lbs_do_association_work(priv);
} else {
lbs_cancel_association_work(priv);
}

View File

@ -219,7 +219,7 @@ static void lbtf_tx_work(struct work_struct *work)
struct sk_buff *skb = NULL;
int err;
if ((priv->vif->type == IEEE80211_IF_TYPE_AP) &&
if ((priv->vif->type == NL80211_IFTYPE_AP) &&
(!skb_queue_empty(&priv->bc_ps_buf)))
skb = skb_dequeue(&priv->bc_ps_buf);
else if (priv->skb_to_tx) {
@ -326,11 +326,11 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,
priv->vif = conf->vif;
switch (conf->type) {
case IEEE80211_IF_TYPE_MESH_POINT:
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
lbtf_set_mode(priv, LBTF_AP_MODE);
break;
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
lbtf_set_mode(priv, LBTF_STA_MODE);
break;
default:
@ -346,8 +346,8 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
{
struct lbtf_private *priv = hw->priv;
if (priv->vif->type == IEEE80211_IF_TYPE_AP ||
priv->vif->type == IEEE80211_IF_TYPE_MESH_POINT)
if (priv->vif->type == NL80211_IFTYPE_AP ||
priv->vif->type == NL80211_IFTYPE_MESH_POINT)
lbtf_beacon_ctrl(priv, 0, 0);
lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
lbtf_set_bssid(priv, 0, NULL);
@ -372,8 +372,8 @@ static int lbtf_op_config_interface(struct ieee80211_hw *hw,
struct sk_buff *beacon;
switch (priv->vif->type) {
case IEEE80211_IF_TYPE_AP:
case IEEE80211_IF_TYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
beacon = ieee80211_beacon_get(hw, vif);
if (beacon) {
lbtf_beacon_set(priv, beacon);
@ -614,7 +614,7 @@ void lbtf_bcn_sent(struct lbtf_private *priv)
{
struct sk_buff *skb = NULL;
if (priv->vif->type != IEEE80211_IF_TYPE_AP)
if (priv->vif->type != NL80211_IFTYPE_AP)
return;
if (skb_queue_empty(&priv->bc_ps_buf)) {

View File

@ -14,6 +14,8 @@
* - RX filtering based on filter configuration (data->rx_filter)
*/
#include <linux/list.h>
#include <linux/spinlock.h>
#include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>
#include <linux/if_arp.h>
@ -28,11 +30,56 @@ static int radios = 2;
module_param(radios, int, 0444);
MODULE_PARM_DESC(radios, "Number of simulated radios");
struct hwsim_vif_priv {
u32 magic;
};
#define HWSIM_VIF_MAGIC 0x69537748
static inline void hwsim_check_magic(struct ieee80211_vif *vif)
{
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
WARN_ON(vp->magic != HWSIM_VIF_MAGIC);
}
static inline void hwsim_set_magic(struct ieee80211_vif *vif)
{
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
vp->magic = HWSIM_VIF_MAGIC;
}
static inline void hwsim_clear_magic(struct ieee80211_vif *vif)
{
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
vp->magic = 0;
}
struct hwsim_sta_priv {
u32 magic;
};
#define HWSIM_STA_MAGIC 0x6d537748
static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta)
{
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
WARN_ON(sp->magic != HWSIM_VIF_MAGIC);
}
static inline void hwsim_set_sta_magic(struct ieee80211_sta *sta)
{
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
sp->magic = HWSIM_VIF_MAGIC;
}
static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
{
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
sp->magic = 0;
}
static struct class *hwsim_class;
static struct ieee80211_hw **hwsim_radios;
static int hwsim_radio_count;
static struct net_device *hwsim_mon; /* global monitor netdev */
@ -68,7 +115,12 @@ static const struct ieee80211_rate hwsim_rates[] = {
{ .bitrate = 540 }
};
static spinlock_t hwsim_radio_lock;
static struct list_head hwsim_radios;
struct mac80211_hwsim_data {
struct list_head list;
struct ieee80211_hw *hw;
struct device *dev;
struct ieee80211_supported_band band;
struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)];
@ -144,11 +196,11 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
}
static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
struct sk_buff *skb)
static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
struct mac80211_hwsim_data *data = hw->priv;
int i, ack = 0;
struct mac80211_hwsim_data *data = hw->priv, *data2;
bool ack = false;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_rx_status rx_status;
@ -161,13 +213,13 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
/* TODO: simulate signal strength (and optional packet drop) */
/* Copy skb to all enabled radios that are on the current frequency */
for (i = 0; i < hwsim_radio_count; i++) {
struct mac80211_hwsim_data *data2;
spin_lock(&hwsim_radio_lock);
list_for_each_entry(data2, &hwsim_radios, list) {
struct sk_buff *nskb;
if (hwsim_radios[i] == NULL || hwsim_radios[i] == hw)
if (data == data2)
continue;
data2 = hwsim_radios[i]->priv;
if (!data2->started || !data2->radio_enabled ||
data->channel->center_freq != data2->channel->center_freq)
continue;
@ -176,11 +228,12 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
if (nskb == NULL)
continue;
if (memcmp(hdr->addr1, hwsim_radios[i]->wiphy->perm_addr,
if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr,
ETH_ALEN) == 0)
ack = 1;
ieee80211_rx_irqsafe(hwsim_radios[i], nskb, &rx_status);
ack = true;
ieee80211_rx_irqsafe(data2->hw, nskb, &rx_status);
}
spin_unlock(&hwsim_radio_lock);
return ack;
}
@ -189,7 +242,7 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct mac80211_hwsim_data *data = hw->priv;
int ack;
bool ack;
struct ieee80211_tx_info *txi;
mac80211_hwsim_monitor_rx(hw, skb);
@ -210,6 +263,12 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
ack = mac80211_hwsim_tx_frame(hw, skb);
txi = IEEE80211_SKB_CB(skb);
if (txi->control.vif)
hwsim_check_magic(txi->control.vif);
if (txi->control.sta)
hwsim_check_sta_magic(txi->control.sta);
memset(&txi->status, 0, sizeof(txi->status));
if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (ack)
@ -246,6 +305,7 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
wiphy_name(hw->wiphy), __func__, conf->type,
print_mac(mac, conf->mac_addr));
hwsim_set_magic(conf->vif);
return 0;
}
@ -257,6 +317,8 @@ static void mac80211_hwsim_remove_interface(
printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
wiphy_name(hw->wiphy), __func__, conf->type,
print_mac(mac, conf->mac_addr));
hwsim_check_magic(conf->vif);
hwsim_clear_magic(conf->vif);
}
@ -267,7 +329,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
struct sk_buff *skb;
struct ieee80211_tx_info *info;
if (vif->type != IEEE80211_IF_TYPE_AP)
hwsim_check_magic(vif);
if (vif->type != NL80211_IFTYPE_AP)
return;
skb = ieee80211_beacon_get(hw, vif);
@ -341,7 +405,45 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
*total_flags = data->rx_filter;
}
static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
hwsim_check_magic(vif);
return 0;
}
static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
u32 changed)
{
hwsim_check_magic(vif);
}
static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)
{
hwsim_check_magic(vif);
switch (cmd) {
case STA_NOTIFY_ADD:
hwsim_set_sta_magic(sta);
break;
case STA_NOTIFY_REMOVE:
hwsim_clear_sta_magic(sta);
break;
}
}
static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
bool set)
{
hwsim_check_sta_magic(sta);
return 0;
}
static const struct ieee80211_ops mac80211_hwsim_ops =
{
@ -352,23 +454,30 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
.remove_interface = mac80211_hwsim_remove_interface,
.config = mac80211_hwsim_config,
.configure_filter = mac80211_hwsim_configure_filter,
.config_interface = mac80211_hwsim_config_interface,
.bss_info_changed = mac80211_hwsim_bss_info_changed,
.sta_notify = mac80211_hwsim_sta_notify,
.set_tim = mac80211_hwsim_set_tim,
};
static void mac80211_hwsim_free(void)
{
int i;
struct list_head tmplist, *i, *tmp;
struct mac80211_hwsim_data *data;
for (i = 0; i < hwsim_radio_count; i++) {
if (hwsim_radios[i]) {
struct mac80211_hwsim_data *data;
data = hwsim_radios[i]->priv;
ieee80211_unregister_hw(hwsim_radios[i]);
device_unregister(data->dev);
ieee80211_free_hw(hwsim_radios[i]);
}
INIT_LIST_HEAD(&tmplist);
spin_lock_bh(&hwsim_radio_lock);
list_for_each_safe(i, tmp, &hwsim_radios)
list_move(i, &tmplist);
spin_unlock_bh(&hwsim_radio_lock);
list_for_each_entry(data, &tmplist, list) {
ieee80211_unregister_hw(data->hw);
device_unregister(data->dev);
ieee80211_free_hw(data->hw);
}
kfree(hwsim_radios);
class_destroy(hwsim_class);
}
@ -398,37 +507,32 @@ static int __init init_mac80211_hwsim(void)
struct ieee80211_hw *hw;
DECLARE_MAC_BUF(mac);
if (radios < 1 || radios > 65535)
if (radios < 1 || radios > 100)
return -EINVAL;
hwsim_radio_count = radios;
hwsim_radios = kcalloc(hwsim_radio_count,
sizeof(struct ieee80211_hw *), GFP_KERNEL);
if (hwsim_radios == NULL)
return -ENOMEM;
spin_lock_init(&hwsim_radio_lock);
INIT_LIST_HEAD(&hwsim_radios);
hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
if (IS_ERR(hwsim_class)) {
kfree(hwsim_radios);
if (IS_ERR(hwsim_class))
return PTR_ERR(hwsim_class);
}
memset(addr, 0, ETH_ALEN);
addr[0] = 0x02;
for (i = 0; i < hwsim_radio_count; i++) {
for (i = 0; i < radios; i++) {
printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n",
i);
hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops);
if (hw == NULL) {
if (!hw) {
printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw "
"failed\n");
err = -ENOMEM;
goto failed;
}
hwsim_radios[i] = hw;
data = hw->priv;
data->hw = hw;
data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw,
"hwsim%d", i);
if (IS_ERR(data->dev)) {
@ -452,6 +556,10 @@ static int __init init_mac80211_hwsim(void)
BIT(NL80211_IFTYPE_AP);
hw->ampdu_queues = 1;
/* ask mac80211 to reserve space for magic */
hw->vif_data_size = sizeof(struct hwsim_vif_priv);
hw->sta_data_size = sizeof(struct hwsim_sta_priv);
memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels));
memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates));
data->band.channels = data->channels;
@ -486,6 +594,8 @@ static int __init init_mac80211_hwsim(void)
setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
(unsigned long) hw);
list_add_tail(&data->list, &hwsim_radios);
}
hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
@ -517,7 +627,6 @@ failed_hw:
device_unregister(data->dev);
failed_drvdata:
ieee80211_free_hw(hw);
hwsim_radios[i] = NULL;
failed:
mac80211_hwsim_free();
return err;
@ -526,8 +635,7 @@ failed:
static void __exit exit_mac80211_hwsim(void)
{
printk(KERN_DEBUG "mac80211_hwsim: unregister %d radios\n",
hwsim_radio_count);
printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
unregister_netdev(hwsim_mon);
mac80211_hwsim_free();

View File

@ -4777,14 +4777,14 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
encoding->flags |= IW_ENCODE_DISABLED;
break;
case IW_ENCODE_ALG_WEP:
ext->key_len = min(le16_to_cpu(priv->keys[idx].len),
(u16) max_key_len);
ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len),
max_key_len);
memcpy(ext->key, priv->keys[idx].data, ext->key_len);
encoding->flags |= IW_ENCODE_ENABLED;
break;
case IW_ENCODE_ALG_TKIP:
ext->key_len = min((u16) sizeof(struct orinoco_tkip_key),
(u16) max_key_len);
ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key),
max_key_len);
memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
encoding->flags |= IW_ENCODE_ENABLED;
break;
@ -5686,9 +5686,9 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev,
/* Timestamp */
iwe.cmd = IWEVCUSTOM;
iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
"tsf=%016llx",
le64_to_cpu(bss->timestamp));
iwe.u.data.length =
snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx",
(unsigned long long) le64_to_cpu(bss->timestamp));
if (iwe.u.data.length)
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
&iwe, custom);

View File

@ -1139,7 +1139,7 @@ static int p54_start(struct ieee80211_hw *dev)
err = priv->open(dev);
if (!err)
priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->mode = NL80211_IFTYPE_MONITOR;
p54_init_vdcf(dev);
@ -1157,7 +1157,7 @@ static void p54_stop(struct ieee80211_hw *dev)
kfree_skb(skb);
priv->stop(dev);
priv->tsf_high32 = priv->tsf_low32 = 0;
priv->mode = IEEE80211_IF_TYPE_INVALID;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
}
static int p54_add_interface(struct ieee80211_hw *dev,
@ -1165,11 +1165,11 @@ static int p54_add_interface(struct ieee80211_hw *dev,
{
struct p54_common *priv = dev->priv;
if (priv->mode != IEEE80211_IF_TYPE_MNTR)
if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
@ -1181,7 +1181,7 @@ static int p54_add_interface(struct ieee80211_hw *dev,
p54_set_filter(dev, 0, NULL);
switch (conf->type) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
p54_set_filter(dev, 1, NULL);
break;
default:
@ -1198,7 +1198,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct p54_common *priv = dev->priv;
priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->mode = NL80211_IFTYPE_MONITOR;
memset(priv->mac_addr, 0, ETH_ALEN);
p54_set_filter(dev, 0, NULL);
}
@ -1380,7 +1380,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
return NULL;
priv = dev->priv;
priv->mode = IEEE80211_IF_TYPE_INVALID;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
skb_queue_head_init(&priv->tx_queue);
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
IEEE80211_HW_RX_INCLUDES_FCS |

View File

@ -616,7 +616,7 @@ static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
struct ieee80211_hw *dev = pci_get_drvdata(pdev);
struct p54p_priv *priv = dev->priv;
if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) {
ieee80211_stop_queues(dev);
p54p_stop(dev);
}
@ -634,7 +634,7 @@ static int p54p_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) {
p54p_open(dev);
ieee80211_wake_queues(dev);
}

View File

@ -384,7 +384,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
2 * (conf->type != IEEE80211_IF_TYPE_STA));
2 * (conf->type != NL80211_IFTYPE_STATION));
rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
/*

View File

@ -483,7 +483,7 @@ struct rt2x00intf_conf {
/*
* Interface type
*/
enum ieee80211_if_types type;
enum nl80211_iftype type;
/*
* TSF sync value, this is dependant on the operation type.

View File

@ -31,7 +31,7 @@
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
enum ieee80211_if_types type,
enum nl80211_iftype type,
u8 *mac, u8 *bssid)
{
struct rt2x00intf_conf conf;
@ -40,11 +40,11 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
conf.type = type;
switch (type) {
case IEEE80211_IF_TYPE_IBSS:
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
conf.sync = TSF_SYNC_BEACON;
break;
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
conf.sync = TSF_SYNC_INFRA;
break;
default:

View File

@ -467,8 +467,8 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
struct rt2x00_dev *rt2x00dev = data;
struct rt2x00_intf *intf = vif_to_intf(vif);
if (vif->type != IEEE80211_IF_TYPE_AP &&
vif->type != IEEE80211_IF_TYPE_IBSS)
if (vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_ADHOC)
return;
/*
@ -1212,8 +1212,8 @@ static void rt2x00lib_resume_intf(void *data, u8 *mac,
/*
* Master or Ad-hoc mode require a new beacon update.
*/
if (vif->type == IEEE80211_IF_TYPE_AP ||
vif->type == IEEE80211_IF_TYPE_IBSS)
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC)
intf->delayed_flags |= DELAYED_UPDATE_BEACON;
spin_unlock(&intf->lock);

View File

@ -88,7 +88,7 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
*/
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
enum ieee80211_if_types type,
enum nl80211_iftype type,
u8 *mac, u8 *bssid);
void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,

View File

@ -211,7 +211,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
return -ENODEV;
switch (conf->type) {
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
/*
* We don't support mixed combinations of
* sta and ap interfaces.
@ -227,8 +227,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
return -ENOBUFS;
break;
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
/*
* We don't support mixed combinations of
* sta and ap interfaces.
@ -268,7 +268,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
* increase interface count and start initialization.
*/
if (conf->type == IEEE80211_IF_TYPE_AP)
if (conf->type == NL80211_IFTYPE_AP)
rt2x00dev->intf_ap_count++;
else
rt2x00dev->intf_sta_count++;
@ -277,7 +277,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
spin_lock_init(&intf->seqlock);
intf->beacon = entry;
if (conf->type == IEEE80211_IF_TYPE_AP)
if (conf->type == NL80211_IFTYPE_AP)
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
@ -311,11 +311,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
* no interface is present.
*/
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
(conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) ||
(conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count))
(conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
(conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
return;
if (conf->type == IEEE80211_IF_TYPE_AP)
if (conf->type == NL80211_IFTYPE_AP)
rt2x00dev->intf_ap_count--;
else
rt2x00dev->intf_sta_count--;
@ -331,7 +331,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
* are cleared to prevent false ACKing of frames.
*/
rt2x00lib_config_intf(rt2x00dev, intf,
IEEE80211_IF_TYPE_INVALID, NULL, NULL);
NL80211_IFTYPE_UNSPECIFIED, NULL, NULL);
}
EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);

View File

@ -155,7 +155,6 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
struct ieee80211_rate *rate =
ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
@ -278,16 +277,22 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
* sequence counter given by mac80211.
*/
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
spin_lock_irqsave(&intf->seqlock, irqflags);
if (likely(tx_info->control.vif)) {
struct rt2x00_intf *intf;
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
intf->seqno += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
intf = vif_to_intf(tx_info->control.vif);
spin_unlock_irqrestore(&intf->seqlock, irqflags);
spin_lock_irqsave(&intf->seqlock, irqflags);
__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
intf->seqno += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
spin_unlock_irqrestore(&intf->seqlock, irqflags);
__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
}
}
/*

View File

@ -615,7 +615,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
reg |= RTL818X_CMD_TX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->mode = NL80211_IFTYPE_MONITOR;
return 0;
err_free_rings:
@ -633,7 +633,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
u8 reg;
int i;
priv->mode = IEEE80211_IF_TYPE_INVALID;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
@ -661,11 +661,11 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev,
{
struct rtl8180_priv *priv = dev->priv;
if (priv->mode != IEEE80211_IF_TYPE_MNTR)
if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
@ -688,7 +688,7 @@ static void rtl8180_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->mode = NL80211_IFTYPE_MONITOR;
priv->vif = NULL;
}

View File

@ -836,11 +836,11 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
struct rtl8187_priv *priv = dev->priv;
int i;
if (priv->mode != IEEE80211_IF_TYPE_MNTR)
if (priv->mode != NL80211_IFTYPE_MONITOR)
return -EOPNOTSUPP;
switch (conf->type) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
priv->mode = conf->type;
break;
default:
@ -865,7 +865,7 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
{
struct rtl8187_priv *priv = dev->priv;
mutex_lock(&priv->conf_mutex);
priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->mode = NL80211_IFTYPE_MONITOR;
priv->vif = NULL;
mutex_unlock(&priv->conf_mutex);
}
@ -1057,7 +1057,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->mode = NL80211_IFTYPE_MONITOR;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_RX_INCLUDES_FCS;

View File

@ -1,6 +1,6 @@
obj-$(CONFIG_ZD1211RW) += zd1211rw.o
zd1211rw-objs := zd_chip.o zd_ieee80211.o zd_mac.o \
zd1211rw-objs := zd_chip.o zd_mac.o \
zd_rf_al2230.o zd_rf_rf2959.o \
zd_rf_al7230b.o zd_rf_uw2453.o \
zd_rf.o zd_usb.o

View File

@ -28,7 +28,6 @@
#include "zd_def.h"
#include "zd_chip.h"
#include "zd_ieee80211.h"
#include "zd_mac.h"
#include "zd_rf.h"

View File

@ -1,100 +0,0 @@
/* ZD1211 USB-WLAN driver for Linux
*
* Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
* Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* In the long term, we'll probably find a better way of handling regulatory
* requirements outside of the driver.
*/
#include <linux/kernel.h>
#include <net/mac80211.h>
#include "zd_ieee80211.h"
#include "zd_mac.h"
struct channel_range {
u8 regdomain;
u8 start;
u8 end; /* exclusive (channel must be less than end) */
};
static const struct channel_range channel_ranges[] = {
{ ZD_REGDOMAIN_FCC, 1, 12 },
{ ZD_REGDOMAIN_IC, 1, 12 },
{ ZD_REGDOMAIN_ETSI, 1, 14 },
{ ZD_REGDOMAIN_JAPAN, 1, 14 },
{ ZD_REGDOMAIN_SPAIN, 1, 14 },
{ ZD_REGDOMAIN_FRANCE, 1, 14 },
/* Japan originally only had channel 14 available (see CHNL_ID 0x40 in
* 802.11). However, in 2001 the range was extended to include channels
* 1-13. The ZyDAS devices still use the old region code but are
* designed to allow the extra channel access in Japan. */
{ ZD_REGDOMAIN_JAPAN_ADD, 1, 15 },
};
static const struct channel_range *zd_channel_range(u8 regdomain)
{
int i;
for (i = 0; i < ARRAY_SIZE(channel_ranges); i++) {
const struct channel_range *range = &channel_ranges[i];
if (range->regdomain == regdomain)
return range;
}
return NULL;
}
#define CHAN_TO_IDX(chan) ((chan) - 1)
static void unmask_bg_channels(struct ieee80211_hw *hw,
const struct channel_range *range,
struct ieee80211_supported_band *sband)
{
u8 channel;
for (channel = range->start; channel < range->end; channel++) {
struct ieee80211_channel *chan =
&sband->channels[CHAN_TO_IDX(channel)];
chan->flags = 0;
}
}
void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain)
{
struct zd_mac *mac = zd_hw_mac(hw);
const struct channel_range *range;
dev_dbg(zd_mac_dev(mac), "regdomain %#02x\n", regdomain);
range = zd_channel_range(regdomain);
if (!range) {
/* The vendor driver overrides the regulatory domain and
* allowed channel registers and unconditionally restricts
* available channels to 1-11 everywhere. Match their
* questionable behaviour only for regdomains which we don't
* recognise. */
dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: "
"%#02x. Defaulting to FCC.\n", regdomain);
range = zd_channel_range(ZD_REGDOMAIN_FCC);
}
unmask_bg_channels(hw, range, &mac->band);
}

View File

@ -1,95 +0,0 @@
/* ZD1211 USB-WLAN driver for Linux
*
* Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
* Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _ZD_IEEE80211_H
#define _ZD_IEEE80211_H
#include <net/mac80211.h>
/* Additional definitions from the standards.
*/
#define ZD_REGDOMAIN_FCC 0x10
#define ZD_REGDOMAIN_IC 0x20
#define ZD_REGDOMAIN_ETSI 0x30
#define ZD_REGDOMAIN_SPAIN 0x31
#define ZD_REGDOMAIN_FRANCE 0x32
#define ZD_REGDOMAIN_JAPAN_ADD 0x40
#define ZD_REGDOMAIN_JAPAN 0x41
enum {
MIN_CHANNEL24 = 1,
MAX_CHANNEL24 = 14,
};
void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain);
#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
struct ofdm_plcp_header {
u8 prefix[3];
__le16 service;
} __attribute__((packed));
static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header)
{
return header->prefix[0] & 0xf;
}
/* The following defines give the encoding of the 4-bit rate field in the
* OFDM (802.11a/802.11g) PLCP header. Notify that these values are used to
* define the zd-rate values for OFDM.
*
* See the struct zd_ctrlset definition in zd_mac.h.
*/
#define ZD_OFDM_PLCP_RATE_6M 0xb
#define ZD_OFDM_PLCP_RATE_9M 0xf
#define ZD_OFDM_PLCP_RATE_12M 0xa
#define ZD_OFDM_PLCP_RATE_18M 0xe
#define ZD_OFDM_PLCP_RATE_24M 0x9
#define ZD_OFDM_PLCP_RATE_36M 0xd
#define ZD_OFDM_PLCP_RATE_48M 0x8
#define ZD_OFDM_PLCP_RATE_54M 0xc
struct cck_plcp_header {
u8 signal;
u8 service;
__le16 length;
__le16 crc16;
} __attribute__((packed));
static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header)
{
return header->signal;
}
/* These defines give the encodings of the signal field in the 802.11b PLCP
* header. The signal field gives the bit rate of the following packet. Even
* if technically wrong we use CCK here also for the 1 MBit/s and 2 MBit/s
* rate to stay consistent with Zydas and our use of the term.
*
* Notify that these values are *not* used in the zd-rates.
*/
#define ZD_CCK_PLCP_SIGNAL_1M 0x0a
#define ZD_CCK_PLCP_SIGNAL_2M 0x14
#define ZD_CCK_PLCP_SIGNAL_5M5 0x37
#define ZD_CCK_PLCP_SIGNAL_11M 0x6e
#endif /* _ZD_IEEE80211_H */

View File

@ -3,7 +3,7 @@
* Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
* Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
* Copyright (C) 2007-2008 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -29,9 +29,23 @@
#include "zd_def.h"
#include "zd_chip.h"
#include "zd_mac.h"
#include "zd_ieee80211.h"
#include "zd_rf.h"
struct zd_reg_alpha2_map {
u32 reg;
char alpha2[2];
};
static struct zd_reg_alpha2_map reg_alpha2_map[] = {
{ ZD_REGDOMAIN_FCC, "US" },
{ ZD_REGDOMAIN_IC, "CA" },
{ ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
{ ZD_REGDOMAIN_JAPAN, "JP" },
{ ZD_REGDOMAIN_JAPAN_ADD, "JP" },
{ ZD_REGDOMAIN_SPAIN, "ES" },
{ ZD_REGDOMAIN_FRANCE, "FR" },
};
/* This table contains the hardware specific values for the modulation rates. */
static const struct ieee80211_rate zd_rates[] = {
{ .bitrate = 10,
@ -95,6 +109,21 @@ static void housekeeping_init(struct zd_mac *mac);
static void housekeeping_enable(struct zd_mac *mac);
static void housekeeping_disable(struct zd_mac *mac);
static int zd_reg2alpha2(u8 regdomain, char *alpha2)
{
unsigned int i;
struct zd_reg_alpha2_map *reg_map;
for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
reg_map = &reg_alpha2_map[i];
if (regdomain == reg_map->reg) {
alpha2[0] = reg_map->alpha2[0];
alpha2[1] = reg_map->alpha2[1];
return 0;
}
}
return 1;
}
int zd_mac_preinit_hw(struct ieee80211_hw *hw)
{
int r;
@ -115,6 +144,7 @@ int zd_mac_init_hw(struct ieee80211_hw *hw)
int r;
struct zd_mac *mac = zd_hw_mac(hw);
struct zd_chip *chip = &mac->chip;
char alpha2[2];
u8 default_regdomain;
r = zd_chip_enable_int(chip);
@ -139,7 +169,9 @@ int zd_mac_init_hw(struct ieee80211_hw *hw)
if (r)
goto disable_int;
zd_geo_init(hw, mac->regdomain);
r = zd_reg2alpha2(mac->regdomain, alpha2);
if (!r)
regulatory_hint(hw->wiphy, alpha2, NULL);
r = 0;
disable_int:
@ -684,15 +716,15 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
{
struct zd_mac *mac = zd_hw_mac(hw);
/* using IEEE80211_IF_TYPE_INVALID to indicate no mode selected */
if (mac->type != IEEE80211_IF_TYPE_INVALID)
/* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */
if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
return -EOPNOTSUPP;
switch (conf->type) {
case IEEE80211_IF_TYPE_MNTR:
case IEEE80211_IF_TYPE_MESH_POINT:
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
mac->type = conf->type;
break;
default:
@ -706,7 +738,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct zd_mac *mac = zd_hw_mac(hw);
mac->type = IEEE80211_IF_TYPE_INVALID;
mac->type = NL80211_IFTYPE_UNSPECIFIED;
zd_set_beacon_interval(&mac->chip, 0);
zd_write_mac_addr(&mac->chip, NULL);
}
@ -725,8 +757,8 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
int associated;
int r;
if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
mac->type == IEEE80211_IF_TYPE_IBSS) {
if (mac->type == NL80211_IFTYPE_MESH_POINT ||
mac->type == NL80211_IFTYPE_ADHOC) {
associated = true;
if (conf->changed & IEEE80211_IFCC_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
@ -753,7 +785,7 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
return 0;
}
void zd_process_intr(struct work_struct *work)
static void zd_process_intr(struct work_struct *work)
{
u16 int_status;
struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
@ -923,7 +955,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
spin_lock_init(&mac->lock);
mac->hw = hw;
mac->type = IEEE80211_IF_TYPE_INVALID;
mac->type = NL80211_IFTYPE_UNSPECIFIED;
memcpy(mac->channels, zd_channels, sizeof(zd_channels));
memcpy(mac->rates, zd_rates, sizeof(zd_rates));

View File

@ -25,7 +25,6 @@
#include <net/mac80211.h>
#include "zd_chip.h"
#include "zd_ieee80211.h"
struct zd_ctrlset {
u8 modulation;
@ -187,6 +186,70 @@ struct zd_mac {
unsigned int pass_ctrl:1;
};
#define ZD_REGDOMAIN_FCC 0x10
#define ZD_REGDOMAIN_IC 0x20
#define ZD_REGDOMAIN_ETSI 0x30
#define ZD_REGDOMAIN_SPAIN 0x31
#define ZD_REGDOMAIN_FRANCE 0x32
#define ZD_REGDOMAIN_JAPAN_ADD 0x40
#define ZD_REGDOMAIN_JAPAN 0x41
enum {
MIN_CHANNEL24 = 1,
MAX_CHANNEL24 = 14,
};
#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
struct ofdm_plcp_header {
u8 prefix[3];
__le16 service;
} __attribute__((packed));
static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header)
{
return header->prefix[0] & 0xf;
}
/* The following defines give the encoding of the 4-bit rate field in the
* OFDM (802.11a/802.11g) PLCP header. Notify that these values are used to
* define the zd-rate values for OFDM.
*
* See the struct zd_ctrlset definition in zd_mac.h.
*/
#define ZD_OFDM_PLCP_RATE_6M 0xb
#define ZD_OFDM_PLCP_RATE_9M 0xf
#define ZD_OFDM_PLCP_RATE_12M 0xa
#define ZD_OFDM_PLCP_RATE_18M 0xe
#define ZD_OFDM_PLCP_RATE_24M 0x9
#define ZD_OFDM_PLCP_RATE_36M 0xd
#define ZD_OFDM_PLCP_RATE_48M 0x8
#define ZD_OFDM_PLCP_RATE_54M 0xc
struct cck_plcp_header {
u8 signal;
u8 service;
__le16 length;
__le16 crc16;
} __attribute__((packed));
static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header)
{
return header->signal;
}
/* These defines give the encodings of the signal field in the 802.11b PLCP
* header. The signal field gives the bit rate of the following packet. Even
* if technically wrong we use CCK here also for the 1 MBit/s and 2 MBit/s
* rate to stay consistent with Zydas and our use of the term.
*
* Notify that these values are *not* used in the zd-rates.
*/
#define ZD_CCK_PLCP_SIGNAL_1M 0x0a
#define ZD_CCK_PLCP_SIGNAL_2M 0x14
#define ZD_CCK_PLCP_SIGNAL_5M5 0x37
#define ZD_CCK_PLCP_SIGNAL_11M 0x6e
static inline struct zd_mac *zd_hw_mac(struct ieee80211_hw *hw)
{
return hw->priv;

View File

@ -23,7 +23,7 @@
#include "zd_def.h"
#include "zd_rf.h"
#include "zd_ieee80211.h"
#include "zd_mac.h"
#include "zd_chip.h"
static const char * const rfs[] = {

View File

@ -92,6 +92,20 @@
* @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
* %NL80211_ATTR_IFINDEX.
*
* @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command
* after being queried by the kernel. CRDA replies by sending a regulatory
* domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our
* current alpha2 if it found a match. It also provides
* NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each
* regulatory rule is a nested set of attributes given by
* %NL80211_ATTR_REG_RULE_FREQ_[START|END] and
* %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by
* %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and
* %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP.
* @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain
* to the the specified ISO/IEC 3166-1 alpha2 country code. The core will
* store this as a valid request and then query userspace for it.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@ -131,7 +145,10 @@ enum nl80211_commands {
NL80211_CMD_SET_BSS,
/* add commands here */
NL80211_CMD_SET_REG,
NL80211_CMD_REQ_SET_REG,
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
__NL80211_CMD_AFTER_LAST,
@ -197,10 +214,21 @@ enum nl80211_commands {
* info given for %NL80211_CMD_GET_MPATH, nested attribute described at
* &enum nl80211_mpath_info.
*
*
* @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
* &enum nl80211_mntr_flags.
*
* @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the
* current regulatory domain should be set to or is already set to.
* For example, 'CR', for Costa Rica. This attribute is used by the kernel
* to query the CRDA to retrieve one regulatory domain. This attribute can
* also be used by userspace to query the kernel for the currently set
* regulatory domain. We chose an alpha2 as that is also used by the
* IEEE-802.11d country information element to identify a country.
* Users can also simply ask the wireless core to set regulatory domain
* to a specific alpha2.
* @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory
* rules.
*
* @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1)
* @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled
* (u8, 0 or 1)
@ -265,6 +293,9 @@ enum nl80211_attrs {
NL80211_ATTR_SUPPORTED_IFTYPES,
NL80211_ATTR_REG_ALPHA2,
NL80211_ATTR_REG_RULES,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@ -278,6 +309,7 @@ enum nl80211_attrs {
#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
#define NL80211_MAX_SUPP_RATES 32
#define NL80211_MAX_SUPP_REG_RULES 32
#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
@ -472,6 +504,66 @@ enum nl80211_bitrate_attr {
NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1
};
/**
* enum nl80211_reg_rule_attr - regulatory rule attributes
* @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional
* considerations for a given frequency range. These are the
* &enum nl80211_reg_rule_flags.
* @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory
* rule in KHz. This is not a center of frequency but an actual regulatory
* band edge.
* @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule
* in KHz. This is not a center a frequency but an actual regulatory
* band edge.
* @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
* frequency range, in KHz.
* @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
* for a given frequency range. The value is in mBi (100 * dBi).
* If you don't have one then don't send this.
* @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
* a given frequency range. The value is in mBm (100 * dBm).
*/
enum nl80211_reg_rule_attr {
__NL80211_REG_RULE_ATTR_INVALID,
NL80211_ATTR_REG_RULE_FLAGS,
NL80211_ATTR_FREQ_RANGE_START,
NL80211_ATTR_FREQ_RANGE_END,
NL80211_ATTR_FREQ_RANGE_MAX_BW,
NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
NL80211_ATTR_POWER_RULE_MAX_EIRP,
/* keep last */
__NL80211_REG_RULE_ATTR_AFTER_LAST,
NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
};
/**
* enum nl80211_reg_rule_flags - regulatory rule flags
*
* @NL80211_RRF_NO_OFDM: OFDM modulation not allowed
* @NL80211_RRF_NO_CCK: CCK modulation not allowed
* @NL80211_RRF_NO_INDOOR: indoor operation not allowed
* @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed
* @NL80211_RRF_DFS: DFS support is required to be used
* @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
* @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
* @NL80211_RRF_PASSIVE_SCAN: passive scan is required
* @NL80211_RRF_NO_IBSS: no IBSS is allowed
*/
enum nl80211_reg_rule_flags {
NL80211_RRF_NO_OFDM = 1<<0,
NL80211_RRF_NO_CCK = 1<<1,
NL80211_RRF_NO_INDOOR = 1<<2,
NL80211_RRF_NO_OUTDOOR = 1<<3,
NL80211_RRF_DFS = 1<<4,
NL80211_RRF_PTP_ONLY = 1<<5,
NL80211_RRF_PTMP_ONLY = 1<<6,
NL80211_RRF_PASSIVE_SCAN = 1<<7,
NL80211_RRF_NO_IBSS = 1<<8,
};
/**
* enum nl80211_mntr_flags - monitor configuration flags
*

View File

@ -287,6 +287,66 @@ struct bss_parameters {
int use_short_slot_time;
};
/**
* enum reg_set_by - Indicates who is trying to set the regulatory domain
* @REGDOM_SET_BY_INIT: regulatory domain was set by initialization. We will be
* using a static world regulatory domain by default.
* @REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world regulatory domain.
* @REGDOM_SET_BY_USER: User asked the wireless core to set the
* regulatory domain.
* @REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the wireless core
* it thinks its knows the regulatory domain we should be in.
* @REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an 802.11 country
* information element with regulatory information it thinks we
* should consider.
*/
enum reg_set_by {
REGDOM_SET_BY_INIT,
REGDOM_SET_BY_CORE,
REGDOM_SET_BY_USER,
REGDOM_SET_BY_DRIVER,
REGDOM_SET_BY_COUNTRY_IE,
};
struct ieee80211_freq_range {
u32 start_freq_khz;
u32 end_freq_khz;
u32 max_bandwidth_khz;
};
struct ieee80211_power_rule {
u32 max_antenna_gain;
u32 max_eirp;
};
struct ieee80211_reg_rule {
struct ieee80211_freq_range freq_range;
struct ieee80211_power_rule power_rule;
u32 flags;
};
struct ieee80211_regdomain {
u32 n_reg_rules;
char alpha2[2];
struct ieee80211_reg_rule reg_rules[];
};
#define MHZ_TO_KHZ(freq) (freq * 1000)
#define KHZ_TO_MHZ(freq) (freq / 1000)
#define DBI_TO_MBI(gain) (gain * 100)
#define MBI_TO_DBI(gain) (gain / 100)
#define DBM_TO_MBM(gain) (gain * 100)
#define MBM_TO_DBM(gain) (gain / 100)
#define REG_RULE(start, end, bw, gain, eirp, reg_flags) { \
.freq_range.start_freq_khz = (start) * 1000, \
.freq_range.end_freq_khz = (end) * 1000, \
.freq_range.max_bandwidth_khz = (bw) * 1000, \
.power_rule.max_antenna_gain = (gain) * 100, \
.power_rule.max_eirp = (eirp) * 100, \
.flags = reg_flags, \
}
/* from net/wireless.h */
struct wiphy;

View File

@ -160,6 +160,7 @@ struct ieee80211_low_level_stats {
* @BSS_CHANGED_ERP_PREAMBLE: preamble changed
* @BSS_CHANGED_ERP_SLOT: slot timing changed
* @BSS_CHANGED_HT: 802.11n parameters changed
* @BSS_CHANGED_BASIC_RATES: Basic rateset changed
*/
enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0,
@ -167,6 +168,7 @@ enum ieee80211_bss_change {
BSS_CHANGED_ERP_PREAMBLE = 1<<2,
BSS_CHANGED_ERP_SLOT = 1<<3,
BSS_CHANGED_HT = 1<<4,
BSS_CHANGED_BASIC_RATES = 1<<5,
};
/**
@ -187,6 +189,9 @@ enum ieee80211_bss_change {
* @assoc_ht: association in HT mode
* @ht_conf: ht capabilities
* @ht_bss_conf: ht extended capabilities
* @basic_rates: bitmap of basic rates, each bit stands for an
* index into the rate table configured by the driver in
* the current band.
*/
struct ieee80211_bss_conf {
/* association related data */
@ -200,6 +205,7 @@ struct ieee80211_bss_conf {
u16 beacon_int;
u16 assoc_capability;
u64 timestamp;
u64 basic_rates;
/* ht related data */
bool assoc_ht;
struct ieee80211_ht_info *ht_conf;
@ -294,6 +300,9 @@ enum mac80211_tx_control_flags {
* (2) driver internal use (if applicable)
* (3) TX status information - driver tells mac80211 what happened
*
* The TX control's sta pointer is only valid during the ->tx call,
* it may be NULL.
*
* @flags: transmit info flags, defined above
* @band: TBD
* @tx_rate_idx: TBD
@ -321,10 +330,11 @@ struct ieee80211_tx_info {
union {
struct {
/* NB: vif can be NULL for injected frames */
struct ieee80211_vif *vif;
struct ieee80211_key_conf *hw_key;
struct ieee80211_sta *sta;
unsigned long jiffies;
u16 aid;
s8 rts_cts_rate_idx, alt_retry_rate_idx;
u8 retry_limit;
u8 icv_len;
@ -471,33 +481,6 @@ struct ieee80211_conf {
struct ieee80211_ht_bss_info ht_bss_conf;
};
/**
* enum ieee80211_if_types - types of 802.11 network interfaces
*
* @IEEE80211_IF_TYPE_INVALID: invalid interface type, not used
* by mac80211 itself
* @IEEE80211_IF_TYPE_AP: interface in AP mode.
* @IEEE80211_IF_TYPE_MGMT: special interface for communication with hostap
* daemon. Drivers should never see this type.
* @IEEE80211_IF_TYPE_STA: interface in STA (client) mode.
* @IEEE80211_IF_TYPE_IBSS: interface in IBSS (ad-hoc) mode.
* @IEEE80211_IF_TYPE_MNTR: interface in monitor (rfmon) mode.
* @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
* @IEEE80211_IF_TYPE_VLAN: VLAN interface bound to an AP, drivers
* will never see this type.
* @IEEE80211_IF_TYPE_MESH_POINT: 802.11s mesh point
*/
enum ieee80211_if_types {
IEEE80211_IF_TYPE_INVALID,
IEEE80211_IF_TYPE_AP,
IEEE80211_IF_TYPE_STA,
IEEE80211_IF_TYPE_IBSS,
IEEE80211_IF_TYPE_MESH_POINT,
IEEE80211_IF_TYPE_MNTR,
IEEE80211_IF_TYPE_WDS,
IEEE80211_IF_TYPE_VLAN,
};
/**
* struct ieee80211_vif - per-interface data
*
@ -509,7 +492,7 @@ enum ieee80211_if_types {
* sizeof(void *).
*/
struct ieee80211_vif {
enum ieee80211_if_types type;
enum nl80211_iftype type;
/* must be last */
u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
};
@ -517,7 +500,7 @@ struct ieee80211_vif {
static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
{
#ifdef CONFIG_MAC80211_MESH
return vif->type == IEEE80211_IF_TYPE_MESH_POINT;
return vif->type == NL80211_IFTYPE_MESH_POINT;
#endif
return false;
}
@ -528,7 +511,7 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
* @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 ieee80211_if_types constants. Determines the type of
* @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
@ -544,7 +527,7 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
* in pure monitor mode.
*/
struct ieee80211_if_init_conf {
enum ieee80211_if_types type;
enum nl80211_iftype type;
struct ieee80211_vif *vif;
void *mac_addr;
};
@ -672,6 +655,33 @@ enum set_key_cmd {
SET_KEY, DISABLE_KEY,
};
/**
* struct ieee80211_sta - station table entry
*
* A station table entry represents a station we are possibly
* communicating with. Since stations are RCU-managed in
* mac80211, any ieee80211_sta pointer you get access to must
* either be protected by rcu_read_lock() explicitly or implicitly,
* or you must take good care to not use such a pointer after a
* call to your sta_notify callback that removed it.
*
* @addr: MAC address
* @aid: AID we assigned to the station if we're an AP
* @supp_rates: Bitmap of supported rates (per band)
* @ht_info: HT capabilities of this STA
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *), size is determined in hw information.
*/
struct ieee80211_sta {
u64 supp_rates[IEEE80211_NUM_BANDS];
u8 addr[ETH_ALEN];
u16 aid;
struct ieee80211_ht_info ht_info;
/* must be last */
u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
};
/**
* enum sta_notify_cmd - sta notify command
*
@ -816,6 +826,8 @@ enum ieee80211_hw_flags {
*
* @vif_data_size: size (in bytes) of the drv_priv data area
* within &struct ieee80211_vif.
* @sta_data_size: size (in bytes) of the drv_priv data area
* within &struct ieee80211_sta.
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
@ -827,12 +839,15 @@ struct ieee80211_hw {
unsigned int extra_tx_headroom;
int channel_change_time;
int vif_data_size;
int sta_data_size;
u16 queues;
u16 ampdu_queues;
u16 max_listen_interval;
s8 max_signal;
};
struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy);
/**
* SET_IEEE80211_DEV - set device for 802.11 hardware
*
@ -1108,7 +1123,7 @@ enum ieee80211_ampdu_mlme_action {
* This callback must be implemented and atomic.
*
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
* must be set or cleared for a given AID. Must be atomic.
* must be set or cleared for a given STA. Must be atomic.
*
* @set_key: See the section "Hardware crypto acceleration"
* This callback can sleep, and is only called between add_interface
@ -1122,7 +1137,9 @@ enum ieee80211_ampdu_mlme_action {
* @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
* configuration done by the regulatory agent in the wiphy's registered
* bands.
* bands. When the scan finishes, ieee80211_scan_completed() must be
* called; note that it also must be called when the scan cannot finish
* because the hardware is turned off! Anything else is a bug!
*
* @get_stats: return low-level statistics
*
@ -1192,7 +1209,8 @@ struct ieee80211_ops {
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list);
int (*set_tim)(struct ieee80211_hw *hw, int aid, int set);
int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
bool set);
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_address, const u8 *address,
struct ieee80211_key_conf *key);
@ -1209,7 +1227,7 @@ struct ieee80211_ops {
int (*set_retry_limit)(struct ieee80211_hw *hw,
u32 short_retry, u32 long_retr);
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, const u8 *addr);
enum sta_notify_cmd, struct ieee80211_sta *sta);
int (*conf_tx)(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
int (*get_tx_stats)(struct ieee80211_hw *hw,
@ -1219,7 +1237,7 @@ struct ieee80211_ops {
int (*tx_last_beacon)(struct ieee80211_hw *hw);
int (*ampdu_action)(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 *ssn);
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
};
/**
@ -1769,4 +1787,17 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
*/
void ieee80211_notify_mac(struct ieee80211_hw *hw,
enum ieee80211_notification_types notif_type);
/**
* ieee80211_find_sta - find a station
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
* @addr: station's address
*
* This function must be called under RCU lock and the
* resulting pointer is only valid under RCU lock as well.
*/
struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
const u8 *addr);
#endif /* MAC80211_H */

View File

@ -60,6 +60,7 @@ enum ieee80211_channel_flags {
* with cfg80211.
*
* @center_freq: center frequency in MHz
* @max_bandwidth: maximum allowed bandwidth for this channel, in MHz
* @hw_value: hardware-specific value for the channel
* @flags: channel flags from &enum ieee80211_channel_flags.
* @orig_flags: channel flags at registration time, used by regulatory
@ -73,6 +74,7 @@ enum ieee80211_channel_flags {
struct ieee80211_channel {
enum ieee80211_band band;
u16 center_freq;
u8 max_bandwidth;
u16 hw_value;
u32 flags;
int max_antenna_gain;
@ -178,6 +180,7 @@ struct ieee80211_supported_band {
* struct wiphy - wireless hardware description
* @idx: the wiphy index assigned to this item
* @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name>
* @reg_notifier: the driver's regulatory notification callback
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@ -197,6 +200,9 @@ struct wiphy {
struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
/* Lets us get back the wiphy on the callback */
int (*reg_notifier)(struct wiphy *wiphy, enum reg_set_by setby);
/* fields below are read-only, assigned by cfg80211 */
/* the item in /sys/class/ieee80211/ points to this,
@ -322,6 +328,58 @@ extern int ieee80211_frequency_to_channel(int freq);
*/
extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
int freq);
/**
* __regulatory_hint - hint to the wireless core a regulatory domain
* @wiphy: if a driver is providing the hint this is the driver's very
* own &struct wiphy
* @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain
* should be in. If @rd is set this should be NULL
* @rd: a complete regulatory domain, if passed the caller need not worry
* about freeing it
*
* The Wireless subsystem can use this function to hint to the wireless core
* what it believes should be the current regulatory domain by
* giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory
* domain should be in or by providing a completely build regulatory domain.
*
* Returns -EALREADY if *a regulatory domain* has already been set. Note that
* this could be by another driver. It is safe for drivers to continue if
* -EALREADY is returned, if drivers are not capable of world roaming they
* should not register more channels than they support. Right now we only
* support listening to the first driver hint. If the driver is capable
* of world roaming but wants to respect its own EEPROM mappings for
* specific regulatory domains it should register the @reg_notifier callback
* on the &struct wiphy. Returns 0 if the hint went through fine or through an
* intersection operation. Otherwise a standard error code is returned.
*
*/
extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
const char *alpha2, struct ieee80211_regdomain *rd);
/**
* regulatory_hint - driver hint to the wireless core a regulatory domain
* @wiphy: the driver's very own &struct wiphy
* @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain
* should be in. If @rd is set this should be NULL. Note that if you
* set this to NULL you should still set rd->alpha2 to some accepted
* alpha2.
* @rd: a complete regulatory domain provided by the driver. If passed
* the driver does not need to worry about freeing it.
*
* Wireless drivers can use this function to hint to the wireless core
* what it believes should be the current regulatory domain by
* giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory
* domain should be in or by providing a completely build regulatory domain.
* If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried
* for a regulatory domain structure for the respective country. If
* a regulatory domain is build and passed you should set the alpha2
* if possible, otherwise set it to the special value of "99" which tells
* the wireless core it is unknown. If you pass a built regulatory domain
* and we return non zero you are in charge of kfree()'ing the structure.
*
* See __regulatory_hint() documentation for possible return values.
*/
extern int regulatory_hint(struct wiphy *wiphy,
const char *alpha2, struct ieee80211_regdomain *rd);
/**
* ieee80211_get_channel - get channel struct from wiphy for specified frequency

View File

@ -179,19 +179,6 @@ config MAC80211_VERBOSE_MPL_DEBUG
Do not select this option.
config MAC80211_LOWTX_FRAME_DUMP
bool "Debug frame dumping"
depends on MAC80211_DEBUG_MENU
---help---
Selecting this option will cause the stack to
print a message for each frame that is handed
to the lowlevel driver for transmission. This
message includes all MAC addresses and the
frame control field.
If unsure, say N and insert the debugging code
you require into the driver you are debugging.
config MAC80211_DEBUG_COUNTERS
bool "Extra statistics for TX/RX debugging"
depends on MAC80211_DEBUG_MENU

View File

@ -17,26 +17,26 @@
#include "rate.h"
#include "mesh.h"
static enum ieee80211_if_types
nl80211_type_to_mac80211_type(enum nl80211_iftype type)
struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
return &local->hw;
}
EXPORT_SYMBOL(wiphy_to_hw);
static bool nl80211_type_check(enum nl80211_iftype type)
{
switch (type) {
case NL80211_IFTYPE_UNSPECIFIED:
return IEEE80211_IF_TYPE_STA;
case NL80211_IFTYPE_ADHOC:
return IEEE80211_IF_TYPE_IBSS;
case NL80211_IFTYPE_STATION:
return IEEE80211_IF_TYPE_STA;
case NL80211_IFTYPE_MONITOR:
return IEEE80211_IF_TYPE_MNTR;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
return IEEE80211_IF_TYPE_MESH_POINT;
#endif
case NL80211_IFTYPE_WDS:
return IEEE80211_IF_TYPE_WDS;
return true;
default:
return IEEE80211_IF_TYPE_INVALID;
return false;
}
}
@ -45,17 +45,15 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
struct vif_params *params)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
enum ieee80211_if_types itype;
struct net_device *dev;
struct ieee80211_sub_if_data *sdata;
int err;
itype = nl80211_type_to_mac80211_type(type);
if (itype == IEEE80211_IF_TYPE_INVALID)
if (!nl80211_type_check(type))
return -EINVAL;
err = ieee80211_if_add(local, name, &dev, itype, params);
if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
err = ieee80211_if_add(local, name, &dev, type, params);
if (err || type != NL80211_IFTYPE_MONITOR || !flags)
return err;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@ -86,7 +84,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct net_device *dev;
enum ieee80211_if_types itype;
struct ieee80211_sub_if_data *sdata;
int ret;
@ -95,8 +92,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
if (!dev)
return -ENODEV;
itype = nl80211_type_to_mac80211_type(type);
if (itype == IEEE80211_IF_TYPE_INVALID)
if (!nl80211_type_check(type))
return -EINVAL;
if (dev == local->mdev)
@ -104,16 +100,16 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ret = ieee80211_if_change_type(sdata, itype);
ret = ieee80211_if_change_type(sdata, type);
if (ret)
return ret;
if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
params->mesh_id_len,
params->mesh_id);
ieee80211_sdata_set_mesh_id(sdata,
params->mesh_id_len,
params->mesh_id);
if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags)
if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
return 0;
sdata->u.mntr_flags = *flags;
@ -368,7 +364,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
sta = sta_info_get_by_idx(local, idx, dev);
if (sta) {
ret = 0;
memcpy(mac, sta->addr, ETH_ALEN);
memcpy(mac, sta->sta.addr, ETH_ALEN);
sta_set_sinfo(sta, sinfo);
}
@ -509,7 +505,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
if (sdata->vif.type != NL80211_IFTYPE_AP)
return -EINVAL;
old = sdata->u.ap.beacon;
@ -532,7 +528,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
if (sdata->vif.type != NL80211_IFTYPE_AP)
return -EINVAL;
old = sdata->u.ap.beacon;
@ -554,7 +550,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
if (sdata->vif.type != NL80211_IFTYPE_AP)
return -EINVAL;
old = sdata->u.ap.beacon;
@ -597,7 +593,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
* Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
memset(msg->da, 0xff, ETH_ALEN);
memcpy(msg->sa, sta->addr, ETH_ALEN);
memcpy(msg->sa, sta->sta.addr, ETH_ALEN);
msg->len = htons(6);
msg->dsap = 0;
msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
@ -652,9 +648,9 @@ static void sta_apply_parameters(struct ieee80211_local *local,
*/
if (params->aid) {
sta->aid = params->aid;
if (sta->aid > IEEE80211_MAX_AID)
sta->aid = 0; /* XXX: should this be an error? */
sta->sta.aid = params->aid;
if (sta->sta.aid > IEEE80211_MAX_AID)
sta->sta.aid = 0; /* XXX: should this be an error? */
}
if (params->listen_interval >= 0)
@ -671,12 +667,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,
rates |= BIT(j);
}
}
sta->supp_rates[local->oper_channel->band] = rates;
sta->sta.supp_rates[local->oper_channel->band] = rates;
}
if (params->ht_capa) {
ieee80211_ht_cap_ie_to_ht_info(params->ht_capa,
&sta->ht_info);
&sta->sta.ht_info);
}
if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
@ -709,8 +705,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
if (params->vlan) {
sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
if (sdata->vif.type != IEEE80211_IF_TYPE_VLAN &&
sdata->vif.type != IEEE80211_IF_TYPE_AP)
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP)
return -EINVAL;
} else
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@ -740,8 +736,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
return err;
}
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
sdata->vif.type == IEEE80211_IF_TYPE_AP)
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
sdata->vif.type == NL80211_IFTYPE_AP)
ieee80211_send_layer2_update(sta);
rcu_read_unlock();
@ -805,8 +801,8 @@ static int ieee80211_change_station(struct wiphy *wiphy,
if (params->vlan && params->vlan != sta->sdata->dev) {
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN &&
vlansdata->vif.type != IEEE80211_IF_TYPE_AP) {
if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
vlansdata->vif.type != NL80211_IFTYPE_AP) {
rcu_read_unlock();
return -EINVAL;
}
@ -840,7 +836,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
return -ENOTSUPP;
rcu_read_lock();
@ -896,7 +892,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
return -ENOTSUPP;
rcu_read_lock();
@ -923,7 +919,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
struct mpath_info *pinfo)
{
if (mpath->next_hop)
memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
else
memset(next_hop, 0, ETH_ALEN);
@ -971,7 +967,7 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
return -ENOTSUPP;
rcu_read_lock();
@ -999,7 +995,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
return -ENOTSUPP;
rcu_read_lock();
@ -1028,7 +1024,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
if (sdata->vif.type != NL80211_IFTYPE_AP)
return -EINVAL;
if (params->use_cts_prot >= 0) {

View File

@ -51,8 +51,6 @@ DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
local->hw.conf.antenna_sel_tx);
DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
local->hw.conf.antenna_sel_rx);
DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d",
local->bridge_packets);
DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
local->rts_threshold);
DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
@ -206,7 +204,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_ADD(frequency);
DEBUGFS_ADD(antenna_sel_tx);
DEBUGFS_ADD(antenna_sel_rx);
DEBUGFS_ADD(bridge_packets);
DEBUGFS_ADD(rts_threshold);
DEBUGFS_ADD(fragmentation_threshold);
DEBUGFS_ADD(short_retry_limit);
@ -263,7 +260,6 @@ void debugfs_hw_del(struct ieee80211_local *local)
DEBUGFS_DEL(frequency);
DEBUGFS_DEL(antenna_sel_tx);
DEBUGFS_DEL(antenna_sel_rx);
DEBUGFS_DEL(bridge_packets);
DEBUGFS_DEL(rts_threshold);
DEBUGFS_DEL(fragmentation_threshold);
DEBUGFS_DEL(short_retry_limit);

View File

@ -206,7 +206,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
rcu_read_lock();
sta = rcu_dereference(key->sta);
if (sta)
sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
sprintf(buf, "../../stations/%s",
print_mac(mac, sta->sta.addr));
rcu_read_unlock();
/* using sta as a boolean is fine outside RCU lock */

View File

@ -173,7 +173,6 @@ IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC);
static ssize_t ieee80211_if_fmt_flags(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@ -192,7 +191,6 @@ __IEEE80211_IF_FILE(flags);
/* AP attributes */
IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
static ssize_t ieee80211_if_fmt_num_buffered_multicast(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@ -207,37 +205,37 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
#ifdef CONFIG_MAC80211_MESH
/* Mesh stats attributes */
IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC);
IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC);
IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
IEEE80211_IF_FILE(dropped_frames_no_route,
u.sta.mshstats.dropped_frames_no_route, DEC);
IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC);
u.mesh.mshstats.dropped_frames_no_route, DEC);
IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
/* Mesh parameters */
IEEE80211_IF_WFILE(dot11MeshMaxRetries,
u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8);
u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8);
IEEE80211_IF_WFILE(dot11MeshRetryTimeout,
u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16);
u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16);
IEEE80211_IF_WFILE(dot11MeshConfirmTimeout,
u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
IEEE80211_IF_WFILE(dot11MeshHoldingTimeout,
u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8);
IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8);
u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
IEEE80211_IF_WFILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC, u8);
IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8);
IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks,
u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout,
u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval,
u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime,
u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries,
u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
IEEE80211_IF_WFILE(path_refresh_time,
u.sta.mshcfg.path_refresh_time, DEC, u32);
u.mesh.mshcfg.path_refresh_time, DEC, u32);
IEEE80211_IF_WFILE(min_discovery_timeout,
u.sta.mshcfg.min_discovery_timeout, DEC, u16);
u.mesh.mshcfg.min_discovery_timeout, DEC, u16);
#endif
@ -265,7 +263,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(auth_alg, sta);
DEBUGFS_ADD(auth_transaction, sta);
DEBUGFS_ADD(flags, sta);
DEBUGFS_ADD(num_beacons_sta, sta);
}
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
@ -276,7 +273,6 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(num_sta_ps, ap);
DEBUGFS_ADD(dtim_count, ap);
DEBUGFS_ADD(num_beacons, ap);
DEBUGFS_ADD(num_buffered_multicast, ap);
}
@ -345,26 +341,26 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
return;
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_MESH_POINT:
case NL80211_IFTYPE_MESH_POINT:
#ifdef CONFIG_MAC80211_MESH
add_mesh_stats(sdata);
add_mesh_config(sdata);
#endif
/* fall through */
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
add_sta_files(sdata);
break;
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
add_ap_files(sdata);
break;
case IEEE80211_IF_TYPE_WDS:
case NL80211_IFTYPE_WDS:
add_wds_files(sdata);
break;
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
add_monitor_files(sdata);
break;
case IEEE80211_IF_TYPE_VLAN:
case NL80211_IFTYPE_AP_VLAN:
add_vlan_files(sdata);
break;
default:
@ -398,7 +394,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_DEL(auth_alg, sta);
DEBUGFS_DEL(auth_transaction, sta);
DEBUGFS_DEL(flags, sta);
DEBUGFS_DEL(num_beacons_sta, sta);
}
static void del_ap_files(struct ieee80211_sub_if_data *sdata)
@ -409,7 +404,6 @@ static void del_ap_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_DEL(num_sta_ps, ap);
DEBUGFS_DEL(dtim_count, ap);
DEBUGFS_DEL(num_beacons, ap);
DEBUGFS_DEL(num_buffered_multicast, ap);
}
@ -482,26 +476,26 @@ static void del_files(struct ieee80211_sub_if_data *sdata)
return;
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_MESH_POINT:
case NL80211_IFTYPE_MESH_POINT:
#ifdef CONFIG_MAC80211_MESH
del_mesh_stats(sdata);
del_mesh_config(sdata);
#endif
/* fall through */
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
del_sta_files(sdata);
break;
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
del_ap_files(sdata);
break;
case IEEE80211_IF_TYPE_WDS:
case NL80211_IFTYPE_WDS:
del_wds_files(sdata);
break;
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
del_monitor_files(sdata);
break;
case IEEE80211_IF_TYPE_VLAN:
case NL80211_IFTYPE_AP_VLAN:
del_vlan_files(sdata);
break;
default:

View File

@ -50,7 +50,7 @@ static const struct file_operations sta_ ##name## _ops = { \
STA_READ_##format(name, field) \
STA_OPS(name)
STA_FILE(aid, aid, D);
STA_FILE(aid, sta.aid, D);
STA_FILE(dev, sdata->dev->name, S);
STA_FILE(rx_packets, rx_packets, LU);
STA_FILE(tx_packets, tx_packets, LU);
@ -176,7 +176,7 @@ static ssize_t sta_agg_status_write(struct file *file,
struct net_device *dev = sta->sdata->dev;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hw *hw = &local->hw;
u8 *da = sta->addr;
u8 *da = sta->sta.addr;
static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1,
@ -253,7 +253,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
if (!stations_dir)
return;
mac = print_mac(mbuf, sta->addr);
mac = print_mac(mbuf, sta->sta.addr);
sta->debugfs.dir = debugfs_create_dir(mac, stations_dir);
if (!sta->debugfs.dir)

View File

@ -89,7 +89,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
memset(mgmt, 0, 24);
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
if (sdata->vif.type == NL80211_IFTYPE_AP)
memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else
memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
@ -139,7 +139,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
memset(mgmt, 0, 24);
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
if (sdata->vif.type == NL80211_IFTYPE_AP)
memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else
memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
@ -185,7 +185,7 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
memset(mgmt, 0, 24);
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
if (sdata->vif.type == NL80211_IFTYPE_AP)
memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
else
memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
@ -274,7 +274,7 @@ void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *r
#endif /* CONFIG_MAC80211_HT_DEBUG */
ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
ra, tid, NULL);
&sta->sta, tid, NULL);
if (ret)
printk(KERN_DEBUG "HW problem - can not stop rx "
"aggregation for tid %d\n", tid);
@ -328,7 +328,7 @@ static void sta_addba_resp_timer_expired(unsigned long data)
rcu_read_lock();
sta = sta_info_get(local, temp_sta->addr);
sta = sta_info_get(local, temp_sta->sta.addr);
if (!sta) {
rcu_read_unlock();
return;
@ -354,7 +354,7 @@ static void sta_addba_resp_timer_expired(unsigned long data)
/* go through the state check in stop_BA_session */
*state = HT_AGG_STATE_OPERATIONAL;
spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid,
ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid,
WLAN_BACK_INITIATOR);
timer_expired_exit:
@ -465,7 +465,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
if (local->ops->ampdu_action)
ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
ra, tid, &start_seq_num);
&sta->sta, tid, &start_seq_num);
if (ret) {
/* No need to requeue the packets in the agg queue, since we
@ -557,7 +557,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
if (local->ops->ampdu_action)
ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
ra, tid, NULL);
&sta->sta, tid, NULL);
/* case HW denied going back to legacy */
if (ret) {
@ -767,7 +767,7 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
#endif
ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr,
ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
(u16)*ptid, WLAN_BACK_TIMER,
WLAN_REASON_QSTA_TIMEOUT);
}
@ -874,7 +874,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
if (local->ops->ampdu_action)
ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
sta->addr, tid, &start_seq_num);
&sta->sta, tid, &start_seq_num);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
#endif /* CONFIG_MAC80211_HT_DEBUG */
@ -899,7 +899,7 @@ end:
spin_unlock_bh(&sta->lock);
end_no_lock:
ieee80211_send_addba_resp(sta->sdata, sta->addr, tid,
ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
dialog_token, status, 1, buf_size, timeout);
}
@ -952,7 +952,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
/* this will allow the state check in stop_BA_session */
*state = HT_AGG_STATE_OPERATIONAL;
spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid,
WLAN_BACK_INITIATOR);
}
}
@ -979,14 +979,14 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
#endif /* CONFIG_MAC80211_HT_DEBUG */
if (initiator == WLAN_BACK_INITIATOR)
ieee80211_sta_stop_rx_ba_session(sdata, sta->addr, tid,
ieee80211_sta_stop_rx_ba_session(sdata, sta->sta.addr, tid,
WLAN_BACK_INITIATOR, 0);
else { /* WLAN_BACK_RECIPIENT */
spin_lock_bh(&sta->lock);
sta->ampdu_mlme.tid_state_tx[tid] =
HT_AGG_STATE_OPERATIONAL;
spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
ieee80211_stop_tx_ba_session(&local->hw, sta->sta.addr, tid,
WLAN_BACK_RECIPIENT);
}
}

View File

@ -29,9 +29,6 @@
#include "key.h"
#include "sta_info.h"
/* ieee80211.o internal definitions, etc. These are not included into
* low-level drivers. */
struct ieee80211_local;
/* Maximum number of broadcast/multicast frames to buffer when some of the
@ -71,9 +68,9 @@ struct ieee80211_fragment_entry {
};
struct ieee80211_sta_bss {
struct ieee80211_bss {
struct list_head list;
struct ieee80211_sta_bss *hnext;
struct ieee80211_bss *hnext;
size_t ssid_len;
atomic_t users;
@ -112,7 +109,7 @@ struct ieee80211_sta_bss {
u8 erp_value;
};
static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss)
static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss)
{
#ifdef CONFIG_MAC80211_MESH
return bss->mesh_cfg;
@ -120,7 +117,7 @@ static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss)
return NULL;
}
static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss)
static inline u8 *bss_mesh_id(struct ieee80211_bss *bss)
{
#ifdef CONFIG_MAC80211_MESH
return bss->mesh_id;
@ -128,7 +125,7 @@ static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss)
return NULL;
}
static inline u8 bss_mesh_id_len(struct ieee80211_sta_bss *bss)
static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss)
{
#ifdef CONFIG_MAC80211_MESH
return bss->mesh_id_len;
@ -232,7 +229,6 @@ struct ieee80211_if_ap {
struct sk_buff_head ps_bc_buf;
atomic_t num_sta_ps; /* number of stations in PS mode */
int dtim_count;
int num_beacons; /* number of TXed beacon frames for this BSS */
};
struct ieee80211_if_wds {
@ -293,13 +289,13 @@ struct mesh_config {
#define IEEE80211_STA_AUTO_BSSID_SEL BIT(11)
#define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
#define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
/* flags for MLME request*/
/* flags for MLME request */
#define IEEE80211_STA_REQ_SCAN 0
#define IEEE80211_STA_REQ_DIRECT_PROBE 1
#define IEEE80211_STA_REQ_AUTH 2
#define IEEE80211_STA_REQ_RUN 3
/* flags used for setting mlme state */
/* STA/IBSS MLME states */
enum ieee80211_sta_mlme_state {
IEEE80211_STA_MLME_DISABLED,
IEEE80211_STA_MLME_DIRECT_PROBE,
@ -308,7 +304,6 @@ enum ieee80211_sta_mlme_state {
IEEE80211_STA_MLME_ASSOCIATED,
IEEE80211_STA_MLME_IBSS_SEARCH,
IEEE80211_STA_MLME_IBSS_JOINED,
IEEE80211_STA_MLME_MESH_UP
};
/* bitfield of allowed auth algs */
@ -325,34 +320,6 @@ struct ieee80211_if_sta {
size_t ssid_len;
u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
size_t scan_ssid_len;
#ifdef CONFIG_MAC80211_MESH
struct timer_list mesh_path_timer;
u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
size_t mesh_id_len;
/* Active Path Selection Protocol Identifier */
u8 mesh_pp_id[4];
/* Active Path Selection Metric Identifier */
u8 mesh_pm_id[4];
/* Congestion Control Mode Identifier */
u8 mesh_cc_id[4];
/* Local mesh Destination Sequence Number */
u32 dsn;
/* Last used PREQ ID */
u32 preq_id;
atomic_t mpaths;
/* Timestamp of last DSN update */
unsigned long last_dsn_update;
/* Timestamp of last DSN sent */
unsigned long last_preq;
struct mesh_rmc *rmc;
spinlock_t mesh_preq_queue_lock;
struct mesh_preq_queue preq_queue;
int preq_queue_len;
struct mesh_stats mshstats;
struct mesh_config mshcfg;
u32 mesh_seqnum;
bool accepting_plinks;
#endif
u16 aid;
u16 ap_capab, capab;
u8 *extra_ie; /* to be added to the end of AssocReq */
@ -384,31 +351,70 @@ struct ieee80211_if_sta {
u32 supp_rates_bits[IEEE80211_NUM_BANDS];
int wmm_last_param_set;
int num_beacons; /* number of TXed beacon frames by this STA */
};
static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta,
u8 mesh_id_len, u8 *mesh_id)
{
#ifdef CONFIG_MAC80211_MESH
ifsta->mesh_id_len = mesh_id_len;
memcpy(ifsta->mesh_id, mesh_id, mesh_id_len);
#endif
}
struct ieee80211_if_mesh {
struct work_struct work;
struct timer_list housekeeping_timer;
struct timer_list mesh_path_timer;
struct sk_buff_head skb_queue;
bool housekeeping;
u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
size_t mesh_id_len;
/* Active Path Selection Protocol Identifier */
u8 mesh_pp_id[4];
/* Active Path Selection Metric Identifier */
u8 mesh_pm_id[4];
/* Congestion Control Mode Identifier */
u8 mesh_cc_id[4];
/* Local mesh Destination Sequence Number */
u32 dsn;
/* Last used PREQ ID */
u32 preq_id;
atomic_t mpaths;
/* Timestamp of last DSN update */
unsigned long last_dsn_update;
/* Timestamp of last DSN sent */
unsigned long last_preq;
struct mesh_rmc *rmc;
spinlock_t mesh_preq_queue_lock;
struct mesh_preq_queue preq_queue;
int preq_queue_len;
struct mesh_stats mshstats;
struct mesh_config mshcfg;
u32 mesh_seqnum;
bool accepting_plinks;
};
#ifdef CONFIG_MAC80211_MESH
#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \
do { (sta)->mshstats.name++; } while (0)
#define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \
do { (msh)->mshstats.name++; } while (0)
#else
#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \
#define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \
do { } while (0)
#endif
/* flags used in struct ieee80211_sub_if_data.flags */
#define IEEE80211_SDATA_ALLMULTI BIT(0)
#define IEEE80211_SDATA_PROMISC BIT(1)
#define IEEE80211_SDATA_USERSPACE_MLME BIT(2)
#define IEEE80211_SDATA_OPERATING_GMODE BIT(3)
/**
* enum ieee80211_sub_if_data_flags - virtual interface flags
*
* @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets
* @IEEE80211_SDATA_PROMISC: interface is promisc
* @IEEE80211_SDATA_USERSPACE_MLME: userspace MLME is active
* @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode
* @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between
* associated stations and deliver multicast frames both
* back to wireless media and to the local net stack.
*/
enum ieee80211_sub_if_data_flags {
IEEE80211_SDATA_ALLMULTI = BIT(0),
IEEE80211_SDATA_PROMISC = BIT(1),
IEEE80211_SDATA_USERSPACE_MLME = BIT(2),
IEEE80211_SDATA_OPERATING_GMODE = BIT(3),
IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(4),
};
struct ieee80211_sub_if_data {
struct list_head list;
@ -424,11 +430,6 @@ struct ieee80211_sub_if_data {
int drop_unencrypted;
/*
* basic rates of this AP or the AP we're associated to
*/
u64 basic_rates;
/* Fragment table for host-based reassembly */
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;
@ -455,6 +456,9 @@ struct ieee80211_sub_if_data {
struct ieee80211_if_wds wds;
struct ieee80211_if_vlan vlan;
struct ieee80211_if_sta sta;
#ifdef CONFIG_MAC80211_MESH
struct ieee80211_if_mesh mesh;
#endif
u32 mntr_flags;
} u;
@ -477,7 +481,6 @@ struct ieee80211_sub_if_data {
struct dentry *auth_alg;
struct dentry *auth_transaction;
struct dentry *flags;
struct dentry *num_beacons_sta;
struct dentry *force_unicast_rateidx;
struct dentry *max_ratectrl_rateidx;
} sta;
@ -485,7 +488,6 @@ struct ieee80211_sub_if_data {
struct dentry *drop_unencrypted;
struct dentry *num_sta_ps;
struct dentry *dtim_count;
struct dentry *num_beacons;
struct dentry *force_unicast_rateidx;
struct dentry *max_ratectrl_rateidx;
struct dentry *num_buffered_multicast;
@ -548,6 +550,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
return container_of(p, struct ieee80211_sub_if_data, vif);
}
static inline void
ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata,
u8 mesh_id_len, u8 *mesh_id)
{
#ifdef CONFIG_MAC80211_MESH
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
ifmsh->mesh_id_len = mesh_id_len;
memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len);
#else
WARN_ON(1);
#endif
}
enum {
IEEE80211_RX_MSG = 1,
IEEE80211_TX_STATUS_MSG = 2,
@ -621,10 +636,6 @@ struct ieee80211_local {
struct crypto_blkcipher *wep_rx_tfm;
u32 wep_iv;
int bridge_packets; /* bridge packets between associated stations and
* deliver multicast frames both back to wireless
* media and to the local net stack */
struct list_head interfaces;
/*
@ -634,8 +645,8 @@ struct ieee80211_local {
spinlock_t key_lock;
bool sta_sw_scanning;
bool sta_hw_scanning;
/* Scanning and BSS list */
bool sw_scanning, hw_scanning;
int scan_channel_idx;
enum ieee80211_band scan_band;
@ -646,9 +657,9 @@ struct ieee80211_local {
struct ieee80211_channel *oper_channel, *scan_channel;
u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
size_t scan_ssid_len;
struct list_head sta_bss_list;
struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE];
spinlock_t sta_bss_lock;
struct list_head bss_list;
struct ieee80211_bss *bss_hash[STA_HASH_SIZE];
spinlock_t bss_lock;
/* SNMP counters */
/* dot11CountersTable */
@ -712,7 +723,6 @@ struct ieee80211_local {
struct dentry *frequency;
struct dentry *antenna_sel_tx;
struct dentry *antenna_sel_rx;
struct dentry *bridge_packets;
struct dentry *rts_threshold;
struct dentry *fragmentation_threshold;
struct dentry *short_retry_limit;
@ -868,87 +878,81 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
}
/* ieee80211.c */
int ieee80211_hw_config(struct ieee80211_local *local);
int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed);
void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
struct ieee80211_ht_info *req_ht_cap,
struct ieee80211_ht_bss_info *req_bss_cap);
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u32 changed);
void ieee80211_configure_filter(struct ieee80211_local *local);
/* ieee80211_ioctl.c */
/* wireless extensions */
extern const struct iw_handler_def ieee80211_iw_handler_def;
int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
/* ieee80211_sta.c */
void ieee80211_sta_timer(unsigned long data);
void ieee80211_sta_work(struct work_struct *work);
void ieee80211_sta_scan_work(struct work_struct *work);
/* STA/IBSS code */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata);
void ieee80211_scan_work(struct work_struct *work);
void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status);
int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len);
int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len);
int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid);
int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len);
void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_sta *ifsta);
int ieee80211_sta_scan_results(struct ieee80211_local *local,
struct iw_request_info *info,
char *buf, size_t len);
ieee80211_rx_result ieee80211_sta_rx_scan(
struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status);
void ieee80211_rx_bss_list_init(struct ieee80211_local *local);
void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local);
int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len);
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, u8 *bssid,
u8 *addr, u64 supp_rates);
int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason);
int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason);
void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u32 changed);
u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
struct ieee802_11_elems *elems,
enum ieee80211_band band);
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
u8 *ssid, size_t ssid_len);
void ieee802_11_parse_elems(u8 *start, size_t len,
struct ieee802_11_elems *elems);
/* scan/BSS handling */
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
u8 *ssid, size_t ssid_len);
int ieee80211_scan_results(struct ieee80211_local *local,
struct iw_request_info *info,
char *buf, size_t len);
ieee80211_rx_result
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
struct ieee80211_rx_status *rx_status);
void ieee80211_rx_bss_list_init(struct ieee80211_local *local);
void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local);
int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
char *ie, size_t len);
void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local);
int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata,
u8 *ssid, size_t ssid_len);
struct ieee80211_sta_bss *
int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata,
u8 *ssid, size_t ssid_len);
struct ieee80211_bss *
ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status,
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee802_11_elems *elems,
int freq, bool beacon);
struct ieee80211_sta_bss *
struct ieee80211_bss *
ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len);
struct ieee80211_sta_bss *
struct ieee80211_bss *
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len);
void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss);
#ifdef CONFIG_MAC80211_MESH
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
#else
static inline void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
{}
#endif
struct ieee80211_bss *bss);
/* interface handling */
void ieee80211_if_setup(struct net_device *dev);
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
struct net_device **new_dev, enum ieee80211_if_types type,
struct net_device **new_dev, enum nl80211_iftype type,
struct vif_params *params);
int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
enum ieee80211_if_types type);
enum nl80211_iftype type);
void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
void ieee80211_remove_interfaces(struct ieee80211_local *local);
@ -992,7 +996,7 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */
extern const unsigned char rfc1042_header[6];
extern const unsigned char bridge_tunnel_header[6];
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
enum ieee80211_if_types type);
enum nl80211_iftype type);
int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
int rate, int erp, int short_preamble);
void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx,
@ -1000,6 +1004,11 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
int encrypt);
void ieee802_11_parse_elems(u8 *start, size_t len,
struct ieee802_11_elems *elems);
int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band);
#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline

View File

@ -1,4 +1,6 @@
/*
* Interface handling (except master interface)
*
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
@ -17,7 +19,540 @@
#include "sta_info.h"
#include "debugfs_netdev.h"
#include "mesh.h"
#include "led.h"
static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
{
int meshhdrlen;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0;
/* FIX: what would be proper limits for MTU?
* This interface uses 802.3 frames. */
if (new_mtu < 256 ||
new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
return -EINVAL;
}
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
dev->mtu = new_mtu;
return 0;
}
static inline int identical_mac_addr_allowed(int type1, int type2)
{
return type1 == NL80211_IFTYPE_MONITOR ||
type2 == NL80211_IFTYPE_MONITOR ||
(type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) ||
(type1 == NL80211_IFTYPE_WDS &&
(type2 == NL80211_IFTYPE_WDS ||
type2 == NL80211_IFTYPE_AP)) ||
(type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) ||
(type1 == NL80211_IFTYPE_AP_VLAN &&
(type2 == NL80211_IFTYPE_AP ||
type2 == NL80211_IFTYPE_AP_VLAN));
}
static int ieee80211_open(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata, *nsdata;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
struct ieee80211_if_init_conf conf;
u32 changed = 0;
int res;
bool need_hw_reconfig = 0;
u8 null_addr[ETH_ALEN] = {0};
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
/* fail early if user set an invalid address */
if (compare_ether_addr(dev->dev_addr, null_addr) &&
!is_valid_ether_addr(dev->dev_addr))
return -EADDRNOTAVAIL;
/* we hold the RTNL here so can safely walk the list */
list_for_each_entry(nsdata, &local->interfaces, list) {
struct net_device *ndev = nsdata->dev;
if (ndev != dev && netif_running(ndev)) {
/*
* Allow only a single IBSS interface to be up at any
* time. This is restricted because beacon distribution
* cannot work properly if both are in the same IBSS.
*
* To remove this restriction we'd have to disallow them
* from setting the same SSID on different IBSS interfaces
* belonging to the same hardware. Then, however, we're
* faced with having to adopt two different TSF timers...
*/
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
nsdata->vif.type == NL80211_IFTYPE_ADHOC)
return -EBUSY;
/*
* The remaining checks are only performed for interfaces
* with the same MAC address.
*/
if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
continue;
/*
* check whether it may have the same address
*/
if (!identical_mac_addr_allowed(sdata->vif.type,
nsdata->vif.type))
return -ENOTUNIQ;
/*
* can only add VLANs to enabled APs
*/
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
nsdata->vif.type == NL80211_IFTYPE_AP)
sdata->bss = &nsdata->u.ap;
}
}
switch (sdata->vif.type) {
case NL80211_IFTYPE_WDS:
if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
return -ENOLINK;
break;
case NL80211_IFTYPE_AP_VLAN:
if (!sdata->bss)
return -ENOLINK;
list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
break;
case NL80211_IFTYPE_AP:
sdata->bss = &sdata->u.ap;
break;
case NL80211_IFTYPE_MESH_POINT:
if (!ieee80211_vif_is_mesh(&sdata->vif))
break;
/* mesh ifaces must set allmulti to forward mcast traffic */
atomic_inc(&local->iff_allmultis);
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_ADHOC:
/* no special treatment */
break;
case NL80211_IFTYPE_UNSPECIFIED:
case __NL80211_IFTYPE_AFTER_LAST:
/* cannot happen */
WARN_ON(1);
break;
}
if (local->open_count == 0) {
res = 0;
if (local->ops->start)
res = local->ops->start(local_to_hw(local));
if (res)
goto err_del_bss;
need_hw_reconfig = 1;
ieee80211_led_radio(local, local->hw.conf.radio_enabled);
}
/*
* Check all interfaces and copy the hopefully now-present
* MAC address to those that have the special null one.
*/
list_for_each_entry(nsdata, &local->interfaces, list) {
struct net_device *ndev = nsdata->dev;
/*
* No need to check netif_running since we do not allow
* it to start up with this invalid address.
*/
if (compare_ether_addr(null_addr, ndev->dev_addr) == 0)
memcpy(ndev->dev_addr,
local->hw.wiphy->perm_addr,
ETH_ALEN);
}
if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0)
memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr,
ETH_ALEN);
/*
* Validate the MAC address for this device.
*/
if (!is_valid_ether_addr(dev->dev_addr)) {
if (!local->open_count && local->ops->stop)
local->ops->stop(local_to_hw(local));
return -EADDRNOTAVAIL;
}
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
/* no need to tell driver */
break;
case NL80211_IFTYPE_MONITOR:
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
local->cooked_mntrs++;
break;
}
/* must be before the call to ieee80211_configure_filter */
local->monitors++;
if (local->monitors == 1)
local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
local->fif_fcsfail++;
if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
local->fif_plcpfail++;
if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
local->fif_control++;
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss++;
netif_addr_lock_bh(local->mdev);
ieee80211_configure_filter(local);
netif_addr_unlock_bh(local->mdev);
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
/* fall through */
default:
conf.vif = &sdata->vif;
conf.type = sdata->vif.type;
conf.mac_addr = dev->dev_addr;
res = local->ops->add_interface(local_to_hw(local), &conf);
if (res)
goto err_stop;
if (ieee80211_vif_is_mesh(&sdata->vif))
ieee80211_start_mesh(sdata);
changed |= ieee80211_reset_erp_info(sdata);
ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_enable_keys(sdata);
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
!(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
netif_carrier_off(dev);
else
netif_carrier_on(dev);
}
if (sdata->vif.type == NL80211_IFTYPE_WDS) {
/* Create STA entry for the WDS peer */
sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
GFP_KERNEL);
if (!sta) {
res = -ENOMEM;
goto err_del_interface;
}
/* no locking required since STA is not live yet */
sta->flags |= WLAN_STA_AUTHORIZED;
res = sta_info_insert(sta);
if (res) {
/* STA has been freed */
goto err_del_interface;
}
}
if (local->open_count == 0) {
res = dev_open(local->mdev);
WARN_ON(res);
if (res)
goto err_del_interface;
tasklet_enable(&local->tx_pending_tasklet);
tasklet_enable(&local->tasklet);
}
/*
* set_multicast_list will be invoked by the networking core
* which will check whether any increments here were done in
* error and sync them down to the hardware as filter flags.
*/
if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
atomic_inc(&local->iff_allmultis);
if (sdata->flags & IEEE80211_SDATA_PROMISC)
atomic_inc(&local->iff_promiscs);
local->open_count++;
if (need_hw_reconfig) {
ieee80211_hw_config(local);
/*
* set default queue parameters so drivers don't
* need to initialise the hardware if the hardware
* doesn't start up with sane defaults
*/
ieee80211_set_wmm_default(sdata);
}
/*
* ieee80211_sta_work is disabled while network interface
* is down. Therefore, some configuration changes may not
* yet be effective. Trigger execution of ieee80211_sta_work
* to fix this.
*/
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC) {
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
queue_work(local->hw.workqueue, &ifsta->work);
}
netif_tx_start_all_queues(dev);
return 0;
err_del_interface:
local->ops->remove_interface(local_to_hw(local), &conf);
err_stop:
if (!local->open_count && local->ops->stop)
local->ops->stop(local_to_hw(local));
err_del_bss:
sdata->bss = NULL;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
list_del(&sdata->u.vlan.list);
return res;
}
static int ieee80211_stop(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_init_conf conf;
struct sta_info *sta;
/*
* Stop TX on this interface first.
*/
netif_tx_stop_all_queues(dev);
/*
* Now delete all active aggregation sessions.
*/
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list, list) {
if (sta->sdata == sdata)
ieee80211_sta_tear_down_BA_sessions(sdata,
sta->sta.addr);
}
rcu_read_unlock();
/*
* Remove all stations associated with this interface.
*
* This must be done before calling ops->remove_interface()
* because otherwise we can later invoke ops->sta_notify()
* whenever the STAs are removed, and that invalidates driver
* assumptions about always getting a vif pointer that is valid
* (because if we remove a STA after ops->remove_interface()
* the driver will have removed the vif info already!)
*
* We could relax this and only unlink the stations from the
* hash table and list but keep them on a per-sdata list that
* will be inserted back again when the interface is brought
* up again, but I don't currently see a use case for that,
* except with WDS which gets a STA entry created when it is
* brought up.
*/
sta_info_flush(local, sdata);
/*
* Don't count this interface for promisc/allmulti while it
* is down. dev_mc_unsync() will invoke set_multicast_list
* on the master interface which will sync these down to the
* hardware as filter flags.
*/
if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
atomic_dec(&local->iff_allmultis);
if (sdata->flags & IEEE80211_SDATA_PROMISC)
atomic_dec(&local->iff_promiscs);
dev_mc_unsync(local->mdev, dev);
/* APs need special treatment */
if (sdata->vif.type == NL80211_IFTYPE_AP) {
struct ieee80211_sub_if_data *vlan, *tmp;
struct beacon_data *old_beacon = sdata->u.ap.beacon;
/* remove beacon */
rcu_assign_pointer(sdata->u.ap.beacon, NULL);
synchronize_rcu();
kfree(old_beacon);
/* down all dependent devices, that is VLANs */
list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
u.vlan.list)
dev_close(vlan->dev);
WARN_ON(!list_empty(&sdata->u.ap.vlans));
}
local->open_count--;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
list_del(&sdata->u.vlan.list);
/* no need to tell driver */
break;
case NL80211_IFTYPE_MONITOR:
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
local->cooked_mntrs--;
break;
}
local->monitors--;
if (local->monitors == 0)
local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
local->fif_fcsfail--;
if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
local->fif_plcpfail--;
if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
local->fif_control--;
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss--;
netif_addr_lock_bh(local->mdev);
ieee80211_configure_filter(local);
netif_addr_unlock_bh(local->mdev);
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED;
memset(sdata->u.sta.bssid, 0, ETH_ALEN);
del_timer_sync(&sdata->u.sta.timer);
/*
* If the timer fired while we waited for it, it will have
* requeued the work. Now the work will be running again
* but will not rearm the timer again because it checks
* whether the interface is running, which, at this point,
* it no longer is.
*/
cancel_work_sync(&sdata->u.sta.work);
/*
* When we get here, the interface is marked down.
* Call synchronize_rcu() to wait for the RX path
* should it be using the interface and enqueuing
* frames at this very time on another CPU.
*/
synchronize_rcu();
skb_queue_purge(&sdata->u.sta.skb_queue);
sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
kfree(sdata->u.sta.extra_ie);
sdata->u.sta.extra_ie = NULL;
sdata->u.sta.extra_ie_len = 0;
/* fall through */
case NL80211_IFTYPE_MESH_POINT:
if (ieee80211_vif_is_mesh(&sdata->vif)) {
/* allmulti is always set on mesh ifaces */
atomic_dec(&local->iff_allmultis);
ieee80211_stop_mesh(sdata);
}
/* fall through */
default:
if (local->scan_sdata == sdata) {
if (!local->ops->hw_scan)
cancel_delayed_work_sync(&local->scan_work);
/*
* The software scan can no longer run now, so we can
* clear out the scan_sdata reference. However, the
* hardware scan may still be running. The complete
* function must be prepared to handle a NULL value.
*/
local->scan_sdata = NULL;
/*
* The memory barrier guarantees that another CPU
* that is hardware-scanning will now see the fact
* that this interface is gone.
*/
smp_mb();
/*
* If software scanning, complete the scan but since
* the scan_sdata is NULL already don't send out a
* scan event to userspace -- the scan is incomplete.
*/
if (local->sw_scanning)
ieee80211_scan_completed(&local->hw);
}
conf.vif = &sdata->vif;
conf.type = sdata->vif.type;
conf.mac_addr = dev->dev_addr;
/* disable all keys for as long as this netdev is down */
ieee80211_disable_keys(sdata);
local->ops->remove_interface(local_to_hw(local), &conf);
}
sdata->bss = NULL;
if (local->open_count == 0) {
if (netif_running(local->mdev))
dev_close(local->mdev);
if (local->ops->stop)
local->ops->stop(local_to_hw(local));
ieee80211_led_radio(local, 0);
flush_workqueue(local->hw.workqueue);
tasklet_disable(&local->tx_pending_tasklet);
tasklet_disable(&local->tasklet);
}
return 0;
}
static void ieee80211_set_multicast_list(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
int allmulti, promisc, sdata_allmulti, sdata_promisc;
allmulti = !!(dev->flags & IFF_ALLMULTI);
promisc = !!(dev->flags & IFF_PROMISC);
sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
if (allmulti != sdata_allmulti) {
if (dev->flags & IFF_ALLMULTI)
atomic_inc(&local->iff_allmultis);
else
atomic_dec(&local->iff_allmultis);
sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
}
if (promisc != sdata_promisc) {
if (dev->flags & IFF_PROMISC)
atomic_inc(&local->iff_promiscs);
else
atomic_dec(&local->iff_promiscs);
sdata->flags ^= IEEE80211_SDATA_PROMISC;
}
dev_mc_sync(local->mdev, dev);
}
static void ieee80211_if_setup(struct net_device *dev)
{
ether_setup(dev);
dev->hard_start_xmit = ieee80211_subif_start_xmit;
dev->wireless_handlers = &ieee80211_iw_handler_def;
dev->set_multicast_list = ieee80211_set_multicast_list;
dev->change_mtu = ieee80211_change_mtu;
dev->open = ieee80211_open;
dev->stop = ieee80211_stop;
dev->destructor = free_netdev;
/* we will validate the address ourselves in ->open */
dev->validate_addr = NULL;
}
/*
* Called when the netdev is removed or, by the code below, before
* the interface type changes.
@ -41,7 +576,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
sdata->fragment_next = 0;
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
beacon = sdata->u.ap.beacon;
rcu_assign_pointer(sdata->u.ap.beacon, NULL);
synchronize_rcu();
@ -53,23 +588,23 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
}
break;
case IEEE80211_IF_TYPE_MESH_POINT:
/* Allow compiler to elide mesh_rmc_free call. */
case NL80211_IFTYPE_MESH_POINT:
if (ieee80211_vif_is_mesh(&sdata->vif))
mesh_rmc_free(sdata);
/* fall through */
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
kfree(sdata->u.sta.extra_ie);
kfree(sdata->u.sta.assocreq_ies);
kfree(sdata->u.sta.assocresp_ies);
kfree_skb(sdata->u.sta.probe_resp);
break;
case IEEE80211_IF_TYPE_WDS:
case IEEE80211_IF_TYPE_VLAN:
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
break;
case IEEE80211_IF_TYPE_INVALID:
case NL80211_IFTYPE_UNSPECIFIED:
case __NL80211_IFTYPE_AFTER_LAST:
BUG();
break;
}
@ -82,55 +617,42 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
* Helper function to initialise an interface to a specific type.
*/
static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
enum ieee80211_if_types type)
enum nl80211_iftype type)
{
struct ieee80211_if_sta *ifsta;
/* clear type-dependent union */
memset(&sdata->u, 0, sizeof(sdata->u));
/* and set some type-dependent values */
sdata->vif.type = type;
sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit;
/* only monitor differs */
sdata->dev->type = ARPHRD_ETHER;
switch (type) {
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
INIT_LIST_HEAD(&sdata->u.ap.vlans);
break;
case IEEE80211_IF_TYPE_MESH_POINT:
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
ifsta = &sdata->u.sta;
INIT_WORK(&ifsta->work, ieee80211_sta_work);
setup_timer(&ifsta->timer, ieee80211_sta_timer,
(unsigned long) sdata);
skb_queue_head_init(&ifsta->skb_queue);
ifsta->capab = WLAN_CAPABILITY_ESS;
ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
IEEE80211_AUTH_ALG_SHARED_KEY;
ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
IEEE80211_STA_AUTO_BSSID_SEL |
IEEE80211_STA_AUTO_CHANNEL_SEL;
if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
ieee80211_sta_setup_sdata(sdata);
break;
case NL80211_IFTYPE_MESH_POINT:
if (ieee80211_vif_is_mesh(&sdata->vif))
ieee80211_mesh_init_sdata(sdata);
break;
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP;
sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit;
sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
MONITOR_FLAG_OTHER_BSS;
break;
case IEEE80211_IF_TYPE_WDS:
case IEEE80211_IF_TYPE_VLAN:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_AP_VLAN:
break;
case IEEE80211_IF_TYPE_INVALID:
case NL80211_IFTYPE_UNSPECIFIED:
case __NL80211_IFTYPE_AFTER_LAST:
BUG();
break;
}
@ -139,7 +661,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
}
int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
enum ieee80211_if_types type)
enum nl80211_iftype type)
{
ASSERT_RTNL();
@ -160,14 +682,16 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
ieee80211_setup_sdata(sdata, type);
/* reset some values that shouldn't be kept across type changes */
sdata->basic_rates = 0;
sdata->bss_conf.basic_rates =
ieee80211_mandatory_rates(sdata->local,
sdata->local->hw.conf.channel->band);
sdata->drop_unencrypted = 0;
return 0;
}
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
struct net_device **new_dev, enum ieee80211_if_types type,
struct net_device **new_dev, enum nl80211_iftype type,
struct vif_params *params)
{
struct net_device *ndev;
@ -225,9 +749,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
if (ieee80211_vif_is_mesh(&sdata->vif) &&
params && params->mesh_id_len)
ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
params->mesh_id_len,
params->mesh_id);
ieee80211_sdata_set_mesh_id(sdata,
params->mesh_id_len,
params->mesh_id);
list_add_tail_rcu(&sdata->list, &local->interfaces);

View File

@ -118,12 +118,12 @@ static const u8 *get_mac_for_key(struct ieee80211_key *key)
* address to indicate a transmit-only key.
*/
if (key->conf.alg != ALG_WEP &&
(key->sdata->vif.type == IEEE80211_IF_TYPE_AP ||
key->sdata->vif.type == IEEE80211_IF_TYPE_VLAN))
(key->sdata->vif.type == NL80211_IFTYPE_AP ||
key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
addr = zero_addr;
if (key->sta)
addr = key->sta->addr;
addr = key->sta->sta.addr;
return addr;
}
@ -331,7 +331,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
*/
key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
} else {
if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
struct sta_info *ap;
/*

View File

@ -45,16 +45,9 @@ struct ieee80211_tx_status_rtap_hdr {
u8 data_retries;
} __attribute__ ((packed));
/* common interface routines */
static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
{
memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
return ETH_ALEN;
}
/* must be called under mdev tx lock */
static void ieee80211_configure_filter(struct ieee80211_local *local)
void ieee80211_configure_filter(struct ieee80211_local *local)
{
unsigned int changed_flags;
unsigned int new_flags = 0;
@ -97,6 +90,20 @@ static void ieee80211_configure_filter(struct ieee80211_local *local)
/* master interface */
static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
{
memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
return ETH_ALEN;
}
static const struct header_ops ieee80211_header_ops = {
.create = eth_header,
.parse = header_parse_80211,
.rebuild = eth_rebuild_header,
.cache = eth_header_cache,
.cache_update = eth_header_cache_update,
};
static int ieee80211_master_open(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
@ -139,519 +146,6 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev)
ieee80211_configure_filter(local);
}
/* regular interfaces */
static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
{
int meshhdrlen;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0;
/* FIX: what would be proper limits for MTU?
* This interface uses 802.3 frames. */
if (new_mtu < 256 ||
new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
return -EINVAL;
}
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
dev->mtu = new_mtu;
return 0;
}
static inline int identical_mac_addr_allowed(int type1, int type2)
{
return (type1 == IEEE80211_IF_TYPE_MNTR ||
type2 == IEEE80211_IF_TYPE_MNTR ||
(type1 == IEEE80211_IF_TYPE_AP &&
type2 == IEEE80211_IF_TYPE_WDS) ||
(type1 == IEEE80211_IF_TYPE_WDS &&
(type2 == IEEE80211_IF_TYPE_WDS ||
type2 == IEEE80211_IF_TYPE_AP)) ||
(type1 == IEEE80211_IF_TYPE_AP &&
type2 == IEEE80211_IF_TYPE_VLAN) ||
(type1 == IEEE80211_IF_TYPE_VLAN &&
(type2 == IEEE80211_IF_TYPE_AP ||
type2 == IEEE80211_IF_TYPE_VLAN)));
}
static int ieee80211_open(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata, *nsdata;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
struct ieee80211_if_init_conf conf;
u32 changed = 0;
int res;
bool need_hw_reconfig = 0;
u8 null_addr[ETH_ALEN] = {0};
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
/* fail early if user set an invalid address */
if (compare_ether_addr(dev->dev_addr, null_addr) &&
!is_valid_ether_addr(dev->dev_addr))
return -EADDRNOTAVAIL;
/* we hold the RTNL here so can safely walk the list */
list_for_each_entry(nsdata, &local->interfaces, list) {
struct net_device *ndev = nsdata->dev;
if (ndev != dev && netif_running(ndev)) {
/*
* Allow only a single IBSS interface to be up at any
* time. This is restricted because beacon distribution
* cannot work properly if both are in the same IBSS.
*
* To remove this restriction we'd have to disallow them
* from setting the same SSID on different IBSS interfaces
* belonging to the same hardware. Then, however, we're
* faced with having to adopt two different TSF timers...
*/
if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)
return -EBUSY;
/*
* The remaining checks are only performed for interfaces
* with the same MAC address.
*/
if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
continue;
/*
* check whether it may have the same address
*/
if (!identical_mac_addr_allowed(sdata->vif.type,
nsdata->vif.type))
return -ENOTUNIQ;
/*
* can only add VLANs to enabled APs
*/
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
nsdata->vif.type == IEEE80211_IF_TYPE_AP)
sdata->bss = &nsdata->u.ap;
}
}
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_WDS:
if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
return -ENOLINK;
break;
case IEEE80211_IF_TYPE_VLAN:
if (!sdata->bss)
return -ENOLINK;
list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
break;
case IEEE80211_IF_TYPE_AP:
sdata->bss = &sdata->u.ap;
break;
case IEEE80211_IF_TYPE_MESH_POINT:
/* mesh ifaces must set allmulti to forward mcast traffic */
atomic_inc(&local->iff_allmultis);
break;
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_MNTR:
case IEEE80211_IF_TYPE_IBSS:
/* no special treatment */
break;
case IEEE80211_IF_TYPE_INVALID:
/* cannot happen */
WARN_ON(1);
break;
}
if (local->open_count == 0) {
res = 0;
if (local->ops->start)
res = local->ops->start(local_to_hw(local));
if (res)
goto err_del_bss;
need_hw_reconfig = 1;
ieee80211_led_radio(local, local->hw.conf.radio_enabled);
}
/*
* Check all interfaces and copy the hopefully now-present
* MAC address to those that have the special null one.
*/
list_for_each_entry(nsdata, &local->interfaces, list) {
struct net_device *ndev = nsdata->dev;
/*
* No need to check netif_running since we do not allow
* it to start up with this invalid address.
*/
if (compare_ether_addr(null_addr, ndev->dev_addr) == 0)
memcpy(ndev->dev_addr,
local->hw.wiphy->perm_addr,
ETH_ALEN);
}
if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0)
memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr,
ETH_ALEN);
/*
* Validate the MAC address for this device.
*/
if (!is_valid_ether_addr(dev->dev_addr)) {
if (!local->open_count && local->ops->stop)
local->ops->stop(local_to_hw(local));
return -EADDRNOTAVAIL;
}
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_VLAN:
/* no need to tell driver */
break;
case IEEE80211_IF_TYPE_MNTR:
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
local->cooked_mntrs++;
break;
}
/* must be before the call to ieee80211_configure_filter */
local->monitors++;
if (local->monitors == 1)
local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
local->fif_fcsfail++;
if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
local->fif_plcpfail++;
if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
local->fif_control++;
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss++;
netif_addr_lock_bh(local->mdev);
ieee80211_configure_filter(local);
netif_addr_unlock_bh(local->mdev);
break;
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
/* fall through */
default:
conf.vif = &sdata->vif;
conf.type = sdata->vif.type;
conf.mac_addr = dev->dev_addr;
res = local->ops->add_interface(local_to_hw(local), &conf);
if (res)
goto err_stop;
if (ieee80211_vif_is_mesh(&sdata->vif))
ieee80211_start_mesh(sdata);
changed |= ieee80211_reset_erp_info(sdata);
ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_enable_keys(sdata);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
!(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
netif_carrier_off(dev);
else
netif_carrier_on(dev);
}
if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
/* Create STA entry for the WDS peer */
sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
GFP_KERNEL);
if (!sta) {
res = -ENOMEM;
goto err_del_interface;
}
/* no locking required since STA is not live yet */
sta->flags |= WLAN_STA_AUTHORIZED;
res = sta_info_insert(sta);
if (res) {
/* STA has been freed */
goto err_del_interface;
}
}
if (local->open_count == 0) {
res = dev_open(local->mdev);
WARN_ON(res);
if (res)
goto err_del_interface;
tasklet_enable(&local->tx_pending_tasklet);
tasklet_enable(&local->tasklet);
}
/*
* set_multicast_list will be invoked by the networking core
* which will check whether any increments here were done in
* error and sync them down to the hardware as filter flags.
*/
if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
atomic_inc(&local->iff_allmultis);
if (sdata->flags & IEEE80211_SDATA_PROMISC)
atomic_inc(&local->iff_promiscs);
local->open_count++;
if (need_hw_reconfig) {
ieee80211_hw_config(local);
/*
* set default queue parameters so drivers don't
* need to initialise the hardware if the hardware
* doesn't start up with sane defaults
*/
ieee80211_set_wmm_default(sdata);
}
/*
* ieee80211_sta_work is disabled while network interface
* is down. Therefore, some configuration changes may not
* yet be effective. Trigger execution of ieee80211_sta_work
* to fix this.
*/
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
queue_work(local->hw.workqueue, &ifsta->work);
}
netif_tx_start_all_queues(dev);
return 0;
err_del_interface:
local->ops->remove_interface(local_to_hw(local), &conf);
err_stop:
if (!local->open_count && local->ops->stop)
local->ops->stop(local_to_hw(local));
err_del_bss:
sdata->bss = NULL;
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
list_del(&sdata->u.vlan.list);
return res;
}
static int ieee80211_stop(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_init_conf conf;
struct sta_info *sta;
/*
* Stop TX on this interface first.
*/
netif_tx_stop_all_queues(dev);
/*
* Now delete all active aggregation sessions.
*/
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list, list) {
if (sta->sdata == sdata)
ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr);
}
rcu_read_unlock();
/*
* Remove all stations associated with this interface.
*
* This must be done before calling ops->remove_interface()
* because otherwise we can later invoke ops->sta_notify()
* whenever the STAs are removed, and that invalidates driver
* assumptions about always getting a vif pointer that is valid
* (because if we remove a STA after ops->remove_interface()
* the driver will have removed the vif info already!)
*
* We could relax this and only unlink the stations from the
* hash table and list but keep them on a per-sdata list that
* will be inserted back again when the interface is brought
* up again, but I don't currently see a use case for that,
* except with WDS which gets a STA entry created when it is
* brought up.
*/
sta_info_flush(local, sdata);
/*
* Don't count this interface for promisc/allmulti while it
* is down. dev_mc_unsync() will invoke set_multicast_list
* on the master interface which will sync these down to the
* hardware as filter flags.
*/
if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
atomic_dec(&local->iff_allmultis);
if (sdata->flags & IEEE80211_SDATA_PROMISC)
atomic_dec(&local->iff_promiscs);
dev_mc_unsync(local->mdev, dev);
/* APs need special treatment */
if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
struct ieee80211_sub_if_data *vlan, *tmp;
struct beacon_data *old_beacon = sdata->u.ap.beacon;
/* remove beacon */
rcu_assign_pointer(sdata->u.ap.beacon, NULL);
synchronize_rcu();
kfree(old_beacon);
/* down all dependent devices, that is VLANs */
list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
u.vlan.list)
dev_close(vlan->dev);
WARN_ON(!list_empty(&sdata->u.ap.vlans));
}
local->open_count--;
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_VLAN:
list_del(&sdata->u.vlan.list);
/* no need to tell driver */
break;
case IEEE80211_IF_TYPE_MNTR:
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
local->cooked_mntrs--;
break;
}
local->monitors--;
if (local->monitors == 0)
local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
local->fif_fcsfail--;
if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
local->fif_plcpfail--;
if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
local->fif_control--;
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss--;
netif_addr_lock_bh(local->mdev);
ieee80211_configure_filter(local);
netif_addr_unlock_bh(local->mdev);
break;
case IEEE80211_IF_TYPE_MESH_POINT:
/* allmulti is always set on mesh ifaces */
atomic_dec(&local->iff_allmultis);
/* fall through */
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED;
memset(sdata->u.sta.bssid, 0, ETH_ALEN);
del_timer_sync(&sdata->u.sta.timer);
/*
* When we get here, the interface is marked down.
* Call synchronize_rcu() to wait for the RX path
* should it be using the interface and enqueuing
* frames at this very time on another CPU.
*/
synchronize_rcu();
skb_queue_purge(&sdata->u.sta.skb_queue);
if (local->scan_sdata == sdata) {
if (!local->ops->hw_scan) {
local->sta_sw_scanning = 0;
cancel_delayed_work(&local->scan_work);
} else
local->sta_hw_scanning = 0;
}
sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
kfree(sdata->u.sta.extra_ie);
sdata->u.sta.extra_ie = NULL;
sdata->u.sta.extra_ie_len = 0;
/* fall through */
default:
conf.vif = &sdata->vif;
conf.type = sdata->vif.type;
conf.mac_addr = dev->dev_addr;
/* disable all keys for as long as this netdev is down */
ieee80211_disable_keys(sdata);
local->ops->remove_interface(local_to_hw(local), &conf);
}
sdata->bss = NULL;
if (local->open_count == 0) {
if (netif_running(local->mdev))
dev_close(local->mdev);
if (local->ops->stop)
local->ops->stop(local_to_hw(local));
ieee80211_led_radio(local, 0);
flush_workqueue(local->hw.workqueue);
tasklet_disable(&local->tx_pending_tasklet);
tasklet_disable(&local->tasklet);
}
return 0;
}
static void ieee80211_set_multicast_list(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
int allmulti, promisc, sdata_allmulti, sdata_promisc;
allmulti = !!(dev->flags & IFF_ALLMULTI);
promisc = !!(dev->flags & IFF_PROMISC);
sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
if (allmulti != sdata_allmulti) {
if (dev->flags & IFF_ALLMULTI)
atomic_inc(&local->iff_allmultis);
else
atomic_dec(&local->iff_allmultis);
sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
}
if (promisc != sdata_promisc) {
if (dev->flags & IFF_PROMISC)
atomic_inc(&local->iff_promiscs);
else
atomic_dec(&local->iff_promiscs);
sdata->flags ^= IEEE80211_SDATA_PROMISC;
}
dev_mc_sync(local->mdev, dev);
}
static const struct header_ops ieee80211_header_ops = {
.create = eth_header,
.parse = header_parse_80211,
.rebuild = eth_rebuild_header,
.cache = eth_header_cache,
.cache_update = eth_header_cache_update,
};
void ieee80211_if_setup(struct net_device *dev)
{
ether_setup(dev);
dev->hard_start_xmit = ieee80211_subif_start_xmit;
dev->wireless_handlers = &ieee80211_iw_handler_def;
dev->set_multicast_list = ieee80211_set_multicast_list;
dev->change_mtu = ieee80211_change_mtu;
dev->open = ieee80211_open;
dev->stop = ieee80211_stop;
dev->destructor = free_netdev;
/* we will validate the address ourselves in ->open */
dev->validate_addr = NULL;
}
/* everything else */
int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
@ -662,18 +156,21 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
if (WARN_ON(!netif_running(sdata->dev)))
return 0;
if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
return -EINVAL;
if (!local->ops->config_interface)
return 0;
memset(&conf, 0, sizeof(conf));
conf.changed = changed;
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC) {
conf.bssid = sdata->u.sta.bssid;
conf.ssid = sdata->u.sta.ssid;
conf.ssid_len = sdata->u.sta.ssid_len;
} else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
} else if (sdata->vif.type == NL80211_IFTYPE_AP) {
conf.bssid = sdata->dev->dev_addr;
conf.ssid = sdata->u.ap.ssid;
conf.ssid_len = sdata->u.ap.ssid_len;
@ -702,7 +199,7 @@ int ieee80211_hw_config(struct ieee80211_local *local)
struct ieee80211_channel *chan;
int ret = 0;
if (local->sta_sw_scanning)
if (local->sw_scanning)
chan = local->scan_channel;
else
chan = local->oper_channel;
@ -827,6 +324,9 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
return;
if (!changed)
return;
@ -1046,29 +546,27 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
rcu_read_lock();
if (info->status.excessive_retries) {
sta = sta_info_get(local, hdr->addr1);
if (sta) {
if (test_sta_flags(sta, WLAN_STA_PS)) {
/*
* The STA is in power save mode, so assume
* that this TX packet failed because of that.
*/
ieee80211_handle_filtered_frame(local, sta, skb);
rcu_read_unlock();
return;
}
sta = sta_info_get(local, hdr->addr1);
if (sta) {
if (info->status.excessive_retries &&
test_sta_flags(sta, WLAN_STA_PS)) {
/*
* The STA is in power save mode, so assume
* that this TX packet failed because of that.
*/
ieee80211_handle_filtered_frame(local, sta, skb);
rcu_read_unlock();
return;
}
}
fc = hdr->frame_control;
fc = hdr->frame_control;
if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
(ieee80211_is_data_qos(fc))) {
u16 tid, ssn;
u8 *qc;
if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
(ieee80211_is_data_qos(fc))) {
u16 tid, ssn;
u8 *qc;
sta = sta_info_get(local, hdr->addr1);
if (sta) {
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf;
ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
@ -1076,17 +574,19 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
ieee80211_send_bar(sta->sdata, hdr->addr1,
tid, ssn);
}
}
if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
sta = sta_info_get(local, hdr->addr1);
if (sta) {
if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
ieee80211_handle_filtered_frame(local, sta, skb);
rcu_read_unlock();
return;
} else {
if (info->status.excessive_retries)
sta->tx_retry_failed++;
sta->tx_retry_count += info->status.retry_count;
}
} else
rate_control_tx_status(local->mdev, skb);
}
rcu_read_unlock();
@ -1174,7 +674,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
if (!netif_running(sdata->dev))
continue;
@ -1250,8 +750,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.queues = 1; /* default */
local->bridge_packets = 1;
local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
local->short_retry_limit = 7;
@ -1262,7 +760,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
spin_lock_init(&local->key_lock);
INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
sta_info_init(local);
@ -1422,7 +920,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
/* add one default STA interface */
result = ieee80211_if_add(local, "wlan%d", NULL,
IEEE80211_IF_TYPE_STA, NULL);
NL80211_IFTYPE_STATION, NULL);
if (result)
printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
wiphy_name(local->hw.wiphy));

View File

@ -12,6 +12,9 @@
#include "ieee80211_i.h"
#include "mesh.h"
#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
#define PP_OFFSET 1 /* Path Selection Protocol */
#define PM_OFFSET 5 /* Path Selection Metric */
#define CC_OFFSET 9 /* Congestion Control Mode */
@ -35,6 +38,16 @@ void ieee80211s_stop(void)
kmem_cache_destroy(rm_cache);
}
static void ieee80211_mesh_housekeeping_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata = (void *) data;
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
ifmsh->housekeeping = true;
queue_work(local->hw.workqueue, &ifmsh->work);
}
/**
* mesh_matches_local - check if the config of a mesh point matches ours
*
@ -46,7 +59,7 @@ void ieee80211s_stop(void)
*/
bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_sta *sta = &sdata->u.sta;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
/*
* As support for each feature is added, check for matching
@ -58,11 +71,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
* - MDA enabled
* - Power management control on fc
*/
if (sta->mesh_id_len == ie->mesh_id_len &&
memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 &&
memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 &&
memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0)
if (ifmsh->mesh_id_len == ie->mesh_id_len &&
memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 &&
memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 &&
memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0)
return true;
return false;
@ -95,11 +108,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
*/
free_plinks = mesh_plink_availables(sdata);
if (free_plinks != sdata->u.sta.accepting_plinks)
ieee80211_sta_timer((unsigned long) sdata);
if (free_plinks != sdata->u.mesh.accepting_plinks)
ieee80211_mesh_housekeeping_timer((unsigned long) sdata);
}
void mesh_ids_set_default(struct ieee80211_if_sta *sta)
void mesh_ids_set_default(struct ieee80211_if_mesh *sta)
{
u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff};
@ -112,22 +125,22 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
{
int i;
sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
if (!sdata->u.sta.rmc)
sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
if (!sdata->u.mesh.rmc)
return -ENOMEM;
sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1;
sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
for (i = 0; i < RMC_BUCKETS; i++)
INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list);
INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list);
return 0;
}
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
{
struct mesh_rmc *rmc = sdata->u.sta.rmc;
struct mesh_rmc *rmc = sdata->u.mesh.rmc;
struct rmc_entry *p, *n;
int i;
if (!sdata->u.sta.rmc)
if (!sdata->u.mesh.rmc)
return;
for (i = 0; i < RMC_BUCKETS; i++)
@ -137,7 +150,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
}
kfree(rmc);
sdata->u.sta.rmc = NULL;
sdata->u.mesh.rmc = NULL;
}
/**
@ -155,7 +168,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
struct ieee80211_sub_if_data *sdata)
{
struct mesh_rmc *rmc = sdata->u.sta.rmc;
struct mesh_rmc *rmc = sdata->u.mesh.rmc;
u32 seqnum = 0;
int entries = 0;
u8 idx;
@ -217,11 +230,11 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
}
}
pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len);
pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len);
*pos++ = WLAN_EID_MESH_ID;
*pos++ = sdata->u.sta.mesh_id_len;
if (sdata->u.sta.mesh_id_len)
memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len);
*pos++ = sdata->u.mesh.mesh_id_len;
if (sdata->u.mesh.mesh_id_len)
memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len);
pos = skb_put(skb, 21);
*pos++ = WLAN_EID_MESH_CONFIG;
@ -230,15 +243,15 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
*pos++ = 1;
/* Active path selection protocol ID */
memcpy(pos, sdata->u.sta.mesh_pp_id, 4);
memcpy(pos, sdata->u.mesh.mesh_pp_id, 4);
pos += 4;
/* Active path selection metric ID */
memcpy(pos, sdata->u.sta.mesh_pm_id, 4);
memcpy(pos, sdata->u.mesh.mesh_pm_id, 4);
pos += 4;
/* Congestion control mode identifier */
memcpy(pos, sdata->u.sta.mesh_cc_id, 4);
memcpy(pos, sdata->u.mesh.mesh_cc_id, 4);
pos += 4;
/* Channel precedence:
@ -248,8 +261,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
pos += 4;
/* Mesh capability */
sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata);
*pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00;
sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata);
*pos++ = sdata->u.mesh.accepting_plinks ? ACCEPT_PLINKS : 0x00;
*pos++ = 0x00;
return;
@ -337,10 +350,10 @@ static void ieee80211_mesh_path_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = wdev_priv(&sdata->wdev);
queue_work(local->hw.workqueue, &ifsta->work);
queue_work(local->hw.workqueue, &ifmsh->work);
}
struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
@ -392,50 +405,264 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
struct ieee80211_sub_if_data *sdata)
{
meshhdr->flags = 0;
meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL;
put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum);
sdata->u.sta.mesh_seqnum++;
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
sdata->u.mesh.mesh_seqnum++;
return 6;
}
static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_mesh *ifmsh)
{
bool free_plinks;
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: running mesh housekeeping\n",
sdata->dev->name);
#endif
ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
mesh_path_expire(sdata);
free_plinks = mesh_plink_availables(sdata);
if (free_plinks != sdata->u.mesh.accepting_plinks)
ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
ifmsh->housekeeping = false;
mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
}
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
ifmsh->housekeeping = true;
queue_work(local->hw.workqueue, &ifmsh->work);
ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
}
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
{
del_timer_sync(&sdata->u.mesh.housekeeping_timer);
/*
* If the timer fired while we waited for it, it will have
* requeued the work. Now the work will be running again
* but will not rearm the timer again because it checks
* whether the interface is running, which, at this point,
* it no longer is.
*/
cancel_work_sync(&sdata->u.mesh.work);
/*
* When we get here, the interface is marked down.
* Call synchronize_rcu() to wait for the RX path
* should it be using the interface and enqueuing
* frames at this very time on another CPU.
*/
synchronize_rcu();
skb_queue_purge(&sdata->u.mesh.skb_queue);
}
static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
u16 stype,
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee80211_rx_status *rx_status)
{
struct ieee80211_local *local= sdata->local;
struct ieee802_11_elems elems;
struct ieee80211_channel *channel;
u64 supp_rates = 0;
size_t baselen;
int freq;
enum ieee80211_band band = rx_status->band;
/* ignore ProbeResp to foreign address */
if (stype == IEEE80211_STYPE_PROBE_RESP &&
compare_ether_addr(mgmt->da, sdata->dev->dev_addr))
return;
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
if (baselen > len)
return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
&elems);
if (elems.ds_params && elems.ds_params_len == 1)
freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
else
freq = rx_status->freq;
channel = ieee80211_get_channel(local->hw.wiphy, freq);
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
return;
if (elems.mesh_id && elems.mesh_config &&
mesh_matches_local(&elems, sdata)) {
supp_rates = ieee80211_sta_get_rates(local, &elems, band);
mesh_neighbour_update(mgmt->sa, supp_rates, sdata,
mesh_peer_accepts_plinks(&elems));
}
}
static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee80211_rx_status *rx_status)
{
switch (mgmt->u.action.category) {
case PLINK_CATEGORY:
mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
break;
case MESH_PATH_SEL_CATEGORY:
mesh_rx_path_sel_frame(sdata, mgmt, len);
break;
}
}
static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
struct ieee80211_rx_status *rx_status;
struct ieee80211_if_mesh *ifmsh;
struct ieee80211_mgmt *mgmt;
u16 stype;
ifmsh = &sdata->u.mesh;
rx_status = (struct ieee80211_rx_status *) skb->cb;
mgmt = (struct ieee80211_mgmt *) skb->data;
stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
switch (stype) {
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len,
rx_status);
break;
case IEEE80211_STYPE_ACTION:
ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
break;
}
kfree_skb(skb);
}
static void ieee80211_mesh_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
container_of(work, struct ieee80211_sub_if_data, u.mesh.work);
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct sk_buff *skb;
if (!netif_running(sdata->dev))
return;
if (local->sw_scanning || local->hw_scanning)
return;
while ((skb = skb_dequeue(&ifmsh->skb_queue)))
ieee80211_mesh_rx_queued_mgmt(sdata, skb);
if (ifmsh->preq_queue_len &&
time_after(jiffies,
ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
mesh_path_start_discovery(sdata);
if (ifmsh->housekeeping)
ieee80211_mesh_housekeeping(sdata, ifmsh);
}
void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list)
if (ieee80211_vif_is_mesh(&sdata->vif))
queue_work(local->hw.workqueue, &sdata->u.mesh.work);
rcu_read_unlock();
}
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T;
ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR;
ifsta->mshcfg.dot11MeshTTL = MESH_TTL;
ifsta->mshcfg.auto_open_plinks = true;
ifsta->mshcfg.dot11MeshMaxPeerLinks =
INIT_WORK(&ifmsh->work, ieee80211_mesh_work);
setup_timer(&ifmsh->housekeeping_timer,
ieee80211_mesh_housekeeping_timer,
(unsigned long) sdata);
skb_queue_head_init(&sdata->u.mesh.skb_queue);
ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T;
ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR;
ifmsh->mshcfg.dot11MeshTTL = MESH_TTL;
ifmsh->mshcfg.auto_open_plinks = true;
ifmsh->mshcfg.dot11MeshMaxPeerLinks =
MESH_MAX_ESTAB_PLINKS;
ifsta->mshcfg.dot11MeshHWMPactivePathTimeout =
ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout =
MESH_PATH_TIMEOUT;
ifsta->mshcfg.dot11MeshHWMPpreqMinInterval =
ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval =
MESH_PREQ_MIN_INT;
ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime =
ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime =
MESH_DIAM_TRAVERSAL_TIME;
ifsta->mshcfg.dot11MeshHWMPmaxPREQretries =
ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries =
MESH_MAX_PREQ_RETRIES;
ifsta->mshcfg.path_refresh_time =
ifmsh->mshcfg.path_refresh_time =
MESH_PATH_REFRESH_TIME;
ifsta->mshcfg.min_discovery_timeout =
ifmsh->mshcfg.min_discovery_timeout =
MESH_MIN_DISCOVERY_TIMEOUT;
ifsta->accepting_plinks = true;
ifsta->preq_id = 0;
ifsta->dsn = 0;
atomic_set(&ifsta->mpaths, 0);
ifmsh->accepting_plinks = true;
ifmsh->preq_id = 0;
ifmsh->dsn = 0;
atomic_set(&ifmsh->mpaths, 0);
mesh_rmc_init(sdata);
ifsta->last_preq = jiffies;
ifmsh->last_preq = jiffies;
/* Allocate all mesh structures when creating the first mesh interface. */
if (!mesh_allocated)
ieee80211s_init();
mesh_ids_set_default(ifsta);
setup_timer(&ifsta->mesh_path_timer,
mesh_ids_set_default(ifmsh);
setup_timer(&ifmsh->mesh_path_timer,
ieee80211_mesh_path_timer,
(unsigned long) sdata);
INIT_LIST_HEAD(&ifsta->preq_queue.list);
spin_lock_init(&ifsta->mesh_preq_queue_lock);
INIT_LIST_HEAD(&ifmsh->preq_queue.list);
spin_lock_init(&ifmsh->mesh_preq_queue_lock);
}
ieee80211_rx_result
ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_mgmt *mgmt;
u16 fc;
if (skb->len < 24)
return RX_DROP_MONITOR;
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_BEACON:
case IEEE80211_STYPE_ACTION:
memcpy(skb->cb, rx_status, sizeof(*rx_status));
skb_queue_tail(&ifmsh->skb_queue, skb);
queue_work(local->hw.workqueue, &ifmsh->work);
return RX_QUEUED;
}
return RX_CONTINUE;
}

View File

@ -206,7 +206,7 @@ int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
struct ieee80211_sub_if_data *sdata);
bool mesh_matches_local(struct ieee802_11_elems *ie,
struct ieee80211_sub_if_data *sdata);
void mesh_ids_set_default(struct ieee80211_if_sta *sta);
void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
void mesh_mgmt_ies_add(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
@ -214,6 +214,11 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void);
void ieee80211s_stop(void);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result
ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status);
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
/* Mesh paths */
int mesh_nexthop_lookup(struct sk_buff *skb,
@ -269,8 +274,8 @@ extern int mesh_allocated;
static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata)
{
return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks -
atomic_read(&sdata->u.sta.mshstats.estab_plinks);
return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks -
atomic_read(&sdata->u.mesh.mshstats.estab_plinks);
}
static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata)
@ -288,8 +293,12 @@ static inline void mesh_path_activate(struct mesh_path *mpath)
for (i = 0; i <= x->hash_mask; i++) \
hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list)
void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
#else
#define mesh_allocated 0
static inline void
ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
#endif
#endif /* IEEE80211S_H */

View File

@ -64,14 +64,14 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
#define DSN_LT(x, y) ((long) (x) - (long) (y) < 0)
#define net_traversal_jiffies(s) \
msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
#define default_lifetime(s) \
MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout)
MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout)
#define min_preq_int_jiff(s) \
(msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval))
#define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries)
(msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval))
#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
#define disc_timeout_jiff(s) \
msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout)
msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)
enum mpath_frame_type {
MPATH_PREQ = 0,
@ -223,7 +223,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
/* bitrate is in units of 100 Kbps, while we need rate in units of
* 1Mbps. This will be corrected on tx_time computation.
*/
rate = sband->bitrates[sta->txrate_idx].bitrate;
rate = sband->bitrates[sta->last_txrate_idx].bitrate;
tx_time = (device_constant + 10 * test_frame_len / rate);
estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
@ -395,7 +395,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
u8 *preq_elem, u32 metric) {
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct mesh_path *mpath;
u8 *dst_addr, *orig_addr;
u8 dst_flags, ttl;
@ -414,11 +414,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
forward = false;
reply = true;
metric = 0;
if (time_after(jiffies, ifsta->last_dsn_update +
if (time_after(jiffies, ifmsh->last_dsn_update +
net_traversal_jiffies(sdata)) ||
time_before(jiffies, ifsta->last_dsn_update)) {
dst_dsn = ++ifsta->dsn;
ifsta->last_dsn_update = jiffies;
time_before(jiffies, ifmsh->last_dsn_update)) {
dst_dsn = ++ifmsh->dsn;
ifmsh->last_dsn_update = jiffies;
}
} else {
rcu_read_lock();
@ -444,7 +444,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
if (reply) {
lifetime = PREQ_IE_LIFETIME(preq_elem);
ttl = ifsta->mshcfg.dot11MeshTTL;
ttl = ifmsh->mshcfg.dot11MeshTTL;
if (ttl != 0)
mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr,
cpu_to_le32(dst_dsn), 0, orig_addr,
@ -452,7 +452,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
cpu_to_le32(lifetime), cpu_to_le32(metric),
0, sdata);
else
ifsta->mshstats.dropped_frames_ttl++;
ifmsh->mshstats.dropped_frames_ttl++;
}
if (forward) {
@ -462,7 +462,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
ttl = PREQ_IE_TTL(preq_elem);
lifetime = PREQ_IE_LIFETIME(preq_elem);
if (ttl <= 1) {
ifsta->mshstats.dropped_frames_ttl++;
ifmsh->mshstats.dropped_frames_ttl++;
return;
}
--ttl;
@ -475,7 +475,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
hopcount, ttl, cpu_to_le32(lifetime),
cpu_to_le32(metric), cpu_to_le32(preq_id),
sdata);
ifsta->mshstats.fwded_frames++;
ifmsh->mshstats.fwded_frames++;
}
}
@ -503,7 +503,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
ttl = PREP_IE_TTL(prep_elem);
if (ttl <= 1) {
sdata->u.sta.mshstats.dropped_frames_ttl++;
sdata->u.mesh.mshstats.dropped_frames_ttl++;
return;
}
@ -517,7 +517,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
spin_unlock_bh(&mpath->state_lock);
goto fail;
}
memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
spin_unlock_bh(&mpath->state_lock);
--ttl;
flags = PREP_IE_FLAGS(prep_elem);
@ -529,16 +529,16 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
cpu_to_le32(orig_dsn), 0, dst_addr,
cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl,
cpu_to_le32(dst_dsn), mpath->next_hop->sta.addr, hopcount, ttl,
cpu_to_le32(lifetime), cpu_to_le32(metric),
0, sdata);
rcu_read_unlock();
sdata->u.sta.mshstats.fwded_frames++;
sdata->u.mesh.mshstats.fwded_frames++;
return;
fail:
rcu_read_unlock();
sdata->u.sta.mshstats.dropped_frames_no_route++;
sdata->u.mesh.mshstats.dropped_frames_no_route++;
return;
}
@ -557,7 +557,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
if (mpath) {
spin_lock_bh(&mpath->state_lock);
if (mpath->flags & MESH_PATH_ACTIVE &&
memcmp(ta, mpath->next_hop->addr, ETH_ALEN) == 0 &&
memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 &&
(!(mpath->flags & MESH_PATH_DSN_VALID) ||
DSN_GT(dst_dsn, mpath->dsn))) {
mpath->flags &= ~MESH_PATH_ACTIVE;
@ -631,7 +631,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
{
struct ieee80211_sub_if_data *sdata = mpath->sdata;
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct mesh_preq_queue *preq_node;
preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL);
@ -640,9 +640,9 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
return;
}
spin_lock(&ifsta->mesh_preq_queue_lock);
if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
spin_unlock(&ifsta->mesh_preq_queue_lock);
spin_lock(&ifmsh->mesh_preq_queue_lock);
if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
spin_unlock(&ifmsh->mesh_preq_queue_lock);
kfree(preq_node);
if (printk_ratelimit())
printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n");
@ -652,21 +652,21 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
preq_node->flags = flags;
list_add_tail(&preq_node->list, &ifsta->preq_queue.list);
++ifsta->preq_queue_len;
spin_unlock(&ifsta->mesh_preq_queue_lock);
list_add_tail(&preq_node->list, &ifmsh->preq_queue.list);
++ifmsh->preq_queue_len;
spin_unlock(&ifmsh->mesh_preq_queue_lock);
if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata)))
queue_work(sdata->local->hw.workqueue, &ifsta->work);
if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
queue_work(sdata->local->hw.workqueue, &ifmsh->work);
else if (time_before(jiffies, ifsta->last_preq)) {
else if (time_before(jiffies, ifmsh->last_preq)) {
/* avoid long wait if did not send preqs for a long time
* and jiffies wrapped around
*/
ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
queue_work(sdata->local->hw.workqueue, &ifsta->work);
ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
queue_work(sdata->local->hw.workqueue, &ifmsh->work);
} else
mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq +
mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
min_preq_int_jiff(sdata));
}
@ -677,25 +677,25 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
*/
void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct mesh_preq_queue *preq_node;
struct mesh_path *mpath;
u8 ttl, dst_flags;
u32 lifetime;
spin_lock(&ifsta->mesh_preq_queue_lock);
if (!ifsta->preq_queue_len ||
time_before(jiffies, ifsta->last_preq +
spin_lock(&ifmsh->mesh_preq_queue_lock);
if (!ifmsh->preq_queue_len ||
time_before(jiffies, ifmsh->last_preq +
min_preq_int_jiff(sdata))) {
spin_unlock(&ifsta->mesh_preq_queue_lock);
spin_unlock(&ifmsh->mesh_preq_queue_lock);
return;
}
preq_node = list_first_entry(&ifsta->preq_queue.list,
preq_node = list_first_entry(&ifmsh->preq_queue.list,
struct mesh_preq_queue, list);
list_del(&preq_node->list);
--ifsta->preq_queue_len;
spin_unlock(&ifsta->mesh_preq_queue_lock);
--ifmsh->preq_queue_len;
spin_unlock(&ifmsh->mesh_preq_queue_lock);
rcu_read_lock();
mpath = mesh_path_lookup(preq_node->dst, sdata);
@ -720,18 +720,18 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
goto enddiscovery;
}
ifsta->last_preq = jiffies;
ifmsh->last_preq = jiffies;
if (time_after(jiffies, ifsta->last_dsn_update +
if (time_after(jiffies, ifmsh->last_dsn_update +
net_traversal_jiffies(sdata)) ||
time_before(jiffies, ifsta->last_dsn_update)) {
++ifsta->dsn;
sdata->u.sta.last_dsn_update = jiffies;
time_before(jiffies, ifmsh->last_dsn_update)) {
++ifmsh->dsn;
sdata->u.mesh.last_dsn_update = jiffies;
}
lifetime = default_lifetime(sdata);
ttl = sdata->u.sta.mshcfg.dot11MeshTTL;
ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
if (ttl == 0) {
sdata->u.sta.mshstats.dropped_frames_ttl++;
sdata->u.mesh.mshstats.dropped_frames_ttl++;
spin_unlock_bh(&mpath->state_lock);
goto enddiscovery;
}
@ -743,10 +743,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
spin_unlock_bh(&mpath->state_lock);
mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr,
cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst,
cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst,
cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0,
ttl, cpu_to_le32(lifetime), 0,
cpu_to_le32(ifsta->preq_id++), sdata);
cpu_to_le32(ifmsh->preq_id++), sdata);
mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
enddiscovery:
@ -783,7 +783,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
mpath = mesh_path_lookup(dst_addr, sdata);
if (!mpath) {
dev_kfree_skb(skb);
sdata->u.sta.mshstats.dropped_frames_no_route++;
sdata->u.mesh.mshstats.dropped_frames_no_route++;
err = -ENOSPC;
goto endlookup;
}
@ -791,7 +791,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
if (mpath->flags & MESH_PATH_ACTIVE) {
if (time_after(jiffies, mpath->exp_time -
msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time))
msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
&& !memcmp(sdata->dev->dev_addr, hdr->addr4,
ETH_ALEN)
&& !(mpath->flags & MESH_PATH_RESOLVING)
@ -799,7 +799,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
mesh_queue_preq(mpath,
PREQ_Q_F_START | PREQ_Q_F_REFRESH);
}
memcpy(hdr->addr1, mpath->next_hop->addr,
memcpy(hdr->addr1, mpath->next_hop->sta.addr,
ETH_ALEN);
} else {
if (!(mpath->flags & MESH_PATH_RESOLVING)) {

View File

@ -153,7 +153,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
if (is_multicast_ether_addr(dst))
return -ENOTSUPP;
if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0)
if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
return -ENOSPC;
err = -ENOMEM;
@ -221,7 +221,7 @@ err_exists:
err_node_alloc:
kfree(new_mpath);
err_path_alloc:
atomic_dec(&sdata->u.sta.mpaths);
atomic_dec(&sdata->u.mesh.mpaths);
return err;
}
@ -306,7 +306,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
struct ieee80211_sub_if_data *sdata = node->mpath->sdata;
del_timer_sync(&node->mpath->timer);
atomic_dec(&sdata->u.sta.mpaths);
atomic_dec(&sdata->u.mesh.mpaths);
kfree(node->mpath);
kfree(node);
}
@ -401,7 +401,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
}
kfree_skb(skb);
sdata->u.sta.mshstats.dropped_frames_no_route++;
sdata->u.mesh.mshstats.dropped_frames_no_route++;
}
/**

View File

@ -36,11 +36,11 @@
#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9
#define MESH_SECURITY_FAILED_VERIFICATION 10
#define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries)
#define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout)
#define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout)
#define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout)
#define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks)
#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)
#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)
#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)
#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
enum plink_frame_type {
PLINK_OPEN = 0,
@ -63,14 +63,14 @@ enum plink_event {
static inline
void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
{
atomic_inc(&sdata->u.sta.mshstats.estab_plinks);
atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
mesh_accept_plinks_update(sdata);
}
static inline
void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
{
atomic_dec(&sdata->u.sta.mshstats.estab_plinks);
atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
mesh_accept_plinks_update(sdata);
}
@ -106,7 +106,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
return NULL;
sta->flags = WLAN_STA_AUTHORIZED;
sta->supp_rates[local->hw.conf.channel->band] = rates;
sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
return sta;
}
@ -243,10 +243,10 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data
}
sta->last_rx = jiffies;
sta->supp_rates[local->hw.conf.channel->band] = rates;
sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN &&
sdata->u.sta.accepting_plinks &&
sdata->u.sta.mshcfg.auto_open_plinks)
sdata->u.mesh.accepting_plinks &&
sdata->u.mesh.mshcfg.auto_open_plinks)
mesh_plink_open(sta);
rcu_read_unlock();
@ -275,7 +275,7 @@ static void mesh_plink_timer(unsigned long data)
return;
}
mpl_dbg("Mesh plink timer for %s fired on state %d\n",
print_mac(mac, sta->addr), sta->plink_state);
print_mac(mac, sta->sta.addr), sta->plink_state);
reason = 0;
llid = sta->llid;
plid = sta->plid;
@ -288,7 +288,7 @@ static void mesh_plink_timer(unsigned long data)
if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
u32 rand;
mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n",
print_mac(mac, sta->addr),
print_mac(mac, sta->sta.addr),
sta->plink_retries, sta->plink_timeout);
get_random_bytes(&rand, sizeof(u32));
sta->plink_timeout = sta->plink_timeout +
@ -296,7 +296,7 @@ static void mesh_plink_timer(unsigned long data)
++sta->plink_retries;
mod_plink_timer(sta, sta->plink_timeout);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid,
0, 0);
break;
}
@ -309,7 +309,7 @@ static void mesh_plink_timer(unsigned long data)
sta->plink_state = PLINK_HOLDING;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid,
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid,
reason);
break;
case PLINK_HOLDING:
@ -352,10 +352,10 @@ int mesh_plink_open(struct sta_info *sta)
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink: starting establishment with %s\n",
print_mac(mac, sta->addr));
print_mac(mac, sta->sta.addr));
return mesh_plink_frame_tx(sdata, PLINK_OPEN,
sta->addr, llid, 0, 0);
sta->sta.addr, llid, 0, 0);
}
void mesh_plink_block(struct sta_info *sta)
@ -379,7 +379,7 @@ int mesh_plink_close(struct sta_info *sta)
#endif
mpl_dbg("Mesh plink: closing link with %s\n",
print_mac(mac, sta->addr));
print_mac(mac, sta->sta.addr));
spin_lock_bh(&sta->lock);
sta->reason = cpu_to_le16(MESH_LINK_CANCELLED);
reason = sta->reason;
@ -400,7 +400,7 @@ int mesh_plink_close(struct sta_info *sta)
llid = sta->llid;
plid = sta->plid;
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->addr, llid,
mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->sta.addr, llid,
plid, reason);
return 0;
}
@ -577,9 +577,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->llid = llid;
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid,
0, 0);
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr,
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr,
llid, plid, 0);
break;
default:
@ -604,7 +604,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
llid = sta->llid;
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
plid, reason);
break;
case OPN_ACPT:
@ -613,7 +613,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
sta->plid = plid;
llid = sta->llid;
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
plid, 0);
break;
case CNF_ACPT:
@ -646,13 +646,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
llid = sta->llid;
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
plid, reason);
break;
case OPN_ACPT:
llid = sta->llid;
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
plid, 0);
break;
case CNF_ACPT:
@ -661,7 +661,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
mesh_plink_inc_estab_count(sdata);
spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink with %s ESTABLISHED\n",
print_mac(mac, sta->addr));
print_mac(mac, sta->sta.addr));
break;
default:
spin_unlock_bh(&sta->lock);
@ -685,7 +685,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
llid = sta->llid;
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
plid, reason);
break;
case OPN_ACPT:
@ -694,8 +694,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
mesh_plink_inc_estab_count(sdata);
spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink with %s ESTABLISHED\n",
print_mac(mac, sta->addr));
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid,
print_mac(mac, sta->sta.addr));
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
plid, 0);
break;
default:
@ -714,13 +714,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
llid = sta->llid;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
plid, reason);
break;
case OPN_ACPT:
llid = sta->llid;
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid,
mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
plid, 0);
break;
default:
@ -743,8 +743,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
llid = sta->llid;
reason = sta->reason;
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid,
plid, reason);
mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr,
llid, plid, reason);
break;
default:
spin_unlock_bh(&sta->lock);

File diff suppressed because it is too large Load Diff

View File

@ -134,7 +134,7 @@ static inline int rate_supported(struct sta_info *sta,
enum ieee80211_band band,
int index)
{
return (sta == NULL || sta->supp_rates[band] & BIT(index));
return (sta == NULL || sta->sta.supp_rates[band] & BIT(index));
}
static inline s8

View File

@ -180,6 +180,8 @@ struct rc_pid_sta_info {
u32 tx_num_failed;
u32 tx_num_xmit;
int txrate_idx;
/* Average failed frames percentage error (i.e. actual vs. target
* percentage), scaled by RC_PID_SMOOTHING. This value is computed
* using using an exponential weighted average technique:

View File

@ -75,7 +75,8 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata;
struct ieee80211_supported_band *sband;
int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
int cur = sta->txrate_idx;
struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv;
int cur = spinfo->txrate_idx;
sdata = sta->sdata;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
@ -111,7 +112,7 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
/* Fit the rate found to the nearest supported rate. */
do {
if (rate_supported(sta, band, rinfo[tmp].index)) {
sta->txrate_idx = rinfo[tmp].index;
spinfo->txrate_idx = rinfo[tmp].index;
break;
}
if (adj < 0)
@ -121,9 +122,9 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
} while (tmp < n_bitrates && tmp >= 0);
#ifdef CONFIG_MAC80211_DEBUGFS
rate_control_pid_event_rate_change(
&((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events,
sta->txrate_idx, sband->bitrates[sta->txrate_idx].bitrate);
rate_control_pid_event_rate_change(&spinfo->events,
spinfo->txrate_idx,
sband->bitrates[spinfo->txrate_idx].bitrate);
#endif
}
@ -148,9 +149,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
struct ieee80211_local *local,
struct sta_info *sta)
{
#ifdef CONFIG_MAC80211_MESH
struct ieee80211_sub_if_data *sdata = sta->sdata;
#endif
struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv;
struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
struct ieee80211_supported_band *sband;
@ -181,11 +180,8 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
pf = spinfo->last_pf;
else {
pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
#ifdef CONFIG_MAC80211_MESH
if (pf == 100 &&
sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100)
mesh_plink_broken(sta);
#endif
pf <<= RC_PID_ARITH_SHIFT;
sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
>> RC_PID_ARITH_SHIFT;
@ -195,16 +191,16 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
spinfo->tx_num_failed = 0;
/* If we just switched rate, update the rate behaviour info. */
if (pinfo->oldrate != sta->txrate_idx) {
if (pinfo->oldrate != spinfo->txrate_idx) {
i = rinfo[pinfo->oldrate].rev_index;
j = rinfo[sta->txrate_idx].rev_index;
j = rinfo[spinfo->txrate_idx].rev_index;
tmp = (pf - spinfo->last_pf);
tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT);
rinfo[j].diff = rinfo[i].diff + tmp;
pinfo->oldrate = sta->txrate_idx;
pinfo->oldrate = spinfo->txrate_idx;
}
rate_control_pid_normalize(pinfo, sband->n_bitrates);
@ -257,19 +253,20 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
if (!sta)
goto unlock;
spinfo = sta->rate_ctrl_priv;
/* Don't update the state if we're not controlling the rate. */
sdata = sta->sdata;
if (sdata->force_unicast_rateidx > -1) {
sta->txrate_idx = sdata->max_ratectrl_rateidx;
spinfo->txrate_idx = sdata->max_ratectrl_rateidx;
goto unlock;
}
/* Ignore all frames that were sent with a different rate than the rate
* we currently advise mac80211 to use. */
if (info->tx_rate_idx != sta->txrate_idx)
if (info->tx_rate_idx != spinfo->txrate_idx)
goto unlock;
spinfo = sta->rate_ctrl_priv;
spinfo->tx_num_xmit++;
#ifdef CONFIG_MAC80211_DEBUGFS
@ -287,17 +284,6 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
spinfo->tx_num_xmit++;
}
if (info->status.excessive_retries) {
sta->tx_retry_failed++;
sta->tx_num_consecutive_failures++;
sta->tx_num_mpdu_fail++;
} else {
sta->tx_num_consecutive_failures = 0;
sta->tx_num_mpdu_ok++;
}
sta->tx_retry_count += info->status.retry_count;
sta->tx_num_mpdu_fail += info->status.retry_count;
/* Update PID controller state. */
period = (HZ * pinfo->sampling_period + 500) / 1000;
if (!period)
@ -317,6 +303,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_sub_if_data *sdata;
struct rc_pid_sta_info *spinfo;
struct sta_info *sta;
int rateidx;
u16 fc;
@ -337,16 +324,15 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
/* If a forced rate is in effect, select it. */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv;
if (sdata->force_unicast_rateidx > -1)
sta->txrate_idx = sdata->force_unicast_rateidx;
spinfo->txrate_idx = sdata->force_unicast_rateidx;
rateidx = sta->txrate_idx;
rateidx = spinfo->txrate_idx;
if (rateidx >= sband->n_bitrates)
rateidx = sband->n_bitrates - 1;
sta->last_txrate_idx = rateidx;
rcu_read_unlock();
sel->rate_idx = rateidx;
@ -367,9 +353,10 @@ static void rate_control_pid_rate_init(void *priv, void *priv_sta,
* Until that method is implemented, we will use the lowest supported
* rate as a workaround. */
struct ieee80211_supported_band *sband;
struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
sta->txrate_idx = rate_lowest_index(local, sband, sta);
spinfo->txrate_idx = rate_lowest_index(local, sband, sta);
sta->fail_avg = 0;
}

View File

@ -295,7 +295,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
if (!netif_running(sdata->dev))
continue;
if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR)
if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
continue;
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
@ -403,12 +403,12 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
struct ieee80211_local *local = rx->local;
struct sk_buff *skb = rx->skb;
if (unlikely(local->sta_hw_scanning))
return ieee80211_sta_rx_scan(rx->sdata, skb, rx->status);
if (unlikely(local->hw_scanning))
return ieee80211_scan_rx(rx->sdata, skb, rx->status);
if (unlikely(local->sta_sw_scanning)) {
if (unlikely(local->sw_scanning)) {
/* drop all the other packets during a software scan anyway */
if (ieee80211_sta_rx_scan(rx->sdata, skb, rx->status)
if (ieee80211_scan_rx(rx->sdata, skb, rx->status)
!= RX_QUEUED)
dev_kfree_skb(skb);
return RX_QUEUED;
@ -501,8 +501,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
/* Drop disallowed frame classes based on STA auth/assoc state;
* IEEE 802.11, Chap 5.5.
*
* 80211.o does filtering only based on association state, i.e., it
* drops Class 3 frames from not associated stations. hostapd sends
* mac80211 filters only based on association state, i.e. it drops
* Class 3 frames from not associated stations. hostapd sends
* deauth/disassoc frames when needed. In addition, hostapd is
* responsible for filtering on both auth and assoc states.
*/
@ -512,7 +512,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
if (unlikely((ieee80211_is_data(hdr->frame_control) ||
ieee80211_is_pspoll(hdr->frame_control)) &&
rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
(!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
if ((!ieee80211_has_fromds(hdr->frame_control) &&
!ieee80211_has_tods(hdr->frame_control) &&
@ -661,7 +661,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
dev->name, print_mac(mac, sta->addr), sta->aid);
dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
@ -685,7 +685,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n",
dev->name, print_mac(mac, sta->addr), sta->aid);
dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
/* Send all buffered frames to the station */
@ -702,7 +702,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %s aid %d send PS frame "
"since STA not sleeping anymore\n", dev->name,
print_mac(mac, sta->addr), sta->aid);
print_mac(mac, sta->sta.addr), sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
info->flags |= IEEE80211_TX_CTL_REQUEUE;
dev_queue_xmit(skb);
@ -724,14 +724,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
/* Update last_rx only for IBSS packets which are for the current
* BSSID to avoid keeping the current IBSS network alive in cases where
* other STAs are using different BSSID. */
if (rx->sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
IEEE80211_IF_TYPE_IBSS);
NL80211_IFTYPE_ADHOC);
if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
sta->last_rx = jiffies;
} else
if (!is_multicast_ether_addr(hdr->addr1) ||
rx->sdata->vif.type == IEEE80211_IF_TYPE_STA) {
rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
/* Update last_rx only for unicast frames in order to prevent
* the Probe Request frames (the only broadcast frames from a
* STA in infrastructure mode) from keeping a connection alive.
@ -751,8 +751,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
sta->last_noise = rx->status->noise;
if (!ieee80211_has_morefrags(hdr->frame_control) &&
(rx->sdata->vif.type == IEEE80211_IF_TYPE_AP ||
rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) {
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
/* Change STA power saving mode only in the end of a frame
* exchange sequence */
if (test_sta_flags(sta, WLAN_STA_PS) &&
@ -982,8 +982,8 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
!(rx->flags & IEEE80211_RX_RA_MATCH)))
return RX_CONTINUE;
if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) &&
(sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
if ((sdata->vif.type != NL80211_IFTYPE_AP) &&
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
return RX_DROP_UNUSABLE;
skb = skb_dequeue(&rx->sta->tx_filtered);
@ -1007,7 +1007,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",
print_mac(mac, rx->sta->addr), rx->sta->aid,
print_mac(mac, rx->sta->sta.addr), rx->sta->sta.aid,
skb_queue_len(&rx->sta->ps_tx_buf));
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
@ -1032,7 +1032,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
*/
printk(KERN_DEBUG "%s: STA %s sent PS Poll even "
"though there are no buffered frames for it\n",
rx->dev->name, print_mac(mac, rx->sta->addr));
rx->dev->name, print_mac(mac, rx->sta->sta.addr));
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
@ -1131,23 +1131,23 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
switch (hdr->frame_control &
cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
case __constant_cpu_to_le16(IEEE80211_FCTL_TODS):
if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP &&
sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
return -1;
break;
case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS &&
sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT))
if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
return -1;
break;
case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS):
if (sdata->vif.type != IEEE80211_IF_TYPE_STA ||
if (sdata->vif.type != NL80211_IFTYPE_STATION ||
(is_multicast_ether_addr(dst) &&
!compare_ether_addr(src, dev->dev_addr)))
return -1;
break;
case __constant_cpu_to_le16(0):
if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
return -1;
break;
}
@ -1221,8 +1221,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
skb = rx->skb;
xmit_skb = NULL;
if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP ||
sdata->vif.type == IEEE80211_IF_TYPE_VLAN) &&
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
(rx->flags & IEEE80211_RX_RA_MATCH)) {
if (is_multicast_ether_addr(ehdr->h_dest)) {
/*
@ -1404,7 +1405,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
if (rx->flags & IEEE80211_RX_RA_MATCH) {
if (!mesh_hdr->ttl)
IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta,
IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh,
dropped_frames_ttl);
else {
struct ieee80211_hdr *fwd_hdr;
@ -1535,8 +1536,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
* FIXME: revisit this, I'm sure we should handle most
* of these frames in other modes as well!
*/
if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
return RX_DROP_MONITOR;
switch (mgmt->u.action.category) {
@ -1591,9 +1592,11 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
return RX_DROP_MONITOR;
if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
if (ieee80211_vif_is_mesh(&sdata->vif))
return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status);
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
return RX_DROP_MONITOR;
if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
@ -1629,7 +1632,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
if (!ieee80211_has_protected(hdr->frame_control))
goto ignore;
if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) {
if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) {
/*
* APs with pairwise keys should never receive Michael MIC
* errors for non-zero keyidx because these are reserved for
@ -1699,7 +1702,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx)
if (!netif_running(sdata->dev))
continue;
if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR ||
if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
!(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
continue;
@ -1798,7 +1801,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
int multicast = is_multicast_ether_addr(hdr->addr1);
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
if (!bssid)
return 0;
if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
@ -1813,7 +1816,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
rx->flags &= ~IEEE80211_RX_RA_MATCH;
}
break;
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
if (!bssid)
return 0;
if (ieee80211_is_beacon(hdr->frame_control)) {
@ -1834,7 +1837,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
bssid, hdr->addr2,
BIT(rx->status->rate_idx));
break;
case IEEE80211_IF_TYPE_MESH_POINT:
case NL80211_IFTYPE_MESH_POINT:
if (!multicast &&
compare_ether_addr(sdata->dev->dev_addr,
hdr->addr1) != 0) {
@ -1844,8 +1847,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
rx->flags &= ~IEEE80211_RX_RA_MATCH;
}
break;
case IEEE80211_IF_TYPE_VLAN:
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_AP:
if (!bssid) {
if (compare_ether_addr(sdata->dev->dev_addr,
hdr->addr1))
@ -1857,16 +1860,17 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
rx->flags &= ~IEEE80211_RX_RA_MATCH;
}
break;
case IEEE80211_IF_TYPE_WDS:
case NL80211_IFTYPE_WDS:
if (bssid || !ieee80211_is_data(hdr->frame_control))
return 0;
if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
return 0;
break;
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
/* take everything */
break;
case IEEE80211_IF_TYPE_INVALID:
case NL80211_IFTYPE_UNSPECIFIED:
case __NL80211_IFTYPE_AFTER_LAST:
/* should never get here */
WARN_ON(1);
break;
@ -1915,7 +1919,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
return;
}
if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
if (unlikely(local->sw_scanning || local->hw_scanning))
rx.flags |= IEEE80211_RX_IN_SCAN;
ieee80211_parse_qos(&rx);
@ -1927,7 +1931,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
if (!netif_running(sdata->dev))
continue;
if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR)
if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
continue;
bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
@ -2136,7 +2140,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
/* if this mpdu is fragmented - terminate rx aggregation session */
sc = le16_to_cpu(hdr->seq_ctrl);
if (sc & IEEE80211_SCTL_FRAG) {
ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr,
ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
ret = 1;
goto end_reorder;

View File

@ -32,26 +32,26 @@
void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
{
spin_lock_init(&local->sta_bss_lock);
INIT_LIST_HEAD(&local->sta_bss_list);
spin_lock_init(&local->bss_lock);
INIT_LIST_HEAD(&local->bss_list);
}
void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local)
{
struct ieee80211_sta_bss *bss, *tmp;
struct ieee80211_bss *bss, *tmp;
list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
list_for_each_entry_safe(bss, tmp, &local->bss_list, list)
ieee80211_rx_bss_put(local, bss);
}
struct ieee80211_sta_bss *
struct ieee80211_bss *
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len)
{
struct ieee80211_sta_bss *bss;
struct ieee80211_bss *bss;
spin_lock_bh(&local->sta_bss_lock);
bss = local->sta_bss_hash[STA_HASH(bssid)];
spin_lock_bh(&local->bss_lock);
bss = local->bss_hash[STA_HASH(bssid)];
while (bss) {
if (!bss_mesh_cfg(bss) &&
!memcmp(bss->bssid, bssid, ETH_ALEN) &&
@ -63,13 +63,13 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
}
bss = bss->hnext;
}
spin_unlock_bh(&local->sta_bss_lock);
spin_unlock_bh(&local->bss_lock);
return bss;
}
/* Caller must hold local->sta_bss_lock */
/* Caller must hold local->bss_lock */
static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss)
struct ieee80211_bss *bss)
{
u8 hash_idx;
@ -79,20 +79,20 @@ static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local,
else
hash_idx = STA_HASH(bss->bssid);
bss->hnext = local->sta_bss_hash[hash_idx];
local->sta_bss_hash[hash_idx] = bss;
bss->hnext = local->bss_hash[hash_idx];
local->bss_hash[hash_idx] = bss;
}
/* Caller must hold local->sta_bss_lock */
/* Caller must hold local->bss_lock */
static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss)
struct ieee80211_bss *bss)
{
struct ieee80211_sta_bss *b, *prev = NULL;
b = local->sta_bss_hash[STA_HASH(bss->bssid)];
struct ieee80211_bss *b, *prev = NULL;
b = local->bss_hash[STA_HASH(bss->bssid)];
while (b) {
if (b == bss) {
if (!prev)
local->sta_bss_hash[STA_HASH(bss->bssid)] =
local->bss_hash[STA_HASH(bss->bssid)] =
bss->hnext;
else
prev->hnext = bss->hnext;
@ -103,11 +103,11 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
}
}
struct ieee80211_sta_bss *
struct ieee80211_bss *
ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len)
{
struct ieee80211_sta_bss *bss;
struct ieee80211_bss *bss;
bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
if (!bss)
@ -120,23 +120,23 @@ ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq,
bss->ssid_len = ssid_len;
}
spin_lock_bh(&local->sta_bss_lock);
spin_lock_bh(&local->bss_lock);
/* TODO: order by RSSI? */
list_add_tail(&bss->list, &local->sta_bss_list);
list_add_tail(&bss->list, &local->bss_list);
__ieee80211_rx_bss_hash_add(local, bss);
spin_unlock_bh(&local->sta_bss_lock);
spin_unlock_bh(&local->bss_lock);
return bss;
}
#ifdef CONFIG_MAC80211_MESH
static struct ieee80211_sta_bss *
static struct ieee80211_bss *
ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
u8 *mesh_cfg, int freq)
{
struct ieee80211_sta_bss *bss;
struct ieee80211_bss *bss;
spin_lock_bh(&local->sta_bss_lock);
bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
spin_lock_bh(&local->bss_lock);
bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
while (bss) {
if (bss_mesh_cfg(bss) &&
!memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
@ -149,15 +149,15 @@ ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_i
}
bss = bss->hnext;
}
spin_unlock_bh(&local->sta_bss_lock);
spin_unlock_bh(&local->bss_lock);
return bss;
}
static struct ieee80211_sta_bss *
static struct ieee80211_bss *
ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
u8 *mesh_cfg, int mesh_config_len, int freq)
{
struct ieee80211_sta_bss *bss;
struct ieee80211_bss *bss;
if (mesh_config_len != MESH_CFG_LEN)
return NULL;
@ -186,16 +186,16 @@ ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_i
memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
bss->mesh_id_len = mesh_id_len;
bss->freq = freq;
spin_lock_bh(&local->sta_bss_lock);
spin_lock_bh(&local->bss_lock);
/* TODO: order by RSSI? */
list_add_tail(&bss->list, &local->sta_bss_list);
list_add_tail(&bss->list, &local->bss_list);
__ieee80211_rx_bss_hash_add(local, bss);
spin_unlock_bh(&local->sta_bss_lock);
spin_unlock_bh(&local->bss_lock);
return bss;
}
#endif
static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
static void ieee80211_rx_bss_free(struct ieee80211_bss *bss)
{
kfree(bss->ies);
kfree(bss_mesh_id(bss));
@ -204,21 +204,21 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
}
void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss)
struct ieee80211_bss *bss)
{
local_bh_disable();
if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) {
local_bh_enable();
return;
}
__ieee80211_rx_bss_hash_del(local, bss);
list_del(&bss->list);
spin_unlock_bh(&local->sta_bss_lock);
spin_unlock_bh(&local->bss_lock);
ieee80211_rx_bss_free(bss);
}
struct ieee80211_sta_bss *
struct ieee80211_bss *
ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee80211_rx_status *rx_status,
struct ieee80211_mgmt *mgmt,
@ -226,7 +226,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
struct ieee802_11_elems *elems,
int freq, bool beacon)
{
struct ieee80211_sta_bss *bss;
struct ieee80211_bss *bss;
int clen;
#ifdef CONFIG_MAC80211_MESH
@ -252,9 +252,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
} else {
#if 0
/* TODO: order by RSSI? */
spin_lock_bh(&local->sta_bss_lock);
list_move_tail(&bss->list, &local->sta_bss_list);
spin_unlock_bh(&local->sta_bss_lock);
spin_lock_bh(&local->bss_lock);
list_move_tail(&bss->list, &local->bss_list);
spin_unlock_bh(&local->bss_lock);
#endif
}
@ -327,11 +327,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
}
ieee80211_rx_result
ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status)
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status)
{
struct ieee80211_mgmt *mgmt;
struct ieee80211_sta_bss *bss;
struct ieee80211_bss *bss;
u8 *elements;
struct ieee80211_channel *channel;
size_t baselen;
@ -424,38 +424,37 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local,
ieee80211_tx_skb(sdata, skb, 0);
}
static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
{
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
ieee80211_vif_is_mesh(&sdata->vif))
ieee80211_sta_timer((unsigned long)sdata);
}
void ieee80211_scan_completed(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
union iwreq_data wrqu;
if (WARN_ON(!local->hw_scanning && !local->sw_scanning))
return;
local->last_scan_completed = jiffies;
memset(&wrqu, 0, sizeof(wrqu));
wireless_send_event(local->scan_sdata->dev, SIOCGIWSCAN, &wrqu, NULL);
if (local->sta_hw_scanning) {
local->sta_hw_scanning = 0;
/*
* local->scan_sdata could have been NULLed by the interface
* down code in case we were scanning on an interface that is
* being taken down.
*/
sdata = local->scan_sdata;
if (sdata)
wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL);
if (local->hw_scanning) {
local->hw_scanning = false;
if (ieee80211_hw_config(local))
printk(KERN_DEBUG "%s: failed to restore operational "
"channel after scan\n", wiphy_name(local->hw.wiphy));
/* Restart STA timer for HW scan case */
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list)
ieee80211_restart_sta_timer(sdata);
rcu_read_unlock();
goto done;
}
local->sta_sw_scanning = 0;
local->sw_scanning = false;
if (ieee80211_hw_config(local))
printk(KERN_DEBUG "%s: failed to restore operational "
"channel after scan\n", wiphy_name(local->hw.wiphy));
@ -476,25 +475,24 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
/* Tell AP we're back */
if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
ieee80211_send_nullfunc(local, sdata, 0);
netif_tx_wake_all_queues(sdata->dev);
}
} else
netif_tx_wake_all_queues(sdata->dev);
ieee80211_restart_sta_timer(sdata);
}
rcu_read_unlock();
done:
ieee80211_mlme_notify_scan_completed(local);
ieee80211_mesh_notify_scan_completed(local);
}
EXPORT_SYMBOL(ieee80211_scan_completed);
void ieee80211_sta_scan_work(struct work_struct *work)
void ieee80211_scan_work(struct work_struct *work)
{
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, scan_work.work);
@ -504,7 +502,10 @@ void ieee80211_sta_scan_work(struct work_struct *work)
int skip;
unsigned long next_delay = 0;
if (!local->sta_sw_scanning)
/*
* Avoid re-scheduling when the sdata is going away.
*/
if (!netif_running(sdata->dev))
return;
switch (local->scan_state) {
@ -538,7 +539,7 @@ void ieee80211_sta_scan_work(struct work_struct *work)
chan = &sband->channels[local->scan_channel_idx];
if (chan->flags & IEEE80211_CHAN_DISABLED ||
(sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
(sdata->vif.type == NL80211_IFTYPE_ADHOC &&
chan->flags & IEEE80211_CHAN_NO_IBSS))
skip = 1;
@ -583,14 +584,13 @@ void ieee80211_sta_scan_work(struct work_struct *work)
break;
}
if (local->sta_sw_scanning)
queue_delayed_work(local->hw.workqueue, &local->scan_work,
next_delay);
queue_delayed_work(local->hw.workqueue, &local->scan_work,
next_delay);
}
int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata,
u8 *ssid, size_t ssid_len)
int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata,
u8 *ssid, size_t ssid_len)
{
struct ieee80211_local *local = scan_sdata->local;
struct ieee80211_sub_if_data *sdata;
@ -615,27 +615,30 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata,
* ResultCode: SUCCESS, INVALID_PARAMETERS
*/
if (local->sta_sw_scanning || local->sta_hw_scanning) {
if (local->sw_scanning || local->hw_scanning) {
if (local->scan_sdata == scan_sdata)
return 0;
return -EBUSY;
}
if (local->ops->hw_scan) {
int rc = local->ops->hw_scan(local_to_hw(local),
ssid, ssid_len);
if (!rc) {
local->sta_hw_scanning = 1;
local->scan_sdata = scan_sdata;
int rc;
local->hw_scanning = true;
rc = local->ops->hw_scan(local_to_hw(local), ssid, ssid_len);
if (rc) {
local->hw_scanning = false;
return rc;
}
return rc;
local->scan_sdata = scan_sdata;
return 0;
}
local->sta_sw_scanning = 1;
local->sw_scanning = true;
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
netif_tx_stop_all_queues(sdata->dev);
ieee80211_send_nullfunc(local, sdata, 1);
@ -672,13 +675,14 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata,
}
int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len)
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
u8 *ssid, size_t ssid_len)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_sta *ifsta;
if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
return ieee80211_sta_start_scan(sdata, ssid, ssid_len);
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return ieee80211_start_scan(sdata, ssid, ssid_len);
/*
* STA has a state machine that might need to defer scanning
@ -686,7 +690,7 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t
* queue it up to the state machine in that case.
*/
if (local->sta_sw_scanning || local->sta_hw_scanning) {
if (local->sw_scanning || local->hw_scanning) {
if (local->scan_sdata == sdata)
return 0;
return -EBUSY;
@ -704,9 +708,9 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t
}
static void ieee80211_sta_add_scan_ies(struct iw_request_info *info,
struct ieee80211_sta_bss *bss,
char **current_ev, char *end_buf)
static void ieee80211_scan_add_ies(struct iw_request_info *info,
struct ieee80211_bss *bss,
char **current_ev, char *end_buf)
{
u8 *pos, *end, *next;
struct iw_event iwe;
@ -746,10 +750,10 @@ static void ieee80211_sta_add_scan_ies(struct iw_request_info *info,
static char *
ieee80211_sta_scan_result(struct ieee80211_local *local,
struct iw_request_info *info,
struct ieee80211_sta_bss *bss,
char *current_ev, char *end_buf)
ieee80211_scan_result(struct ieee80211_local *local,
struct iw_request_info *info,
struct ieee80211_bss *bss,
char *current_ev, char *end_buf)
{
struct iw_event iwe;
char *buf;
@ -825,7 +829,7 @@ ieee80211_sta_scan_result(struct ieee80211_local *local,
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
&iwe, "");
ieee80211_sta_add_scan_ies(info, bss, &current_ev, end_buf);
ieee80211_scan_add_ies(info, bss, &current_ev, end_buf);
if (bss->supp_rates_len > 0) {
/* display all supported rates in readable format */
@ -911,23 +915,23 @@ ieee80211_sta_scan_result(struct ieee80211_local *local,
}
int ieee80211_sta_scan_results(struct ieee80211_local *local,
struct iw_request_info *info,
char *buf, size_t len)
int ieee80211_scan_results(struct ieee80211_local *local,
struct iw_request_info *info,
char *buf, size_t len)
{
char *current_ev = buf;
char *end_buf = buf + len;
struct ieee80211_sta_bss *bss;
struct ieee80211_bss *bss;
spin_lock_bh(&local->sta_bss_lock);
list_for_each_entry(bss, &local->sta_bss_list, list) {
spin_lock_bh(&local->bss_lock);
list_for_each_entry(bss, &local->bss_list, list) {
if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
spin_unlock_bh(&local->sta_bss_lock);
spin_unlock_bh(&local->bss_lock);
return -E2BIG;
}
current_ev = ieee80211_sta_scan_result(local, info, bss,
current_ev = ieee80211_scan_result(local, info, bss,
current_ev, end_buf);
}
spin_unlock_bh(&local->sta_bss_lock);
spin_unlock_bh(&local->bss_lock);
return current_ev - buf;
}

View File

@ -73,11 +73,11 @@ static int sta_info_hash_del(struct ieee80211_local *local,
{
struct sta_info *s;
s = local->sta_hash[STA_HASH(sta->addr)];
s = local->sta_hash[STA_HASH(sta->sta.addr)];
if (!s)
return -ENOENT;
if (s == sta) {
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)],
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)],
s->hnext);
return 0;
}
@ -94,13 +94,13 @@ static int sta_info_hash_del(struct ieee80211_local *local,
/* protected by RCU */
static struct sta_info *__sta_info_find(struct ieee80211_local *local,
u8 *addr)
const u8 *addr)
{
struct sta_info *sta;
sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
while (sta) {
if (compare_ether_addr(sta->addr, addr) == 0)
if (compare_ether_addr(sta->sta.addr, addr) == 0)
break;
sta = rcu_dereference(sta->hnext);
}
@ -151,7 +151,7 @@ static void __sta_info_free(struct ieee80211_local *local,
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Destroyed STA %s\n",
wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr));
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
kfree(sta);
@ -219,8 +219,8 @@ void sta_info_destroy(struct sta_info *sta)
static void sta_info_hash_add(struct ieee80211_local *local,
struct sta_info *sta)
{
sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta);
sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)];
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
}
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
@ -231,14 +231,14 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
int i;
DECLARE_MAC_BUF(mbuf);
sta = kzalloc(sizeof(*sta), gfp);
sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
if (!sta)
return NULL;
spin_lock_init(&sta->lock);
spin_lock_init(&sta->flaglock);
memcpy(sta->addr, addr, ETH_ALEN);
memcpy(sta->sta.addr, addr, ETH_ALEN);
sta->local = local;
sta->sdata = sdata;
@ -271,7 +271,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Allocated STA %s\n",
wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr));
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
#ifdef CONFIG_MAC80211_MESH
@ -300,15 +300,15 @@ int sta_info_insert(struct sta_info *sta)
goto out_free;
}
if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 ||
is_multicast_ether_addr(sta->addr))) {
if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 ||
is_multicast_ether_addr(sta->sta.addr))) {
err = -EINVAL;
goto out_free;
}
spin_lock_irqsave(&local->sta_lock, flags);
/* check if STA exists already */
if (__sta_info_find(local, sta->addr)) {
if (__sta_info_find(local, sta->sta.addr)) {
spin_unlock_irqrestore(&local->sta_lock, flags);
err = -EEXIST;
goto out_free;
@ -319,18 +319,18 @@ int sta_info_insert(struct sta_info *sta)
/* notify driver */
if (local->ops->sta_notify) {
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data,
u.ap);
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
STA_NOTIFY_ADD, sta->addr);
STA_NOTIFY_ADD, &sta->sta);
}
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Inserted STA %s\n",
wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
wiphy_name(local->hw.wiphy), print_mac(mac, sta->sta.addr));
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
spin_unlock_irqrestore(&local->sta_lock, flags);
@ -379,11 +379,12 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss,
{
BUG_ON(!bss);
__bss_tim_set(bss, sta->aid);
__bss_tim_set(bss, sta->sta.aid);
if (sta->local->ops->set_tim) {
sta->local->tim_in_locked_section = true;
sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1);
sta->local->ops->set_tim(local_to_hw(sta->local),
&sta->sta, true);
sta->local->tim_in_locked_section = false;
}
}
@ -404,11 +405,12 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
{
BUG_ON(!bss);
__bss_tim_clear(bss, sta->aid);
__bss_tim_clear(bss, sta->sta.aid);
if (sta->local->ops->set_tim) {
sta->local->tim_in_locked_section = true;
sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0);
sta->local->ops->set_tim(local_to_hw(sta->local),
&sta->sta, false);
sta->local->tim_in_locked_section = false;
}
}
@ -424,7 +426,7 @@ void sta_info_clear_tim_bit(struct sta_info *sta)
spin_unlock_irqrestore(&sta->local->sta_lock, flags);
}
void __sta_info_unlink(struct sta_info **sta)
static void __sta_info_unlink(struct sta_info **sta)
{
struct ieee80211_local *local = (*sta)->local;
struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
@ -456,13 +458,13 @@ void __sta_info_unlink(struct sta_info **sta)
local->num_sta--;
if (local->ops->sta_notify) {
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data,
u.ap);
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
STA_NOTIFY_REMOVE, (*sta)->addr);
STA_NOTIFY_REMOVE, &(*sta)->sta);
}
if (ieee80211_vif_is_mesh(&sdata->vif)) {
@ -474,7 +476,7 @@ void __sta_info_unlink(struct sta_info **sta)
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Removed STA %s\n",
wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr));
wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->sta.addr));
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
/*
@ -570,7 +572,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
local->total_ps_buffered--;
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "Buffered frame expired (STA "
"%s)\n", print_mac(mac, sta->addr));
"%s)\n", print_mac(mac, sta->sta.addr));
#endif
dev_kfree_skb(skb);
@ -802,3 +804,40 @@ void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata)
schedule_work(&local->sta_flush_work);
spin_unlock_irqrestore(&local->sta_lock, flags);
}
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
unsigned long exp_time)
{
struct ieee80211_local *local = sdata->local;
struct sta_info *sta, *tmp;
LIST_HEAD(tmp_list);
DECLARE_MAC_BUF(mac);
unsigned long flags;
spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
if (time_after(jiffies, sta->last_rx + exp_time)) {
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
sdata->dev->name, print_mac(mac, sta->sta.addr));
#endif
__sta_info_unlink(&sta);
if (sta)
list_add(&sta->list, &tmp_list);
}
spin_unlock_irqrestore(&local->sta_lock, flags);
list_for_each_entry_safe(sta, tmp, &tmp_list, list)
sta_info_destroy(sta);
}
struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
const u8 *addr)
{
struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr);
if (!sta)
return NULL;
return &sta->sta;
}
EXPORT_SYMBOL(ieee80211_find_sta);

View File

@ -167,8 +167,6 @@ struct sta_ampdu_mlme {
* @lock: used for locking all fields that require locking, see comments
* in the header file.
* @flaglock: spinlock for flags accesses
* @ht_info: HT capabilities of this STA
* @supp_rates: Bitmap of supported rates (per band)
* @addr: MAC address of this STA
* @aid: STA's unique AID (1..2007, 0 = not assigned yet),
* only used in AP (and IBSS?) mode
@ -195,15 +193,11 @@ struct sta_ampdu_mlme {
* @tx_filtered_count: TBD
* @tx_retry_failed: TBD
* @tx_retry_count: TBD
* @tx_num_consecutive_failures: TBD
* @tx_num_mpdu_ok: TBD
* @tx_num_mpdu_fail: TBD
* @fail_avg: moving percentage of failed MSDUs
* @tx_packets: number of RX/TX MSDUs
* @tx_bytes: TBD
* @tx_fragments: number of transmitted MPDUs
* @txrate_idx: TBD
* @last_txrate_idx: TBD
* @last_txrate_idx: Index of the last used transmit rate
* @tid_seq: TBD
* @wme_tx_queue: TBD
* @ampdu_mlme: TBD
@ -218,6 +212,7 @@ struct sta_ampdu_mlme {
* @plink_timeout: TBD
* @plink_timer: TBD
* @debugfs: debug filesystem info
* @sta: station information we share with the driver
*/
struct sta_info {
/* General information, mostly static */
@ -230,10 +225,7 @@ struct sta_info {
void *rate_ctrl_priv;
spinlock_t lock;
spinlock_t flaglock;
struct ieee80211_ht_info ht_info;
u64 supp_rates[IEEE80211_NUM_BANDS];
u8 addr[ETH_ALEN];
u16 aid;
u16 listen_interval;
/*
@ -273,10 +265,6 @@ struct sta_info {
/* Updated from TX status path only, no locking requirements */
unsigned long tx_filtered_count;
unsigned long tx_retry_failed, tx_retry_count;
/* TODO: update in generic code not rate control? */
u32 tx_num_consecutive_failures;
u32 tx_num_mpdu_ok;
u32 tx_num_mpdu_fail;
/* moving percentage of failed MSDUs */
unsigned int fail_avg;
@ -284,8 +272,7 @@ struct sta_info {
unsigned long tx_packets;
unsigned long tx_bytes;
unsigned long tx_fragments;
int txrate_idx;
int last_txrate_idx;
unsigned int last_txrate_idx;
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
@ -327,6 +314,9 @@ struct sta_info {
struct dentry *agg_status;
} debugfs;
#endif
/* keep last! */
struct ieee80211_sta sta;
};
static inline enum plink_state sta_plink_state(struct sta_info *sta)
@ -452,7 +442,6 @@ int sta_info_insert(struct sta_info *sta);
* has already unlinked it.
*/
void sta_info_unlink(struct sta_info **sta);
void __sta_info_unlink(struct sta_info **sta);
void sta_info_destroy(struct sta_info *sta);
void sta_info_set_tim_bit(struct sta_info *sta);
@ -464,5 +453,7 @@ void sta_info_stop(struct ieee80211_local *local);
int sta_info_flush(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
unsigned long exp_time);
#endif /* STA_INFO_H */

View File

@ -304,7 +304,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
u8 bcast[ETH_ALEN] =
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u8 *sta_addr = key->sta->addr;
u8 *sta_addr = key->sta->sta.addr;
if (is_multicast_ether_addr(ra))
sta_addr = bcast;

View File

@ -38,43 +38,6 @@
/* misc utils */
#ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP
static void ieee80211_dump_frame(const char *ifname, const char *title,
const struct sk_buff *skb)
{
const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
unsigned int hdrlen;
DECLARE_MAC_BUF(mac);
printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len);
if (skb->len < 4) {
printk("\n");
return;
}
hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (hdrlen > skb->len)
hdrlen = skb->len;
if (hdrlen >= 4)
printk(" FC=0x%04x DUR=0x%04x",
le16_to_cpu(hdr->frame_control), le16_to_cpu(hdr->duration_id));
if (hdrlen >= 10)
printk(" A1=%s", print_mac(mac, hdr->addr1));
if (hdrlen >= 16)
printk(" A2=%s", print_mac(mac, hdr->addr2));
if (hdrlen >= 24)
printk(" A3=%s", print_mac(mac, hdr->addr3));
if (hdrlen >= 30)
printk(" A4=%s", print_mac(mac, hdr->addr4));
printk("\n");
}
#else /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
static inline void ieee80211_dump_frame(const char *ifname, const char *title,
struct sk_buff *skb)
{
}
#endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
int next_frag_len)
{
@ -111,7 +74,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
hdr = (struct ieee80211_hdr *)tx->skb->data;
if (ieee80211_is_ctl(hdr->frame_control)) {
/* TODO: These control frames are not currently sent by
* 80211.o, but should they be implemented, this function
* mac80211, but should they be implemented, this function
* needs to be updated to support duration field calculation.
*
* RTS: time needed to transmit pending data/mgmt frame plus
@ -153,7 +116,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
if (r->bitrate > txrate->bitrate)
break;
if (tx->sdata->basic_rates & BIT(i))
if (tx->sdata->bss_conf.basic_rates & BIT(i))
rate = r->bitrate;
switch (sband->band) {
@ -222,11 +185,11 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
return TX_CONTINUE;
if (unlikely(tx->local->sta_sw_scanning) &&
if (unlikely(tx->local->sw_scanning) &&
!ieee80211_is_probe_req(hdr->frame_control))
return TX_DROP;
if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
return TX_CONTINUE;
if (tx->flags & IEEE80211_TX_PS_BUFFERED)
@ -236,7 +199,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
ieee80211_is_data(hdr->frame_control))) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
DECLARE_MAC_BUF(mac);
@ -250,7 +213,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
} else {
if (unlikely(ieee80211_is_data(hdr->frame_control) &&
tx->local->num_sta == 0 &&
tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) {
tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) {
/*
* No associated STAs - no need to send multicast
* frames.
@ -281,7 +244,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
struct ieee80211_if_ap *ap;
if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
if (sdata->vif.type != NL80211_IFTYPE_AP)
continue;
ap = &sdata->u.ap;
skb = skb_dequeue(&ap->ps_bc_buf);
@ -381,7 +344,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries "
"before %d)\n",
print_mac(mac, sta->addr), sta->aid,
print_mac(mac, sta->sta.addr), sta->sta.aid,
skb_queue_len(&sta->ps_tx_buf));
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@ -392,7 +355,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: STA %s TX "
"buffer full - dropping oldest frame\n",
tx->dev->name, print_mac(mac, sta->addr));
tx->dev->name, print_mac(mac, sta->sta.addr));
}
#endif
dev_kfree_skb(old);
@ -411,7 +374,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) {
printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll "
"set -> send frame\n", tx->dev->name,
print_mac(mac, sta->addr));
print_mac(mac, sta->sta.addr));
}
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
clear_sta_flags(sta, WLAN_STA_PSPOLL);
@ -485,6 +448,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
if (likely(tx->rate_idx < 0)) {
rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
if (tx->sta)
tx->sta->last_txrate_idx = rsel.rate_idx;
tx->rate_idx = rsel.rate_idx;
if (unlikely(rsel.probe_idx >= 0)) {
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
@ -528,7 +493,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
sband = tx->local->hw.wiphy->bands[tx->channel->band];
if (tx->sta)
info->control.aid = tx->sta->aid;
info->control.sta = &tx->sta->sta;
if (!info->control.retry_limit) {
if (!is_multicast_ether_addr(hdr->addr1)) {
@ -594,7 +559,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
for (idx = 0; idx < sband->n_bitrates; idx++) {
if (sband->bitrates[idx].bitrate > rate->bitrate)
continue;
if (tx->sdata->basic_rates & BIT(idx) &&
if (tx->sdata->bss_conf.basic_rates & BIT(idx) &&
(baserate < 0 ||
(sband->bitrates[baserate].bitrate
< sband->bitrates[idx].bitrate)))
@ -608,7 +573,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
}
if (tx->sta)
info->control.aid = tx->sta->aid;
info->control.sta = &tx->sta->sta;
return TX_CONTINUE;
}
@ -622,7 +587,14 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
u8 *qc;
int tid;
/* only for injected frames */
/*
* Packet injection may want to control the sequence
* number, if we have no matching interface then we
* neither assign one ourselves nor ask the driver to.
*/
if (unlikely(!info->control.vif))
return TX_CONTINUE;
if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
return TX_CONTINUE;
@ -847,7 +819,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
sband = tx->local->hw.wiphy->bands[tx->channel->band];
skb->do_not_encrypt = 1;
info->flags |= IEEE80211_TX_CTL_INJECTED;
tx->flags &= ~IEEE80211_TX_FRAGMENTED;
/*
@ -979,7 +950,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
/* process and remove the injection radiotap header */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (unlikely(sdata->vif.type == IEEE80211_IF_TYPE_MNTR)) {
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
return TX_DROP;
@ -1060,8 +1031,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
return IEEE80211_TX_AGAIN;
info = IEEE80211_SKB_CB(skb);
ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
"TX to low-level driver", skb);
ret = local->ops->tx(local_to_hw(local), skb);
if (ret)
return IEEE80211_TX_AGAIN;
@ -1091,9 +1060,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
}
ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
"TX to low-level driver",
tx->extra_frag[i]);
ret = local->ops->tx(local_to_hw(local),
tx->extra_frag[i]);
if (ret)
@ -1298,6 +1264,11 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
struct ieee80211_sub_if_data *osdata;
int headroom;
bool may_encrypt;
enum {
NOT_MONITOR,
FOUND_SDATA,
UNKNOWN_ADDRESS,
} monitor_iface = NOT_MONITOR;
int ret;
if (skb->iif)
@ -1330,9 +1301,53 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
if (mesh_nexthop_lookup(skb, osdata))
return 0;
if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta,
IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
fwded_frames);
}
} else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) {
struct ieee80211_sub_if_data *sdata;
struct ieee80211_local *local = osdata->local;
struct ieee80211_hdr *hdr;
int hdrlen;
u16 len_rthdr;
info->flags |= IEEE80211_TX_CTL_INJECTED;
monitor_iface = UNKNOWN_ADDRESS;
len_rthdr = ieee80211_get_radiotap_len(skb->data);
hdr = (struct ieee80211_hdr *)skb->data + len_rthdr;
hdrlen = ieee80211_hdrlen(hdr->frame_control);
/* check the header is complete in the frame */
if (likely(skb->len >= len_rthdr + hdrlen)) {
/*
* We process outgoing injected frames that have a
* local address we handle as though they are our
* own frames.
* This code here isn't entirely correct, the local
* MAC address is not necessarily enough to find
* the interface to use; for that proper VLAN/WDS
* support we will need a different mechanism.
*/
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces,
list) {
if (!netif_running(sdata->dev))
continue;
if (compare_ether_addr(sdata->dev->dev_addr,
hdr->addr2)) {
dev_hold(sdata->dev);
dev_put(odev);
osdata = sdata;
odev = osdata->dev;
skb->iif = sdata->dev->ifindex;
monitor_iface = FOUND_SDATA;
break;
}
}
rcu_read_unlock();
}
}
may_encrypt = !skb->do_not_encrypt;
@ -1349,7 +1364,12 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
return 0;
}
info->control.vif = &osdata->vif;
if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN)
osdata = container_of(osdata->bss,
struct ieee80211_sub_if_data,
u.ap);
if (likely(monitor_iface != UNKNOWN_ADDRESS))
info->control.vif = &osdata->vif;
ret = ieee80211_tx(odev, skb);
dev_put(odev);
@ -1457,8 +1477,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_AP:
case IEEE80211_IF_TYPE_VLAN:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
/* DA BSSID SA */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
@ -1466,7 +1486,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 24;
break;
case IEEE80211_IF_TYPE_WDS:
case NL80211_IFTYPE_WDS:
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);
@ -1476,16 +1496,16 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
hdrlen = 30;
break;
#ifdef CONFIG_MAC80211_MESH
case IEEE80211_IF_TYPE_MESH_POINT:
case NL80211_IFTYPE_MESH_POINT:
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memset(hdr.addr1, 0, ETH_ALEN);
memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
if (!sdata->u.sta.mshcfg.dot11MeshTTL) {
if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
/* Do not send frames with mesh_ttl == 0 */
sdata->u.sta.mshstats.dropped_frames_ttl++;
sdata->u.mesh.mshstats.dropped_frames_ttl++;
ret = 0;
goto fail;
}
@ -1493,7 +1513,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
hdrlen = 30;
break;
#endif
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
/* BSSID SA DA */
memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN);
@ -1501,7 +1521,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
memcpy(hdr.addr3, skb->data, ETH_ALEN);
hdrlen = 24;
break;
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
/* DA SA BSSID */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
@ -1580,19 +1600,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
nh_pos -= skip_header_bytes;
h_pos -= skip_header_bytes;
/* TODO: implement support for fragments so that there is no need to
* reallocate and copy payload; it might be enough to support one
* extra fragment that would be copied in the beginning of the frame
* data.. anyway, it would be nice to include this into skb structure
* somehow
*
* There are few options for this:
* use skb->cb as an extra space for 802.11 header
* allocate new buffer if not enough headroom
* make sure that there is enough headroom in every skb by increasing
* build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
* alloc_skb() (net/core/skbuff.c)
*/
head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
/*
@ -1815,10 +1822,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
struct rate_selection rsel;
struct beacon_data *beacon;
struct ieee80211_supported_band *sband;
struct ieee80211_mgmt *mgmt;
int *num_beacons;
enum ieee80211_band band = local->hw.conf.channel->band;
u8 *pos;
sband = local->hw.wiphy->bands[band];
@ -1827,7 +1831,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
sdata = vif_to_sdata(vif);
bdev = sdata->dev;
if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
if (sdata->vif.type == NL80211_IFTYPE_AP) {
ap = &sdata->u.ap;
beacon = rcu_dereference(ap->beacon);
if (ap && beacon) {
@ -1865,11 +1869,9 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
if (beacon->tail)
memcpy(skb_put(skb, beacon->tail_len),
beacon->tail, beacon->tail_len);
num_beacons = &ap->num_beacons;
} else
goto out;
} else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
struct ieee80211_hdr *hdr;
ifsta = &sdata->u.sta;
@ -1884,8 +1886,10 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_BEACON);
num_beacons = &ifsta->num_beacons;
} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
struct ieee80211_mgmt *mgmt;
u8 *pos;
/* headroom, head length, tail length and maximum TIM length */
skb = dev_alloc_skb(local->tx_headroom + 400);
if (!skb)
@ -1909,8 +1913,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
*pos++ = 0x0;
mesh_mgmt_ies_add(skb, sdata);
num_beacons = &sdata->u.sta.num_beacons;
} else {
WARN_ON(1);
goto out;
@ -1947,7 +1949,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
info->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
info->control.retry_limit = 1;
(*num_beacons)++;
out:
rcu_read_unlock();
return skb;
@ -2009,7 +2010,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
rcu_read_lock();
beacon = rcu_dereference(bss->beacon);
if (sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon || !beacon->head)
if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head)
goto out;
if (bss->dtim_count != 0)

View File

@ -43,7 +43,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) =
u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
enum ieee80211_if_types type)
enum nl80211_iftype type)
{
__le16 fc = hdr->frame_control;
@ -77,10 +77,10 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
if (ieee80211_is_back_req(fc)) {
switch (type) {
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
return hdr->addr2;
case IEEE80211_IF_TYPE_AP:
case IEEE80211_IF_TYPE_VLAN:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
return hdr->addr1;
default:
break; /* fall through to the return */
@ -231,16 +231,21 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
struct ieee80211_rate *rate)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_sub_if_data *sdata;
u16 dur;
int erp;
bool short_preamble = false;
erp = 0;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
if (vif) {
sdata = vif_to_sdata(vif);
short_preamble = sdata->bss_conf.use_short_preamble;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
}
dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp,
sdata->bss_conf.use_short_preamble);
short_preamble);
return cpu_to_le16(dur);
}
@ -252,7 +257,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_rate *rate;
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_sub_if_data *sdata;
bool short_preamble;
int erp;
u16 dur;
@ -260,13 +265,17 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
short_preamble = sdata->bss_conf.use_short_preamble;
short_preamble = false;
rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
erp = 0;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
if (vif) {
sdata = vif_to_sdata(vif);
short_preamble = sdata->bss_conf.use_short_preamble;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
}
/* CTS duration */
dur = ieee80211_frame_duration(local, 10, rate->bitrate,
@ -289,7 +298,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_rate *rate;
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_sub_if_data *sdata;
bool short_preamble;
int erp;
u16 dur;
@ -297,12 +306,16 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
short_preamble = sdata->bss_conf.use_short_preamble;
short_preamble = false;
rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
erp = 0;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
if (vif) {
sdata = vif_to_sdata(vif);
short_preamble = sdata->bss_conf.use_short_preamble;
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
erp = rate->flags & IEEE80211_RATE_ERP_G;
}
/* Data frame duration */
dur = ieee80211_frame_duration(local, frame_len, rate->bitrate,
@ -376,15 +389,16 @@ void ieee80211_iterate_active_interfaces(
list_for_each_entry(sdata, &local->interfaces, list) {
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_INVALID:
case IEEE80211_IF_TYPE_MNTR:
case IEEE80211_IF_TYPE_VLAN:
case __NL80211_IFTYPE_AFTER_LAST:
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP_VLAN:
continue;
case IEEE80211_IF_TYPE_AP:
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
case IEEE80211_IF_TYPE_WDS:
case IEEE80211_IF_TYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
break;
}
if (netif_running(sdata->dev))
@ -409,15 +423,16 @@ void ieee80211_iterate_active_interfaces_atomic(
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_INVALID:
case IEEE80211_IF_TYPE_MNTR:
case IEEE80211_IF_TYPE_VLAN:
case __NL80211_IFTYPE_AFTER_LAST:
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP_VLAN:
continue;
case IEEE80211_IF_TYPE_AP:
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
case IEEE80211_IF_TYPE_WDS:
case IEEE80211_IF_TYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
break;
}
if (netif_running(sdata->dev))
@ -612,3 +627,59 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
dev_queue_xmit(skb);
}
int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
{
int ret = -EINVAL;
struct ieee80211_channel *chan;
struct ieee80211_local *local = sdata->local;
chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
chan->flags & IEEE80211_CHAN_NO_IBSS) {
printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
"%d MHz\n", sdata->dev->name, chan->center_freq);
return ret;
}
local->oper_channel = chan;
if (local->sw_scanning || local->hw_scanning)
ret = 0;
else
ret = ieee80211_hw_config(local);
rate_control_clear(local);
}
return ret;
}
u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band)
{
struct ieee80211_supported_band *sband;
struct ieee80211_rate *bitrates;
u64 mandatory_rates;
enum ieee80211_rate_flags mandatory_flag;
int i;
sband = local->hw.wiphy->bands[band];
if (!sband) {
WARN_ON(1);
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
}
if (band == IEEE80211_BAND_2GHZ)
mandatory_flag = IEEE80211_RATE_MANDATORY_B;
else
mandatory_flag = IEEE80211_RATE_MANDATORY_A;
bitrates = sband->bitrates;
mandatory_rates = 0;
for (i = 0; i < sband->n_bitrates; i++)
if (bitrates[i].flags & mandatory_flag)
mandatory_rates |= BIT(i);
return mandatory_rates;
}

View File

@ -122,8 +122,8 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
return -EOPNOTSUPP;
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC) {
int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
if (ret)
return ret;
@ -273,21 +273,21 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev,
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
int type;
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
return -EOPNOTSUPP;
switch (*mode) {
case IW_MODE_INFRA:
type = IEEE80211_IF_TYPE_STA;
type = NL80211_IFTYPE_STATION;
break;
case IW_MODE_ADHOC:
type = IEEE80211_IF_TYPE_IBSS;
type = NL80211_IFTYPE_ADHOC;
break;
case IW_MODE_REPEAT:
type = IEEE80211_IF_TYPE_WDS;
type = NL80211_IFTYPE_WDS;
break;
case IW_MODE_MONITOR:
type = IEEE80211_IF_TYPE_MNTR;
type = NL80211_IFTYPE_MONITOR;
break;
default:
return -EINVAL;
@ -305,22 +305,22 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_AP:
case NL80211_IFTYPE_AP:
*mode = IW_MODE_MASTER;
break;
case IEEE80211_IF_TYPE_STA:
case NL80211_IFTYPE_STATION:
*mode = IW_MODE_INFRA;
break;
case IEEE80211_IF_TYPE_IBSS:
case NL80211_IFTYPE_ADHOC:
*mode = IW_MODE_ADHOC;
break;
case IEEE80211_IF_TYPE_MNTR:
case NL80211_IFTYPE_MONITOR:
*mode = IW_MODE_MONITOR;
break;
case IEEE80211_IF_TYPE_WDS:
case NL80211_IFTYPE_WDS:
*mode = IW_MODE_REPEAT;
break;
case IEEE80211_IF_TYPE_VLAN:
case NL80211_IFTYPE_AP_VLAN:
*mode = IW_MODE_SECOND; /* FIXME */
break;
default:
@ -330,47 +330,19 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev,
return 0;
}
int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
{
int ret = -EINVAL;
struct ieee80211_channel *chan;
struct ieee80211_local *local = sdata->local;
chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
chan->flags & IEEE80211_CHAN_NO_IBSS) {
printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
"%d MHz\n", sdata->dev->name, chan->center_freq);
return ret;
}
local->oper_channel = chan;
if (local->sta_sw_scanning || local->sta_hw_scanning)
ret = 0;
else
ret = ieee80211_hw_config(local);
rate_control_clear(local);
}
return ret;
}
static int ieee80211_ioctl_siwfreq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *freq, char *extra)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
if (sdata->vif.type == NL80211_IFTYPE_STATION)
sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
if (freq->e == 0) {
if (freq->m < 0) {
if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
if (sdata->vif.type == NL80211_IFTYPE_STATION)
sdata->u.sta.flags |=
IEEE80211_STA_AUTO_CHANNEL_SEL;
return 0;
@ -414,8 +386,8 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev,
len--;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC) {
int ret;
if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
if (len > IEEE80211_MAX_SSID_LEN)
@ -435,7 +407,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev,
return 0;
}
if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
if (sdata->vif.type == NL80211_IFTYPE_AP) {
memcpy(sdata->u.ap.ssid, ssid, len);
memset(sdata->u.ap.ssid + len, 0,
IEEE80211_MAX_SSID_LEN - len);
@ -454,8 +426,8 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC) {
int res = ieee80211_sta_get_ssid(sdata, ssid, &len);
if (res == 0) {
data->length = len;
@ -465,7 +437,7 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev,
return res;
}
if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
if (sdata->vif.type == NL80211_IFTYPE_AP) {
len = sdata->u.ap.ssid_len;
if (len > IW_ESSID_MAX_SIZE)
len = IW_ESSID_MAX_SIZE;
@ -485,8 +457,8 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC) {
int ret;
if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
@ -505,7 +477,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
return ret;
ieee80211_sta_req_auth(sdata, &sdata->u.sta);
return 0;
} else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
} else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
/*
* If it is necessary to update the WDS peer address
* while the interface is running, then we need to do
@ -533,8 +505,8 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC) {
if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED ||
sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) {
ap_addr->sa_family = ARPHRD_ETHER;
@ -544,7 +516,7 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
memset(&ap_addr->sa_data, 0, ETH_ALEN);
return 0;
}
} else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
} else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
ap_addr->sa_family = ARPHRD_ETHER;
memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
return 0;
@ -566,10 +538,10 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev,
if (!netif_running(dev))
return -ENETDOWN;
if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT &&
sdata->vif.type != IEEE80211_IF_TYPE_AP)
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP)
return -EOPNOTSUPP;
/* if SSID was specified explicitly then use that */
@ -580,7 +552,7 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev,
ssid_len = req->essid_len;
}
return ieee80211_sta_req_scan(sdata, ssid, ssid_len);
return ieee80211_request_scan(sdata, ssid, ssid_len);
}
@ -594,10 +566,10 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (local->sta_sw_scanning || local->sta_hw_scanning)
if (local->sw_scanning || local->hw_scanning)
return -EAGAIN;
res = ieee80211_sta_scan_results(local, info, extra, data->length);
res = ieee80211_scan_results(local, info, extra, data->length);
if (res >= 0) {
data->length = res;
return 0;
@ -655,7 +627,7 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
@ -664,8 +636,8 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev,
sta = sta_info_get(local, sdata->u.sta.bssid);
if (sta && sta->txrate_idx < sband->n_bitrates)
rate->value = sband->bitrates[sta->txrate_idx].bitrate;
if (sta && sta->last_txrate_idx < sband->n_bitrates)
rate->value = sband->bitrates[sta->last_txrate_idx].bitrate;
else
rate->value = 0;
@ -886,8 +858,8 @@ static int ieee80211_ioctl_siwmlme(struct net_device *dev,
struct iw_mlme *mlme = (struct iw_mlme *) extra;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
return -EINVAL;
switch (mlme->cmd) {
@ -982,7 +954,7 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev,
erq->length = sdata->keys[idx]->conf.keylen;
erq->flags |= IW_ENCODE_ENABLED;
if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
switch (ifsta->auth_alg) {
case WLAN_AUTH_OPEN:
@ -1056,7 +1028,7 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
sdata->drop_unencrypted = !!data->value;
break;
case IW_AUTH_PRIVACY_INVOKED:
if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
if (sdata->vif.type != NL80211_IFTYPE_STATION)
ret = -EINVAL;
else {
sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
@ -1071,8 +1043,8 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
}
break;
case IW_AUTH_80211_AUTH_ALG:
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC)
sdata->u.sta.auth_algs = data->value;
else
ret = -EOPNOTSUPP;
@ -1094,8 +1066,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev
rcu_read_lock();
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC)
sta = sta_info_get(local, sdata->u.sta.bssid);
if (!sta) {
wstats->discard.fragment = 0;
@ -1125,8 +1097,8 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev,
switch (data->flags & IW_AUTH_INDEX) {
case IW_AUTH_80211_AUTH_ALG:
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
if (sdata->vif.type == NL80211_IFTYPE_STATION ||
sdata->vif.type == NL80211_IFTYPE_ADHOC)
data->value = sdata->u.sta.auth_algs;
else
ret = -EOPNOTSUPP;

View File

@ -210,7 +210,7 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
DECLARE_MAC_BUF(mac);
printk(KERN_DEBUG "allocated aggregation queue"
" %d tid %d addr %s pool=0x%lX\n",
i, tid, print_mac(mac, sta->addr),
i, tid, print_mac(mac, sta->sta.addr),
local->queue_pool[0]);
}
#endif /* CONFIG_MAC80211_HT_DEBUG */

View File

@ -1,5 +1,4 @@
/*
* IEEE 802.11 driver (80211.o) - QoS datatypes
* Copyright 2004, Instant802 Networks, Inc.
* Copyright 2005, Devicescape Software, Inc.
*

Some files were not shown because too many files have changed in this diff Show More