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

This commit is contained in:
David S. Miller 2009-09-02 14:18:09 -07:00
commit 3f968de276
36 changed files with 895 additions and 541 deletions

View file

@ -2,8 +2,17 @@
# Wireless LAN device configuration
#
menu "Wireless LAN"
menuconfig WLAN
bool "Wireless LAN"
depends on !S390
---help---
This section contains all the pre 802.11 and 802.11 wireless
device drivers. For a complete list of drivers and documentation
on them refer to the wireless wiki:
http://wireless.kernel.org/en/users/Drivers
if WLAN
menuconfig WLAN_PRE80211
bool "Wireless LAN (pre-802.11)"
@ -337,7 +346,6 @@ config USB_NET_RNDIS_WLAN
select USB_USBNET
select USB_NET_CDCETHER
select USB_NET_RNDIS_HOST
select WIRELESS_EXT
---help---
This is a driver for wireless RNDIS devices.
These are USB based adapters found in devices such as:
@ -506,4 +514,4 @@ source "drivers/net/wireless/orinoco/Kconfig"
source "drivers/net/wireless/wl12xx/Kconfig"
source "drivers/net/wireless/iwmc3200wifi/Kconfig"
endmenu
endif # WLAN

View file

@ -84,15 +84,14 @@ static void ath_btcoex_period_timer(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *) data;
struct ath_btcoex_info *btinfo = &sc->btcoex_info;
unsigned long flags;
ath_detect_bt_priority(sc);
spin_lock_irqsave(&btinfo->btcoex_lock, flags);
spin_lock_bh(&btinfo->btcoex_lock);
ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type);
spin_unlock_irqrestore(&btinfo->btcoex_lock, flags);
spin_unlock_bh(&btinfo->btcoex_lock);
if (btinfo->btcoex_period != btinfo->btcoex_no_stomp) {
if (btinfo->hw_timer_enabled)
@ -119,18 +118,17 @@ static void ath_btcoex_no_stomp_timer(void *arg)
{
struct ath_softc *sc = (struct ath_softc *)arg;
struct ath_btcoex_info *btinfo = &sc->btcoex_info;
unsigned long flags;
DPRINTF(sc, ATH_DBG_BTCOEX, "no stomp timer running \n");
spin_lock_irqsave(&btinfo->btcoex_lock, flags);
spin_lock_bh(&btinfo->btcoex_lock);
if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE);
else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW);
spin_unlock_irqrestore(&btinfo->btcoex_lock, flags);
spin_unlock_bh(&btinfo->btcoex_lock);
}
static int ath_init_btcoex_info(struct ath_hw *hw,

View file

@ -1712,8 +1712,15 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
AR_RTC_FORCE_WAKE_ON_INT);
if (!AR_SREV_9100(ah))
REG_WRITE(ah, AR_RC, AR_RC_AHB);
REG_WRITE(ah, AR_RTC_RESET, 0);
udelay(2);
if (!AR_SREV_9100(ah))
REG_WRITE(ah, AR_RC, 0);
REG_WRITE(ah, AR_RTC_RESET, 1);
if (!ath9k_hw_wait(ah,

View file

@ -506,6 +506,10 @@ static void ath9k_tasklet(unsigned long data)
sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC;
}
if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(sc->sc_ah);
/* re-enable hardware interrupt */
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
ath9k_ps_restore(sc);
@ -521,7 +525,8 @@ irqreturn_t ath_isr(int irq, void *dev)
ATH9K_INT_TX | \
ATH9K_INT_BMISS | \
ATH9K_INT_CST | \
ATH9K_INT_TSFOOR)
ATH9K_INT_TSFOOR | \
ATH9K_INT_GENTIMER)
struct ath_softc *sc = dev;
struct ath_hw *ah = sc->sc_ah;
@ -602,10 +607,6 @@ irqreturn_t ath_isr(int irq, void *dev)
sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
}
if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(ah);
chip_reset:
ath_debug_stat_interrupt(sc, status);
@ -2772,6 +2773,7 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
sc->sc_flags &= ~SC_OP_SCANNING;
sc->sc_flags |= SC_OP_FULL_RESET;
spin_unlock_bh(&sc->ani_lock);
ath_beacon_config(sc, NULL);
mutex_unlock(&sc->mutex);
}

View file

@ -58,6 +58,7 @@ MODULE_DESCRIPTION("Broadcom B43 wireless driver");
MODULE_AUTHOR("Martin Langer");
MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_AUTHOR("Gábor Stefanik");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID);
@ -90,7 +91,7 @@ MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
static int modparam_btcoex = 1;
module_param_named(btcoex, modparam_btcoex, int, 0444);
MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)");
MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistence (default on)");
int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
module_param_named(verbose, b43_modparam_verbose, int, 0644);

View file

@ -518,58 +518,40 @@ static unsigned int b43_aphy_op_get_default_chan(struct b43_wldev *dev)
static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
{//TODO
struct b43_phy *phy = &dev->phy;
u64 hf;
u16 tmp;
int autodiv = 0;
if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
autodiv = 1;
hf = b43_hf_read(dev);
hf &= ~B43_HF_ANTDIVHELP;
b43_hf_write(dev, hf);
b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
tmp &= ~B43_PHY_BBANDCFG_RXANT;
tmp |= (autodiv ? B43_ANTENNA_AUTO1 : antenna)
<< B43_PHY_BBANDCFG_RXANT_SHIFT;
b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
b43_phy_maskset(dev, B43_PHY_BBANDCFG, ~B43_PHY_BBANDCFG_RXANT,
(autodiv ? B43_ANTENNA_AUTO1 : antenna) <<
B43_PHY_BBANDCFG_RXANT_SHIFT);
if (autodiv) {
tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
if (antenna == B43_ANTENNA_AUTO0)
if (antenna == B43_ANTENNA_AUTO1)
tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
else
tmp |= B43_PHY_ANTDWELL_AUTODIV1;
b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
}
if (phy->rev < 3) {
tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
tmp = (tmp & 0xFF00) | 0x24;
b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
} else {
tmp = b43_phy_read(dev, B43_PHY_OFDM61);
tmp |= 0x10;
b43_phy_write(dev, B43_PHY_OFDM61, tmp);
if (phy->analog == 3) {
b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
0x1D);
b43_phy_write(dev, B43_PHY_ADIVRELATED,
8);
if (phy->rev < 3)
b43_phy_maskset(dev, B43_PHY_ANTDWELL, 0xFF00, 0x24);
else {
b43_phy_set(dev, B43_PHY_OFDM61, 0x10);
if (phy->rev == 3) {
b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, 0x1D);
b43_phy_write(dev, B43_PHY_ADIVRELATED, 8);
} else {
b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
0x3A);
tmp =
b43_phy_read(dev,
B43_PHY_ADIVRELATED);
tmp = (tmp & 0xFF00) | 8;
b43_phy_write(dev, B43_PHY_ADIVRELATED,
tmp);
b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, 0x3A);
b43_phy_maskset(dev, B43_PHY_ADIVRELATED, 0xFF00, 8);
}
}
hf |= B43_HF_ANTDIVHELP;
b43_hf_write(dev, hf);
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
}
static void b43_aphy_op_adjust_txpower(struct b43_wldev *dev)

View file

@ -2651,65 +2651,54 @@ static unsigned int b43_gphy_op_get_default_chan(struct b43_wldev *dev)
static void b43_gphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
{
struct b43_phy *phy = &dev->phy;
u64 hf;
u16 tmp;
int autodiv = 0;
if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
autodiv = 1;
hf = b43_hf_read(dev);
hf &= ~B43_HF_ANTDIVHELP;
b43_hf_write(dev, hf);
b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
tmp &= ~B43_PHY_BBANDCFG_RXANT;
tmp |= (autodiv ? B43_ANTENNA_AUTO1 : antenna)
<< B43_PHY_BBANDCFG_RXANT_SHIFT;
b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
b43_phy_maskset(dev, B43_PHY_BBANDCFG, ~B43_PHY_BBANDCFG_RXANT,
(autodiv ? B43_ANTENNA_AUTO1 : antenna) <<
B43_PHY_BBANDCFG_RXANT_SHIFT);
if (autodiv) {
tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
if (antenna == B43_ANTENNA_AUTO0)
if (antenna == B43_ANTENNA_AUTO1)
tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
else
tmp |= B43_PHY_ANTDWELL_AUTODIV1;
b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
}
tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT);
if (autodiv)
tmp |= B43_PHY_ANTWRSETT_ARXDIV;
else
tmp &= ~B43_PHY_ANTWRSETT_ARXDIV;
b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp);
if (autodiv)
b43_phy_set(dev, B43_PHY_ANTWRSETT, B43_PHY_ANTWRSETT_ARXDIV);
else {
b43_phy_mask(dev, B43_PHY_ANTWRSETT,
B43_PHY_ANTWRSETT_ARXDIV);
}
if (phy->rev >= 2) {
tmp = b43_phy_read(dev, B43_PHY_OFDM61);
tmp |= B43_PHY_OFDM61_10;
b43_phy_write(dev, B43_PHY_OFDM61, tmp);
b43_phy_set(dev, B43_PHY_OFDM61, B43_PHY_OFDM61_10);
b43_phy_maskset(dev, B43_PHY_DIVSRCHGAINBACK, 0xFF00, 0x15);
tmp =
b43_phy_read(dev, B43_PHY_DIVSRCHGAINBACK);
tmp = (tmp & 0xFF00) | 0x15;
b43_phy_write(dev, B43_PHY_DIVSRCHGAINBACK,
tmp);
if (phy->rev == 2) {
b43_phy_write(dev, B43_PHY_ADIVRELATED,
8);
} else {
tmp =
b43_phy_read(dev,
B43_PHY_ADIVRELATED);
tmp = (tmp & 0xFF00) | 8;
b43_phy_write(dev, B43_PHY_ADIVRELATED,
tmp);
}
if (phy->rev == 2)
b43_phy_write(dev, B43_PHY_ADIVRELATED, 8);
else
b43_phy_maskset(dev, B43_PHY_ADIVRELATED, 0xFF00, 8);
}
if (phy->rev >= 6)
b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC);
hf |= B43_HF_ANTDIVHELP;
b43_hf_write(dev, hf);
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
}
static int b43_gphy_op_interf_mitigation(struct b43_wldev *dev,

View file

@ -1,9 +1,10 @@
/*
Broadcom B43 wireless driver
IEEE 802.11g LP-PHY driver
IEEE 802.11a/g LP-PHY driver
Copyright (c) 2008-2009 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
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

View file

@ -1,9 +1,10 @@
/*
Broadcom B43 wireless driver
IEEE 802.11g LP-PHY and radio device data tables
IEEE 802.11a/g LP-PHY and radio device data tables
Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
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
@ -1612,11 +1613,62 @@ static struct lpphy_tx_gain_table_entry lpphy_rev1_nopa_tx_gain_table[] = {
};
static struct lpphy_tx_gain_table_entry lpphy_rev1_2ghz_tx_gain_table[] = {
{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 85, },
{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 81, },
{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 78, },
{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 76, },
{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 74, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, },
{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 72, },
{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 72, },
{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 72, },
{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
@ -1689,57 +1741,6 @@ static struct lpphy_tx_gain_table_entry lpphy_rev1_2ghz_tx_gain_table[] = {
{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 72, },
{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 63, },
{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 61, },
{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 71, },
{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 69, },
{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 67, },
{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 65, },
{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 63, },
{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 58, },
{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 70, },
{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 65, },
{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 63, },
{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 61, },
{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 61, },
{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 59, },
{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 67, },
{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 65, },
{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 63, },
{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 62, },
{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 65, },
{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 63, },
{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 61, },
{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 60, },
{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 58, },
{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 68, },
{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 66, },
{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 64, },
{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 62, },
};
static struct lpphy_tx_gain_table_entry lpphy_rev1_5ghz_tx_gain_table[] = {
@ -2167,103 +2168,103 @@ static struct lpphy_tx_gain_table_entry lpphy_rev2_5ghz_tx_gain_table[] = {
{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 68, },
{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 66, },
{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 248, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 241, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 234, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 227, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 221, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 215, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 208, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 203, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 197, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 191, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 186, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 181, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 175, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 170, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 166, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 161, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 156, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 152, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 148, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 143, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 139, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 135, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 132, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 128, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 124, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 121, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 117, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 114, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 111, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 108, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 104, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 102, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 99, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 96, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 93, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 90, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 88, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 85, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 83, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 81, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 78, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 76, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 74, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 72, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 70, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 68, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 66, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 62, .pad = 255, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 62, .pad = 248, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 60, .pad = 248, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 60, .pad = 241, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 59, .pad = 241, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 59, .pad = 234, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 57, .pad = 234, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 57, .pad = 227, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 55, .pad = 227, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 55, .pad = 221, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 54, .pad = 221, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 54, .pad = 215, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 52, .pad = 215, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 52, .pad = 208, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 51, .pad = 208, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 51, .pad = 203, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 49, .pad = 203, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 49, .pad = 197, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 48, .pad = 197, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 48, .pad = 191, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 47, .pad = 191, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 47, .pad = 186, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 45, .pad = 186, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 45, .pad = 181, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 44, .pad = 181, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 44, .pad = 175, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 43, .pad = 175, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 43, .pad = 170, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 42, .pad = 170, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 42, .pad = 166, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 40, .pad = 166, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 40, .pad = 161, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 39, .pad = 161, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 39, .pad = 156, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 38, .pad = 156, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 38, .pad = 152, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 37, .pad = 152, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 37, .pad = 148, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 36, .pad = 148, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 36, .pad = 143, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 35, .pad = 143, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 35, .pad = 139, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 34, .pad = 139, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 34, .pad = 135, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 33, .pad = 135, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 33, .pad = 132, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 32, .pad = 132, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 32, .pad = 128, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 248, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 241, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 234, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 227, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 221, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 215, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 208, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 197, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 191, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 186, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 181, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 175, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 170, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 166, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 161, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 156, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 152, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 148, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 143, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 139, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 135, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 132, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 128, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 124, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 121, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 117, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 114, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 111, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 108, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 104, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 102, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 99, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 96, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 93, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 90, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 88, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 85, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 83, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 81, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 78, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 76, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 74, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 72, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 70, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 68, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 66, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 255, .pad = 62, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 248, .pad = 62, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 248, .pad = 60, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 241, .pad = 60, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 241, .pad = 59, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 234, .pad = 59, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 234, .pad = 57, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 227, .pad = 57, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 227, .pad = 55, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 221, .pad = 55, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 221, .pad = 54, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 215, .pad = 54, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 215, .pad = 52, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 208, .pad = 52, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 208, .pad = 51, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 203, .pad = 51, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 203, .pad = 49, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 197, .pad = 49, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 197, .pad = 48, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 191, .pad = 48, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 191, .pad = 47, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 186, .pad = 47, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 186, .pad = 45, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 181, .pad = 45, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 181, .pad = 44, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 175, .pad = 44, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 175, .pad = 43, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 170, .pad = 43, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 170, .pad = 42, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 166, .pad = 42, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 166, .pad = 40, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 161, .pad = 40, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 161, .pad = 39, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 156, .pad = 39, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 156, .pad = 38, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 152, .pad = 38, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 152, .pad = 37, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 148, .pad = 37, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 148, .pad = 36, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 143, .pad = 36, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 143, .pad = 35, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 139, .pad = 35, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 139, .pad = 34, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 135, .pad = 34, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 135, .pad = 33, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 132, .pad = 33, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 132, .pad = 32, .dac = 0, .bb_mult = 64, },
{ .gm = 255, .pga = 128, .pad = 32, .dac = 0, .bb_mult = 64, },
};
void lpphy_rev0_1_table_init(struct b43_wldev *dev)

View file

@ -4,7 +4,7 @@
config IPW2100
tristate "Intel PRO/Wireless 2100 Network Connection"
depends on PCI && WLAN_80211
depends on PCI && WLAN_80211 && CFG80211
select WIRELESS_EXT
select FW_LOADER
select LIB80211
@ -63,7 +63,7 @@ config IPW2100_DEBUG
config IPW2200
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
depends on PCI && WLAN_80211
depends on PCI && WLAN_80211 && CFG80211
select WIRELESS_EXT
select FW_LOADER
select LIB80211
@ -150,7 +150,7 @@ config IPW2200_DEBUG
config LIBIPW
tristate
depends on PCI && WLAN_80211
depends on PCI && WLAN_80211 && CFG80211
select WIRELESS_EXT
select CRYPTO
select CRYPTO_ARC4

View file

@ -818,15 +818,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
{
int status;
u8 retries;
int rs_index, index = 0;
int rs_index, mac_index, index = 0;
struct iwl_lq_sta *lq_sta = priv_sta;
struct iwl_link_quality_cmd *table;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_hw *hw = priv->hw;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_rate_scale_data *window = NULL;
struct iwl_rate_scale_data *search_win = NULL;
enum mac80211_rate_control_flags mac_flags;
u32 tx_rate;
struct iwl_scale_tbl_info tbl_type;
struct iwl_scale_tbl_info *curr_tbl, *search_tbl;
@ -876,17 +876,24 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
if (priv->band == IEEE80211_BAND_5GHZ)
rs_index -= IWL_FIRST_OFDM_RATE;
mac_flags = info->status.rates[0].flags;
mac_index = info->status.rates[0].idx;
/* For HT packets, map MCS to PLCP */
if (mac_flags & IEEE80211_TX_RC_MCS) {
mac_index &= RATE_MCS_CODE_MSK; /* Remove # of streams */
if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE))
mac_index++;
}
if ((info->status.rates[0].idx < 0) ||
(tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) ||
(tbl_type.is_ht40 != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
(tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) ||
if ((mac_index < 0) ||
(tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
(tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
(tbl_type.is_dup != !!(mac_flags & IEEE80211_TX_RC_DUP_DATA)) ||
(tbl_type.ant_type != info->antenna_sel_tx) ||
(!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) ||
(!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
(hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate !=
hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) {
IWL_DEBUG_RATE(priv, "initial rate does not match 0x%x\n", tx_rate);
(!!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS)) ||
(!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
(rs_index != mac_index)) {
IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate);
/* the last LQ command could failed so the LQ in ucode not
* the same in driver sync up
*/
@ -2542,8 +2549,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD;
} else {
if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT)
/* Check for invalid rates */
if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) ||
((sband->band == IEEE80211_BAND_5GHZ) &&
(rate_idx < IWL_FIRST_OFDM_RATE)))
rate_idx = rate_lowest_index(sband, sta);
/* On valid 5 GHz rate, adjust index */
else if (sband->band == IEEE80211_BAND_5GHZ)
rate_idx -= IWL_FIRST_OFDM_RATE;
info->control.rates[0].flags = 0;
@ -2584,9 +2595,6 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_conf *conf = &priv->hw->conf;
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
struct iwl_lq_sta *lq_sta = priv_sta;
u16 mask_bit = 0;
int count;
int start_rate = 0;
lq_sta->flush_timer = 0;
lq_sta->supp_rates = sta->supp_rates[sband->band];
@ -2661,20 +2669,10 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
lq_sta->drv = priv;
/* Find highest tx rate supported by hardware and destination station */
mask_bit = sta->supp_rates[sband->band];
count = sband->n_bitrates;
if (sband->band == IEEE80211_BAND_5GHZ) {
count += IWL_FIRST_OFDM_RATE;
start_rate = IWL_FIRST_OFDM_RATE;
mask_bit <<= IWL_FIRST_OFDM_RATE;
}
mask_bit = mask_bit & lq_sta->active_legacy_rate;
lq_sta->last_txrate_idx = 4;
for (i = start_rate; i < count; i++)
if (mask_bit & BIT(i))
lq_sta->last_txrate_idx = i;
/* Set last_txrate_idx to lowest rate */
lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
if (sband->band == IEEE80211_BAND_5GHZ)
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
rs_initialize_lq(priv, conf, sta, lq_sta);
}

View file

@ -73,6 +73,7 @@ enum {
IWL_RATE_54M_INDEX,
IWL_RATE_60M_INDEX,
IWL_RATE_COUNT, /*FIXME:RS:change to IWL_RATE_INDEX_COUNT,*/
IWL_RATE_COUNT_LEGACY = IWL_RATE_COUNT - 1, /* Excluding 60M */
IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1,
IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
IWL_RATE_INVALID = IWL_RATE_COUNT,

View file

@ -96,7 +96,6 @@ EXPORT_SYMBOL(iwl_rates);
void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info)
{
int rate_index;
struct ieee80211_tx_rate *r = &info->control.rates[0];
info->antenna_sel_tx =
@ -111,10 +110,7 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
r->flags |= IEEE80211_TX_RC_DUP_DATA;
if (rate_n_flags & RATE_MCS_SGI_MSK)
r->flags |= IEEE80211_TX_RC_SHORT_GI;
rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags);
if (info->band == IEEE80211_BAND_5GHZ)
rate_index -= IWL_FIRST_OFDM_RATE;
r->idx = rate_index;
r->idx = iwl_hwrate_to_mac80211_idx(rate_n_flags, info->band);
}
EXPORT_SYMBOL(iwl_hwrate_to_tx_control);
@ -149,6 +145,27 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
}
EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
{
int idx = 0;
int band_offset = 0;
/* HT rate format: mac80211 wants an MCS number, which is just LSB */
if (rate_n_flags & RATE_MCS_HT_MSK) {
idx = (rate_n_flags & 0xff);
return idx;
/* Legacy rate format, search for match in table */
} else {
if (band == IEEE80211_BAND_5GHZ)
band_offset = IWL_FIRST_OFDM_RATE;
for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
return idx - band_offset;
}
return -1;
}
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant)
{
int i;
@ -439,12 +456,12 @@ static void iwlcore_init_hw_rates(struct iwl_priv *priv,
{
int i;
for (i = 0; i < IWL_RATE_COUNT; i++) {
for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
rates[i].bitrate = iwl_rates[i].ieee * 5;
rates[i].hw_value = i; /* Rate scaling will work on indexes */
rates[i].hw_value_short = i;
rates[i].flags = 0;
if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) {
/*
* If CCK != 1M then set short preamble rate flag.
*/
@ -480,7 +497,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
if (!channels)
return -ENOMEM;
rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)),
rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
GFP_KERNEL);
if (!rates) {
kfree(channels);
@ -492,7 +509,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
/* just OFDM */
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
if (priv->cfg->sku & IWL_SKU_N)
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
@ -502,7 +519,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
sband->channels = channels;
/* OFDM & CCK */
sband->bitrates = rates;
sband->n_bitrates = IWL_RATE_COUNT;
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
if (priv->cfg->sku & IWL_SKU_N)
iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
@ -1231,7 +1248,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
for (i = 0; i < hw->n_bitrates; i++) {
rate = &(hw->bitrates[i]);
if (rate->hw_value < IWL_RATE_COUNT)
if (rate->hw_value < IWL_RATE_COUNT_LEGACY)
priv->active_rate |= (1 << rate->hw_value);
}

View file

@ -423,6 +423,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info);
int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv);

View file

@ -216,8 +216,27 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
struct iwl_powertable_cmd *cmd,
int dynps_ms, int wakeup_period)
{
/*
* These are the original power level 3 sleep successions. The
* device may behave better with such succession and was also
* only tested with that. Just like the original sleep commands,
* also adjust the succession here to the wakeup_period below.
* The ranges are the same as for the sleep commands, 0-2, 3-9
* and >10, which is selected based on the DTIM interval for
* the sleep index but here we use the wakeup period since that
* is what we need to do for the latency requirements.
*/
static const u8 slp_succ_r0[IWL_POWER_VEC_SIZE] = { 2, 2, 2, 2, 2 };
static const u8 slp_succ_r1[IWL_POWER_VEC_SIZE] = { 2, 4, 6, 7, 9 };
static const u8 slp_succ_r2[IWL_POWER_VEC_SIZE] = { 2, 7, 9, 9, 0xFF };
const u8 *slp_succ = slp_succ_r0;
int i;
if (wakeup_period > IWL_DTIM_RANGE_0_MAX)
slp_succ = slp_succ_r1;
if (wakeup_period > IWL_DTIM_RANGE_1_MAX)
slp_succ = slp_succ_r2;
memset(cmd, 0, sizeof(*cmd));
cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
@ -230,7 +249,8 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms);
for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
cmd->sleep_interval[i] = cpu_to_le32(wakeup_period);
cmd->sleep_interval[i] =
cpu_to_le32(min_t(int, slp_succ[i], wakeup_period));
IWL_DEBUG_POWER(priv, "Automatic sleep command\n");
}
@ -301,7 +321,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
if (priv->cfg->ops->lib->update_chain_flags &&
update_chains)
priv->cfg->ops->lib->update_chain_flags(priv);
else
else if (priv->cfg->ops->lib->update_chain_flags)
IWL_DEBUG_POWER(priv,
"Cannot update the power, chain noise "
"calibration running: %d\n",

View file

@ -962,6 +962,9 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
return;
}
/* This will be used in several places later */
rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
/* rx_status carries information about the packet to mac80211 */
rx_status.mactime = le64_to_cpu(phy_res->timestamp);
rx_status.freq =
@ -969,10 +972,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
rx_status.rate_idx =
iwl_hwrate_to_plcp_idx(le32_to_cpu(phy_res->rate_n_flags));
if (rx_status.band == IEEE80211_BAND_5GHZ)
rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
iwl_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
rx_status.flag = 0;
/* TSF isn't reliable. In order to allow smooth user experience,
@ -1034,7 +1034,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
rx_status.flag |= RX_FLAG_SHORTPRE;
/* Set up the HT phy flags */
rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
if (rate_n_flags & RATE_MCS_HT_MSK)
rx_status.flag |= RX_FLAG_HT;
if (rate_n_flags & RATE_MCS_HT40_MSK)

View file

@ -566,62 +566,81 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
struct iwl_tx_cmd *tx_cmd,
struct ieee80211_tx_info *info,
__le16 fc, int sta_id,
int is_hcca)
__le16 fc, int is_hcca)
{
u32 rate_flags = 0;
u32 rate_flags;
int rate_idx;
u8 rts_retry_limit = 0;
u8 data_retry_limit = 0;
u8 rts_retry_limit;
u8 data_retry_limit;
u8 rate_plcp;
rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff,
IWL_RATE_COUNT - 1);
rate_plcp = iwl_rates[rate_idx].plcp;
rts_retry_limit = (is_hcca) ?
RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT;
if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
rate_flags |= RATE_MCS_CCK_MSK;
if (ieee80211_is_probe_resp(fc)) {
data_retry_limit = 3;
if (data_retry_limit < rts_retry_limit)
rts_retry_limit = data_retry_limit;
} else
data_retry_limit = IWL_DEFAULT_TX_RETRY;
/* Set retry limit on DATA packets and Probe Responses*/
if (priv->data_retry_limit != -1)
data_retry_limit = priv->data_retry_limit;
else if (ieee80211_is_probe_resp(fc))
data_retry_limit = 3;
else
data_retry_limit = IWL_DEFAULT_TX_RETRY;
tx_cmd->data_retry_limit = data_retry_limit;
/* Set retry limit on RTS packets */
rts_retry_limit = (is_hcca) ? RTS_HCCA_RETRY_LIMIT :
RTS_DFAULT_RETRY_LIMIT;
if (data_retry_limit < rts_retry_limit)
rts_retry_limit = data_retry_limit;
tx_cmd->rts_retry_limit = rts_retry_limit;
/* DATA packets will use the uCode station table for rate/antenna
* selection */
if (ieee80211_is_data(fc)) {
tx_cmd->initial_rate_index = 0;
tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
} else {
switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
case cpu_to_le16(IEEE80211_STYPE_AUTH):
case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) {
tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK;
tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK;
}
break;
default:
break;
}
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
return;
}
tx_cmd->rts_retry_limit = rts_retry_limit;
tx_cmd->data_retry_limit = data_retry_limit;
/**
* If the current TX rate stored in mac80211 has the MCS bit set, it's
* not really a TX rate. Thus, we use the lowest supported rate for
* this band. Also use the lowest supported rate if the stored rate
* index is invalid.
*/
rate_idx = info->control.rates[0].idx;
if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS ||
(rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY))
rate_idx = rate_lowest_index(&priv->bands[info->band],
info->control.sta);
/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
if (info->band == IEEE80211_BAND_5GHZ)
rate_idx += IWL_FIRST_OFDM_RATE;
/* Get PLCP rate for tx_cmd->rate_n_flags */
rate_plcp = iwl_rates[rate_idx].plcp;
/* Zero out flags for this packet */
rate_flags = 0;
/* Set CCK flag as needed */
if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
rate_flags |= RATE_MCS_CCK_MSK;
/* Set up RTS and CTS flags for certain packets */
switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
case cpu_to_le16(IEEE80211_STYPE_AUTH):
case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) {
tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK;
tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK;
}
break;
default:
break;
}
/* Set up antennas */
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
/* Set the rate in the TX cmd */
tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags);
}
@ -701,12 +720,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
goto drop_unlock;
}
if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) ==
IWL_INVALID_RATE) {
IWL_ERR(priv, "ERROR: No TX rate available.\n");
goto drop_unlock;
}
fc = hdr->frame_control;
#ifdef CONFIG_IWLWIFI_DEBUG
@ -807,7 +820,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_dbg_log_tx_data_frame(priv, len, hdr);
/* set is_hcca to 0; it probably will never be implemented */
iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, 0);
iwl_update_stats(priv, true, fc, len);
/*

View file

@ -1373,7 +1373,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
fill_rx = 1;
/* Rx interrupt, but nothing sent from uCode */
if (i == r)
IWL_DEBUG(priv, IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
while (i != r) {
rxb = rxq->queue[i];
@ -1404,15 +1404,13 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
* handle those that need handling via function in
* rx_handlers table. See iwl3945_setup_rx_handlers() */
if (priv->rx_handlers[pkt->hdr.cmd]) {
IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
"r = %d, i = %d, %s, 0x%02x\n", r, i,
IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
} else {
/* No handling needed */
IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
"r %d i %d No handler needed for %s, 0x%02x\n",
IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n",
r, i, get_cmd_string(pkt->hdr.cmd),
pkt->hdr.cmd);
}

View file

@ -238,8 +238,9 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
return iwm_set_tx_key(iwm, key_index);
}
int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
u8 *mac, struct station_info *sinfo)
static int iwm_cfg80211_get_station(struct wiphy *wiphy,
struct net_device *ndev,
u8 *mac, struct station_info *sinfo)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
@ -326,11 +327,8 @@ static int iwm_cfg80211_change_iface(struct wiphy *wiphy,
iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
if (iwm->umac_profile_active) {
int ret = iwm_invalidate_mlme_profile(iwm);
if (ret < 0)
IWM_ERR(iwm, "Couldn't invalidate profile\n");
}
if (iwm->umac_profile_active)
iwm_invalidate_mlme_profile(iwm);
return 0;
}
@ -565,6 +563,7 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
{
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
struct ieee80211_channel *chan = sme->channel;
struct key_params key_param;
int ret;
if (!test_bit(IWM_STATUS_READY, &iwm->status))
@ -573,6 +572,14 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
if (!sme->ssid)
return -EINVAL;
if (iwm->umac_profile_active) {
ret = iwm_invalidate_mlme_profile(iwm);
if (ret) {
IWM_ERR(iwm, "Couldn't invalidate profile\n");
return ret;
}
}
if (chan)
iwm->channel =
ieee80211_frequency_to_channel(chan->center_freq);
@ -614,7 +621,48 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
return iwm_send_mlme_profile(iwm);
/*
* We save the WEP key in case we want to do shared authentication.
* We have to do it so because UMAC will assert whenever it gets a
* key before a profile.
*/
if (sme->key) {
key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL);
if (key_param.key == NULL)
return -ENOMEM;
key_param.key_len = sme->key_len;
key_param.seq_len = 0;
key_param.cipher = sme->crypto.ciphers_pairwise[0];
ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx,
NULL, &key_param);
kfree(key_param.key);
if (ret < 0) {
IWM_ERR(iwm, "Invalid key_params\n");
return ret;
}
iwm->default_key = sme->key_idx;
}
ret = iwm_send_mlme_profile(iwm);
if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
sme->key == NULL)
return ret;
/*
* We want to do shared auth.
* We need to actually set the key we previously cached,
* and then tell the UMAC it's the default one.
* That will trigger the auth+assoc UMAC machinery, and again,
* this must be done after setting the profile.
*/
ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]);
if (ret < 0)
return ret;
return iwm_set_tx_key(iwm, iwm->default_key);
}
static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
@ -625,7 +673,7 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active);
if (iwm->umac_profile_active)
return iwm_invalidate_mlme_profile(iwm);
iwm_invalidate_mlme_profile(iwm);
return 0;
}

View file

@ -756,6 +756,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm)
return ret;
}
set_bit(IWM_STATUS_SME_CONNECTING, &iwm->status);
return 0;
}

View file

@ -108,6 +108,8 @@ struct iwm_debugfs {
struct dentry *txq_dentry;
struct dentry *tx_credit_dentry;
struct dentry *rx_ticket_dentry;
struct dentry *fw_err_dentry;
};
#ifdef CONFIG_IWM_DEBUG

View file

@ -98,7 +98,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules,
iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write,
"%llu\n");
static int iwm_txrx_open(struct inode *inode, struct file *filp)
static int iwm_generic_open(struct inode *inode, struct file *filp)
{
filp->private_data = inode->i_private;
return 0;
@ -289,25 +289,111 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
return ret;
}
static ssize_t iwm_debugfs_fw_err_read(struct file *filp,
char __user *buffer,
size_t count, loff_t *ppos)
{
struct iwm_priv *iwm = filp->private_data;
char buf[512];
int buf_len = 512;
size_t len = 0;
if (*ppos != 0)
return 0;
if (count < sizeof(buf))
return -ENOSPC;
if (!iwm->last_fw_err)
return -ENOMEM;
if (iwm->last_fw_err->line_num == 0)
goto out;
len += snprintf(buf + len, buf_len - len, "%cMAC FW ERROR:\n",
(le32_to_cpu(iwm->last_fw_err->category) == UMAC_SYS_ERR_CAT_LMAC)
? 'L' : 'U');
len += snprintf(buf + len, buf_len - len,
"\tCategory: %d\n",
le32_to_cpu(iwm->last_fw_err->category));
len += snprintf(buf + len, buf_len - len,
"\tStatus: 0x%x\n",
le32_to_cpu(iwm->last_fw_err->status));
len += snprintf(buf + len, buf_len - len,
"\tPC: 0x%x\n",
le32_to_cpu(iwm->last_fw_err->pc));
len += snprintf(buf + len, buf_len - len,
"\tblink1: %d\n",
le32_to_cpu(iwm->last_fw_err->blink1));
len += snprintf(buf + len, buf_len - len,
"\tblink2: %d\n",
le32_to_cpu(iwm->last_fw_err->blink2));
len += snprintf(buf + len, buf_len - len,
"\tilink1: %d\n",
le32_to_cpu(iwm->last_fw_err->ilink1));
len += snprintf(buf + len, buf_len - len,
"\tilink2: %d\n",
le32_to_cpu(iwm->last_fw_err->ilink2));
len += snprintf(buf + len, buf_len - len,
"\tData1: 0x%x\n",
le32_to_cpu(iwm->last_fw_err->data1));
len += snprintf(buf + len, buf_len - len,
"\tData2: 0x%x\n",
le32_to_cpu(iwm->last_fw_err->data2));
len += snprintf(buf + len, buf_len - len,
"\tLine number: %d\n",
le32_to_cpu(iwm->last_fw_err->line_num));
len += snprintf(buf + len, buf_len - len,
"\tUMAC status: 0x%x\n",
le32_to_cpu(iwm->last_fw_err->umac_status));
len += snprintf(buf + len, buf_len - len,
"\tLMAC status: 0x%x\n",
le32_to_cpu(iwm->last_fw_err->lmac_status));
len += snprintf(buf + len, buf_len - len,
"\tSDIO status: 0x%x\n",
le32_to_cpu(iwm->last_fw_err->sdio_status));
out:
return simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
}
static const struct file_operations iwm_debugfs_txq_fops = {
.owner = THIS_MODULE,
.open = iwm_txrx_open,
.open = iwm_generic_open,
.read = iwm_debugfs_txq_read,
};
static const struct file_operations iwm_debugfs_tx_credit_fops = {
.owner = THIS_MODULE,
.open = iwm_txrx_open,
.open = iwm_generic_open,
.read = iwm_debugfs_tx_credit_read,
};
static const struct file_operations iwm_debugfs_rx_ticket_fops = {
.owner = THIS_MODULE,
.open = iwm_txrx_open,
.open = iwm_generic_open,
.read = iwm_debugfs_rx_ticket_read,
};
static const struct file_operations iwm_debugfs_fw_err_fops = {
.owner = THIS_MODULE,
.open = iwm_generic_open,
.read = iwm_debugfs_fw_err_read,
};
int iwm_debugfs_init(struct iwm_priv *iwm)
{
int i, result;
@ -423,6 +509,16 @@ int iwm_debugfs_init(struct iwm_priv *iwm)
goto error;
}
iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200,
iwm->dbg.dbgdir, iwm,
&iwm_debugfs_fw_err_fops);
result = PTR_ERR(iwm->dbg.fw_err_dentry);
if (IS_ERR(iwm->dbg.fw_err_dentry) && (result != -ENODEV)) {
IWM_ERR(iwm, "Couldn't create last FW err: %d\n", result);
goto error;
}
return 0;
error:
@ -441,6 +537,7 @@ void iwm_debugfs_exit(struct iwm_priv *iwm)
debugfs_remove(iwm->dbg.txq_dentry);
debugfs_remove(iwm->dbg.tx_credit_dentry);
debugfs_remove(iwm->dbg.rx_ticket_dentry);
debugfs_remove(iwm->dbg.fw_err_dentry);
if (iwm->bus_ops->debugfs_exit)
iwm->bus_ops->debugfs_exit(iwm);

View file

@ -261,6 +261,33 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0);
}
static int iwm_init_calib(struct iwm_priv *iwm, unsigned long cfg_bitmap,
unsigned long expected_bitmap, u8 rx_iq_cmd)
{
/* Read RX IQ calibration result from EEPROM */
if (test_bit(rx_iq_cmd, &cfg_bitmap)) {
iwm_store_rxiq_calib_result(iwm);
set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
}
iwm_send_prio_table(iwm);
iwm_send_init_calib_cfg(iwm, cfg_bitmap);
while (iwm->calib_done_map != expected_bitmap) {
if (iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT)) {
IWM_DBG_FW(iwm, DBG, "Initial calibration timeout\n");
return -ETIMEDOUT;
}
IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
"0x%lx, expected calibrations: 0x%lx\n",
iwm->calib_done_map, expected_bitmap);
}
return 0;
}
/*
* We currently have to load 3 FWs:
* 1) The UMAC (Upper MAC).
@ -276,6 +303,7 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
int iwm_load_fw(struct iwm_priv *iwm)
{
unsigned long init_calib_map, periodic_calib_map;
unsigned long expected_calib_map;
int ret;
/* We first start downloading the UMAC */
@ -317,27 +345,21 @@ int iwm_load_fw(struct iwm_priv *iwm)
}
init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK;
expected_calib_map = iwm->conf.expected_calib_map &
IWM_CALIB_MAP_INIT_MSK;
periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map);
/* Read RX IQ calibration result from EEPROM */
if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map)) {
iwm_store_rxiq_calib_result(iwm);
set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
}
iwm_send_prio_table(iwm);
iwm_send_init_calib_cfg(iwm, init_calib_map);
while (iwm->calib_done_map != init_calib_map) {
ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
if (ret) {
IWM_ERR(iwm, "Wait for calibration result timeout\n");
ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map,
CALIB_CFG_RX_IQ_IDX);
if (ret < 0) {
/* Let's try the old way */
ret = iwm_init_calib(iwm, expected_calib_map,
expected_calib_map,
PHY_CALIBRATE_RX_IQ_CMD);
if (ret < 0) {
IWM_ERR(iwm, "Calibration result timeout\n");
goto out;
}
IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
"0x%lx, requested calibrations: 0x%lx\n",
iwm->calib_done_map, init_calib_map);
}
/* Handle LMAC CALIBRATION_COMPLETE notification */

View file

@ -64,6 +64,7 @@
struct iwm_conf {
u32 sdio_ior_timeout;
unsigned long calib_map;
unsigned long expected_calib_map;
bool reset_on_fatal_err;
bool auto_connect;
bool wimax_not_present;
@ -175,8 +176,9 @@ struct iwm_key {
#define IWM_STATUS_READY 0
#define IWM_STATUS_SCANNING 1
#define IWM_STATUS_SCAN_ABORTING 2
#define IWM_STATUS_ASSOCIATING 3
#define IWM_STATUS_SME_CONNECTING 3
#define IWM_STATUS_ASSOCIATED 4
#define IWM_STATUS_RESETTING 5
struct iwm_tx_queue {
int id;
@ -273,6 +275,7 @@ struct iwm_priv {
struct iw_statistics wstats;
struct delayed_work stats_request;
struct delayed_work disconnect;
struct iwm_debugfs dbg;
@ -286,6 +289,8 @@ struct iwm_priv {
u8 *resp_ie;
int resp_ie_len;
struct iwm_fw_error_hdr *last_fw_err;
char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
};
@ -315,6 +320,7 @@ int iwm_mode_to_nl80211_iftype(int mode);
int iwm_priv_init(struct iwm_priv *iwm);
void iwm_priv_deinit(struct iwm_priv *iwm);
void iwm_reset(struct iwm_priv *iwm);
void iwm_resetting(struct iwm_priv *iwm);
void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
struct iwm_umac_notif_alive *alive);
int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb);

View file

@ -396,9 +396,24 @@ enum {
CALIBRATION_CMD_NUM,
};
enum {
CALIB_CFG_RX_BB_IDX = 0,
CALIB_CFG_DC_IDX = 1,
CALIB_CFG_LO_IDX = 2,
CALIB_CFG_TX_IQ_IDX = 3,
CALIB_CFG_RX_IQ_IDX = 4,
CALIB_CFG_NOISE_IDX = 5,
CALIB_CFG_CRYSTAL_IDX = 6,
CALIB_CFG_TEMPERATURE_IDX = 7,
CALIB_CFG_PAPD_IDX = 8,
CALIB_CFG_LAST_IDX = CALIB_CFG_PAPD_IDX,
CALIB_CFG_MODULE_NUM,
};
#define IWM_CALIB_MAP_INIT_MSK 0xFFFF
#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16)
#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24)
#define IWM_CALIB_OPCODE_TO_INDEX(op) (op - PHY_CALIBRATE_OPCODES_NUM)
struct iwm_lmac_calib_hdr {
u8 opcode;

View file

@ -53,7 +53,12 @@
static struct iwm_conf def_iwm_conf = {
.sdio_ior_timeout = 5000,
.calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
.calib_map = BIT(CALIB_CFG_DC_IDX) |
BIT(CALIB_CFG_LO_IDX) |
BIT(CALIB_CFG_TX_IQ_IDX) |
BIT(CALIB_CFG_RX_IQ_IDX) |
BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
.expected_calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
BIT(PHY_CALIBRATE_LO_CMD) |
BIT(PHY_CALIBRATE_TX_IQ_CMD) |
BIT(PHY_CALIBRATE_RX_IQ_CMD) |
@ -108,8 +113,28 @@ static void iwm_statistics_request(struct work_struct *work)
iwm_send_umac_stats_req(iwm, 0);
}
int __iwm_up(struct iwm_priv *iwm);
int __iwm_down(struct iwm_priv *iwm);
static void iwm_disconnect_work(struct work_struct *work)
{
struct iwm_priv *iwm =
container_of(work, struct iwm_priv, disconnect.work);
if (iwm->umac_profile_active)
iwm_invalidate_mlme_profile(iwm);
clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
iwm->umac_profile_active = 0;
memset(iwm->bssid, 0, ETH_ALEN);
iwm->channel = 0;
iwm_link_off(iwm);
wake_up_interruptible(&iwm->mlme_queue);
cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL);
}
static int __iwm_up(struct iwm_priv *iwm);
static int __iwm_down(struct iwm_priv *iwm);
static void iwm_reset_worker(struct work_struct *work)
{
@ -162,7 +187,8 @@ static void iwm_reset_worker(struct work_struct *work)
memcpy(iwm->umac_profile, profile, sizeof(*profile));
iwm_send_mlme_profile(iwm);
kfree(profile);
}
} else
clear_bit(IWM_STATUS_RESETTING, &iwm->status);
out:
mutex_unlock(&iwm->mutex);
@ -175,7 +201,7 @@ static void iwm_watchdog(unsigned long data)
IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n");
if (modparam_reset)
schedule_work(&iwm->reset_worker);
iwm_resetting(iwm);
}
int iwm_priv_init(struct iwm_priv *iwm)
@ -198,6 +224,7 @@ int iwm_priv_init(struct iwm_priv *iwm)
spin_lock_init(&iwm->cmd_lock);
iwm->scan_id = 1;
INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request);
INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work);
INIT_WORK(&iwm->reset_worker, iwm_reset_worker);
INIT_LIST_HEAD(&iwm->bss_list);
@ -233,6 +260,11 @@ int iwm_priv_init(struct iwm_priv *iwm)
iwm->watchdog.data = (unsigned long)iwm;
mutex_init(&iwm->mutex);
iwm->last_fw_err = kzalloc(sizeof(struct iwm_fw_error_hdr),
GFP_KERNEL);
if (iwm->last_fw_err == NULL)
return -ENOMEM;
return 0;
}
@ -244,6 +276,7 @@ void iwm_priv_deinit(struct iwm_priv *iwm)
destroy_workqueue(iwm->txq[i].wq);
destroy_workqueue(iwm->rx_wq);
kfree(iwm->last_fw_err);
}
/*
@ -258,7 +291,11 @@ void iwm_reset(struct iwm_priv *iwm)
if (test_bit(IWM_STATUS_READY, &iwm->status))
iwm_target_reset(iwm);
iwm->status = 0;
if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) {
iwm->status = 0;
set_bit(IWM_STATUS_RESETTING, &iwm->status);
} else
iwm->status = 0;
iwm->scan_id = 1;
list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
@ -274,6 +311,13 @@ void iwm_reset(struct iwm_priv *iwm)
iwm_link_off(iwm);
}
void iwm_resetting(struct iwm_priv *iwm)
{
set_bit(IWM_STATUS_RESETTING, &iwm->status);
schedule_work(&iwm->reset_worker);
}
/*
* Notification code:
*
@ -538,7 +582,7 @@ static int iwm_channels_init(struct iwm_priv *iwm)
return 0;
}
int __iwm_up(struct iwm_priv *iwm)
static int __iwm_up(struct iwm_priv *iwm)
{
int ret;
struct iwm_notif *notif_reboot, *notif_ack = NULL;
@ -672,7 +716,7 @@ int iwm_up(struct iwm_priv *iwm)
return ret;
}
int __iwm_down(struct iwm_priv *iwm)
static int __iwm_down(struct iwm_priv *iwm)
{
int ret;

View file

@ -102,6 +102,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
error = (struct iwm_umac_notif_error *)buf;
fw_err = &error->err;
memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr));
IWM_ERR(iwm, "%cMAC FW ERROR:\n",
(le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category));
@ -118,6 +120,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status));
IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));
iwm_resetting(iwm);
return 0;
}
@ -487,8 +491,6 @@ static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf,
start = (struct iwm_umac_notif_assoc_start *)buf;
set_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n",
start->bssid, le32_to_cpu(start->roam_reason));
@ -507,47 +509,80 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n",
complete->bssid, complete->status);
clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
switch (le32_to_cpu(complete->status)) {
case UMAC_ASSOC_COMPLETE_SUCCESS:
set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
iwm->channel = complete->channel;
/* Internal roaming state, avoid notifying SME. */
if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
&& iwm->conf.mode == UMAC_MODE_BSS) {
cancel_delayed_work(&iwm->disconnect);
cfg80211_roamed(iwm_to_ndev(iwm),
complete->bssid,
iwm->req_ie, iwm->req_ie_len,
iwm->resp_ie, iwm->resp_ie_len,
GFP_KERNEL);
break;
}
iwm_link_on(iwm);
if (iwm->conf.mode == UMAC_MODE_IBSS)
goto ibss;
cfg80211_connect_result(iwm_to_ndev(iwm),
if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
cfg80211_connect_result(iwm_to_ndev(iwm),
complete->bssid,
iwm->req_ie, iwm->req_ie_len,
iwm->resp_ie, iwm->resp_ie_len,
WLAN_STATUS_SUCCESS,
GFP_KERNEL);
else
cfg80211_roamed(iwm_to_ndev(iwm),
complete->bssid,
iwm->req_ie, iwm->req_ie_len,
iwm->resp_ie, iwm->resp_ie_len,
WLAN_STATUS_SUCCESS, GFP_KERNEL);
GFP_KERNEL);
break;
case UMAC_ASSOC_COMPLETE_FAILURE:
clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
memset(iwm->bssid, 0, ETH_ALEN);
iwm->channel = 0;
/* Internal roaming state, avoid notifying SME. */
if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
&& iwm->conf.mode == UMAC_MODE_BSS) {
cancel_delayed_work(&iwm->disconnect);
break;
}
iwm_link_off(iwm);
if (iwm->conf.mode == UMAC_MODE_IBSS)
goto ibss;
cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid,
NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
cfg80211_connect_result(iwm_to_ndev(iwm),
complete->bssid,
NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
else
cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0,
GFP_KERNEL);
break;
default:
break;
}
clear_bit(IWM_STATUS_RESETTING, &iwm->status);
return 0;
ibss:
cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
clear_bit(IWM_STATUS_RESETTING, &iwm->status);
return 0;
}
@ -556,13 +591,20 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
struct iwm_wifi_cmd *cmd)
{
struct iwm_umac_notif_profile_invalidate *invalid;
u32 reason;
invalid = (struct iwm_umac_notif_profile_invalidate *)buf;
reason = le32_to_cpu(invalid->reason);
IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n",
le32_to_cpu(invalid->reason));
IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason);
clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
if (reason != UMAC_PROFILE_INVALID_REQUEST &&
test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status))
cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL,
0, WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status);
clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
iwm->umac_profile_active = 0;
@ -576,6 +618,19 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
return 0;
}
#define IWM_DISCONNECT_INTERVAL (5 * HZ)
static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf,
unsigned long buf_size,
struct iwm_wifi_cmd *cmd)
{
IWM_DBG_MLME(iwm, DBG, "Connection terminated\n");
schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL);
return 0;
}
static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf,
unsigned long buf_size,
struct iwm_wifi_cmd *cmd)
@ -813,7 +868,8 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable,
iwm->resp_ie_len, GFP_KERNEL);
} else {
IWM_ERR(iwm, "Unsupported management frame");
IWM_ERR(iwm, "Unsupported management frame: 0x%x",
le16_to_cpu(mgt->frame_control));
return 0;
}
@ -834,8 +890,7 @@ static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,
case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE:
return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd);
case WIFI_IF_NTFY_CONNECTION_TERMINATED:
IWM_DBG_MLME(iwm, DBG, "Connection terminated\n");
break;
return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd);
case WIFI_IF_NTFY_SCAN_COMPLETE:
return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd);
case WIFI_IF_NTFY_STA_TABLE_CHANGE:

View file

@ -253,8 +253,8 @@ struct ndis_80211_pmkid_cand_list {
struct ndis_80211_status_indication {
__le32 status_type;
union {
enum ndis_80211_media_stream_mode media_stream_mode;
enum ndis_80211_radio_status radio_status;
__le32 media_stream_mode;
__le32 radio_status;
struct ndis_80211_auth_request auth_request[0];
struct ndis_80211_pmkid_cand_list cand_list;
} u;
@ -466,7 +466,7 @@ struct rndis_wlan_private {
u32 param_workaround_interval;
/* hardware state */
int radio_on;
bool radio_on;
int infra_mode;
bool connected;
u8 bssid[ETH_ALEN];
@ -560,7 +560,6 @@ static struct rndis_wlan_private *get_rndis_wlan_priv(struct usbnet *dev)
return (struct rndis_wlan_private *)dev->driver_priv;
}
static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv)
{
switch (priv->param_power_output) {
@ -576,7 +575,6 @@ static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv)
}
}
static bool is_wpa_key(struct rndis_wlan_private *priv, int idx)
{
int cipher = priv->encr_keys[idx].cipher;
@ -585,7 +583,6 @@ static bool is_wpa_key(struct rndis_wlan_private *priv, int idx)
cipher == WLAN_CIPHER_SUITE_TKIP);
}
static int rndis_cipher_to_alg(u32 cipher)
{
switch (cipher) {
@ -613,7 +610,6 @@ static int rndis_akm_suite_to_key_mgmt(u32 akm_suite)
}
}
#ifdef DEBUG
static const char *oid_to_string(__le32 oid)
{
@ -675,7 +671,6 @@ static const char *oid_to_string(__le32 oid)
}
#endif
/* translate error code */
static int rndis_error_status(__le32 rndis_status)
{
@ -699,7 +694,6 @@ static int rndis_error_status(__le32 rndis_status)
return ret;
}
static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev);
@ -758,7 +752,6 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
return ret;
}
static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev);
@ -817,7 +810,6 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
return ret;
}
static int rndis_reset(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -840,7 +832,6 @@ static int rndis_reset(struct usbnet *usbdev)
return 0;
}
/*
* Specs say that we can only set config parameters only soon after device
* initialization.
@ -927,16 +918,9 @@ static int rndis_set_config_parameter(struct usbnet *dev, char *param,
static int rndis_set_config_parameter_str(struct usbnet *dev,
char *param, char *value)
{
return(rndis_set_config_parameter(dev, param, 2, value));
return rndis_set_config_parameter(dev, param, 2, value);
}
/*static int rndis_set_config_parameter_u32(struct usbnet *dev,
char *param, u32 value)
{
return(rndis_set_config_parameter(dev, param, 0, &value));
}*/
/*
* data conversion functions
*/
@ -946,7 +930,6 @@ static int level_to_qual(int level)
return qual >= 0 ? (qual <= 100 ? qual : 100) : 0;
}
/*
* common functions
*/
@ -966,8 +949,8 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
}
if (ret == 0) {
memcpy(&priv->essid, ssid, sizeof(priv->essid));
priv->radio_on = 1;
devdbg(usbdev, "set_essid: radio_on = 1");
priv->radio_on = true;
devdbg(usbdev, "set_essid: radio_on = true");
}
return ret;
@ -1027,8 +1010,7 @@ static bool is_associated(struct usbnet *usbdev)
return (ret == 0 && !is_zero_ether_addr(bssid));
}
static int disassociate(struct usbnet *usbdev, int reset_ssid)
static int disassociate(struct usbnet *usbdev, bool reset_ssid)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_ssid ssid;
@ -1037,8 +1019,8 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid)
if (priv->radio_on) {
ret = rndis_set_oid(usbdev, OID_802_11_DISASSOCIATE, NULL, 0);
if (ret == 0) {
priv->radio_on = 0;
devdbg(usbdev, "disassociate: radio_on = 0");
priv->radio_on = false;
devdbg(usbdev, "disassociate: radio_on = false");
if (reset_ssid)
msleep(100);
@ -1064,7 +1046,6 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid)
return ret;
}
static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version,
enum nl80211_auth_type auth_type, int keymgmt)
{
@ -1109,7 +1090,6 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version,
return 0;
}
static int set_priv_filter(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -1127,7 +1107,6 @@ static int set_priv_filter(struct usbnet *usbdev)
sizeof(tmp));
}
static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -1163,7 +1142,6 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
return 0;
}
static int set_infra_mode(struct usbnet *usbdev, int mode)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -1189,7 +1167,6 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
return 0;
}
static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold)
{
__le32 tmp;
@ -1204,7 +1181,6 @@ static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold)
sizeof(tmp));
}
static int set_frag_threshold(struct usbnet *usbdev, u32 frag_threshold)
{
__le32 tmp;
@ -1219,7 +1195,6 @@ static int set_frag_threshold(struct usbnet *usbdev, u32 frag_threshold)
sizeof(tmp));
}
static void set_default_iw_params(struct usbnet *usbdev)
{
set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA);
@ -1229,17 +1204,15 @@ static void set_default_iw_params(struct usbnet *usbdev)
set_encr_mode(usbdev, RNDIS_WLAN_ALG_NONE, RNDIS_WLAN_ALG_NONE);
}
static int deauthenticate(struct usbnet *usbdev)
{
int ret;
ret = disassociate(usbdev, 1);
ret = disassociate(usbdev, true);
set_default_iw_params(usbdev);
return ret;
}
static int set_channel(struct usbnet *usbdev, int channel)
{
struct ndis_80211_conf config;
@ -1270,7 +1243,6 @@ static int set_channel(struct usbnet *usbdev, int channel)
return ret;
}
/* index must be 0 - N, as per NDIS */
static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
int index)
@ -1322,10 +1294,9 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len,
return 0;
}
static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
int index, const u8 *addr, const u8 *rx_seq,
int seq_len, u32 cipher, int flags)
int seq_len, u32 cipher, __le32 flags)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
struct ndis_80211_key ndis_key;
@ -1417,7 +1388,6 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
return 0;
}
static int restore_key(struct usbnet *usbdev, int key_idx)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -1436,7 +1406,6 @@ static int restore_key(struct usbnet *usbdev, int key_idx)
return add_wep_key(usbdev, key.material, key.len, key_idx);
}
static void restore_keys(struct usbnet *usbdev)
{
int i;
@ -1445,13 +1414,11 @@ static void restore_keys(struct usbnet *usbdev)
restore_key(usbdev, i);
}
static void clear_key(struct rndis_wlan_private *priv, int idx)
{
memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx]));
}
/* remove_key is for both wep and wpa */
static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid)
{
@ -1508,7 +1475,6 @@ static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid)
return 0;
}
static void set_multicast_list(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -1568,7 +1534,6 @@ static void set_multicast_list(struct usbnet *usbdev)
le32_to_cpu(filter), ret);
}
/*
* cfg80211 ops
*/
@ -1597,7 +1562,6 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy,
return set_infra_mode(usbdev, mode);
}
static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
@ -1619,7 +1583,6 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return 0;
}
static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
int dbm)
{
@ -1634,7 +1597,7 @@ static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
*/
if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) {
if (!priv->radio_on)
disassociate(usbdev, 1); /* turn on radio */
disassociate(usbdev, true); /* turn on radio */
return 0;
}
@ -1642,7 +1605,6 @@ static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
return -ENOTSUPP;
}
static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
@ -1655,7 +1617,6 @@ static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
return 0;
}
#define SCAN_DELAY_JIFFIES (6 * HZ)
static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_scan_request *request)
@ -1692,7 +1653,6 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
struct ndis_80211_bssid_ex *bssid)
{
@ -1741,7 +1701,6 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
GFP_KERNEL);
}
static int rndis_check_bssid_list(struct usbnet *usbdev)
{
void *buf = NULL;
@ -1790,7 +1749,6 @@ static int rndis_check_bssid_list(struct usbnet *usbdev)
return ret;
}
static void rndis_get_scan_results(struct work_struct *work)
{
struct rndis_wlan_private *priv =
@ -1923,7 +1881,7 @@ static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
return ret;
err_turn_radio_on:
disassociate(usbdev, 1);
disassociate(usbdev, true);
return ret;
}
@ -2031,7 +1989,7 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
return ret;
err_turn_radio_on:
disassociate(usbdev, 1);
disassociate(usbdev, true);
return ret;
}
@ -2065,7 +2023,7 @@ static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;
int flags;
__le32 flags;
devdbg(usbdev, "rndis_add_key(%i, %pM, %08x)", key_index, mac_addr,
params->cipher);
@ -2175,7 +2133,9 @@ static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
return 0;
}
/*
* workers, indication handlers, device poller
*/
static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -2293,7 +2253,6 @@ static void rndis_wlan_set_multicast_list(struct net_device *dev)
queue_work(priv->workqueue, &priv->work);
}
static void rndis_wlan_auth_indication(struct usbnet *usbdev,
struct ndis_80211_status_indication *indication,
int len)
@ -2476,7 +2435,6 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev,
}
}
static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -2523,7 +2481,6 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen)
}
}
static int rndis_wlan_get_caps(struct usbnet *usbdev)
{
struct {
@ -2560,7 +2517,6 @@ static int rndis_wlan_get_caps(struct usbnet *usbdev)
return retval;
}
#define DEVICE_POLLER_JIFFIES (HZ)
static void rndis_device_poller(struct work_struct *work)
{
@ -2632,7 +2588,9 @@ static void rndis_device_poller(struct work_struct *work)
update_jiffies);
}
/*
* driver/device initialization
*/
static int bcm4320a_early_init(struct usbnet *usbdev)
{
/* bcm4320a doesn't handle configuration parameters well. Try
@ -2642,7 +2600,6 @@ static int bcm4320a_early_init(struct usbnet *usbdev)
return 0;
}
static int bcm4320b_early_init(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -2721,7 +2678,6 @@ static const struct net_device_ops rndis_wlan_netdev_ops = {
.ndo_set_multicast_list = rndis_wlan_set_multicast_list,
};
static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
{
struct wiphy *wiphy;
@ -2823,8 +2779,8 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD);
/* turn radio on */
priv->radio_on = 1;
disassociate(usbdev, 1);
priv->radio_on = true;
disassociate(usbdev, true);
netif_carrier_off(usbdev->net);
return 0;
@ -2840,13 +2796,12 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
return retval;
}
static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
/* turn radio off */
disassociate(usbdev, 0);
disassociate(usbdev, false);
cancel_delayed_work_sync(&priv->dev_poller_work);
cancel_delayed_work_sync(&priv->scan_work);
@ -2863,7 +2818,6 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
wiphy_free(priv->wdev.wiphy);
}
static int rndis_wlan_reset(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -2885,7 +2839,6 @@ static int rndis_wlan_reset(struct usbnet *usbdev)
return deauthenticate(usbdev);
}
static int rndis_wlan_stop(struct usbnet *usbdev)
{
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
@ -2894,7 +2847,7 @@ static int rndis_wlan_stop(struct usbnet *usbdev)
devdbg(usbdev, "rndis_wlan_stop");
retval = disassociate(usbdev, 0);
retval = disassociate(usbdev, false);
priv->work_pending = 0;
cancel_delayed_work_sync(&priv->dev_poller_work);
@ -2916,7 +2869,6 @@ static int rndis_wlan_stop(struct usbnet *usbdev)
return retval;
}
static const struct driver_info bcm4320b_info = {
.description = "Wireless RNDIS device, BCM4320b based",
.flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |

View file

@ -154,7 +154,7 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
}
void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
unsigned int header_length,
struct rxdone_entry_desc *rxdesc)
{
@ -199,7 +199,7 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
* move the header more then iv_len since we must
* make room for the payload move as well.
*/
if (l2pad) {
if (rxdesc->dev_flags & RXDONE_L2PAD) {
skb_push(skb, iv_len - align);
skb_put(skb, icv_len);
@ -230,7 +230,7 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
* Move payload for alignment purposes. Note that
* this is only needed when no l2 padding is present.
*/
if (!l2pad) {
if (!(rxdesc->dev_flags & RXDONE_L2PAD)) {
memmove(skb->data + transfer,
skb->data + transfer + align,
payload_len);

View file

@ -206,6 +206,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
u8 rate_idx, rate_flags, retry_rates;
unsigned int i;
bool success;
/*
* Unmap the skb.
@ -216,7 +217,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* Remove L2 padding which was added during
*/
if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
rt2x00queue_payload_align(entry->skb, true, header_length);
rt2x00queue_remove_l2pad(entry->skb, header_length);
/*
* If the IV/EIV data was stripped from the frame before it was
@ -233,14 +234,19 @@ void rt2x00lib_txdone(struct queue_entry *entry,
*/
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);
/*
* Determine if the frame has been successfully transmitted.
*/
success =
test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
test_bit(TXDONE_UNKNOWN, &txdesc->flags) ||
test_bit(TXDONE_FALLBACK, &txdesc->flags);
/*
* Update TX statistics.
*/
rt2x00dev->link.qual.tx_success +=
test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
test_bit(TXDONE_UNKNOWN, &txdesc->flags);
rt2x00dev->link.qual.tx_failed +=
test_bit(TXDONE_FAILURE, &txdesc->flags);
rt2x00dev->link.qual.tx_success += success;
rt2x00dev->link.qual.tx_failed += !success;
rate_idx = skbdesc->tx_rate_idx;
rate_flags = skbdesc->tx_rate_flags;
@ -263,22 +269,20 @@ void rt2x00lib_txdone(struct queue_entry *entry,
tx_info->status.rates[i].flags = rate_flags;
tx_info->status.rates[i].count = 1;
}
if (i < (IEEE80211_TX_MAX_RATES -1))
if (i < (IEEE80211_TX_MAX_RATES - 1))
tx_info->status.rates[i].idx = -1; /* terminate */
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
test_bit(TXDONE_UNKNOWN, &txdesc->flags))
if (success)
tx_info->flags |= IEEE80211_TX_STAT_ACK;
else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
else
rt2x00dev->low_level_stats.dot11ACKFailureCount++;
}
if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
if (test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
test_bit(TXDONE_UNKNOWN, &txdesc->flags))
if (success)
rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
else
rt2x00dev->low_level_stats.dot11RTSFailureCount++;
}
@ -360,7 +364,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb;
struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
unsigned int header_length;
bool l2pad;
int rate_idx;
/*
* Allocate a new sk_buffer. If no new buffer available, drop the
@ -389,7 +392,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
* aligned on a 4 byte boundary.
*/
header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
l2pad = !!(rxdesc.dev_flags & RXDONE_L2PAD);
/*
* Hardware might have stripped the IV/EIV/ICV data,
@ -399,10 +401,12 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
*/
if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
(rxdesc.flags & RX_FLAG_IV_STRIPPED))
rt2x00crypto_rx_insert_iv(entry->skb, l2pad, header_length,
rt2x00crypto_rx_insert_iv(entry->skb, header_length,
&rxdesc);
else if (rxdesc.dev_flags & RXDONE_L2PAD)
rt2x00queue_remove_l2pad(entry->skb, header_length);
else
rt2x00queue_payload_align(entry->skb, l2pad, header_length);
rt2x00queue_align_payload(entry->skb, header_length);
/*
* Check if the frame was received using HT. In that case,

View file

@ -120,21 +120,42 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
/**
* rt2x00queue_payload_align - Align 802.11 payload to 4-byte boundary
* rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary
* @skb: The skb to align
*
* Align the start of the 802.11 frame to a 4-byte boundary, this could
* mean the payload is not aligned properly though.
*/
void rt2x00queue_align_frame(struct sk_buff *skb);
/**
* rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary
* @skb: The skb to align
* @l2pad: Should L2 padding be used
* @header_length: Length of 802.11 header
*
* This function prepares the @skb to be send to the device or mac80211.
* If @l2pad is set to true padding will occur between the 802.11 header
* and payload. Otherwise the padding will be done in front of the 802.11
* header.
* When @l2pad is set the function will check for the &SKBDESC_L2_PADDED
* flag in &skb_frame_desc. If that flag is set, the padding is removed
* and the flag cleared. Otherwise the padding is added and the flag is set.
* Align the 802.11 payload to a 4-byte boundary, this could
* mean the header is not aligned properly though.
*/
void rt2x00queue_payload_align(struct sk_buff *skb,
bool l2pad, unsigned int header_length);
void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length);
/**
* rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary
* @skb: The skb to align
* @header_length: Length of 802.11 header
*
* Apply L2 padding to align both header and payload to 4-byte boundary
*/
void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length);
/**
* rt2x00queue_insert_l2pad - Remove L2 padding from 802.11 frame
* @skb: The skb to align
* @header_length: Length of 802.11 header
*
* Remove L2 padding used to align both header and payload to 4-byte boundary,
* by removing the L2 padding the header will no longer be 4-byte aligned.
*/
void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length);
/**
* rt2x00queue_write_tx_frame - Write TX frame to hardware
@ -324,7 +345,7 @@ void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
struct txentry_desc *txdesc);
void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length);
void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
unsigned int header_length,
struct rxdone_entry_desc *rxdesc);
#else

View file

@ -148,35 +148,89 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}
void rt2x00queue_payload_align(struct sk_buff *skb,
bool l2pad, unsigned int header_length)
void rt2x00queue_align_frame(struct sk_buff *skb)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
unsigned int frame_length = skb->len;
unsigned int align = ALIGN_SIZE(skb, header_length);
unsigned int align = ALIGN_SIZE(skb, 0);
if (!align)
return;
if (l2pad) {
if (skbdesc->flags & SKBDESC_L2_PADDED) {
/* Remove L2 padding */
memmove(skb->data + align, skb->data, header_length);
skb_pull(skb, align);
skbdesc->flags &= ~SKBDESC_L2_PADDED;
} else {
/* Add L2 padding */
skb_push(skb, align);
memmove(skb->data, skb->data + align, header_length);
skbdesc->flags |= SKBDESC_L2_PADDED;
}
skb_push(skb, align);
memmove(skb->data, skb->data + align, frame_length);
skb_trim(skb, frame_length);
}
void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_lengt)
{
unsigned int frame_length = skb->len;
unsigned int align = ALIGN_SIZE(skb, header_lengt);
if (!align)
return;
skb_push(skb, align);
memmove(skb->data, skb->data + align, frame_length);
skb_trim(skb, frame_length);
}
void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
unsigned int frame_length = skb->len;
unsigned int header_align = ALIGN_SIZE(skb, 0);
unsigned int payload_align = ALIGN_SIZE(skb, header_length);
unsigned int l2pad = 4 - (payload_align - header_align);
if (header_align == payload_align) {
/*
* Both header and payload must be moved the same
* amount of bytes to align them properly. This means
* we don't use the L2 padding but just move the entire
* frame.
*/
rt2x00queue_align_frame(skb);
} else if (!payload_align) {
/*
* Simple L2 padding, only the header needs to be moved,
* the payload is already properly aligned.
*/
skb_push(skb, header_align);
memmove(skb->data, skb->data + header_align, frame_length);
skbdesc->flags |= SKBDESC_L2_PADDED;
} else {
/* Generic payload alignment to 4-byte boundary */
skb_push(skb, align);
memmove(skb->data, skb->data + align, frame_length);
/*
*
* Complicated L2 padding, both header and payload need
* to be moved. By default we only move to the start
* of the buffer, so our header alignment needs to be
* increased if there is not enough room for the header
* to be moved.
*/
if (payload_align > header_align)
header_align += 4;
skb_push(skb, header_align);
memmove(skb->data, skb->data + header_align, header_length);
memmove(skb->data + header_length + l2pad,
skb->data + header_length + l2pad + header_align,
frame_length - header_length);
skbdesc->flags |= SKBDESC_L2_PADDED;
}
}
void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
unsigned int l2pad = 4 - (header_length & 3);
if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED))
return;
memmove(skb->data + l2pad, skb->data, header_length);
skb_pull(skb, l2pad);
}
static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
@ -456,18 +510,15 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
/*
* When DMA allocation is required we should guarentee to the
* driver that the DMA is aligned to a 4-byte boundary.
* Aligning the header to this boundary can be done by calling
* rt2x00queue_payload_align with the header length of 0.
* However some drivers require L2 padding to pad the payload
* rather then the header. This could be a requirement for
* PCI and USB devices, while header alignment only is valid
* for PCI devices.
*/
if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
rt2x00queue_payload_align(entry->skb, true,
txdesc.header_length);
rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
rt2x00queue_payload_align(entry->skb, false, 0);
rt2x00queue_align_frame(entry->skb);
/*
* It could be possible that the queue was corrupted and this

View file

@ -6,20 +6,17 @@
* Copyright (C) 2007 Dmitry Torokhov
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* 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.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/types.h>

View file

@ -13,8 +13,7 @@ config MAC80211
comment "CFG80211 needs to be enabled for MAC80211"
depends on CFG80211=n
menu "Rate control algorithm selection"
depends on MAC80211 != n
if MAC80211 != n
config MAC80211_RC_PID
bool "PID controller based rate control algorithm" if EMBEDDED
@ -61,7 +60,7 @@ config MAC80211_RC_DEFAULT
default "pid" if MAC80211_RC_DEFAULT_PID
default ""
endmenu
endif
config MAC80211_MESH
bool "Enable mac80211 mesh networking (pre-802.11s) support"

View file

@ -40,6 +40,10 @@ config CFG80211_REG_DEBUG
default n
---help---
You can enable this if you want to debug regulatory changes.
For more information on cfg80211 regulatory refer to the wireless
wiki:
http://wireless.kernel.org/en/developers/Regulatory
If unsure, say N.

View file

@ -141,7 +141,7 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
dev->bss_generation++;
}
static u8 *find_ie(u8 num, u8 *ies, size_t len)
static u8 *find_ie(u8 num, u8 *ies, int len)
{
while (len > 2 && ies[0] != num) {
len -= ies[1] + 2;