Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
d950f264ff
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = ®_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;
|
||||
}
|
||||
|
|
@ -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:
|
||||
--------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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])");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -384,7 +384,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
|
|||
rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®);
|
||||
rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6);
|
||||
rt2x00_set_field16(®, 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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "zd_def.h"
|
||||
#include "zd_chip.h"
|
||||
#include "zd_ieee80211.h"
|
||||
#include "zd_mac.h"
|
||||
#include "zd_rf.h"
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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 = ®_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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, ¤t_ev, end_buf);
|
||||
ieee80211_scan_add_ies(info, bss, ¤t_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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue