---------------------------
+ What: ide-tape driver
+ When: July 2008
+ Files: drivers/ide/ide-tape.c
+ Why: This driver might not have any users anymore and maintaining it for no
+ reason is an effort no one wants to make.
+ Who: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>, Borislav Petkov
+ <petkovbb@googlemail.com>
+
+ ---------------------------
+
What: libata spindown skipping and warning
When: Dec 2008
Why: Some halt(8) implementations synchronize caches for and spin
---------------------------
-What: bcm43xx wireless network driver
-When: 2.6.26
-Files: drivers/net/wireless/bcm43xx
-Why: This driver's functionality has been replaced by the
- mac80211-based b43 and b43legacy drivers.
-Who: John W. Linville <linville@tuxdriver.com>
-
----------------------------
-
-What: ieee80211 softmac wireless networking component
-When: 2.6.26 (or after removal of bcm43xx and port of zd1211rw to mac80211)
-Files: net/ieee80211/softmac
-Why: No in-kernel drivers will depend on it any longer.
-Who: John W. Linville <linville@tuxdriver.com>
-
----------------------------
-
-What: rc80211-simple rate control algorithm for mac80211
-When: 2.6.26
-Files: net/mac80211/rc80211-simple.c
-Why: This algorithm was provided for reference but always exhibited bad
- responsiveness and performance and has some serious flaws. It has been
- replaced by rc80211-pid.
-Who: Stefano Brivio <stefano.brivio@polimi.it>
-
----------------------------
-
What (Why):
- include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
(superseded by xt_TOS/xt_tos target & match)
is largely pointless as without a lot of work only the most
trivial of Solaris binaries can work with the emulation code.
Who: David S. Miller <davem@davemloft.net>
+
+ ---------------------------
+
+ What: init_mm export
+ When: 2.6.26
+ Why: Not used in-tree. The current out-of-tree users used it to
+ work around problems in the CPA code which should be resolved
+ by now. One usecase was described to provide verification code
+ of the CPA operation. That's a good idea in general, but such
+ code / infrastructure should be in the kernel and not in some
+ out-of-tree driver.
+ Who: Thomas Gleixner <tglx@linutronix.de>
To send me the DSDT, as root/sudo:
- cat /sys/firmware/acpi/DSDT > dsdt
+ cat /sys/firmware/acpi/tables/DSDT > dsdt
And send me the resulting 'dsdt' file.
e.g. With the BCM4318 on the Acer Aspire 5020 series:
ndiswrapper: Light blinks on when transmitting
-bcm43xx/b43: Solid light, blinks off when transmitting
+b43: Solid light, blinks off when transmitting
Wireless radio control is unconditionally enabled - all Acer laptops that support
acer-wmi come with built-in wireless. However, should you feel so inclined to
The LED is exposed through the LED subsystem, and can be found in:
- /sys/devices/platform/acer-wmi/leds/acer-mail:green/
+ /sys/devices/platform/acer-wmi/leds/acer-wmi::mail/
The mail LED is autodetected, so if you don't have one, the LED device won't
be registered.
W: http://www.lesswatts.org/projects/acpi/
S: Maintained
+ AD1889 ALSA SOUND DRIVER
+ P: Kyle McMartin
+ M: kyle@parisc-linux.org
+ P: Thibaut Varene
+ M: T-Bone@parisc-linux.org
+ W: http://wiki.parisc-linux.org/AD1889
+ L: linux-parisc@vger.kernel.org
+ S: Maintained
+
ADM1025 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
BLACKFIN ARCHITECTURE
P: Bryan Wu
- M: bryan.wu@analog.com
+ M: cooloney@kernel.org
L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
W: http://blackfin.uclinux.org
S: Supported
BLACKFIN EMAC DRIVER
P: Bryan Wu
- M: bryan.wu@analog.com
+ M: cooloney@kernel.org
L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
W: http://blackfin.uclinux.org
S: Supported
W: http://linuxwireless.org/en/users/Drivers/b43
S: Maintained
-BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION)
-P: Larry Finger
-M: Larry.Finger@lwfinger.net
-P: Stefano Brivio
-M: stefano.brivio@polimi.it
-L: linux-wireless@vger.kernel.org
-W: http://bcm43xx.berlios.de/
-S: Obsolete
-
BEFS FILE SYSTEM
P: Sergey S. Kostyliov
M: rathamahata@php4.ru
W: http://accessrunner.sourceforge.net/
S: Maintained
+ CONTROL GROUPS (CGROUPS)
+ P: Paul Menage
+ M: menage@google.com
+ L: containers@lists.linux-foundation.org
+ S: Maintained
+
CORETEMP HARDWARE MONITORING DRIVER
P: Rudolf Marek
M: r.marek@assembler.cz
W: http://linux-fbdev.sourceforge.net/
S: Maintained
+ FREESCALE DMA DRIVER
+ P; Zhang Wei
+ M: wei.zhang@freescale.com
+ L: linuxppc-embedded@ozlabs.org
+ L: linux-kernel@vger.kernel.org
+ S: Maintained
+
FREESCALE SOC FS_ENET DRIVER
P: Pantelis Antoniou
M: pantelis.antoniou@gmail.com
S: Maintained
IPATH DRIVER:
- P: Arthur Jones
+ P: Ralph Campbell
M: infinipath@qlogic.com
L: general@lists.openfabrics.org
T: git git://git.qlogic.com/ipath-linux-2.6
W: http://www.linux-mm.org
S: Maintained
+ MEMORY RESOURCE CONTROLLER
+ P: Balbir Singh
+ M: balbir@linux.vnet.ibm.com
+ P: Pavel Emelyanov
+ M: xemul@openvz.org
+ P: KAMEZAWA Hiroyuki
+ M: kamezawa.hiroyu@jp.fujitsu.com
+ L: linux-mm@kvack.org
+ L: linux-kernel@vger.kernel.org
+ S: Maintained
+
MEI MN10300/AM33 PORT
P: David Howells
M: dhowells@redhat.com
NETEFFECT IWARP RNIC DRIVER (IW_NES)
P: Faisal Latif
M: flatif@neteffect.com
+ P: Nishi Gupta
+ M: ngupta@neteffect.com
P: Glenn Streiff
M: gstreiff@neteffect.com
L: general@lists.openfabrics.org
L: lm-sensors@lm-sensors.org
S: Maintained
-SOFTMAC LAYER (IEEE 802.11)
-P: Daniel Drake
-M: dsd@gentoo.org
-L: linux-wireless@vger.kernel.org
-S: Obsolete
-
SOFTWARE RAID (Multiple Disks) SUPPORT
P: Ingo Molnar
M: mingo@redhat.com
- /*
+/*
* Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
* Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org>
static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int);
-static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
+ struct ath5k_tx_status *);
static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int);
-static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
+ struct ath5k_tx_status *);
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *,
+ struct ath5k_rx_status *);
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *,
+ struct ath5k_rx_status *);
static int ath5k_hw_get_capabilities(struct ath5k_hw *);
static int ath5k_eeprom_init(struct ath5k_hw *);
static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
{
- return turbo == true ? (usec * 80) : (usec * 40);
+ return turbo ? (usec * 80) : (usec * 40);
}
static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
{
- return turbo == true ? (clock / 80) : (clock / 40);
+ return turbo ? (clock / 80) : (clock / 40);
}
/*
for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
data = ath5k_hw_reg_read(ah, reg);
- if ((is_set == true) && (data & flag))
+ if (is_set && (data & flag))
break;
else if ((data & flag) == val)
break;
* HW information
*/
- /* Get reg domain from eeprom */
- ath5k_get_regdomain(ah);
-
ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
ah->ah_turbo = false;
}
if (ah->ah_version == AR5K_AR5212)
- ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
+ ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
else if (ah->ah_version <= AR5K_AR5211)
- ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
+ ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
/* Bring device out of sleep and reset it's units */
ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
/* Identify single chip solutions */
if((srev <= AR5K_SREV_VER_AR5414) &&
- (srev >= AR5K_SREV_VER_AR2424)) {
+ (srev >= AR5K_SREV_VER_AR2413)) {
ah->ah_single_chip = true;
} else {
ah->ah_single_chip = false;
ah->ah_radio = AR5K_RF5110;
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
ah->ah_radio = AR5K_RF5111;
- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
+
ah->ah_radio = AR5K_RF5112;
+
+ if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
+ } else {
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
+ }
+
+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
+ ah->ah_radio = AR5K_RF2413;
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
} else {
+
ah->ah_radio = AR5K_RF5413;
+
+ if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 &&
+ ah->ah_mac_srev >= AR5K_SREV_VER_AR2424)
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424;
+ else if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2425)
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
+ else
+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
+
+
}
ah->ah_phy = AR5K_PHY(0);
*/
static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
{
- u32 turbo, mode, clock;
+ struct pci_dev *pdev = ah->ah_sc->pdev;
+ u32 turbo, mode, clock, bus_flags;
int ret;
turbo = 0;
AR5K_PHY_TURBO);
}
- /* ...reset chipset and PCI device */
- if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah,
- AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
+ /* reseting PCI on PCI-E cards results card to hang
+ * and always return 0xffff... so we ingore that flag
+ * for PCI-E cards */
+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+ /* Reset chipset */
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ if (ret) {
ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n");
return -EIO;
}
/* Get rate tables */
switch (mode) {
- case MODE_IEEE80211A:
+ case AR5K_MODE_11A:
return &ath5k_rt_11a;
- case MODE_ATHEROS_TURBO:
+ case AR5K_MODE_11A_TURBO:
return &ath5k_rt_turbo;
- case MODE_IEEE80211B:
+ case AR5K_MODE_11B:
return &ath5k_rt_11b;
- case MODE_IEEE80211G:
+ case AR5K_MODE_11G:
return &ath5k_rt_11g;
- case MODE_ATHEROS_TURBOG:
+ case AR5K_MODE_11G_TURBO:
return &ath5k_rt_xr;
}
{
ATH5K_TRACE(ah->ah_sc);
+ __set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
+
if (ah->ah_rf_banks != NULL)
kfree(ah->ah_rf_banks);
ds_coef_exp, ds_coef_man, clock;
if (!(ah->ah_version == AR5K_AR5212) ||
- !(channel->val & CHANNEL_OFDM))
+ !(channel->hw_value & CHANNEL_OFDM))
BUG();
/* Seems there are two PLLs, one for baseband sampling and one
* for tuning. Tuning basebands are 40 MHz or 80MHz when in
* turbo. */
- clock = channel->val & CHANNEL_TURBO ? 80 : 40;
+ clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
coef_scaled = ((5 * (clock << 24)) / 2) /
- channel->freq;
+ channel->center_freq;
for (coef_exp = 31; coef_exp > 0; coef_exp--)
if ((coef_scaled >> coef_exp) & 0x1)
* ath5k_hw_write_rate_duration - set rate duration during hw resets
*
* @ah: the &struct ath5k_hw
- * @driver_mode: one of enum ieee80211_phymode or our one of our own
- * vendor modes
+ * @mode: one of enum ath5k_driver_mode
*
* Write the rate duration table for the current mode upon hw reset. This
* is a helper for ath5k_hw_reset(). It seems all this is doing is setting
*
*/
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
- unsigned int driver_mode)
+ unsigned int mode)
{
struct ath5k_softc *sc = ah->ah_sc;
const struct ath5k_rate_table *rt;
+ struct ieee80211_rate srate = {};
unsigned int i;
/* Get rate table for the current operating mode */
- rt = ath5k_hw_get_rate_table(ah,
- driver_mode);
+ rt = ath5k_hw_get_rate_table(ah, mode);
/* Write rate duration table */
for (i = 0; i < rt->rate_count; i++) {
const struct ath5k_rate *rate, *control_rate;
+
u32 reg;
u16 tx_time;
/* Set ACK timeout */
reg = AR5K_RATE_DUR(rate->rate_code);
+ srate.bitrate = control_rate->rate_kbps/100;
+
/* An ACK frame consists of 10 bytes. If you add the FCS,
* which ieee80211_generic_frame_duration() adds,
* its 14 bytes. Note we use the control rate and not the
* actual rate for this rate. See mac80211 tx.c
* ieee80211_duration() for a brief description of
* what rate we should choose to TX ACKs. */
- tx_time = ieee80211_generic_frame_duration(sc->hw,
- sc->vif, 10, control_rate->rate_kbps/100);
+ tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
+ sc->vif, 10, &srate));
ath5k_hw_reg_write(ah, tx_time, reg);
struct ieee80211_channel *channel, bool change_channel)
{
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- u32 data, s_seq, s_ant, s_led[3];
- unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
+ struct pci_dev *pdev = ah->ah_sc->pdev;
+ u32 data, s_seq, s_ant, s_led[3], dma_size;
+ unsigned int i, mode, freq, ee_mode, ant[2];
int ret;
ATH5K_TRACE(ah->ah_sc);
*/
/*DCU/Antenna selection not available on 5210*/
if (ah->ah_version != AR5K_AR5210) {
- if (change_channel == true) {
+ if (change_channel) {
/* Seq number for queue 0 -do this for all queues ? */
s_seq = ath5k_hw_reg_read(ah,
AR5K_QUEUE_DFS_SEQNUM(0));
s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
- if (change_channel == true && ah->ah_rf_banks != NULL)
+ if (change_channel && ah->ah_rf_banks != NULL)
ath5k_hw_get_rf_gain(ah);
/*Wakeup the device*/
- ret = ath5k_hw_nic_wakeup(ah, channel->val, false);
+ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
if (ret)
return ret;
if (ah->ah_version != AR5K_AR5210) {
if (ah->ah_radio != AR5K_RF5111 &&
ah->ah_radio != AR5K_RF5112 &&
- ah->ah_radio != AR5K_RF5413) {
+ ah->ah_radio != AR5K_RF5413 &&
+ ah->ah_radio != AR5K_RF2413) {
ATH5K_ERR(ah->ah_sc,
"invalid phy radio: %u\n", ah->ah_radio);
return -EINVAL;
}
- switch (channel->val & CHANNEL_MODES) {
+ switch (channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
- mode = AR5K_INI_VAL_11A;
+ mode = AR5K_MODE_11A;
freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A;
- driver_mode = MODE_IEEE80211A;
break;
case CHANNEL_G:
- mode = AR5K_INI_VAL_11G;
+ mode = AR5K_MODE_11G;
freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11G;
- driver_mode = MODE_IEEE80211G;
break;
case CHANNEL_B:
- mode = AR5K_INI_VAL_11B;
+ mode = AR5K_MODE_11B;
freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11B;
- driver_mode = MODE_IEEE80211B;
break;
case CHANNEL_T:
- mode = AR5K_INI_VAL_11A_TURBO;
+ mode = AR5K_MODE_11A_TURBO;
freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A;
- driver_mode = MODE_ATHEROS_TURBO;
break;
/*Is this ok on 5211 too ?*/
case CHANNEL_TG:
- mode = AR5K_INI_VAL_11G_TURBO;
+ mode = AR5K_MODE_11G_TURBO;
freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11G;
- driver_mode = MODE_ATHEROS_TURBOG;
break;
case CHANNEL_XR:
if (ah->ah_version == AR5K_AR5211) {
"XR mode not available on 5211");
return -EINVAL;
}
- mode = AR5K_INI_VAL_XR;
+ mode = AR5K_MODE_XR;
freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A;
- driver_mode = MODE_IEEE80211A;
break;
default:
ATH5K_ERR(ah->ah_sc,
- "invalid channel: %d\n", channel->freq);
+ "invalid channel: %d\n", channel->center_freq);
return -EINVAL;
}
/*
* Write some more initial register settings
*/
- if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */
+ if (ah->ah_version == AR5K_AR5212) {
ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
- if (channel->val == CHANNEL_G)
- ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */
+ if (channel->hw_value == CHANNEL_G)
+ if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413)
+ ath5k_hw_reg_write(ah, 0x00f80d80,
+ AR5K_PHY(83));
+ else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424)
+ ath5k_hw_reg_write(ah, 0x00380140,
+ AR5K_PHY(83));
+ else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425)
+ ath5k_hw_reg_write(ah, 0x00fc0ec0,
+ AR5K_PHY(83));
+ else /* 2425 */
+ ath5k_hw_reg_write(ah, 0x00fc0fc0,
+ AR5K_PHY(83));
else
- ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83));
+ ath5k_hw_reg_write(ah, 0x00000000,
+ AR5K_PHY(83));
- ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */
ath5k_hw_reg_write(ah, 0x000009b5, 0xa228);
ath5k_hw_reg_write(ah, 0x0000000f, 0x8060);
ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
AR5K_SREV_RAD_5112A) {
ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
AR5K_PHY_CCKTXCTL);
- if (channel->val & CHANNEL_5GHZ)
+ if (channel->hw_value & CHANNEL_5GHZ)
data = 0xffb81020;
else
data = 0xffb80d20;
* mac80211 are integrated */
if (ah->ah_version == AR5K_AR5212 &&
ah->ah_sc->vif != NULL)
- ath5k_hw_write_rate_duration(ah, driver_mode);
+ ath5k_hw_write_rate_duration(ah, mode);
/*
* Write RF registers
/* Write OFDM timings on 5212*/
if (ah->ah_version == AR5K_AR5212 &&
- channel->val & CHANNEL_OFDM) {
+ channel->hw_value & CHANNEL_OFDM) {
ret = ath5k_hw_write_ofdm_timings(ah, channel);
if (ret)
return ret;
/*Enable/disable 802.11b mode on 5111
(enable 2111 frequency converter + CCK)*/
if (ah->ah_radio == AR5K_RF5111) {
- if (driver_mode == MODE_IEEE80211B)
+ if (mode == AR5K_MODE_11B)
AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
AR5K_TXCFG_B_MODE);
else
/*
* Set Rx/Tx DMA Configuration
- *(passing dma size not available on 5210)
+ *
+ * Set maximum DMA size (512) except for PCI-E cards since
+ * it causes rx overruns and tx errors (tested on 5424 but since
+ * rx overruns also occur on 5416/5418 with madwifi we set 128
+ * for all PCI-E cards to be safe).
+ *
+ * In dumps this is 128 for allchips.
+ *
+ * XXX: need to check 5210 for this
+ * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * guess we can tweak it and see how it goes ;-)
*/
+ dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
if (ah->ah_version != AR5K_AR5210) {
- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR,
- AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE);
- AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW,
- AR5K_DMASIZE_512B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, dma_size);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, dma_size);
}
/*
if (ah->ah_version != AR5K_AR5210) {
data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
AR5K_PHY_RX_DELAY_M;
- data = (channel->val & CHANNEL_CCK) ?
+ data = (channel->hw_value & CHANNEL_CCK) ?
((data << 2) / 22) : (data / 10);
udelay(100 + data);
if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_CAL, 0, false)) {
ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
- channel->freq);
+ channel->center_freq);
return -EAGAIN;
}
- ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
+ ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
if (ret)
return ret;
/* A and G modes can use QAM modulation which requires enabling
* I and Q calibration. Don't bother in B mode. */
- if (!(driver_mode == MODE_IEEE80211B)) {
+ if (!(mode == AR5K_MODE_11B)) {
ah->ah_calibration = true;
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
/*
* Set the 32MHz reference clock on 5212 phy clock sleep register
+ *
+ * TODO: Find out how to switch to external 32Khz clock to save power
*/
if (ah->ah_version == AR5K_AR5212) {
ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
- ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ?
- AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112,
- AR5K_PHY_SPENDING);
+ ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
+ }
+
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
+ ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
+ ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
+ if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413)
+ ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
}
/*
staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
/* fallthrough */
case AR5K_PM_NETWORK_SLEEP:
- if (set_chip == true)
+ if (set_chip)
ath5k_hw_reg_write(ah,
AR5K_SLEEP_CTL_SLE | sleep_duration,
AR5K_SLEEP_CTL);
break;
case AR5K_PM_FULL_SLEEP:
- if (set_chip == true)
+ if (set_chip)
ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
AR5K_SLEEP_CTL);
break;
case AR5K_PM_AWAKE:
- if (set_chip == false)
+ if (!set_chip)
goto commit;
ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
AR5K_TXCFG_TXFULL);
- if (increase == false) {
+ if (!increase) {
if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
goto done;
} else
/*
* Write to eeprom - currently disabled, use at your own risk
*/
+#if 0
static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
{
-#if 0
+
u32 status, timeout;
ATH5K_TRACE(ah->ah_sc);
}
udelay(15);
}
-#endif
+
ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
return -EIO;
}
+#endif
/*
* Translate binary channel representation in EEPROM to frequency
}
/*
- * Read/Write regulatory domain
- */
-static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write,
- enum ath5k_regdom *regdomain)
-{
- u16 ee_regdomain;
-
- /* Read current value */
- if (write != true) {
- ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain;
- *regdomain = ath5k_regdom_to_ieee(ee_regdomain);
- return true;
- }
-
- ee_regdomain = ath5k_regdom_from_ieee(*regdomain);
-
- /* Try to write a new value */
- if (ah->ah_capabilities.cap_eeprom.ee_protect &
- AR5K_EEPROM_PROTECT_WR_128_191)
- return false;
- if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0)
- return false;
-
- ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
-
- return true;
-}
-
-/*
- * Use the above to write a new regulatory domain
- */
-int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain)
-{
- enum ath5k_regdom ieee_regdomain;
-
- ieee_regdomain = ath5k_regdom_to_ieee(regdomain);
-
- if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true)
- return 0;
-
- return -EIO;
-}
-
-/*
* Fill the capabilities struct
*/
static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
ah->ah_capabilities.cap_range.range_2ghz_max = 0;
/* Set supported modes */
- __set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode);
- __set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode);
+ __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
+ __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
} else {
/*
* XXX The tranceiver supports frequencies from 4920 to 6100GHz
ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
/* Set supported modes */
- __set_bit(MODE_IEEE80211A,
+ __set_bit(AR5K_MODE_11A,
ah->ah_capabilities.cap_mode);
- __set_bit(MODE_ATHEROS_TURBO,
+ __set_bit(AR5K_MODE_11A_TURBO,
ah->ah_capabilities.cap_mode);
if (ah->ah_version == AR5K_AR5212)
- __set_bit(MODE_ATHEROS_TURBOG,
+ __set_bit(AR5K_MODE_11G_TURBO,
ah->ah_capabilities.cap_mode);
}
ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
if (AR5K_EEPROM_HDR_11B(ee_header))
- __set_bit(MODE_IEEE80211B,
+ __set_bit(AR5K_MODE_11B,
ah->ah_capabilities.cap_mode);
if (AR5K_EEPROM_HDR_11G(ee_header))
- __set_bit(MODE_IEEE80211G,
+ __set_bit(AR5K_MODE_11G,
ah->ah_capabilities.cap_mode);
}
}
* Set simple BSSID mask on 5212
*/
if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0);
- ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1);
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
}
/*
{
ATH5K_TRACE(ah->ah_sc);
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+
+ /* TODO: ANI Support */
}
/*
{
ATH5K_TRACE(ah->ah_sc);
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+
+ /* TODO: ANI Support */
}
/*
return 0;
/* Set Slot time */
- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
AR5K_SLOT_TIME);
/* Set ACK_CTS timeout */
- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
/* Set Transmit Latency */
- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
AR5K_INIT_TRANSMIT_LATENCY_TURBO :
AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
/* Set IFS0 */
- if (ah->ah_turbo == true)
+ if (ah->ah_turbo)
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
(ah->ah_aifs + tq->tqi_aifs) *
AR5K_INIT_SLOT_TIME_TURBO) <<
AR5K_INIT_SIFS, AR5K_IFS0);
/* Set IFS1 */
- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
/* Set PHY register 0x9844 (??) */
- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
(ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 :
(ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C,
AR5K_PHY(17));
/* Set Frame Control Register */
- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
(AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
AR5K_PHY_TURBO_SHORT | 0x2020) :
(AR5K_PHY_FRAME_CTL_INI | 0x1020),
/*
* Calculate and set retry limits
*/
- if (ah->ah_software_retry == true) {
+ if (ah->ah_software_retry) {
/* XXX Need to test this */
retry_lg = ah->ah_limit_tx_retries;
retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
unsigned int rtscts_rate, unsigned int rtscts_duration)
{
u32 frame_type;
- struct ath5k_hw_2w_tx_desc *tx_desc;
+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
unsigned int frame_len;
- tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
/*
* Validate input
return -EINVAL;
}
- /* Clear status descriptor */
- memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
-
- /* Initialize control descriptor */
- tx_desc->tx_control_0 = 0;
- tx_desc->tx_control_1 = 0;
+ /* Clear descriptor */
+ memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
/* Setup control descriptor */
if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
return -EINVAL;
- tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+ tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
/* Verify and set buffer length */
if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
return -EINVAL;
- tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+ tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
/*
* Verify and set header length
if (ah->ah_version == AR5K_AR5210) {
if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
return -EINVAL;
- tx_desc->tx_control_0 |=
+ tx_ctl->tx_control_0 |=
AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
}
frame_type = type /*<< 2 ?*/;
}
- tx_desc->tx_control_0 |=
+ tx_ctl->tx_control_0 |=
AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
} else {
- tx_desc->tx_control_0 |=
+ tx_ctl->tx_control_0 |=
AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
- tx_desc->tx_control_1 |=
+ tx_ctl->tx_control_1 |=
AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
}
#define _TX_FLAGS(_c, _flag) \
if (flags & AR5K_TXDESC_##_flag) \
- tx_desc->tx_control_##_c |= \
+ tx_ctl->tx_control_##_c |= \
AR5K_2W_TX_DESC_CTL##_c##_##_flag
_TX_FLAGS(0, CLRDMASK);
* WEP crap
*/
if (key_index != AR5K_TXKEYIX_INVALID) {
- tx_desc->tx_control_0 |=
+ tx_ctl->tx_control_0 |=
AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
- tx_desc->tx_control_1 |=
+ tx_ctl->tx_control_1 |=
AR5K_REG_SM(key_index,
AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
}
*/
if ((ah->ah_version == AR5K_AR5210) &&
(flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
- tx_desc->tx_control_1 |= rtscts_duration &
+ tx_ctl->tx_control_1 |= rtscts_duration &
AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
return 0;
unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
unsigned int rtscts_duration)
{
- struct ath5k_hw_4w_tx_desc *tx_desc;
- struct ath5k_hw_tx_status *tx_status;
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
unsigned int frame_len;
ATH5K_TRACE(ah->ah_sc);
- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
/*
* Validate input
return -EINVAL;
}
- /* Clear status descriptor */
- memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
-
- /* Initialize control descriptor */
- tx_desc->tx_control_0 = 0;
- tx_desc->tx_control_1 = 0;
- tx_desc->tx_control_2 = 0;
- tx_desc->tx_control_3 = 0;
+ /* Clear descriptor */
+ memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
/* Setup control descriptor */
if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
return -EINVAL;
- tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+ tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
/* Verify and set buffer length */
if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
return -EINVAL;
- tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+ tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
- tx_desc->tx_control_0 |=
+ tx_ctl->tx_control_0 |=
AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
- tx_desc->tx_control_1 |= AR5K_REG_SM(type,
+ tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
- tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+ tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
- tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+ tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
#define _TX_FLAGS(_c, _flag) \
if (flags & AR5K_TXDESC_##_flag) \
- tx_desc->tx_control_##_c |= \
+ tx_ctl->tx_control_##_c |= \
AR5K_4W_TX_DESC_CTL##_c##_##_flag
_TX_FLAGS(0, CLRDMASK);
* WEP crap
*/
if (key_index != AR5K_TXKEYIX_INVALID) {
- tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
- tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
+ tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+ tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
}
if ((flags & AR5K_TXDESC_RTSENA) &&
(flags & AR5K_TXDESC_CTSENA))
return -EINVAL;
- tx_desc->tx_control_2 |= rtscts_duration &
+ tx_ctl->tx_control_2 |= rtscts_duration &
AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
- tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+ tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
}
unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
unsigned int tx_rate3, u_int tx_tries3)
{
- struct ath5k_hw_4w_tx_desc *tx_desc;
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
/*
* Rates can be 0 as long as the retry count is 0 too.
}
if (ah->ah_version == AR5K_AR5212) {
- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
#define _XTX_TRIES(_n) \
if (tx_tries##_n) { \
- tx_desc->tx_control_2 |= \
+ tx_ctl->tx_control_2 |= \
AR5K_REG_SM(tx_tries##_n, \
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
- tx_desc->tx_control_3 |= \
+ tx_ctl->tx_control_3 |= \
AR5K_REG_SM(tx_rate##_n, \
AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
}
* Proccess the tx status descriptor on 5210/5211
*/
static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
- struct ath5k_desc *desc)
+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
{
+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
struct ath5k_hw_tx_status *tx_status;
- struct ath5k_hw_2w_tx_desc *tx_desc;
- tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
+ ATH5K_TRACE(ah->ah_sc);
+
+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+ tx_status = &desc->ud.ds_tx5210.tx_stat;
/* No frame has been send or error */
if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
/*
* Get descriptor status
*/
- desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
- desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
- desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
- /*TODO: desc->ds_us.tx.ts_virtcol + test*/
- desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ /*TODO: ts->ts_virtcol + test*/
+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
AR5K_DESC_TX_STATUS1_SEQ_NUM);
- desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
- desc->ds_us.tx.ts_antenna = 1;
- desc->ds_us.tx.ts_status = 0;
- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
+ ts->ts_antenna = 1;
+ ts->ts_status = 0;
+ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
if (tx_status->tx_status_0 &
AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
- desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
+ ts->ts_status |= AR5K_TXERR_XRETRY;
if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
- desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
+ ts->ts_status |= AR5K_TXERR_FIFO;
if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
- desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
+ ts->ts_status |= AR5K_TXERR_FILT;
}
return 0;
* Proccess a tx descriptor on 5212
*/
static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
- struct ath5k_desc *desc)
+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
{
+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
struct ath5k_hw_tx_status *tx_status;
- struct ath5k_hw_4w_tx_desc *tx_desc;
ATH5K_TRACE(ah->ah_sc);
- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
+
+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+ tx_status = &desc->ud.ds_tx5212.tx_stat;
/* No frame has been send or error */
if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
/*
* Get descriptor status
*/
- desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
- desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
- desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
- desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
AR5K_DESC_TX_STATUS1_SEQ_NUM);
- desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
- desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
+ ts->ts_antenna = (tx_status->tx_status_1 &
AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
- desc->ds_us.tx.ts_status = 0;
+ ts->ts_status = 0;
switch (AR5K_REG_MS(tx_status->tx_status_1,
AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
case 0:
- desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
+ ts->ts_rate = tx_ctl->tx_control_3 &
AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
break;
case 1:
- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
break;
case 2:
- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
break;
case 3:
- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
break;
}
if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
if (tx_status->tx_status_0 &
AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
- desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
+ ts->ts_status |= AR5K_TXERR_XRETRY;
if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
- desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
+ ts->ts_status |= AR5K_TXERR_FIFO;
if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
- desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
+ ts->ts_status |= AR5K_TXERR_FILT;
}
return 0;
int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
u32 size, unsigned int flags)
{
- struct ath5k_rx_desc *rx_desc;
+ struct ath5k_hw_rx_ctl *rx_ctl;
ATH5K_TRACE(ah->ah_sc);
- rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
+ rx_ctl = &desc->ud.ds_rx.rx_ctl;
/*
- *Clear ds_hw
+ * Clear the descriptor
* If we don't clean the status descriptor,
* while scanning we get too many results,
* most of them virtual, after some secs
* of scanning system hangs. M.F.
*/
- memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
-
- /*Initialize rx descriptor*/
- rx_desc->rx_control_0 = 0;
- rx_desc->rx_control_1 = 0;
+ memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
/* Setup descriptor */
- rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
- if (unlikely(rx_desc->rx_control_1 != size))
+ rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+ if (unlikely(rx_ctl->rx_control_1 != size))
return -EINVAL;
if (flags & AR5K_RXDESC_INTREQ)
- rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+ rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
return 0;
}
/*
* Proccess the rx status descriptor on 5210/5211
*/
-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
- struct ath5k_desc *desc)
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
{
- struct ath5k_hw_old_rx_status *rx_status;
+ struct ath5k_hw_rx_status *rx_status;
- rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
+ rx_status = &desc->ud.ds_rx.u.rx_stat;
/* No frame received / not ready */
- if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
+ if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE)
== 0))
return -EINPROGRESS;
/*
* Frame receive status
*/
- desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
- AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
- desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
- desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
- desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
- desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
- AR5K_OLD_RX_DESC_STATUS0_MORE;
- desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
- desc->ds_us.rx.rs_status = 0;
+ rs->rs_datalen = rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
+ rs->rs_antenna = rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+ rs->rs_more = rx_status->rx_status_0 &
+ AR5K_5210_RX_DESC_STATUS0_MORE;
+ /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ rs->rs_status = 0;
/*
* Key table status
*/
- if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
- desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
+ if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
+ rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
else
- desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
/*
* Receive/descriptor errors
*/
- if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
- == 0) {
- if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
- desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
+ if ((rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+ if (rx_status->rx_status_1 &
+ AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_CRC;
if (rx_status->rx_status_1 &
- AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
- desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
+ AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
+ rs->rs_status |= AR5K_RXERR_FIFO;
if (rx_status->rx_status_1 &
- AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
- desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
- desc->ds_us.rx.rs_phyerr =
- AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
+ rs->rs_status |= AR5K_RXERR_PHY;
+ rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
}
if (rx_status->rx_status_1 &
- AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
- desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
+ AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_DECRYPT;
}
return 0;
/*
* Proccess the rx status descriptor on 5212
*/
-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
- struct ath5k_desc *desc)
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
{
- struct ath5k_hw_new_rx_status *rx_status;
+ struct ath5k_hw_rx_status *rx_status;
struct ath5k_hw_rx_error *rx_err;
ATH5K_TRACE(ah->ah_sc);
- rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
+ rx_status = &desc->ud.ds_rx.u.rx_stat;
/* Overlay on error */
- rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
+ rx_err = &desc->ud.ds_rx.u.rx_err;
/* No frame received / not ready */
- if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
+ if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE)
== 0))
return -EINPROGRESS;
/*
* Frame receive status
*/
- desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
- AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
- desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
- desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
- desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
- desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
- AR5K_NEW_RX_DESC_STATUS0_MORE;
- desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
- desc->ds_us.rx.rs_status = 0;
+ rs->rs_datalen = rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
+ rs->rs_antenna = rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+ rs->rs_more = rx_status->rx_status_0 &
+ AR5K_5212_RX_DESC_STATUS0_MORE;
+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ rs->rs_status = 0;
/*
* Key table status
*/
- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
- desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
- AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
+ if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
+ rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
else
- desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
/*
* Receive/descriptor errors
*/
if ((rx_status->rx_status_1 &
- AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
- desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
+ AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_CRC;
if (rx_status->rx_status_1 &
- AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
- desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
- desc->ds_us.rx.rs_phyerr =
- AR5K_REG_MS(rx_err->rx_error_1,
- AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+ AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
+ rs->rs_status |= AR5K_RXERR_PHY;
+ rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1,
+ AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
}
if (rx_status->rx_status_1 &
- AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
- desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
+ AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ rs->rs_status |= AR5K_RXERR_DECRYPT;
- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
- desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
+ if (rx_status->rx_status_1 &
+ AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
+ rs->rs_status |= AR5K_RXERR_MIC;
}
return 0;
}
-/*********************************\
- Regulatory Domain/Channels Setup
-\*********************************/
-
-u16 ath5k_get_regdomain(struct ath5k_hw *ah)
-{
- u16 regdomain;
- enum ath5k_regdom ieee_regdomain;
-#ifdef COUNTRYCODE
- u16 code;
-#endif
-
- ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain);
- ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
-
-#ifdef COUNTRYCODE
- /*
- * Get the regulation domain by country code. This will ignore
- * the settings found in the EEPROM.
- */
- code = ieee80211_name2countrycode(COUNTRYCODE);
- ieee_regdomain = ieee80211_countrycode2regdomain(code);
-#endif
-
- regdomain = ath5k_regdom_from_ieee(ieee_regdomain);
- ah->ah_capabilities.cap_regdomain.reg_current = regdomain;
-
- return regdomain;
-}
/****************\
lbs_deb_cmd("disconnected, so exit PS mode\n");
lbs_ps_wakeup(priv, 0);
}
- lbs_deb_leave(LBS_DEB_CMD);
+ lbs_deb_leave(LBS_DEB_ASSOC);
}
/**
return 0;
}
-static int lbs_ret_802_11_key_material(struct lbs_private *priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_key_material *pkeymaterial =
- &resp->params.keymaterial;
- u16 action = le16_to_cpu(pkeymaterial->action);
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- /* Copy the returned key to driver private data */
- if (action == CMD_ACT_GET) {
- u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
- u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
-
- while (buf_ptr < resp_end) {
- struct MrvlIEtype_keyParamSet * pkeyparamset =
- (struct MrvlIEtype_keyParamSet *) buf_ptr;
- struct enc_key * pkey;
- u16 param_set_len = le16_to_cpu(pkeyparamset->length);
- u16 key_len = le16_to_cpu(pkeyparamset->keylen);
- u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
- u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
- u8 * end;
-
- end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
- + sizeof (pkeyparamset->length)
- + param_set_len;
- /* Make sure we don't access past the end of the IEs */
- if (end > resp_end)
- break;
-
- if (key_flags & KEY_INFO_WPA_UNICAST)
- pkey = &priv->wpa_unicast_key;
- else if (key_flags & KEY_INFO_WPA_MCAST)
- pkey = &priv->wpa_mcast_key;
- else
- break;
-
- /* Copy returned key into driver */
- memset(pkey, 0, sizeof(struct enc_key));
- if (key_len > sizeof(pkey->key))
- break;
- pkey->type = key_type;
- pkey->flags = key_flags;
- pkey->len = key_len;
- memcpy(pkey->key, pkeyparamset->key, pkey->len);
-
- buf_ptr = end + 1;
- }
- }
-
- lbs_deb_enter(LBS_DEB_CMD);
- return 0;
-}
-
static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
ret = lbs_ret_reg_access(priv, respcmd, resp);
break;
- case CMD_RET(CMD_802_11_SCAN):
- ret = lbs_ret_80211_scan(priv, resp);
- break;
-
case CMD_RET(CMD_802_11_GET_LOG):
ret = lbs_ret_get_log(priv, resp);
break;
ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
break;
- case CMD_RET(CMD_802_11_KEY_MATERIAL):
- ret = lbs_ret_802_11_key_material(priv, resp);
- break;
-
case CMD_RET(CMD_802_11_EEPROM_ACCESS):
ret = lbs_ret_802_11_eeprom_access(priv, resp);
break;
respcmd = le16_to_cpu(resp->command);
result = le16_to_cpu(resp->result);
- lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
+ lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
- lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
+ lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len);
if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
goto done;
}
if (respcmd != CMD_RET(curcmd) &&
- respcmd != CMD_802_11_ASSOCIATE && curcmd != CMD_RET_802_11_ASSOCIATE) {
+ respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) {
lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
/*
- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
#define RT2X00_H
#include <linux/bitops.h>
-#include <linux/prefetch.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
+#include <linux/leds.h>
#include <linux/mutex.h>
#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "rt2x00debug.h"
+#include "rt2x00leds.h"
#include "rt2x00reg.h"
-#include "rt2x00ring.h"
+#include "rt2x00queue.h"
/*
* Module information.
*/
-#define DRV_VERSION "2.0.14"
+#define DRV_VERSION "2.1.4"
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
/*
DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
/*
- * Ring sizes.
- * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes.
- * DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings.
- * MGMT_FRAME_SIZE is used for the BEACON ring.
- */
-#define DATA_FRAME_SIZE 2432
-#define MGMT_FRAME_SIZE 256
-
-/*
- * Number of entries in a packet ring.
- * PCI devices only need 1 Beacon entry,
- * but USB devices require a second because they
- * have to send a Guardian byte first.
- */
-#define RX_ENTRIES 12
-#define TX_ENTRIES 12
-#define ATIM_ENTRIES 1
-#define BEACON_ENTRIES 2
-
-/*
* Standard timing and size defines.
* These values should follow the ieee80211 specifications.
*/
/*
* Interface structure
- * Configuration details about the current interface.
+ * Per interface configuration details, this structure
+ * is allocated as the private data for ieee80211_vif.
*/
-struct interface {
+struct rt2x00_intf {
/*
- * Interface identification. The value is assigned
- * to us by the 80211 stack, and is used to request
- * new beacons.
+ * All fields within the rt2x00_intf structure
+ * must be protected with a spinlock.
*/
- struct ieee80211_vif *id;
+ spinlock_t lock;
/*
- * Current working type (IEEE80211_IF_TYPE_*).
+ * BSS configuration. Copied from the structure
+ * passed to us through the bss_info_changed()
+ * callback funtion.
*/
- int type;
+ struct ieee80211_bss_conf conf;
/*
* MAC of the device.
* BBSID of the AP to associate with.
*/
u8 bssid[ETH_ALEN];
-};
-static inline int is_interface_present(struct interface *intf)
-{
- return !!intf->id;
-}
+ /*
+ * Entry in the beacon queue which belongs to
+ * this interface. Each interface has its own
+ * dedicated beacon entry.
+ */
+ struct queue_entry *beacon;
+
+ /*
+ * Actions that needed rescheduling.
+ */
+ unsigned int delayed_flags;
+#define DELAYED_UPDATE_BEACON 0x00000001
+#define DELAYED_CONFIG_ERP 0x00000002
+};
-static inline int is_interface_type(struct interface *intf, int type)
+static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
{
- return intf->type == type;
+ return (struct rt2x00_intf *)vif->drv_priv;
}
-/*
+/**
+ * struct hw_mode_spec: Hardware specifications structure
+ *
* Details about the supported modes, rates and channels
* of a particular chipset. This is used by rt2x00lib
* to build the ieee80211_hw_mode array for mac80211.
+ *
+ * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
+ * @supported_rates: Rate types which are supported (CCK, OFDM).
+ * @num_channels: Number of supported channels. This is used as array size
+ * for @tx_power_a, @tx_power_bg and @channels.
+ * channels: Device/chipset specific channel values (See &struct rf_channel).
+ * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
+ * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
+ * @tx_power_default: Default TX power value to use when either
+ * @tx_power_a or @tx_power_bg is missing.
*/
struct hw_mode_spec {
- /*
- * Number of modes, rates and channels.
- */
- int num_modes;
- int num_rates;
- int num_channels;
+ unsigned int supported_bands;
+#define SUPPORT_BAND_2GHZ 0x00000001
+#define SUPPORT_BAND_5GHZ 0x00000002
+
+ unsigned int supported_rates;
+#define SUPPORT_RATE_CCK 0x00000001
+#define SUPPORT_RATE_OFDM 0x00000002
+
+ unsigned int num_channels;
+ const struct rf_channel *channels;
- /*
- * txpower values.
- */
const u8 *tx_power_a;
const u8 *tx_power_bg;
u8 tx_power_default;
-
- /*
- * Device/chipset specific value.
- */
- const struct rf_channel *channels;
};
/*
struct antenna_setup ant;
- int phymode;
+ enum ieee80211_band band;
- int basic_rates;
- int slot_time;
+ u32 basic_rates;
+ u32 slot_time;
short sifs;
short pifs;
};
/*
+ * Configuration structure for erp settings.
+ */
+struct rt2x00lib_erp {
+ int short_preamble;
+
+ int ack_timeout;
+ int ack_consume_time;
+};
+
+/*
+ * Configuration structure wrapper around the
+ * rt2x00 interface configuration handler.
+ */
+struct rt2x00intf_conf {
+ /*
+ * Interface type
+ */
+ enum ieee80211_if_types type;
+
+ /*
+ * TSF sync value, this is dependant on the operation type.
+ */
+ enum tsf_sync sync;
+
+ /*
+ * The MAC and BSSID addressess are simple array of bytes,
+ * these arrays are little endian, so when sending the addressess
+ * to the drivers, copy the it into a endian-signed variable.
+ *
+ * Note that all devices (except rt2500usb) have 32 bits
+ * register word sizes. This means that whatever variable we
+ * pass _must_ be a multiple of 32 bits. Otherwise the device
+ * might not accept what we are sending to it.
+ * This will also make it easier for the driver to write
+ * the data to the device.
+ */
+ __le32 mac[2];
+ __le32 bssid[2];
+};
+
+/*
* rt2x00lib callback functions.
*/
struct rt2x00lib_ops {
*/
int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev);
+ u16 (*get_firmware_crc) (void *data, const size_t len);
int (*load_firmware) (struct rt2x00_dev *rt2x00dev, void *data,
const size_t len);
void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
/*
- * Ring initialization handlers
+ * queue initialization handlers
*/
void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
- struct data_entry *entry);
+ struct queue_entry *entry);
void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
- struct data_entry *entry);
+ struct queue_entry *entry);
/*
* Radio control handlers.
struct link_qual *qual);
void (*reset_tuner) (struct rt2x00_dev *rt2x00dev);
void (*link_tuner) (struct rt2x00_dev *rt2x00dev);
+ void (*led_brightness) (struct led_classdev *led_cdev,
+ enum led_brightness brightness);
/*
* TX control handlers
*/
void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
- struct txdata_entry_desc *desc,
+ struct txentry_desc *txdesc,
struct ieee80211_tx_control *control);
int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
- struct data_ring *ring, struct sk_buff *skb,
+ struct data_queue *queue, struct sk_buff *skb,
struct ieee80211_tx_control *control);
int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb);
void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
- unsigned int queue);
+ const unsigned int queue);
/*
* RX control handlers
*/
- void (*fill_rxdone) (struct data_entry *entry,
- struct rxdata_entry_desc *desc);
+ void (*fill_rxdone) (struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc);
/*
* Configuration handlers.
*/
- void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac);
- void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid);
- void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type,
- const int tsf_sync);
- void (*config_preamble) (struct rt2x00_dev *rt2x00dev,
- const int short_preamble,
- const int ack_timeout,
- const int ack_consume_time);
- void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags,
- struct rt2x00lib_conf *libconf);
+ void (*config_intf) (struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_intf *intf,
+ struct rt2x00intf_conf *conf,
+ const unsigned int flags);
+#define CONFIG_UPDATE_TYPE ( 1 << 1 )
+#define CONFIG_UPDATE_MAC ( 1 << 2 )
+#define CONFIG_UPDATE_BSSID ( 1 << 3 )
+
+ int (*config_erp) (struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_erp *erp);
+ void (*config) (struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf,
+ const unsigned int flags);
#define CONFIG_UPDATE_PHYMODE ( 1 << 1 )
#define CONFIG_UPDATE_CHANNEL ( 1 << 2 )
#define CONFIG_UPDATE_TXPOWER ( 1 << 3 )
*/
struct rt2x00_ops {
const char *name;
- const unsigned int rxd_size;
- const unsigned int txd_size;
+ const unsigned int max_sta_intf;
+ const unsigned int max_ap_intf;
const unsigned int eeprom_size;
const unsigned int rf_size;
+ const struct data_queue_desc *rx;
+ const struct data_queue_desc *tx;
+ const struct data_queue_desc *bcn;
+ const struct data_queue_desc *atim;
const struct rt2x00lib_ops *lib;
const struct ieee80211_ops *hw;
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
/*
* Driver features
*/
+ DRIVER_SUPPORT_MIXED_INTERFACES,
DRIVER_REQUIRE_FIRMWARE,
- DRIVER_REQUIRE_BEACON_RING,
+ DRIVER_REQUIRE_BEACON_GUARD,
+ DRIVER_REQUIRE_ATIM_QUEUE,
/*
* Driver configuration
CONFIG_EXTERNAL_LNA_BG,
CONFIG_DOUBLE_ANTENNA,
CONFIG_DISABLE_LINK_TUNING,
- CONFIG_SHORT_PREAMBLE,
};
/*
* macro's should be used for correct typecasting.
*/
void *dev;
-#define rt2x00dev_pci(__dev) ( (struct pci_dev*)(__dev)->dev )
-#define rt2x00dev_usb(__dev) ( (struct usb_interface*)(__dev)->dev )
+#define rt2x00dev_pci(__dev) ( (struct pci_dev *)(__dev)->dev )
+#define rt2x00dev_usb(__dev) ( (struct usb_interface *)(__dev)->dev )
+#define rt2x00dev_usb_dev(__dev)\
+ ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) )
/*
* Callback functions.
* IEEE80211 control structure.
*/
struct ieee80211_hw *hw;
- struct ieee80211_hw_mode *hwmodes;
- unsigned int curr_hwmode;
-#define HWMODE_B 0
-#define HWMODE_G 1
-#define HWMODE_A 2
+ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+ enum ieee80211_band curr_band;
/*
* rfkill structure for RF state switching support.
* This will only be compiled in when required.
*/
#ifdef CONFIG_RT2X00_LIB_RFKILL
+ unsigned long rfkill_state;
+ #define RFKILL_STATE_ALLOCATED 1
+ #define RFKILL_STATE_REGISTERED 2
struct rfkill *rfkill;
struct input_polled_dev *poll_dev;
#endif /* CONFIG_RT2X00_LIB_RFKILL */
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
+ * LED structure for changing the LED status
+ * by mac8011 or the kernel.
+ */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+ unsigned int led_flags;
+ struct rt2x00_trigger trigger_qual;
+ struct rt2x00_led led_radio;
+ struct rt2x00_led led_assoc;
+ struct rt2x00_led led_qual;
+ u16 led_mcu_reg;
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+ /*
* Device flags.
* In these flags the current status and some
* of the device capabilities are stored.
/*
* Register pointers
- * csr_addr: Base register address. (PCI)
- * csr_cache: CSR cache for usb_control_msg. (USB)
+ * csr.base: CSR base register address. (PCI)
+ * csr.cache: CSR cache for usb_control_msg. (USB)
*/
- void __iomem *csr_addr;
- void *csr_cache;
+ union csr {
+ void __iomem *base;
+ void *cache;
+ } csr;
/*
* Mutex to protect register accesses on USB devices.
unsigned int packet_filter;
/*
- * Interface configuration.
+ * Interface details:
+ * - Open ap interface count.
+ * - Open sta interface count.
+ * - Association count.
*/
- struct interface interface;
+ unsigned int intf_ap_count;
+ unsigned int intf_sta_count;
+ unsigned int intf_associated;
/*
* Link quality
u16 tx_power;
/*
- * LED register (for rt61pci & rt73usb).
- */
- u16 led_reg;
-
- /*
- * Led mode (LED_MODE_*)
- */
- u8 led_mode;
-
- /*
* Rssi <-> Dbm offset
*/
u8 rssi_offset;
/*
* Scheduled work.
*/
- struct work_struct beacon_work;
+ struct work_struct intf_work;
struct work_struct filter_work;
- struct work_struct config_work;
/*
- * Data ring arrays for RX, TX and Beacon.
- * The Beacon array also contains the Atim ring
+ * Data queue arrays for RX, TX and Beacon.
+ * The Beacon array also contains the Atim queue
* if that is supported by the device.
*/
- int data_rings;
- struct data_ring *rx;
- struct data_ring *tx;
- struct data_ring *bcn;
+ int data_queues;
+ struct data_queue *rx;
+ struct data_queue *tx;
+ struct data_queue *bcn;
/*
* Firmware image.
};
/*
- * For-each loop for the ring array.
- * All rings have been allocated as a single array,
- * this means we can create a very simply loop macro
- * that is capable of looping through all rings.
- * ring_end(), txring_end() and ring_loop() are helper macro's which
- * should not be used directly. Instead the following should be used:
- * ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim)
- * txring_for_each() - Loops through TX data rings (TX only)
- * txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim)
- */
-#define ring_end(__dev) \
- &(__dev)->rx[(__dev)->data_rings]
-
-#define txring_end(__dev) \
- &(__dev)->tx[(__dev)->hw->queues]
-
-#define ring_loop(__entry, __start, __end) \
- for ((__entry) = (__start); \
- prefetch(&(__entry)[1]), (__entry) != (__end); \
- (__entry) = &(__entry)[1])
-
-#define ring_for_each(__dev, __entry) \
- ring_loop(__entry, (__dev)->rx, ring_end(__dev))
-
-#define txring_for_each(__dev, __entry) \
- ring_loop(__entry, (__dev)->tx, txring_end(__dev))
-
-#define txringall_for_each(__dev, __entry) \
- ring_loop(__entry, (__dev)->tx, ring_end(__dev))
-
-/*
* Generic RF access.
* The RF is being accessed by word index.
*/
return ((size * 8 * 10) % rate);
}
-/*
- * Library functions.
+/**
+ * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @queue: mac80211/rt2x00 queue index
+ * (see &enum ieee80211_tx_queue and &enum rt2x00_bcn_queue).
+ */
+struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
+ const unsigned int queue);
+
+/**
+ * rt2x00queue_get_entry - Get queue entry where the given index points to.
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @index: Index identifier for obtaining the correct index.
+ */
+struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
+ enum queue_index index);
+
+/**
+ * rt2x00queue_index_inc - Index incrementation function
+ * @queue: Queue (&struct data_queue) to perform the action on.
+ * @action: Index type (&enum queue_index) to perform the action on.
+ *
+ * This function will increase the requested index on the queue,
+ * it will grab the appropriate locks and handle queue overflow events by
+ * resetting the index to the start of the queue.
*/
-struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
- const unsigned int queue);
+void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
+
/*
* Interrupt context handlers.
*/
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_txdone(struct data_entry *entry,
- const int status, const int retry);
-void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
- struct rxdata_entry_desc *desc);
+void rt2x00lib_txdone(struct queue_entry *entry,
+ struct txdone_entry_desc *txdesc);
+void rt2x00lib_rxdone(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc);
/*
* TX descriptor initializer
/*
- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
#include "rt2x00dump.h"
/*
- * Ring handler.
- */
-struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
- const unsigned int queue)
-{
- int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
-
- /*
- * Check if we are requesting a reqular TX ring,
- * or if we are requesting a Beacon or Atim ring.
- * For Atim rings, we should check if it is supported.
- */
- if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
- return &rt2x00dev->tx[queue];
-
- if (!rt2x00dev->bcn || !beacon)
- return NULL;
-
- if (queue == IEEE80211_TX_QUEUE_BEACON)
- return &rt2x00dev->bcn[0];
- else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
- return &rt2x00dev->bcn[1];
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_get_ring);
-
-/*
* Link tuning handlers
*/
void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
}
/*
- * Ring initialization
- */
-static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
-{
- struct data_ring *ring = rt2x00dev->rx;
- unsigned int i;
-
- if (!rt2x00dev->ops->lib->init_rxentry)
- return;
-
- if (ring->data_addr)
- memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++)
- rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
-
- rt2x00_ring_index_clear(ring);
-}
-
-static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
-{
- struct data_ring *ring;
- unsigned int i;
-
- if (!rt2x00dev->ops->lib->init_txentry)
- return;
-
- txringall_for_each(rt2x00dev, ring) {
- if (ring->data_addr)
- memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++)
- rt2x00dev->ops->lib->init_txentry(rt2x00dev,
- &ring->entry[i]);
-
- rt2x00_ring_index_clear(ring);
- }
-}
-
-/*
* Radio control handlers.
*/
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
return 0;
/*
- * Initialize all data rings.
+ * Initialize all data queues.
*/
- rt2x00lib_init_rxrings(rt2x00dev);
- rt2x00lib_init_txrings(rt2x00dev);
+ rt2x00queue_init_rx(rt2x00dev);
+ rt2x00queue_init_tx(rt2x00dev);
/*
* Enable radio.
/*
* Stop all scheduled work.
*/
- if (work_pending(&rt2x00dev->beacon_work))
- cancel_work_sync(&rt2x00dev->beacon_work);
+ if (work_pending(&rt2x00dev->intf_work))
+ cancel_work_sync(&rt2x00dev->intf_work);
if (work_pending(&rt2x00dev->filter_work))
cancel_work_sync(&rt2x00dev->filter_work);
- if (work_pending(&rt2x00dev->config_work))
- cancel_work_sync(&rt2x00dev->config_work);
/*
* Stop the TX queues.
* When we are enabling the RX, we should also start the link tuner.
*/
if (state == STATE_RADIO_RX_ON &&
- is_interface_present(&rt2x00dev->interface))
+ (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count))
rt2x00lib_start_link_tuner(rt2x00dev);
}
rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual);
/*
+ * Send a signal to the led to update the led signal strength.
+ */
+ rt2x00leds_led_quality(rt2x00dev, rt2x00dev->link.qual.avg_rssi);
+
+ /*
* Evaluate antenna setup, make this the last step since this could
* possibly reset some statistics.
*/
unsigned int filter = rt2x00dev->packet_filter;
/*
- * Since we had stored the filter inside interface.filter,
+ * Since we had stored the filter inside rt2x00dev->packet_filter,
* we should now clear that field. Otherwise the driver will
* assume nothing has changed (*total_flags will be compared
- * to interface.filter to determine if any action is required).
+ * to rt2x00dev->packet_filter to determine if any action is required).
*/
rt2x00dev->packet_filter = 0;
filter, &filter, 0, NULL);
}
-static void rt2x00lib_configuration_scheduled(struct work_struct *work)
+static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
{
- struct rt2x00_dev *rt2x00dev =
- container_of(work, struct rt2x00_dev, config_work);
- struct ieee80211_bss_conf bss_conf;
+ struct rt2x00_dev *rt2x00dev = data;
+ struct rt2x00_intf *intf = vif_to_intf(vif);
+ struct sk_buff *skb;
+ struct ieee80211_tx_control control;
+ struct ieee80211_bss_conf conf;
+ int delayed_flags;
+
+ /*
+ * Copy all data we need during this action under the protection
+ * of a spinlock. Otherwise race conditions might occur which results
+ * into an invalid configuration.
+ */
+ spin_lock(&intf->lock);
+
+ memcpy(&conf, &intf->conf, sizeof(conf));
+ delayed_flags = intf->delayed_flags;
+ intf->delayed_flags = 0;
+
+ spin_unlock(&intf->lock);
- bss_conf.use_short_preamble =
- test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+ if (delayed_flags & DELAYED_UPDATE_BEACON) {
+ skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
+ if (skb) {
+ rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
+ &control);
+ dev_kfree_skb(skb);
+ }
+ }
+
+ if (delayed_flags & DELAYED_CONFIG_ERP)
+ rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf);
+}
+
+static void rt2x00lib_intf_scheduled(struct work_struct *work)
+{
+ struct rt2x00_dev *rt2x00dev =
+ container_of(work, struct rt2x00_dev, intf_work);
/*
- * FIXME: shouldn't invoke it this way because all other contents
- * of bss_conf is invalid.
+ * Iterate over each interface and perform the
+ * requested configurations.
*/
- rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id,
- &bss_conf, BSS_CHANGED_ERP_PREAMBLE);
+ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+ rt2x00lib_intf_scheduled_iter,
+ rt2x00dev);
}
/*
* Interrupt context handlers.
*/
-static void rt2x00lib_beacondone_scheduled(struct work_struct *work)
+static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
{
- struct rt2x00_dev *rt2x00dev =
- container_of(work, struct rt2x00_dev, beacon_work);
- struct data_ring *ring =
- rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
- struct data_entry *entry = rt2x00_get_data_entry(ring);
- struct sk_buff *skb;
+ struct rt2x00_intf *intf = vif_to_intf(vif);
- skb = ieee80211_beacon_get(rt2x00dev->hw,
- rt2x00dev->interface.id,
- &entry->tx_status.control);
- if (!skb)
+ if (vif->type != IEEE80211_IF_TYPE_AP &&
+ vif->type != IEEE80211_IF_TYPE_IBSS)
return;
- rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
- &entry->tx_status.control);
-
- dev_kfree_skb(skb);
+ spin_lock(&intf->lock);
+ intf->delayed_flags |= DELAYED_UPDATE_BEACON;
+ spin_unlock(&intf->lock);
}
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
return;
- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work);
+ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+ rt2x00lib_beacondone_iter,
+ rt2x00dev);
+
+ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
}
EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
-void rt2x00lib_txdone(struct data_entry *entry,
- const int status, const int retry)
+void rt2x00lib_txdone(struct queue_entry *entry,
+ struct txdone_entry_desc *txdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
- struct ieee80211_tx_status *tx_status = &entry->tx_status;
- struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats;
- int success = !!(status == TX_SUCCESS || status == TX_SUCCESS_RETRY);
- int fail = !!(status == TX_FAIL_RETRY || status == TX_FAIL_INVALID ||
- status == TX_FAIL_OTHER);
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct skb_frame_desc *skbdesc;
+ struct ieee80211_tx_status tx_status;
+ int success = !!(txdesc->status == TX_SUCCESS ||
+ txdesc->status == TX_SUCCESS_RETRY);
+ int fail = !!(txdesc->status == TX_FAIL_RETRY ||
+ txdesc->status == TX_FAIL_INVALID ||
+ txdesc->status == TX_FAIL_OTHER);
/*
* Update TX statistics.
*/
- tx_status->flags = 0;
- tx_status->ack_signal = 0;
- tx_status->excessive_retries = (status == TX_FAIL_RETRY);
- tx_status->retry_count = retry;
rt2x00dev->link.qual.tx_success += success;
- rt2x00dev->link.qual.tx_failed += retry + fail;
+ rt2x00dev->link.qual.tx_failed += txdesc->retry + fail;
+
+ /*
+ * Initialize TX status
+ */
+ tx_status.flags = 0;
+ tx_status.ack_signal = 0;
+ tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY);
+ tx_status.retry_count = txdesc->retry;
+ memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control));
- if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) {
+ if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
if (success)
- tx_status->flags |= IEEE80211_TX_STATUS_ACK;
+ tx_status.flags |= IEEE80211_TX_STATUS_ACK;
else
- stats->dot11ACKFailureCount++;
+ rt2x00dev->low_level_stats.dot11ACKFailureCount++;
}
- tx_status->queue_length = entry->ring->stats.limit;
- tx_status->queue_number = tx_status->control.queue;
+ tx_status.queue_length = entry->queue->limit;
+ tx_status.queue_number = tx_status.control.queue;
- if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+ if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
if (success)
- stats->dot11RTSSuccessCount++;
+ rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
else
- stats->dot11RTSFailureCount++;
+ rt2x00dev->low_level_stats.dot11RTSFailureCount++;
}
/*
- * Send the tx_status to mac80211 & debugfs.
- * mac80211 will clean up the skb structure.
+ * Send the tx_status to debugfs. Only send the status report
+ * to mac80211 when the frame originated from there. If this was
+ * a extra frame coming through a mac80211 library call (RTS/CTS)
+ * then we should not send the status report back.
+ * If send to mac80211, mac80211 will clean up the skb structure,
+ * otherwise we have to do it ourself.
*/
- get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
+ skbdesc = get_skb_frame_desc(entry->skb);
+ skbdesc->frame_type = DUMP_FRAME_TXDONE;
+
rt2x00debug_dump_frame(rt2x00dev, entry->skb);
- ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
+
+ if (!(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED))
+ ieee80211_tx_status_irqsafe(rt2x00dev->hw,
+ entry->skb, &tx_status);
+ else
+ dev_kfree_skb(entry->skb);
entry->skb = NULL;
}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
-void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
- struct rxdata_entry_desc *desc)
+void rt2x00lib_rxdone(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
- struct ieee80211_hw_mode *mode;
- struct ieee80211_rate *rate;
+ struct ieee80211_supported_band *sband;
struct ieee80211_hdr *hdr;
+ const struct rt2x00_rate *rate;
unsigned int i;
- int val = 0;
+ int idx = -1;
u16 fc;
/*
* Update RX statistics.
*/
- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
- for (i = 0; i < mode->num_rates; i++) {
- rate = &mode->rates[i];
+ sband = &rt2x00dev->bands[rt2x00dev->curr_band];
+ for (i = 0; i < sband->n_bitrates; i++) {
+ rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
- /*
- * When frame was received with an OFDM bitrate,
- * the signal is the PLCP value. If it was received with
- * a CCK bitrate the signal is the rate in 0.5kbit/s.
- */
- if (!desc->ofdm)
- val = DEVICE_GET_RATE_FIELD(rate->val, RATE);
- else
- val = DEVICE_GET_RATE_FIELD(rate->val, PLCP);
-
- if (val == desc->signal) {
- val = rate->val;
+ if ((rxdesc->signal_plcp && rate->plcp == rxdesc->signal) ||
+ (!rxdesc->signal_plcp && rate->bitrate == rxdesc->signal)) {
+ idx = i;
break;
}
}
/*
* Only update link status if this is a beacon frame carrying our bssid.
*/
- hdr = (struct ieee80211_hdr*)skb->data;
+ hdr = (struct ieee80211_hdr *)entry->skb->data;
fc = le16_to_cpu(hdr->frame_control);
- if (is_beacon(fc) && desc->my_bss)
- rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);
+ if (is_beacon(fc) && rxdesc->my_bss)
+ rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi);
rt2x00dev->link.qual.rx_success++;
- rx_status->rate = val;
+ rx_status->rate_idx = idx;
rx_status->signal =
- rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi);
- rx_status->ssi = desc->rssi;
- rx_status->flag = desc->flags;
+ rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
+ rx_status->ssi = rxdesc->rssi;
+ rx_status->flag = rxdesc->flags;
rx_status->antenna = rt2x00dev->link.ant.active.rx;
/*
- * Send frame to mac80211 & debugfs
+ * Send frame to mac80211 & debugfs.
+ * mac80211 will clean up the skb structure.
*/
- get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
- rt2x00debug_dump_frame(rt2x00dev, skb);
- ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
+ get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_RXDONE;
+ rt2x00debug_dump_frame(rt2x00dev, entry->skb);
+ ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
+ entry->skb = NULL;
}
EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
- struct txdata_entry_desc desc;
- struct skb_desc *skbdesc = get_skb_desc(skb);
- struct ieee80211_hdr *ieee80211hdr = skbdesc->data;
+ struct txentry_desc txdesc;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skbdesc->data;
+ const struct rt2x00_rate *rate;
int tx_rate;
- int bitrate;
int length;
int duration;
int residual;
u16 frame_control;
u16 seq_ctrl;
- memset(&desc, 0, sizeof(desc));
-
- desc.cw_min = skbdesc->ring->tx_params.cw_min;
- desc.cw_max = skbdesc->ring->tx_params.cw_max;
- desc.aifs = skbdesc->ring->tx_params.aifs;
+ memset(&txdesc, 0, sizeof(txdesc));
- /*
- * Identify queue
- */
- if (control->queue < rt2x00dev->hw->queues)
- desc.queue = control->queue;
- else if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
- control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
- desc.queue = QUEUE_MGMT;
- else
- desc.queue = QUEUE_OTHER;
+ txdesc.queue = skbdesc->entry->queue->qid;
+ txdesc.cw_min = skbdesc->entry->queue->cw_min;
+ txdesc.cw_max = skbdesc->entry->queue->cw_max;
+ txdesc.aifs = skbdesc->entry->queue->aifs;
/*
* Read required fields from ieee80211 header.
*/
- frame_control = le16_to_cpu(ieee80211hdr->frame_control);
- seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl);
+ frame_control = le16_to_cpu(hdr->frame_control);
+ seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
- tx_rate = control->tx_rate;
+ tx_rate = control->tx_rate->hw_value;
/*
* Check whether this frame is to be acked
*/
if (!(control->flags & IEEE80211_TXCTL_NO_ACK))
- __set_bit(ENTRY_TXD_ACK, &desc.flags);
+ __set_bit(ENTRY_TXD_ACK, &txdesc.flags);
/*
* Check if this is a RTS/CTS frame
*/
if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) {
- __set_bit(ENTRY_TXD_BURST, &desc.flags);
+ __set_bit(ENTRY_TXD_BURST, &txdesc.flags);
if (is_rts_frame(frame_control)) {
- __set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags);
- __set_bit(ENTRY_TXD_ACK, &desc.flags);
+ __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags);
+ __set_bit(ENTRY_TXD_ACK, &txdesc.flags);
} else
- __clear_bit(ENTRY_TXD_ACK, &desc.flags);
+ __clear_bit(ENTRY_TXD_ACK, &txdesc.flags);
if (control->rts_cts_rate)
- tx_rate = control->rts_cts_rate;
+ tx_rate = control->rts_cts_rate->hw_value;
}
- /*
- * Check for OFDM
- */
- if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK)
- __set_bit(ENTRY_TXD_OFDM_RATE, &desc.flags);
+ rate = rt2x00_get_rate(tx_rate);
/*
* Check if more fragments are pending
*/
- if (ieee80211_get_morefrag(ieee80211hdr)) {
- __set_bit(ENTRY_TXD_BURST, &desc.flags);
- __set_bit(ENTRY_TXD_MORE_FRAG, &desc.flags);
+ if (ieee80211_get_morefrag(hdr)) {
+ __set_bit(ENTRY_TXD_BURST, &txdesc.flags);
+ __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags);
}
/*
* Beacons and probe responses require the tsf timestamp
* to be inserted into the frame.
*/
- if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
+ if (control->queue == RT2X00_BCN_QUEUE_BEACON ||
is_probe_resp(frame_control))
- __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc.flags);
+ __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags);
/*
* Determine with what IFS priority this frame should be send.
* or this fragment came after RTS/CTS.
*/
if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 ||
- test_bit(ENTRY_TXD_RTS_FRAME, &desc.flags))
- desc.ifs = IFS_SIFS;
+ test_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags))
+ txdesc.ifs = IFS_SIFS;
else
- desc.ifs = IFS_BACKOFF;
+ txdesc.ifs = IFS_BACKOFF;
/*
* PLCP setup
* Length calculation depends on OFDM/CCK rate.
*/
- desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
- desc.service = 0x04;
+ txdesc.signal = rate->plcp;
+ txdesc.service = 0x04;
length = skbdesc->data_len + FCS_LEN;
- if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) {
- desc.length_high = (length >> 6) & 0x3f;
- desc.length_low = length & 0x3f;
- } else {
- bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
+ if (rate->flags & DEV_RATE_OFDM) {
+ __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags);
+ txdesc.length_high = (length >> 6) & 0x3f;
+ txdesc.length_low = length & 0x3f;
+ } else {
/*
* Convert length to microseconds.
*/
- residual = get_duration_res(length, bitrate);
- duration = get_duration(length, bitrate);
+ residual = get_duration_res(length, rate->bitrate);
+ duration = get_duration(length, rate->bitrate);
if (residual != 0) {
duration++;
/*
* Check if we need to set the Length Extension
*/
- if (bitrate == 110 && residual <= 30)
- desc.service |= 0x80;
+ if (rate->bitrate == 110 && residual <= 30)
+ txdesc.service |= 0x80;
}
- desc.length_high = (duration >> 8) & 0xff;
- desc.length_low = duration & 0xff;
+ txdesc.length_high = (duration >> 8) & 0xff;
+ txdesc.length_low = duration & 0xff;
/*
* When preamble is enabled we should set the
* preamble bit for the signal.
*/
- if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
- desc.signal |= 0x08;
+ if (rt2x00_get_rate_preamble(tx_rate))
+ txdesc.signal |= 0x08;
}
- rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control);
+ rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &txdesc, control);
/*
- * Update ring entry.
+ * Update queue entry.
*/
skbdesc->entry->skb = skb;
- memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
/*
* The frame has been completely initialized and ready
/*
* Driver initialization handlers.
*/
+const struct rt2x00_rate rt2x00_supported_rates[12] = {
+ {
+ .flags = DEV_RATE_CCK | DEV_RATE_BASIC,
+ .bitrate = 10,
+ .ratemask = BIT(0),
+ .plcp = 0x00,
+ },
+ {
+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
+ .bitrate = 20,
+ .ratemask = BIT(1),
+ .plcp = 0x01,
+ },
+ {
+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
+ .bitrate = 55,
+ .ratemask = BIT(2),
+ .plcp = 0x02,
+ },
+ {
+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
+ .bitrate = 110,
+ .ratemask = BIT(3),
+ .plcp = 0x03,
+ },
+ {
+ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
+ .bitrate = 60,
+ .ratemask = BIT(4),
+ .plcp = 0x0b,
+ },
+ {
+ .flags = DEV_RATE_OFDM,
+ .bitrate = 90,
+ .ratemask = BIT(5),
+ .plcp = 0x0f,
+ },
+ {
+ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
+ .bitrate = 120,
+ .ratemask = BIT(6),
+ .plcp = 0x0a,
+ },
+ {
+ .flags = DEV_RATE_OFDM,
+ .bitrate = 180,
+ .ratemask = BIT(7),
+ .plcp = 0x0e,
+ },
+ {
+ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
+ .bitrate = 240,
+ .ratemask = BIT(8),
+ .plcp = 0x09,
+ },
+ {
+ .flags = DEV_RATE_OFDM,
+ .bitrate = 360,
+ .ratemask = BIT(9),
+ .plcp = 0x0d,
+ },
+ {
+ .flags = DEV_RATE_OFDM,
+ .bitrate = 480,
+ .ratemask = BIT(10),
+ .plcp = 0x08,
+ },
+ {
+ .flags = DEV_RATE_OFDM,
+ .bitrate = 540,
+ .ratemask = BIT(11),
+ .plcp = 0x0c,
+ },
+};
+
static void rt2x00lib_channel(struct ieee80211_channel *entry,
const int channel, const int tx_power,
const int value)
{
- entry->chan = channel;
- if (channel <= 14)
- entry->freq = 2407 + (5 * channel);
- else
- entry->freq = 5000 + (5 * channel);
- entry->val = value;
- entry->flag =
- IEEE80211_CHAN_W_IBSS |
- IEEE80211_CHAN_W_ACTIVE_SCAN |
- IEEE80211_CHAN_W_SCAN;
- entry->power_level = tx_power;
- entry->antenna_max = 0xff;
+ entry->center_freq = ieee80211_channel_to_frequency(channel);
+ entry->hw_value = value;
+ entry->max_power = tx_power;
+ entry->max_antenna_gain = 0xff;
}
static void rt2x00lib_rate(struct ieee80211_rate *entry,
- const int rate, const int mask,
- const int plcp, const int flags)
+ const u16 index, const struct rt2x00_rate *rate)
{
- entry->rate = rate;
- entry->val =
- DEVICE_SET_RATE_FIELD(rate, RATE) |
- DEVICE_SET_RATE_FIELD(mask, RATEMASK) |
- DEVICE_SET_RATE_FIELD(plcp, PLCP);
- entry->flags = flags;
- entry->val2 = entry->val;
- if (entry->flags & IEEE80211_RATE_PREAMBLE2)
- entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);
- entry->min_rssi_ack = 0;
- entry->min_rssi_ack_delta = 0;
+ entry->flags = 0;
+ entry->bitrate = rate->bitrate;
+ entry->hw_value = rt2x00_create_rate_hw_value(index, 0);
+ entry->hw_value_short = entry->hw_value;
+
+ if (rate->flags & DEV_RATE_SHORT_PREAMBLE) {
+ entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
+ entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1);
+ }
}
static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
struct hw_mode_spec *spec)
{
struct ieee80211_hw *hw = rt2x00dev->hw;
- struct ieee80211_hw_mode *hwmodes;
struct ieee80211_channel *channels;
struct ieee80211_rate *rates;
+ unsigned int num_rates;
unsigned int i;
unsigned char tx_power;
- hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL);
- if (!hwmodes)
- goto exit;
+ num_rates = 0;
+ if (spec->supported_rates & SUPPORT_RATE_CCK)
+ num_rates += 4;
+ if (spec->supported_rates & SUPPORT_RATE_OFDM)
+ num_rates += 8;
channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL);
if (!channels)
- goto exit_free_modes;
+ return -ENOMEM;
- rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL);
+ rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL);
if (!rates)
goto exit_free_channels;
/*
* Initialize Rate list.
*/
- rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB,
- 0x00, IEEE80211_RATE_CCK);
- rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB,
- 0x01, IEEE80211_RATE_CCK_2);
- rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB,
- 0x02, IEEE80211_RATE_CCK_2);
- rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB,
- 0x03, IEEE80211_RATE_CCK_2);
-
- if (spec->num_rates > 4) {
- rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB,
- 0x0b, IEEE80211_RATE_OFDM);
- rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB,
- 0x0f, IEEE80211_RATE_OFDM);
- rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB,
- 0x0a, IEEE80211_RATE_OFDM);
- rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB,
- 0x0e, IEEE80211_RATE_OFDM);
- rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB,
- 0x09, IEEE80211_RATE_OFDM);
- rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB,
- 0x0d, IEEE80211_RATE_OFDM);
- rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB,
- 0x08, IEEE80211_RATE_OFDM);
- rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB,
- 0x0c, IEEE80211_RATE_OFDM);
- }
+ for (i = 0; i < num_rates; i++)
+ rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i));
/*
* Initialize Channel list.
*/
for (i = 0; i < spec->num_channels; i++) {
- if (spec->channels[i].channel <= 14)
- tx_power = spec->tx_power_bg[i];
- else if (spec->tx_power_a)
- tx_power = spec->tx_power_a[i];
- else
- tx_power = spec->tx_power_default;
+ if (spec->channels[i].channel <= 14) {
+ if (spec->tx_power_bg)
+ tx_power = spec->tx_power_bg[i];
+ else
+ tx_power = spec->tx_power_default;
+ } else {
+ if (spec->tx_power_a)
+ tx_power = spec->tx_power_a[i];
+ else
+ tx_power = spec->tx_power_default;
+ }
rt2x00lib_channel(&channels[i],
spec->channels[i].channel, tx_power, i);
}
/*
- * Intitialize 802.11b
- * Rates: CCK.
- * Channels: OFDM.
- */
- if (spec->num_modes > HWMODE_B) {
- hwmodes[HWMODE_B].mode = MODE_IEEE80211B;
- hwmodes[HWMODE_B].num_channels = 14;
- hwmodes[HWMODE_B].num_rates = 4;
- hwmodes[HWMODE_B].channels = channels;
- hwmodes[HWMODE_B].rates = rates;
- }
-
- /*
- * Intitialize 802.11g
+ * Intitialize 802.11b, 802.11g
* Rates: CCK, OFDM.
- * Channels: OFDM.
- */
- if (spec->num_modes > HWMODE_G) {
- hwmodes[HWMODE_G].mode = MODE_IEEE80211G;
- hwmodes[HWMODE_G].num_channels = 14;
- hwmodes[HWMODE_G].num_rates = spec->num_rates;
- hwmodes[HWMODE_G].channels = channels;
- hwmodes[HWMODE_G].rates = rates;
+ * Channels: 2.4 GHz
+ */
+ if (spec->supported_bands & SUPPORT_BAND_2GHZ) {
+ rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14;
+ rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates;
+ rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels;
+ rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+ &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
}
/*
* Rates: OFDM.
* Channels: OFDM, UNII, HiperLAN2.
*/
- if (spec->num_modes > HWMODE_A) {
- hwmodes[HWMODE_A].mode = MODE_IEEE80211A;
- hwmodes[HWMODE_A].num_channels = spec->num_channels - 14;
- hwmodes[HWMODE_A].num_rates = spec->num_rates - 4;
- hwmodes[HWMODE_A].channels = &channels[14];
- hwmodes[HWMODE_A].rates = &rates[4];
+ if (spec->supported_bands & SUPPORT_BAND_5GHZ) {
+ rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels =
+ spec->num_channels - 14;
+ rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates =
+ num_rates - 4;
+ rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14];
+ rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+ &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
}
- if (spec->num_modes > HWMODE_G &&
- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G]))
- goto exit_free_rates;
-
- if (spec->num_modes > HWMODE_B &&
- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B]))
- goto exit_free_rates;
-
- if (spec->num_modes > HWMODE_A &&
- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A]))
- goto exit_free_rates;
-
- rt2x00dev->hwmodes = hwmodes;
-
return 0;
-exit_free_rates:
- kfree(rates);
-
-exit_free_channels:
+ exit_free_channels:
kfree(channels);
-
-exit_free_modes:
- kfree(hwmodes);
-
-exit:
ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");
return -ENOMEM;
}
if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
ieee80211_unregister_hw(rt2x00dev->hw);
- if (likely(rt2x00dev->hwmodes)) {
- kfree(rt2x00dev->hwmodes->channels);
- kfree(rt2x00dev->hwmodes->rates);
- kfree(rt2x00dev->hwmodes);
- rt2x00dev->hwmodes = NULL;
+ if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
+ kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+ kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates);
+ rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+ rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
}
}
/*
* Initialization/uninitialization handlers.
*/
-static int rt2x00lib_alloc_entries(struct data_ring *ring,
- const u16 max_entries, const u16 data_size,
- const u16 desc_size)
-{
- struct data_entry *entry;
- unsigned int i;
-
- ring->stats.limit = max_entries;
- ring->data_size = data_size;
- ring->desc_size = desc_size;
-
- /*
- * Allocate all ring entries.
- */
- entry = kzalloc(ring->stats.limit * sizeof(*entry), GFP_KERNEL);
- if (!entry)
- return -ENOMEM;
-
- for (i = 0; i < ring->stats.limit; i++) {
- entry[i].flags = 0;
- entry[i].ring = ring;
- entry[i].skb = NULL;
- entry[i].entry_idx = i;
- }
-
- ring->entry = entry;
-
- return 0;
-}
-
-static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev)
-{
- struct data_ring *ring;
-
- /*
- * Allocate the RX ring.
- */
- if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE,
- rt2x00dev->ops->rxd_size))
- return -ENOMEM;
-
- /*
- * First allocate the TX rings.
- */
- txring_for_each(rt2x00dev, ring) {
- if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE,
- rt2x00dev->ops->txd_size))
- return -ENOMEM;
- }
-
- if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
- return 0;
-
- /*
- * Allocate the BEACON ring.
- */
- if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES,
- MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size))
- return -ENOMEM;
-
- /*
- * Allocate the Atim ring.
- */
- if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES,
- DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
- return -ENOMEM;
-
- return 0;
-}
-
-static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
-{
- struct data_ring *ring;
-
- ring_for_each(rt2x00dev, ring) {
- kfree(ring->entry);
- ring->entry = NULL;
- }
-}
-
static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
{
if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
return;
/*
- * Unregister rfkill.
+ * Unregister extra components.
*/
rt2x00rfkill_unregister(rt2x00dev);
rt2x00dev->ops->lib->uninitialize(rt2x00dev);
/*
- * Free allocated ring entries.
+ * Free allocated queue entries.
*/
- rt2x00lib_free_ring_entries(rt2x00dev);
+ rt2x00queue_uninitialize(rt2x00dev);
}
static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
return 0;
/*
- * Allocate all ring entries.
+ * Allocate all queue entries.
*/
- status = rt2x00lib_alloc_ring_entries(rt2x00dev);
- if (status) {
- ERROR(rt2x00dev, "Ring entries allocation failed.\n");
+ status = rt2x00queue_initialize(rt2x00dev);
+ if (status)
return status;
- }
/*
* Initialize the device.
__set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags);
/*
- * Register the rfkill handler.
+ * Register the extra components.
*/
- status = rt2x00rfkill_register(rt2x00dev);
- if (status)
- goto exit;
+ rt2x00rfkill_register(rt2x00dev);
return 0;
-exit_unitialize:
- rt2x00lib_uninitialize(rt2x00dev);
-
exit:
- rt2x00lib_free_ring_entries(rt2x00dev);
+ rt2x00lib_uninitialize(rt2x00dev);
return status;
}
* If this is the first interface which is added,
* we should load the firmware now.
*/
- if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
- retval = rt2x00lib_load_firmware(rt2x00dev);
- if (retval)
- return retval;
- }
+ retval = rt2x00lib_load_firmware(rt2x00dev);
+ if (retval)
+ return retval;
/*
* Initialize the device.
return retval;
}
+ rt2x00dev->intf_ap_count = 0;
+ rt2x00dev->intf_sta_count = 0;
+ rt2x00dev->intf_associated = 0;
+
__set_bit(DEVICE_STARTED, &rt2x00dev->flags);
return 0;
*/
rt2x00lib_disable_radio(rt2x00dev);
+ rt2x00dev->intf_ap_count = 0;
+ rt2x00dev->intf_sta_count = 0;
+ rt2x00dev->intf_associated = 0;
+
__clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
}
/*
* driver allocation handlers.
*/
-static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
+int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
{
- struct data_ring *ring;
- unsigned int index;
-
- /*
- * We need the following rings:
- * RX: 1
- * TX: hw->queues
- * Beacon: 1 (if required)
- * Atim: 1 (if required)
- */
- rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues +
- (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags));
-
- ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL);
- if (!ring) {
- ERROR(rt2x00dev, "Ring allocation failed.\n");
- return -ENOMEM;
- }
+ int retval = -ENOMEM;
/*
- * Initialize pointers
+ * Make room for rt2x00_intf inside the per-interface
+ * structure ieee80211_vif.
*/
- rt2x00dev->rx = ring;
- rt2x00dev->tx = &rt2x00dev->rx[1];
- if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
- rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues];
-
- /*
- * Initialize ring parameters.
- * RX: queue_idx = 0
- * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index
- * TX: cw_min: 2^5 = 32.
- * TX: cw_max: 2^10 = 1024.
- */
- rt2x00dev->rx->rt2x00dev = rt2x00dev;
- rt2x00dev->rx->queue_idx = 0;
-
- index = IEEE80211_TX_QUEUE_DATA0;
- txring_for_each(rt2x00dev, ring) {
- ring->rt2x00dev = rt2x00dev;
- ring->queue_idx = index++;
- ring->tx_params.aifs = 2;
- ring->tx_params.cw_min = 5;
- ring->tx_params.cw_max = 10;
- }
-
- return 0;
-}
-
-static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev)
-{
- kfree(rt2x00dev->rx);
- rt2x00dev->rx = NULL;
- rt2x00dev->tx = NULL;
- rt2x00dev->bcn = NULL;
-}
-
-int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
-{
- int retval = -ENOMEM;
+ rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
/*
* Let the driver probe the device to detect the capabilities.
/*
* Initialize configuration work.
*/
- INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled);
+ INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
- INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled);
INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
/*
- * Reset current working type.
- */
- rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID;
-
- /*
- * Allocate ring array.
+ * Allocate queue array.
*/
- retval = rt2x00lib_alloc_rings(rt2x00dev);
+ retval = rt2x00queue_allocate(rt2x00dev);
if (retval)
goto exit;
}
/*
- * Register LED.
+ * Register extra components.
*/
-
- /*
- * Allocatie rfkill.
- */
- retval = rt2x00rfkill_allocate(rt2x00dev);
- if (retval)
- goto exit;
-
- /*
- * Open the debugfs entry.
- */
+ rt2x00leds_register(rt2x00dev);
+ rt2x00rfkill_allocate(rt2x00dev);
rt2x00debug_register(rt2x00dev);
__set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
rt2x00lib_uninitialize(rt2x00dev);
/*
- * Close debugfs entry.
+ * Free extra components
*/
rt2x00debug_deregister(rt2x00dev);
-
- /*
- * Free rfkill
- */
rt2x00rfkill_free(rt2x00dev);
/*
+ * Free LED.
+ */
+ rt2x00leds_unregister(rt2x00dev);
+
+ /*
* Free ieee80211_hw memory.
*/
rt2x00lib_remove_hw(rt2x00dev);
rt2x00lib_free_firmware(rt2x00dev);
/*
- * Free ring structures.
+ * Free queue structures.
*/
- rt2x00lib_free_rings(rt2x00dev);
+ rt2x00queue_free(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
__set_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags);
/*
- * Disable radio and unitialize all items
- * that must be recreated on resume.
+ * Disable radio.
*/
rt2x00lib_stop(rt2x00dev);
rt2x00lib_uninitialize(rt2x00dev);
+
+ /*
+ * Suspend/disable extra components.
+ */
+ rt2x00leds_suspend(rt2x00dev);
+ rt2x00rfkill_suspend(rt2x00dev);
rt2x00debug_deregister(rt2x00dev);
exit:
}
EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
+static void rt2x00lib_resume_intf(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct rt2x00_dev *rt2x00dev = data;
+ struct rt2x00_intf *intf = vif_to_intf(vif);
+
+ spin_lock(&intf->lock);
+
+ rt2x00lib_config_intf(rt2x00dev, intf,
+ vif->type, intf->mac, intf->bssid);
+
+
+ /*
+ * Master or Ad-hoc mode require a new beacon update.
+ */
+ if (vif->type == IEEE80211_IF_TYPE_AP ||
+ vif->type == IEEE80211_IF_TYPE_IBSS)
+ intf->delayed_flags |= DELAYED_UPDATE_BEACON;
+
+ spin_unlock(&intf->lock);
+}
+
int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
{
- struct interface *intf = &rt2x00dev->interface;
int retval;
NOTICE(rt2x00dev, "Waking up.\n");
/*
- * Open the debugfs entry and restore led handling.
+ * Restore/enable extra components.
*/
rt2x00debug_register(rt2x00dev);
+ rt2x00rfkill_resume(rt2x00dev);
+ rt2x00leds_resume(rt2x00dev);
/*
* Only continue if mac80211 had open interfaces.
if (!rt2x00dev->hw->conf.radio_enabled)
rt2x00lib_disable_radio(rt2x00dev);
- rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
- rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
- rt2x00lib_config_type(rt2x00dev, intf->type);
+ /*
+ * Iterator over each active interface to
+ * reconfigure the hardware.
+ */
+ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+ rt2x00lib_resume_intf, rt2x00dev);
/*
* We are ready again to receive requests from mac80211.
ieee80211_start_queues(rt2x00dev->hw);
/*
- * When in Master or Ad-hoc mode,
- * restart Beacon transmitting by faking a beacondone event.
+ * During interface iteration we might have changed the
+ * delayed_flags, time to handles the event by calling
+ * the work handler directly.
*/
- if (intf->type == IEEE80211_IF_TYPE_AP ||
- intf->type == IEEE80211_IF_TYPE_IBSS)
- rt2x00lib_beacondone(rt2x00dev);
+ rt2x00lib_intf_scheduled(&rt2x00dev->intf_work);
return 0;
/*
- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
#define RFKILL_POLL_INTERVAL ( 1000 )
/*
+ * rt2x00_rate: Per rate device information
+ */
+struct rt2x00_rate {
+ unsigned short flags;
+#define DEV_RATE_CCK 0x0001
+#define DEV_RATE_OFDM 0x0002
+#define DEV_RATE_SHORT_PREAMBLE 0x0004
+#define DEV_RATE_BASIC 0x0008
+
+ unsigned short bitrate; /* In 100kbit/s */
+ unsigned short ratemask;
+
+ unsigned short plcp;
+};
+
+extern const struct rt2x00_rate rt2x00_supported_rates[12];
+
+static inline u16 rt2x00_create_rate_hw_value(const u16 index,
+ const u16 short_preamble)
+{
+ return (short_preamble << 8) | (index & 0xff);
+}
+
+static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
+{
+ return &rt2x00_supported_rates[hw_value & 0xff];
+}
+
+static inline int rt2x00_get_rate_preamble(const u16 hw_value)
+{
+ return (hw_value & 0xff00);
+}
+
+/*
* Radio control handlers.
*/
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
/*
* Configuration handlers.
*/
-void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
-void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
-void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
+void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_intf *intf,
+ enum ieee80211_if_types type,
+ u8 *mac, u8 *bssid);
+void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_intf *intf,
+ struct ieee80211_bss_conf *conf);
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
enum antenna rx, enum antenna tx);
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config);
/*
+ * Queue handlers.
+ */
+void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev);
+void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev);
+int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
+int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
+void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
+
+/*
* Firmware handlers.
*/
#ifdef CONFIG_RT2X00_LIB_FIRMWARE
* RFkill handlers.
*/
#ifdef CONFIG_RT2X00_LIB_RFKILL
- int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
+ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev);
- int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
+ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev);
+ void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev);
+ void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev);
#else
- static inline int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
+ static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
{
- return 0;
}
static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
{
}
- static inline int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
+ static inline void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
{
- return 0;
}
static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
{
}
+
+ static inline void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev)
+ {
+ }
+
+ static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev)
+ {
+ }
#endif /* CONFIG_RT2X00_LIB_RFKILL */
+/*
+ * LED handlers
+ */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
+void rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
+void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev);
+void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev);
+void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev);
+#else
+static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
+ int rssi)
+{
+}
+
+static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
#endif /* RT2X00LIB_H */
/*
- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
}
}
- int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
+ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
{
- int retval;
-
- if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
- return 0;
+ if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+ !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+ return;
- retval = rfkill_register(rt2x00dev->rfkill);
- if (retval) {
+ if (rfkill_register(rt2x00dev->rfkill)) {
ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
- return retval;
+ return;
}
- retval = input_register_polled_device(rt2x00dev->poll_dev);
- if (retval) {
+ if (input_register_polled_device(rt2x00dev->poll_dev)) {
ERROR(rt2x00dev, "Failed to register polled device.\n");
rfkill_unregister(rt2x00dev->rfkill);
- return retval;
+ return;
}
+ __set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
+
/*
* Force initial poll which will detect the initial device state,
* and correctly sends the signal to the rfkill layer about this
* state.
*/
rt2x00rfkill_poll(rt2x00dev->poll_dev);
-
- return 0;
}
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+ if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+ !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
return;
input_unregister_polled_device(rt2x00dev->poll_dev);
rfkill_unregister(rt2x00dev->rfkill);
+
+ __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
}
- int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
+ static struct input_polled_dev *
+ rt2x00rfkill_allocate_polldev(struct rt2x00_dev *rt2x00dev)
{
- struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
+ struct input_polled_dev *poll_dev;
+
+ poll_dev = input_allocate_polled_device();
+ if (!poll_dev)
+ return NULL;
+
+ poll_dev->private = rt2x00dev;
+ poll_dev->poll = rt2x00rfkill_poll;
+ poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
+
+ poll_dev->input->name = rt2x00dev->ops->name;
+ poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy);
+ poll_dev->input->id.bustype = BUS_HOST;
+ poll_dev->input->id.vendor = 0x1814;
+ poll_dev->input->id.product = rt2x00dev->chip.rt;
+ poll_dev->input->id.version = rt2x00dev->chip.rev;
+ poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy);
+ poll_dev->input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_WLAN, poll_dev->input->keybit);
+
+ return poll_dev;
+ }
+ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
+ {
if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
- return 0;
+ return;
- rt2x00dev->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
+ rt2x00dev->rfkill =
+ rfkill_allocate(wiphy_dev(rt2x00dev->hw->wiphy), RFKILL_TYPE_WLAN);
if (!rt2x00dev->rfkill) {
ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
- goto exit;
+ return;
}
rt2x00dev->rfkill->name = rt2x00dev->ops->name;
rt2x00dev->rfkill->state = -1;
rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio;
- rt2x00dev->poll_dev = input_allocate_polled_device();
+ rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev);
if (!rt2x00dev->poll_dev) {
ERROR(rt2x00dev, "Failed to allocate polled device.\n");
- goto exit_free_rfkill;
+ rfkill_free(rt2x00dev->rfkill);
+ rt2x00dev->rfkill = NULL;
+ return;
}
- rt2x00dev->poll_dev->private = rt2x00dev;
- rt2x00dev->poll_dev->poll = rt2x00rfkill_poll;
- rt2x00dev->poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
+ return;
+ }
- rt2x00dev->poll_dev->input->name = rt2x00dev->ops->name;
- rt2x00dev->poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy);
- rt2x00dev->poll_dev->input->id.bustype = BUS_HOST;
- rt2x00dev->poll_dev->input->id.vendor = 0x1814;
- rt2x00dev->poll_dev->input->id.product = rt2x00dev->chip.rt;
- rt2x00dev->poll_dev->input->id.version = rt2x00dev->chip.rev;
- rt2x00dev->poll_dev->input->dev.parent = device;
- rt2x00dev->poll_dev->input->evbit[0] = BIT(EV_KEY);
- set_bit(KEY_WLAN, rt2x00dev->poll_dev->input->keybit);
+ void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
+ {
+ if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+ !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+ return;
- return 0;
+ input_free_polled_device(rt2x00dev->poll_dev);
+ rt2x00dev->poll_dev = NULL;
- exit_free_rfkill:
rfkill_free(rt2x00dev->rfkill);
-
- exit:
- return -ENOMEM;
+ rt2x00dev->rfkill = NULL;
}
- void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
+ void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+ if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+ !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
return;
input_free_polled_device(rt2x00dev->poll_dev);
- rfkill_free(rt2x00dev->rfkill);
+ rt2x00dev->poll_dev = NULL;
+ }
+
+ void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev)
+ {
+ if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) ||
+ !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
+ return;
+
+ rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev);
+ if (!rt2x00dev->poll_dev) {
+ ERROR(rt2x00dev, "Failed to allocate polled device.\n");
+ return;
+ }
}
/*
- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
Supported chipsets: RT2561, RT2561s, RT2661.
*/
+#include <linux/crc-itu-t.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
rt2x00_rf_write(rt2x00dev, word, value);
}
+#ifdef CONFIG_RT61PCI_LEDS
+/*
+ * This function is only called from rt61pci_led_brightness()
+ * make gcc happy by placing this function inside the
+ * same ifdef statement as the caller.
+ */
static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 command, const u8 token,
const u8 arg0, const u8 arg1)
rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1);
rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
}
+#endif /* CONFIG_RT61PCI_LEDS */
static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®);
- return rt2x00_get_field32(reg, MAC_CSR13_BIT5);;
+ return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
}
#else
#define rt61pci_rfkill_poll NULL
#endif /* CONFIG_RT61PCI_RFKILL */
+#ifdef CONFIG_RT61PCI_LEDS
+static void rt61pci_led_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct rt2x00_led *led =
+ container_of(led_cdev, struct rt2x00_led, led_dev);
+ unsigned int enabled = brightness != LED_OFF;
+ unsigned int a_mode =
+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+ unsigned int bg_mode =
+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+
+ if (led->type == LED_TYPE_RADIO) {
+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+ MCU_LEDCS_RADIO_STATUS, enabled);
+
+ rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
+ (led->rt2x00dev->led_mcu_reg & 0xff),
+ ((led->rt2x00dev->led_mcu_reg >> 8)));
+ } else if (led->type == LED_TYPE_ASSOC) {
+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+ MCU_LEDCS_LINK_BG_STATUS, bg_mode);
+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+ MCU_LEDCS_LINK_A_STATUS, a_mode);
+
+ rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
+ (led->rt2x00dev->led_mcu_reg & 0xff),
+ ((led->rt2x00dev->led_mcu_reg >> 8)));
+ } else if (led->type == LED_TYPE_QUALITY) {
+ /*
+ * The brightness is divided into 6 levels (0 - 5),
+ * this means we need to convert the brightness
+ * argument into the matching level within that range.
+ */
+ rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+ brightness / (LED_FULL / 6), 0);
+ }
+}
+#else
+#define rt61pci_led_brightness NULL
+#endif /* CONFIG_RT61PCI_LEDS */
+
/*
* Configuration handlers.
*/
-static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
+static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_intf *intf,
+ struct rt2x00intf_conf *conf,
+ const unsigned int flags)
{
- u32 tmp;
-
- tmp = le32_to_cpu(mac[1]);
- rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
- mac[1] = cpu_to_le32(tmp);
-
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
- (2 * sizeof(__le32)));
-}
+ unsigned int beacon_base;
+ u32 reg;
-static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
-{
- u32 tmp;
+ if (flags & CONFIG_UPDATE_TYPE) {
+ /*
+ * Clear current synchronisation setup.
+ * For the Beacon base registers we only need to clear
+ * the first byte since that byte contains the VALID and OWNER
+ * bits which (when set to 0) will invalidate the entire beacon.
+ */
+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
+ rt2x00pci_register_write(rt2x00dev, beacon_base, 0);
- tmp = le32_to_cpu(bssid[1]);
- rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
- bssid[1] = cpu_to_le32(tmp);
+ /*
+ * Enable synchronisation.
+ */
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
+ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
+ rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync);
+ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ }
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
- (2 * sizeof(__le32)));
-}
+ if (flags & CONFIG_UPDATE_MAC) {
+ reg = le32_to_cpu(conf->mac[1]);
+ rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
+ conf->mac[1] = cpu_to_le32(reg);
-static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
- const int tsf_sync)
-{
- u32 reg;
+ rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2,
+ conf->mac, sizeof(conf->mac));
+ }
- /*
- * Clear current synchronisation setup.
- * For the Beacon base registers we only need to clear
- * the first byte since that byte contains the VALID and OWNER
- * bits which (when set to 0) will invalidate the entire beacon.
- */
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+ if (flags & CONFIG_UPDATE_BSSID) {
+ reg = le32_to_cpu(conf->bssid[1]);
+ rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3);
+ conf->bssid[1] = cpu_to_le32(reg);
- /*
- * Enable synchronisation.
- */
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
- rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE,
- (tsf_sync == TSF_SYNC_BEACON));
- rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
- rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4,
+ conf->bssid, sizeof(conf->bssid));
+ }
}
-static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev,
- const int short_preamble,
- const int ack_timeout,
- const int ack_consume_time)
+static int rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_erp *erp)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
- rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
+ rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®);
rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE,
- !!short_preamble);
+ !!erp->short_preamble);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+
+ return 0;
}
static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev,
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
- (rt2x00dev->curr_hwmode != HWMODE_A));
+ (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ));
break;
case ANTENNA_A:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
- if (rt2x00dev->curr_hwmode == HWMODE_A)
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
else
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
break;
- case ANTENNA_SW_DIVERSITY:
- /*
- * NOTE: We should never come here because rt2x00lib is
- * supposed to catch this and send us the correct antenna
- * explicitely. However we are nog going to bug about this.
- * Instead, just default to antenna B.
- */
case ANTENNA_B:
+ default:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
- if (rt2x00dev->curr_hwmode == HWMODE_A)
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
else
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
break;
- case ANTENNA_SW_DIVERSITY:
- /*
- * NOTE: We should never come here because rt2x00lib is
- * supposed to catch this and send us the correct antenna
- * explicitely. However we are nog going to bug about this.
- * Instead, just default to antenna B.
- */
case ANTENNA_B:
+ default:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
break;
rt61pci_bbp_read(rt2x00dev, 4, &r4);
rt61pci_bbp_read(rt2x00dev, 77, &r77);
- /* FIXME: Antenna selection for the rf 2529 is very confusing in the
- * legacy driver. The code below should be ok for non-diversity setups.
- */
-
/*
* Configure the RX antenna.
*/
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
break;
- case ANTENNA_SW_DIVERSITY:
case ANTENNA_HW_DIVERSITY:
/*
- * NOTE: We should never come here because rt2x00lib is
- * supposed to catch this and send us the correct antenna
- * explicitely. However we are nog going to bug about this.
- * Instead, just default to antenna B.
+ * FIXME: Antenna selection for the rf 2529 is very confusing
+ * in the legacy driver. Just default to antenna B until the
+ * legacy code can be properly translated into rt2x00 code.
*/
case ANTENNA_B:
+ default:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
unsigned int i;
u32 reg;
- if (rt2x00dev->curr_hwmode == HWMODE_A) {
+ /*
+ * We should never come here because rt2x00lib is supposed
+ * to catch this and send us the correct antenna explicitely.
+ */
+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+ ant->tx == ANTENNA_SW_DIVERSITY);
+
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
sel = antenna_sel_a;
lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
} else {
rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®);
rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG,
- (rt2x00dev->curr_hwmode == HWMODE_B ||
- rt2x00dev->curr_hwmode == HWMODE_G));
+ rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
rt2x00_set_field32(®, PHY_CSR0_PA_PE_A,
- (rt2x00dev->curr_hwmode == HWMODE_A));
+ rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
}
static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
- const unsigned int flags,
- struct rt2x00lib_conf *libconf)
+ struct rt2x00lib_conf *libconf,
+ const unsigned int flags)
{
if (flags & CONFIG_UPDATE_PHYMODE)
rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
}
/*
- * LED functions.
- */
-static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- u8 arg0;
- u8 arg1;
-
- rt2x00pci_register_read(rt2x00dev, MAC_CSR14, ®);
- rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70);
- rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
-
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
- (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
- (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
-
- arg0 = rt2x00dev->led_reg & 0xff;
- arg1 = (rt2x00dev->led_reg >> 8) & 0xff;
-
- rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
-}
-
-static void rt61pci_disable_led(struct rt2x00_dev *rt2x00dev)
-{
- u16 led_reg;
- u8 arg0;
- u8 arg1;
-
- led_reg = rt2x00dev->led_reg;
- rt2x00_set_field16(&led_reg, MCU_LEDCS_RADIO_STATUS, 0);
- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
-
- arg0 = led_reg & 0xff;
- arg1 = (led_reg >> 8) & 0xff;
-
- rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
-}
-
-static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
-{
- u8 led;
-
- if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
- return;
-
- /*
- * Led handling requires a positive value for the rssi,
- * to do that correctly we need to add the correction.
- */
- rssi += rt2x00dev->rssi_offset;
-
- if (rssi <= 30)
- led = 0;
- else if (rssi <= 39)
- led = 1;
- else if (rssi <= 49)
- led = 2;
- else if (rssi <= 53)
- led = 3;
- else if (rssi <= 63)
- led = 4;
- else
- led = 5;
-
- rt61pci_mcu_request(rt2x00dev, MCU_LED_STRENGTH, 0xff, led, 0);
-}
-
-/*
* Link tuning
*/
static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
u8 up_bound;
u8 low_bound;
- /*
- * Update Led strength
- */
- rt61pci_activity_led(rt2x00dev, rssi);
-
rt61pci_bbp_read(rt2x00dev, 17, &r17);
/*
* Determine r17 bounds.
*/
- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
low_bound = 0x28;
up_bound = 0x48;
if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
}
/*
+ * If we are not associated, we should go straight to the
+ * dynamic CCA tuning.
+ */
+ if (!rt2x00dev->intf_associated)
+ goto dynamic_cca_tune;
+
+ /*
* Special big-R17 for very short distance
*/
if (rssi >= -35) {
return;
}
+dynamic_cca_tune:
+
/*
* r17 does not yet exceed upper limit, continue and base
* the r17 tuning on the false CCA count.
}
/*
- * Firmware name function.
+ * Firmware functions
*/
static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
return fw_name;
}
-/*
- * Initialization functions.
- */
+static u16 rt61pci_get_firmware_crc(void *data, const size_t len)
+{
+ u16 crc;
+
+ /*
+ * Use the crc itu-t algorithm.
+ * The last 2 bytes in the firmware array are the crc checksum itself,
+ * this means that we should never pass those 2 bytes to the crc
+ * algorithm.
+ */
+ crc = crc_itu_t(0, data, len - 2);
+ crc = crc_itu_t_byte(crc, 0);
+ crc = crc_itu_t_byte(crc, 0);
+
+ return crc;
+}
+
static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
const size_t len)
{
return 0;
}
+/*
+ * Initialization functions.
+ */
static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
- struct data_entry *entry)
+ struct queue_entry *entry)
{
- __le32 *rxd = entry->priv;
+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
u32 word;
- rt2x00_desc_read(rxd, 5, &word);
+ rt2x00_desc_read(priv_rx->desc, 5, &word);
rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
- entry->data_dma);
- rt2x00_desc_write(rxd, 5, word);
+ priv_rx->data_dma);
+ rt2x00_desc_write(priv_rx->desc, 5, word);
- rt2x00_desc_read(rxd, 0, &word);
+ rt2x00_desc_read(priv_rx->desc, 0, &word);
rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(rxd, 0, word);
+ rt2x00_desc_write(priv_rx->desc, 0, word);
}
static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
- struct data_entry *entry)
+ struct queue_entry *entry)
{
- __le32 *txd = entry->priv;
+ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
u32 word;
- rt2x00_desc_read(txd, 1, &word);
+ rt2x00_desc_read(priv_tx->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
- rt2x00_desc_write(txd, 1, word);
+ rt2x00_desc_write(priv_tx->desc, 1, word);
- rt2x00_desc_read(txd, 5, &word);
- rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx);
+ rt2x00_desc_read(priv_tx->desc, 5, &word);
+ rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
- rt2x00_desc_write(txd, 5, word);
+ rt2x00_desc_write(priv_tx->desc, 5, word);
- rt2x00_desc_read(txd, 6, &word);
+ rt2x00_desc_read(priv_tx->desc, 6, &word);
rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
- entry->data_dma);
- rt2x00_desc_write(txd, 6, word);
+ priv_tx->data_dma);
+ rt2x00_desc_write(priv_tx->desc, 6, word);
- rt2x00_desc_read(txd, 0, &word);
+ rt2x00_desc_read(priv_tx->desc, 0, &word);
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(txd, 0, word);
+ rt2x00_desc_write(priv_tx->desc, 0, word);
}
-static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
+static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
+ struct queue_entry_priv_pci_rx *priv_rx;
+ struct queue_entry_priv_pci_tx *priv_tx;
u32 reg;
/*
*/
rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®);
rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
+ rt2x00dev->tx[0].limit);
rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
+ rt2x00dev->tx[1].limit);
rt2x00_set_field32(®, TX_RING_CSR0_AC2_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit);
+ rt2x00dev->tx[2].limit);
rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit);
+ rt2x00dev->tx[3].limit);
rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg);
rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®);
- rt2x00_set_field32(®, TX_RING_CSR1_MGMT_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit);
rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size /
- 4);
+ rt2x00dev->tx[0].desc_size / 4);
rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
+ priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®);
rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
+ priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
+ priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®);
rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
+ priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
+ priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®);
rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma);
+ priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
+ priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®);
rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma);
+ priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, ®);
- rt2x00_set_field32(®, MGMT_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma);
- rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg);
-
rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®);
- rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE,
- rt2x00dev->rx->stats.limit);
+ rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE,
rt2x00dev->rx->desc_size / 4);
rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
+ priv_rx = rt2x00dev->rx->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®);
rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER,
- rt2x00dev->rx->data_dma);
+ priv_rx->desc_dma);
rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®);
rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC1, 2);
rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC2, 2);
rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC3, 2);
- rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_MGMT, 0);
rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®);
rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
- rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1);
rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®);
rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000);
+ rt2x00pci_register_read(rt2x00dev, MAC_CSR14, ®);
+ rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70);
+ rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
+
/*
* Invalidate all Shared Keys (SEC_CSR0),
* and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
/*
+ * Clear all beacons
+ * For the Beacon base registers we only need to clear
+ * the first byte since that byte contains the VALID and OWNER
+ * bits which (when set to 0) will invalidate the entire beacon.
+ */
+ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+
+ /*
* We must clear the error counters.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
rt61pci_bbp_write(rt2x00dev, 102, 0x16);
rt61pci_bbp_write(rt2x00dev, 107, 0x04);
- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
- reg_id, value);
rt61pci_bbp_write(rt2x00dev, reg_id, value);
}
}
- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
return 0;
}
/*
* Initialize all registers.
*/
- if (rt61pci_init_rings(rt2x00dev) ||
+ if (rt61pci_init_queues(rt2x00dev) ||
rt61pci_init_registers(rt2x00dev) ||
rt61pci_init_bbp(rt2x00dev)) {
ERROR(rt2x00dev, "Register initialization failed.\n");
rt2x00_set_field32(®, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
- /*
- * Enable LED
- */
- rt61pci_enable_led(rt2x00dev);
-
return 0;
}
{
u32 reg;
- /*
- * Disable LED
- */
- rt61pci_disable_led(rt2x00dev);
-
rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
/*
rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1);
rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1);
rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1);
- rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_MGMT, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
/*
*/
static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
- struct txdata_entry_desc *desc,
+ struct txentry_desc *txdesc,
struct ieee80211_tx_control *control)
{
- struct skb_desc *skbdesc = get_skb_desc(skb);
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txd = skbdesc->desc;
u32 word;
* Start writing the descriptor words.
*/
rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
- rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
- rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
- rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
+ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
+ rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
+ rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
+ rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
rt2x00_desc_write(txd, 1, word);
rt2x00_desc_read(txd, 2, &word);
- rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
- rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
+ rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
+ rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 5, &word);
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
- TXPOWER_TO_DEV(control->power_level));
+ TXPOWER_TO_DEV(rt2x00dev->tx_power));
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
rt2x00_desc_write(txd, 5, word);
- rt2x00_desc_read(txd, 11, &word);
- rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
- rt2x00_desc_write(txd, 11, word);
+ if (skbdesc->desc_len > TXINFO_SIZE) {
+ rt2x00_desc_read(txd, 11, &word);
+ rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
+ rt2x00_desc_write(txd, 11, word);
+ }
rt2x00_desc_read(txd, 0, &word);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
+ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
- test_bit(ENTRY_TXD_ACK, &desc->flags));
+ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
+ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
+ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_BURST,
- test_bit(ENTRY_TXD_BURST, &desc->flags));
+ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
* TX data initialization
*/
static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- unsigned int queue)
+ const unsigned int queue)
{
u32 reg;
- if (queue == IEEE80211_TX_QUEUE_BEACON) {
+ if (queue == RT2X00_BCN_QUEUE_BEACON) {
/*
* For Wi-Fi faily generated beacons between participating
* stations. Set TBTT phase adaptive adjustment step to 8us.
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
+ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
+ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
}
(queue == IEEE80211_TX_QUEUE_DATA2));
rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3,
(queue == IEEE80211_TX_QUEUE_DATA3));
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_MGMT,
- (queue == IEEE80211_TX_QUEUE_DATA4));
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
}
return 0;
}
- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
offset += 14;
return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
}
-static void rt61pci_fill_rxdone(struct data_entry *entry,
- struct rxdata_entry_desc *desc)
+static void rt61pci_fill_rxdone(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc)
{
- __le32 *rxd = entry->priv;
+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
u32 word0;
u32 word1;
- rt2x00_desc_read(rxd, 0, &word0);
- rt2x00_desc_read(rxd, 1, &word1);
+ rt2x00_desc_read(priv_rx->desc, 0, &word0);
+ rt2x00_desc_read(priv_rx->desc, 1, &word1);
- desc->flags = 0;
+ rxdesc->flags = 0;
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
/*
* Obtain the status about this packet.
- */
- desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
- desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
+ * When frame was received with an OFDM bitrate,
+ * the signal is the PLCP value. If it was received with
+ * a CCK bitrate the signal is the rate in 100kbit/s.
+ */
+ rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+ rxdesc->signal_plcp = rxdesc->ofdm;
+ rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1);
+ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}
/*
*/
static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
{
- struct data_ring *ring;
- struct data_entry *entry;
- struct data_entry *entry_done;
- __le32 *txd;
+ struct data_queue *queue;
+ struct queue_entry *entry;
+ struct queue_entry *entry_done;
+ struct queue_entry_priv_pci_tx *priv_tx;
+ struct txdone_entry_desc txdesc;
u32 word;
u32 reg;
u32 old_reg;
int type;
int index;
- int tx_status;
- int retry;
/*
* During each loop we will compare the freshly read
/*
* Skip this entry when it contains an invalid
- * ring identication number.
+ * queue identication number.
*/
type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
- ring = rt2x00lib_get_ring(rt2x00dev, type);
- if (unlikely(!ring))
+ queue = rt2x00queue_get_queue(rt2x00dev, type);
+ if (unlikely(!queue))
continue;
/*
* index number.
*/
index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
- if (unlikely(index >= ring->stats.limit))
+ if (unlikely(index >= queue->limit))
continue;
- entry = &ring->entry[index];
- txd = entry->priv;
- rt2x00_desc_read(txd, 0, &word);
+ entry = &queue->entries[index];
+ priv_tx = entry->priv_data;
+ rt2x00_desc_read(priv_tx->desc, 0, &word);
if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
!rt2x00_get_field32(word, TXD_W0_VALID))
return;
- entry_done = rt2x00_get_data_entry_done(ring);
+ entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
while (entry != entry_done) {
- /* Catch up. Just report any entries we missed as
- * failed. */
+ /* Catch up.
+ * Just report any entries we missed as failed.
+ */
WARNING(rt2x00dev,
- "TX status report missed for entry %p\n",
- entry_done);
- rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER,
- 0);
- entry_done = rt2x00_get_data_entry_done(ring);
+ "TX status report missed for entry %d\n",
+ entry_done->entry_idx);
+
+ txdesc.status = TX_FAIL_OTHER;
+ txdesc.retry = 0;
+
+ rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
+ entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
}
/*
* Obtain the status about this packet.
*/
- tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
- retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
+ txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
+ txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
- rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
+ rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
}
}
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+ EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
if (value < -10 || value > 10)
* If the eeprom value is invalid,
* switch to default led mode.
*/
+#ifdef CONFIG_RT61PCI_LEDS
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
- rt2x00dev->led_mode = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
+ value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
+
+ switch (value) {
+ case LED_MODE_TXRX_ACTIVITY:
+ case LED_MODE_ASUS:
+ case LED_MODE_ALPHA:
+ case LED_MODE_DEFAULT:
+ rt2x00dev->led_flags =
+ LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC;
+ break;
+ case LED_MODE_SIGNAL_STRENGTH:
+ rt2x00dev->led_flags =
+ LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC |
+ LED_SUPPORT_QUALITY;
+ break;
+ }
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
- rt2x00dev->led_mode);
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_0));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_1));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_2));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_3));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_4));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_RDY_G));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_RDY_A));
+#endif /* CONFIG_RT61PCI_LEDS */
return 0;
}
rt2x00dev->hw->extra_tx_headroom = 0;
rt2x00dev->hw->max_signal = MAX_SIGNAL;
rt2x00dev->hw->max_rssi = MAX_RX_SSI;
- rt2x00dev->hw->queues = 5;
+ rt2x00dev->hw->queues = 4;
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
/*
* Initialize hw_mode information.
*/
- spec->num_modes = 2;
- spec->num_rates = 12;
+ spec->supported_bands = SUPPORT_BAND_2GHZ;
+ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
spec->tx_power_a = NULL;
spec->tx_power_bg = txpower;
spec->tx_power_default = DEFAULT_TXPOWER;
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
rt2x00_rf(&rt2x00dev->chip, RF5325)) {
- spec->num_modes = 3;
+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_seq);
txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
rt61pci_probe_hw_mode(rt2x00dev);
/*
- * This device requires firmware
+ * This device requires firmware.
*/
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
+ * - Multicast filter seems to kill broadcast traffic so never use it.
*/
- if (mc_count)
- *total_flags |= FIF_ALLMULTI;
+ *total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
!(*total_flags & FIF_ALLMULTI));
- rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, 0);
- rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1);
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS,
+ !(*total_flags & FIF_CONTROL));
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
}
return tsf;
}
-static void rt61pci_reset_tsf(struct ieee80211_hw *hw)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
-
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR12, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR13, 0);
-}
-
static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct skb_desc *desc;
- struct data_ring *ring;
- struct data_entry *entry;
+ struct rt2x00_intf *intf = vif_to_intf(control->vif);
+ struct skb_frame_desc *skbdesc;
+ unsigned int beacon_base;
+ u32 reg;
- /*
- * Just in case the ieee80211 doesn't set this,
- * but we need this queue set for the descriptor
- * initialization.
- */
- control->queue = IEEE80211_TX_QUEUE_BEACON;
- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
- entry = rt2x00_get_data_entry(ring);
+ if (unlikely(!intf->beacon))
+ return -ENOBUFS;
/*
* We need to append the descriptor in front of the
* beacon frame.
*/
- if (skb_headroom(skb) < TXD_DESC_SIZE) {
- if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC)) {
+ if (skb_headroom(skb) < intf->beacon->queue->desc_size) {
+ if (pskb_expand_head(skb, intf->beacon->queue->desc_size,
+ 0, GFP_ATOMIC)) {
dev_kfree_skb(skb);
return -ENOMEM;
}
/*
* Add the descriptor in front of the skb.
*/
- skb_push(skb, ring->desc_size);
- memset(skb->data, 0, ring->desc_size);
+ skb_push(skb, intf->beacon->queue->desc_size);
+ memset(skb->data, 0, intf->beacon->queue->desc_size);
/*
* Fill in skb descriptor
*/
- desc = get_skb_desc(skb);
- desc->desc_len = ring->desc_size;
- desc->data_len = skb->len - ring->desc_size;
- desc->desc = skb->data;
- desc->data = skb->data + ring->desc_size;
- desc->ring = ring;
- desc->entry = entry;
+ skbdesc = get_skb_frame_desc(skb);
+ memset(skbdesc, 0, sizeof(*skbdesc));
+ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
+ skbdesc->data = skb->data + intf->beacon->queue->desc_size;
+ skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
+ skbdesc->desc = skb->data;
+ skbdesc->desc_len = intf->beacon->queue->desc_size;
+ skbdesc->entry = intf->beacon;
+
+ /*
+ * Disable beaconing while we are reloading the beacon data,
+ * otherwise we might be sending out invalid data.
+ */
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
+ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0);
+ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0);
+ rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ /*
+ * mac80211 doesn't provide the control->queue variable
+ * for beacons. Set our own queue identification so
+ * it can be used during descriptor initialization.
+ */
+ control->queue = RT2X00_BCN_QUEUE_BEACON;
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Write entire beacon with descriptor to register,
* and kick the beacon generator.
*/
- rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0,
+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
+ rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
skb->data, skb->len);
- rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
+ rt61pci_kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt61pci_get_tsf,
- .reset_tsf = rt61pci_reset_tsf,
.beacon_update = rt61pci_beacon_update,
};
.irq_handler = rt61pci_interrupt,
.probe_hw = rt61pci_probe_hw,
.get_firmware_name = rt61pci_get_firmware_name,
+ .get_firmware_crc = rt61pci_get_firmware_crc,
.load_firmware = rt61pci_load_firmware,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
.link_stats = rt61pci_link_stats,
.reset_tuner = rt61pci_reset_tuner,
.link_tuner = rt61pci_link_tuner,
+ .led_brightness = rt61pci_led_brightness,
.write_tx_desc = rt61pci_write_tx_desc,
.write_tx_data = rt2x00pci_write_tx_data,
.kick_tx_queue = rt61pci_kick_tx_queue,
.fill_rxdone = rt61pci_fill_rxdone,
- .config_mac_addr = rt61pci_config_mac_addr,
- .config_bssid = rt61pci_config_bssid,
- .config_type = rt61pci_config_type,
- .config_preamble = rt61pci_config_preamble,
+ .config_intf = rt61pci_config_intf,
+ .config_erp = rt61pci_config_erp,
.config = rt61pci_config,
};
+static const struct data_queue_desc rt61pci_queue_rx = {
+ .entry_num = RX_ENTRIES,
+ .data_size = DATA_FRAME_SIZE,
+ .desc_size = RXD_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_pci_rx),
+};
+
+static const struct data_queue_desc rt61pci_queue_tx = {
+ .entry_num = TX_ENTRIES,
+ .data_size = DATA_FRAME_SIZE,
+ .desc_size = TXD_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
+};
+
+static const struct data_queue_desc rt61pci_queue_bcn = {
+ .entry_num = 4 * BEACON_ENTRIES,
+ .data_size = MGMT_FRAME_SIZE,
+ .desc_size = TXINFO_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
+};
+
static const struct rt2x00_ops rt61pci_ops = {
.name = KBUILD_MODNAME,
- .rxd_size = RXD_DESC_SIZE,
- .txd_size = TXD_DESC_SIZE,
+ .max_sta_intf = 1,
+ .max_ap_intf = 4,
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
+ .rx = &rt61pci_queue_rx,
+ .tx = &rt61pci_queue_tx,
+ .bcn = &rt61pci_queue_bcn,
.lib = &rt61pci_rt2x00_ops,
.hw = &rt61pci_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
/*
- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
Supported chipsets: rt2571W & rt2671.
*/
+#include <linux/crc-itu-t.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-/*
- * Configuration handlers.
- */
-static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
+#ifdef CONFIG_RT73USB_LEDS
+static void rt73usb_led_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
{
- u32 tmp;
+ struct rt2x00_led *led =
+ container_of(led_cdev, struct rt2x00_led, led_dev);
+ unsigned int enabled = brightness != LED_OFF;
+ unsigned int a_mode =
+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+ unsigned int bg_mode =
+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
- tmp = le32_to_cpu(mac[1]);
- rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
- mac[1] = cpu_to_le32(tmp);
+ if (in_atomic()) {
+ NOTICE(led->rt2x00dev,
+ "Ignoring LED brightness command for led %d\n",
+ led->type);
+ return;
+ }
- rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
- (2 * sizeof(__le32)));
+ if (led->type == LED_TYPE_RADIO) {
+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+ MCU_LEDCS_RADIO_STATUS, enabled);
+
+ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
+ 0, led->rt2x00dev->led_mcu_reg,
+ REGISTER_TIMEOUT);
+ } else if (led->type == LED_TYPE_ASSOC) {
+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+ MCU_LEDCS_LINK_BG_STATUS, bg_mode);
+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+ MCU_LEDCS_LINK_A_STATUS, a_mode);
+
+ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
+ 0, led->rt2x00dev->led_mcu_reg,
+ REGISTER_TIMEOUT);
+ } else if (led->type == LED_TYPE_QUALITY) {
+ /*
+ * The brightness is divided into 6 levels (0 - 5),
+ * this means we need to convert the brightness
+ * argument into the matching level within that range.
+ */
+ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
+ brightness / (LED_FULL / 6),
+ led->rt2x00dev->led_mcu_reg,
+ REGISTER_TIMEOUT);
+ }
}
+#else
+#define rt73usb_led_brightness NULL
+#endif /* CONFIG_RT73USB_LEDS */
-static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
+/*
+ * Configuration handlers.
+ */
+static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_intf *intf,
+ struct rt2x00intf_conf *conf,
+ const unsigned int flags)
{
- u32 tmp;
+ unsigned int beacon_base;
+ u32 reg;
- tmp = le32_to_cpu(bssid[1]);
- rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
- bssid[1] = cpu_to_le32(tmp);
+ if (flags & CONFIG_UPDATE_TYPE) {
+ /*
+ * Clear current synchronisation setup.
+ * For the Beacon base registers we only need to clear
+ * the first byte since that byte contains the VALID and OWNER
+ * bits which (when set to 0) will invalidate the entire beacon.
+ */
+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
+ rt73usb_register_write(rt2x00dev, beacon_base, 0);
- rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
- (2 * sizeof(__le32)));
-}
+ /*
+ * Enable synchronisation.
+ */
+ rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
+ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
+ rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync);
+ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ }
-static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
- const int tsf_sync)
-{
- u32 reg;
+ if (flags & CONFIG_UPDATE_MAC) {
+ reg = le32_to_cpu(conf->mac[1]);
+ rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
+ conf->mac[1] = cpu_to_le32(reg);
- /*
- * Clear current synchronisation setup.
- * For the Beacon base registers we only need to clear
- * the first byte since that byte contains the VALID and OWNER
- * bits which (when set to 0) will invalidate the entire beacon.
- */
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+ rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
+ conf->mac, sizeof(conf->mac));
+ }
- /*
- * Enable synchronisation.
- */
- rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
- rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE,
- (tsf_sync == TSF_SYNC_BEACON));
- rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
- rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync);
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ if (flags & CONFIG_UPDATE_BSSID) {
+ reg = le32_to_cpu(conf->bssid[1]);
+ rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3);
+ conf->bssid[1] = cpu_to_le32(reg);
+
+ rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
+ conf->bssid, sizeof(conf->bssid));
+ }
}
-static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
- const int short_preamble,
- const int ack_timeout,
- const int ack_consume_time)
+static int rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_erp *erp)
{
u32 reg;
/*
- * When in atomic context, reschedule and let rt2x00lib
- * call this function again.
+ * When in atomic context, we should let rt2x00lib
+ * try this configuration again later.
*/
- if (in_atomic()) {
- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
- return;
- }
+ if (in_atomic())
+ return -EAGAIN;
rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
- rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
+ rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®);
rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE,
- !!short_preamble);
+ !!erp->short_preamble);
rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+
+ return 0;
}
static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev,
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
- && (rt2x00dev->curr_hwmode != HWMODE_A);
+ && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
break;
case ANTENNA_A:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
- if (rt2x00dev->curr_hwmode == HWMODE_A)
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
else
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
break;
- case ANTENNA_SW_DIVERSITY:
- /*
- * NOTE: We should never come here because rt2x00lib is
- * supposed to catch this and send us the correct antenna
- * explicitely. However we are nog going to bug about this.
- * Instead, just default to antenna B.
- */
case ANTENNA_B:
+ default:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
- if (rt2x00dev->curr_hwmode == HWMODE_A)
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
else
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
break;
- case ANTENNA_SW_DIVERSITY:
- /*
- * NOTE: We should never come here because rt2x00lib is
- * supposed to catch this and send us the correct antenna
- * explicitely. However we are nog going to bug about this.
- * Instead, just default to antenna B.
- */
case ANTENNA_B:
+ default:
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
break;
unsigned int i;
u32 reg;
- if (rt2x00dev->curr_hwmode == HWMODE_A) {
+ /*
+ * We should never come here because rt2x00lib is supposed
+ * to catch this and send us the correct antenna explicitely.
+ */
+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+ ant->tx == ANTENNA_SW_DIVERSITY);
+
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
sel = antenna_sel_a;
lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
} else {
rt73usb_register_read(rt2x00dev, PHY_CSR0, ®);
rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG,
- (rt2x00dev->curr_hwmode == HWMODE_B ||
- rt2x00dev->curr_hwmode == HWMODE_G));
+ (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
rt2x00_set_field32(®, PHY_CSR0_PA_PE_A,
- (rt2x00dev->curr_hwmode == HWMODE_A));
+ (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
}
static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
- const unsigned int flags,
- struct rt2x00lib_conf *libconf)
+ struct rt2x00lib_conf *libconf,
+ const unsigned int flags)
{
if (flags & CONFIG_UPDATE_PHYMODE)
rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
}
/*
- * LED functions.
- */
-static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
-
- rt73usb_register_read(rt2x00dev, MAC_CSR14, ®);
- rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70);
- rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
- rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
-
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
- (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
- (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
-
- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
- rt2x00dev->led_reg, REGISTER_TIMEOUT);
-}
-
-static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
-{
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0);
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
-
- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
- rt2x00dev->led_reg, REGISTER_TIMEOUT);
-}
-
-static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
-{
- u32 led;
-
- if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
- return;
-
- /*
- * Led handling requires a positive value for the rssi,
- * to do that correctly we need to add the correction.
- */
- rssi += rt2x00dev->rssi_offset;
-
- if (rssi <= 30)
- led = 0;
- else if (rssi <= 39)
- led = 1;
- else if (rssi <= 49)
- led = 2;
- else if (rssi <= 53)
- led = 3;
- else if (rssi <= 63)
- led = 4;
- else
- led = 5;
-
- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led,
- rt2x00dev->led_reg, REGISTER_TIMEOUT);
-}
-
-/*
* Link tuning
*/
static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
u8 up_bound;
u8 low_bound;
- /*
- * Update Led strength
- */
- rt73usb_activity_led(rt2x00dev, rssi);
-
rt73usb_bbp_read(rt2x00dev, 17, &r17);
/*
* Determine r17 bounds.
*/
- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
low_bound = 0x28;
up_bound = 0x48;
}
/*
+ * If we are not associated, we should go straight to the
+ * dynamic CCA tuning.
+ */
+ if (!rt2x00dev->intf_associated)
+ goto dynamic_cca_tune;
+
+ /*
* Special big-R17 for very short distance
*/
if (rssi > -35) {
return;
}
+dynamic_cca_tune:
+
/*
* r17 does not yet exceed upper limit, continue and base
* the r17 tuning on the false CCA count.
}
/*
- * Firmware name function.
+ * Firmware functions
*/
static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
return FIRMWARE_RT2571;
}
-/*
- * Initialization functions.
- */
+static u16 rt73usb_get_firmware_crc(void *data, const size_t len)
+{
+ u16 crc;
+
+ /*
+ * Use the crc itu-t algorithm.
+ * The last 2 bytes in the firmware array are the crc checksum itself,
+ * this means that we should never pass those 2 bytes to the crc
+ * algorithm.
+ */
+ crc = crc_itu_t(0, data, len - 2);
+ crc = crc_itu_t_byte(crc, 0);
+ crc = crc_itu_t_byte(crc, 0);
+
+ return crc;
+}
+
static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
const size_t len)
{
rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT,
- FIRMWARE_IMAGE_BASE + i, 0x0000,
+ FIRMWARE_IMAGE_BASE + i, 0,
cache, buflen, timeout);
ptr += buflen;
* we need to specify a long timeout time.
*/
status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
- 0x0000, USB_MODE_FIRMWARE,
+ 0, USB_MODE_FIRMWARE,
REGISTER_TIMEOUT_FIRMWARE);
if (status < 0) {
ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
return status;
}
- rt73usb_disable_led(rt2x00dev);
-
return 0;
}
+/*
+ * Initialization functions.
+ */
static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
+ rt73usb_register_read(rt2x00dev, MAC_CSR14, ®);
+ rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70);
+ rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
+ rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
+
/*
* Invalidate all Shared Keys (SEC_CSR0),
* and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
/*
+ * Clear all beacons
+ * For the Beacon base registers we only need to clear
+ * the first byte since that byte contains the VALID and OWNER
+ * bits which (when set to 0) will invalidate the entire beacon.
+ */
+ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+
+ /*
* We must clear the error counters.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
rt73usb_bbp_write(rt2x00dev, 102, 0x16);
rt73usb_bbp_write(rt2x00dev, 107, 0x04);
- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
- reg_id, value);
rt73usb_bbp_write(rt2x00dev, reg_id, value);
}
}
- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
return 0;
}
return -EIO;
}
- /*
- * Enable LED
- */
- rt73usb_enable_led(rt2x00dev);
-
return 0;
}
static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
- /*
- * Disable LED
- */
- rt73usb_disable_led(rt2x00dev);
-
rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
/*
*/
static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
- struct txdata_entry_desc *desc,
+ struct txentry_desc *txdesc,
struct ieee80211_tx_control *control)
{
- struct skb_desc *skbdesc = get_skb_desc(skb);
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txd = skbdesc->desc;
u32 word;
* Start writing the descriptor words.
*/
rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
- rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
- rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
- rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
+ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
+ rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
+ rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
+ rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
rt2x00_desc_write(txd, 1, word);
rt2x00_desc_read(txd, 2, &word);
- rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
- rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
+ rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
+ rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 5, &word);
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
- TXPOWER_TO_DEV(control->power_level));
+ TXPOWER_TO_DEV(rt2x00dev->tx_power));
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
rt2x00_desc_write(txd, 5, word);
rt2x00_desc_read(txd, 0, &word);
rt2x00_set_field32(&word, TXD_W0_BURST,
- test_bit(ENTRY_TXD_BURST, &desc->flags));
+ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
+ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
- test_bit(ENTRY_TXD_ACK, &desc->flags));
+ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
+ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
+ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_BURST2,
- test_bit(ENTRY_TXD_BURST, &desc->flags));
+ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
* TX data initialization
*/
static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- unsigned int queue)
+ const unsigned int queue)
{
u32 reg;
- if (queue != IEEE80211_TX_QUEUE_BEACON)
+ if (queue != RT2X00_BCN_QUEUE_BEACON)
return;
/*
rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
+ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
+ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1);
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
return 0;
}
- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
if (lna == 3 || lna == 2)
offset += 10;
return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
}
-static void rt73usb_fill_rxdone(struct data_entry *entry,
- struct rxdata_entry_desc *desc)
+static void rt73usb_fill_rxdone(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc)
{
- struct skb_desc *skbdesc = get_skb_desc(entry->skb);
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *rxd = (__le32 *)entry->skb->data;
+ unsigned int offset = entry->queue->desc_size + 2;
u32 word0;
u32 word1;
+ /*
+ * Copy descriptor to the available headroom inside the skbuffer.
+ */
+ skb_push(entry->skb, offset);
+ memcpy(entry->skb->data, rxd, entry->queue->desc_size);
+ rxd = (__le32 *)entry->skb->data;
+
+ /*
+ * The descriptor is now aligned to 4 bytes and thus it is
+ * now safe to read it on all architectures.
+ */
rt2x00_desc_read(rxd, 0, &word0);
rt2x00_desc_read(rxd, 1, &word1);
- desc->flags = 0;
+ rxdesc->flags = 0;
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
/*
* Obtain the status about this packet.
+ * When frame was received with an OFDM bitrate,
+ * the signal is the PLCP value. If it was received with
+ * a CCK bitrate the signal is the rate in 100kbit/s.
+ */
+ rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+ rxdesc->signal_plcp = rxdesc->ofdm;
+ rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
+ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
+
+ /*
+ * Adjust the skb memory window to the frame boundaries.
*/
- desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
- desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
+ skb_pull(entry->skb, offset + entry->queue->desc_size);
+ skb_trim(entry->skb, rxdesc->size);
/*
* Set descriptor and data pointer.
*/
- skbdesc->desc = entry->skb->data;
- skbdesc->desc_len = entry->ring->desc_size;
- skbdesc->data = entry->skb->data + entry->ring->desc_size;
- skbdesc->data_len = desc->size;
+ skbdesc->data = entry->skb->data;
+ skbdesc->data_len = rxdesc->size;
+ skbdesc->desc = rxd;
+ skbdesc->desc_len = entry->queue->desc_size;
}
/*
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+ EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
if (value < -10 || value > 10)
/*
* Store led settings, for correct led behaviour.
*/
+#ifdef CONFIG_RT73USB_LEDS
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
- rt2x00dev->led_mode);
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
+ switch (value) {
+ case LED_MODE_TXRX_ACTIVITY:
+ case LED_MODE_ASUS:
+ case LED_MODE_ALPHA:
+ case LED_MODE_DEFAULT:
+ rt2x00dev->led_flags =
+ LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC;
+ break;
+ case LED_MODE_SIGNAL_STRENGTH:
+ rt2x00dev->led_flags =
+ LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC |
+ LED_SUPPORT_QUALITY;
+ break;
+ }
+
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_0));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_1));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_2));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_3));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_4));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_RDY_G));
- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_RDY_A));
+#endif /* CONFIG_RT73USB_LEDS */
return 0;
}
rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
rt2x00dev->hw->max_signal = MAX_SIGNAL;
rt2x00dev->hw->max_rssi = MAX_RX_SSI;
- rt2x00dev->hw->queues = 5;
+ rt2x00dev->hw->queues = 4;
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
/*
* Initialize hw_mode information.
*/
- spec->num_modes = 2;
- spec->num_rates = 12;
+ spec->supported_bands = SUPPORT_BAND_2GHZ;
+ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
spec->tx_power_a = NULL;
spec->tx_power_bg = txpower;
spec->tx_power_default = DEFAULT_TXPOWER;
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
spec->channels = rf_vals_bg_2528;
} else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) {
+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5226);
spec->channels = rf_vals_5226;
} else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) {
spec->num_channels = 14;
spec->channels = rf_vals_5225_2527;
} else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
spec->channels = rf_vals_5225_2527;
}
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
rt2x00_rf(&rt2x00dev->chip, RF5226)) {
- spec->num_modes = 3;
-
txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
for (i = 0; i < 14; i++)
txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
rt73usb_probe_hw_mode(rt2x00dev);
/*
- * This device requires firmware
+ * This device requires firmware.
*/
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
+ * - Multicast filter seems to kill broadcast traffic so never use it.
*/
- if (mc_count)
- *total_flags |= FIF_ALLMULTI;
+ *total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
!(*total_flags & FIF_ALLMULTI));
rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);
- rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1);
+ rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS,
+ !(*total_flags & FIF_CONTROL));
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
}
#define rt73usb_get_tsf NULL
#endif
-static void rt73usb_reset_tsf(struct ieee80211_hw *hw)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
-
- rt73usb_register_write(rt2x00dev, TXRX_CSR12, 0);
- rt73usb_register_write(rt2x00dev, TXRX_CSR13, 0);
-}
-
static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_tx_control *control)
+ struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct skb_desc *desc;
- struct data_ring *ring;
- struct data_entry *entry;
- int timeout;
+ struct rt2x00_intf *intf = vif_to_intf(control->vif);
+ struct skb_frame_desc *skbdesc;
+ unsigned int beacon_base;
+ unsigned int timeout;
+ u32 reg;
- /*
- * Just in case the ieee80211 doesn't set this,
- * but we need this queue set for the descriptor
- * initialization.
- */
- control->queue = IEEE80211_TX_QUEUE_BEACON;
- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
- entry = rt2x00_get_data_entry(ring);
+ if (unlikely(!intf->beacon))
+ return -ENOBUFS;
/*
* Add the descriptor in front of the skb.
*/
- skb_push(skb, ring->desc_size);
- memset(skb->data, 0, ring->desc_size);
+ skb_push(skb, intf->beacon->queue->desc_size);
+ memset(skb->data, 0, intf->beacon->queue->desc_size);
/*
* Fill in skb descriptor
*/
- desc = get_skb_desc(skb);
- desc->desc_len = ring->desc_size;
- desc->data_len = skb->len - ring->desc_size;
- desc->desc = skb->data;
- desc->data = skb->data + ring->desc_size;
- desc->ring = ring;
- desc->entry = entry;
+ skbdesc = get_skb_frame_desc(skb);
+ memset(skbdesc, 0, sizeof(*skbdesc));
+ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
+ skbdesc->data = skb->data + intf->beacon->queue->desc_size;
+ skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
+ skbdesc->desc = skb->data;
+ skbdesc->desc_len = intf->beacon->queue->desc_size;
+ skbdesc->entry = intf->beacon;
+
+ /*
+ * Disable beaconing while we are reloading the beacon data,
+ * otherwise we might be sending out invalid data.
+ */
+ rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
+ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0);
+ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0);
+ rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
+ rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ /*
+ * mac80211 doesn't provide the control->queue variable
+ * for beacons. Set our own queue identification so
+ * it can be used during descriptor initialization.
+ */
+ control->queue = RT2X00_BCN_QUEUE_BEACON;
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Write entire beacon with descriptor to register,
* and kick the beacon generator.
*/
+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32));
rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
- USB_VENDOR_REQUEST_OUT,
- HW_BEACON_BASE0, 0x0000,
+ USB_VENDOR_REQUEST_OUT, beacon_base, 0,
skb->data, skb->len, timeout);
- rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
+ rt73usb_kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt73usb_get_tsf,
- .reset_tsf = rt73usb_reset_tsf,
.beacon_update = rt73usb_beacon_update,
};
static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.probe_hw = rt73usb_probe_hw,
.get_firmware_name = rt73usb_get_firmware_name,
+ .get_firmware_crc = rt73usb_get_firmware_crc,
.load_firmware = rt73usb_load_firmware,
.initialize = rt2x00usb_initialize,
.uninitialize = rt2x00usb_uninitialize,
.link_stats = rt73usb_link_stats,
.reset_tuner = rt73usb_reset_tuner,
.link_tuner = rt73usb_link_tuner,
+ .led_brightness = rt73usb_led_brightness,
.write_tx_desc = rt73usb_write_tx_desc,
.write_tx_data = rt2x00usb_write_tx_data,
.get_tx_data_len = rt73usb_get_tx_data_len,
.kick_tx_queue = rt73usb_kick_tx_queue,
.fill_rxdone = rt73usb_fill_rxdone,
- .config_mac_addr = rt73usb_config_mac_addr,
- .config_bssid = rt73usb_config_bssid,
- .config_type = rt73usb_config_type,
- .config_preamble = rt73usb_config_preamble,
+ .config_intf = rt73usb_config_intf,
+ .config_erp = rt73usb_config_erp,
.config = rt73usb_config,
};
+static const struct data_queue_desc rt73usb_queue_rx = {
+ .entry_num = RX_ENTRIES,
+ .data_size = DATA_FRAME_SIZE,
+ .desc_size = RXD_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_usb_rx),
+};
+
+static const struct data_queue_desc rt73usb_queue_tx = {
+ .entry_num = TX_ENTRIES,
+ .data_size = DATA_FRAME_SIZE,
+ .desc_size = TXD_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
+};
+
+static const struct data_queue_desc rt73usb_queue_bcn = {
+ .entry_num = 4 * BEACON_ENTRIES,
+ .data_size = MGMT_FRAME_SIZE,
+ .desc_size = TXINFO_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
+};
+
static const struct rt2x00_ops rt73usb_ops = {
.name = KBUILD_MODNAME,
- .rxd_size = RXD_DESC_SIZE,
- .txd_size = TXD_DESC_SIZE,
+ .max_sta_intf = 1,
+ .max_ap_intf = 4,
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
+ .rx = &rt73usb_queue_rx,
+ .tx = &rt73usb_queue_tx,
+ .bcn = &rt73usb_queue_bcn,
.lib = &rt73usb_rt2x00_ops,
.hw = &rt73usb_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
/* D-Link */
{ USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) },
/* Gemtek */
{ USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
/* Gigabyte */
struct xfrm_state
{
/* Note: bydst is re-used during gc */
+ struct list_head all;
struct hlist_node bydst;
struct hlist_node bysrc;
struct hlist_node byspi;
struct xfrm_state_afinfo {
unsigned int family;
unsigned int proto;
- unsigned int eth_proto;
+ __be16 eth_proto;
struct module *owner;
const struct xfrm_type *type_map[IPPROTO_MAX];
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
struct xfrm_policy
{
struct xfrm_policy *next;
+ struct list_head bytype;
struct hlist_node bydst;
struct hlist_node byidx;
int priority;
};
+struct xfrm_state_walk {
+ struct xfrm_state *state;
+ int count;
+ u8 proto;
+};
+
+struct xfrm_policy_walk {
+ struct xfrm_policy *policy;
+ int count;
+ u8 type, cur_type;
+};
+
extern void xfrm_init(void);
extern void xfrm4_init(void);
extern void xfrm_state_init(void);
extern int xfrm_proc_init(void);
#endif
-extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
+static inline void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
+{
+ walk->proto = proto;
+ walk->state = NULL;
+ walk->count = 0;
+}
+
+static inline void xfrm_state_walk_done(struct xfrm_state_walk *walk)
+{
+ if (walk->state != NULL) {
+ xfrm_state_put(walk->state);
+ walk->state = NULL;
+ }
+}
+
+extern int xfrm_state_walk(struct xfrm_state_walk *walk,
+ int (*func)(struct xfrm_state *, int, void*), void *);
extern struct xfrm_state *xfrm_state_alloc(void);
extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
struct flowi *fl, struct xfrm_tmpl *tmpl,
#endif
struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
-extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *);
+
+static inline void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type)
+{
+ walk->cur_type = XFRM_POLICY_TYPE_MAIN;
+ walk->type = type;
+ walk->policy = NULL;
+ walk->count = 0;
+}
+
+static inline void xfrm_policy_walk_done(struct xfrm_policy_walk *walk)
+{
+ if (walk->policy != NULL) {
+ xfrm_pol_put(walk->policy);
+ walk->policy = NULL;
+ }
+}
+
+extern int xfrm_policy_walk(struct xfrm_policy_walk *walk,
+ int (*func)(struct xfrm_policy *, int, int, void*), void *);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
struct xfrm_selector *sel,
skb->dev = __find_vlan_dev(dev, vid);
if (!skb->dev) {
pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n",
- __FUNCTION__, (unsigned int)vid, dev->name);
+ __func__, (unsigned int)vid, dev->name);
goto err_unlock;
}
ntohs(vhdr->h_vlan_TCI));
pr_debug("%s: priority: %u for TCI: %hu\n",
- __FUNCTION__, skb->priority, ntohs(vhdr->h_vlan_TCI));
+ __func__, skb->priority, ntohs(vhdr->h_vlan_TCI));
switch (skb->pkt_type) {
case PACKET_BROADCAST: /* Yeah, stats collect these together.. */
struct net_device *vdev = dev;
pr_debug("%s: skb: %p type: %hx len: %u vlan_id: %hx, daddr: %p\n",
- __FUNCTION__, skb, type, len, vlan_dev_info(dev)->vlan_id,
+ __func__, skb, type, len, vlan_dev_info(dev)->vlan_id,
daddr);
/* build vlan header only if re_order_header flag is NOT set. This
return -ENOMEM;
}
vlan_dev_info(vdev)->cnt_inc_headroom_on_tx++;
- pr_debug("%s: %s: had to grow skb\n", __FUNCTION__, vdev->name);
+ pr_debug("%s: %s: had to grow skb\n", __func__, vdev->name);
}
if (build_vlan_header) {
vlan_dev_info(dev)->cnt_encap_on_xmit++;
pr_debug("%s: proto to encap: 0x%hx\n",
- __func__, htons(veth->h_vlan_proto));
- __FUNCTION__, ntohs(veth->h_vlan_proto));
++ __func__, ntohs(veth->h_vlan_proto));
/* Construct the second two bytes. This field looks something
* like:
* usr_priority: 3 bits (high bits)
}
pr_debug("%s: about to send skb: %p to dev: %s\n",
- __FUNCTION__, skb, skb->dev->name);
+ __func__, skb, skb->dev->name);
pr_debug(" " MAC_FMT " " MAC_FMT " %4hx %4hx %4hx\n",
veth->h_dest[0], veth->h_dest[1], veth->h_dest[2],
veth->h_dest[3], veth->h_dest[4], veth->h_dest[5],
err = -EADDRNOTAVAIL;
if (!sysctl_ip_nonlocal_bind &&
!inet->freebind &&
- addr->sin_addr.s_addr != INADDR_ANY &&
+ addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
chk_addr_ret != RTN_BROADCAST)
{
struct sock *sk = sock->sk;
int err = 0;
+ struct net *net = sk->sk_net;
switch (cmd) {
case SIOCGSTAMP:
case SIOCADDRT:
case SIOCDELRT:
case SIOCRTMSG:
- err = ip_rt_ioctl(sk->sk_net, cmd, (void __user *)arg);
+ err = ip_rt_ioctl(net, cmd, (void __user *)arg);
break;
case SIOCDARP:
case SIOCGARP:
case SIOCSARP:
- err = arp_ioctl(sk->sk_net, cmd, (void __user *)arg);
+ err = arp_ioctl(net, cmd, (void __user *)arg);
break;
case SIOCGIFADDR:
case SIOCSIFADDR:
case SIOCSIFPFLAGS:
case SIOCGIFPFLAGS:
case SIOCSIFFLAGS:
- err = devinet_ioctl(cmd, (void __user *)arg);
+ err = devinet_ioctl(net, cmd, (void __user *)arg);
break;
default:
if (sk->sk_prot->ioctl)
if (sysctl_ip_dynaddr > 1) {
printk(KERN_INFO "%s(): shifting inet->"
"saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
- __FUNCTION__,
+ __func__,
NIPQUAD(old_saddr),
NIPQUAD(new_saddr));
}
ip_init();
- tcp_v4_init(&inet_family_ops);
+ tcp_v4_init();
/* Setup TCP slab cache for open requests. */
tcp_init();
* Set the ICMP layer up
*/
- icmp_init(&inet_family_ops);
+ if (icmp_init() < 0)
+ panic("Failed to create the ICMP control socket.\n");
/*
* Initialise the multicast router
static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
{
struct in_pktinfo info;
- struct rtable *rt = (struct rtable *)skb->dst;
+ struct rtable *rt = skb->rtable;
info.ipi_addr.s_addr = ip_hdr(skb)->daddr;
if (rt) {
}
if (!mreq.imr_ifindex) {
- if (mreq.imr_address.s_addr == INADDR_ANY) {
+ if (mreq.imr_address.s_addr == htonl(INADDR_ANY)) {
inet->mc_index = 0;
inet->mc_addr = 0;
err = 0;
- '3' from resolv.h */
#define NONE __constant_htonl(INADDR_NONE)
+ #define ANY __constant_htonl(INADDR_ANY)
/*
* Public IP configuration
mm_segment_t oldfs = get_fs();
set_fs(get_ds());
- res = devinet_ioctl(cmd, (struct ifreq __user *) arg);
+ res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
set_fs(oldfs);
return res;
}
if (rarp->ar_pro != htons(ETH_P_IP))
goto drop;
- if (!pskb_may_pull(skb,
- sizeof(struct arphdr) +
- (2 * dev->addr_len) +
- (2 * 4)))
+ if (!pskb_may_pull(skb, arp_hdr_len(dev)))
goto drop;
/* OK, it is all there and looks valid, process... */
DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip));
switch (num) {
case 0:
- if ((ic_myaddr = in_aton(ip)) == INADDR_ANY)
+ if ((ic_myaddr = in_aton(ip)) == ANY)
ic_myaddr = NONE;
break;
case 1:
- if ((ic_servaddr = in_aton(ip)) == INADDR_ANY)
+ if ((ic_servaddr = in_aton(ip)) == ANY)
ic_servaddr = NONE;
break;
case 2:
- if ((ic_gateway = in_aton(ip)) == INADDR_ANY)
+ if ((ic_gateway = in_aton(ip)) == ANY)
ic_gateway = NONE;
break;
case 3:
- if ((ic_netmask = in_aton(ip)) == INADDR_ANY)
+ if ((ic_netmask = in_aton(ip)) == ANY)
ic_netmask = NONE;
break;
case 4:
* introducing MSS oddities to segment boundaries. In rare cases where
* mss_now != mss_cache, we will request caller to create a small skb
* per input skb which could be mostly avoided here (if desired).
+ *
+ * We explicitly want to create a request for splitting write queue tail
+ * to a small skb for Nagle purposes while avoiding unnecessary modulos,
+ * thus all the complexity (cwnd_len is always MSS multiple which we
+ * return whenever allowed by the other factors). Basically we need the
+ * modulo only when the receiver window alone is the limiting factor or
+ * when we would be allowed to send the split-due-to-Nagle skb fully.
*/
static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
unsigned int mss_now, unsigned int cwnd)
if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk)))
return cwnd_len;
- if (skb == tcp_write_queue_tail(sk) && cwnd_len <= skb->len)
+ needed = min(skb->len, window);
+
+ if (skb == tcp_write_queue_tail(sk) && cwnd_len <= needed)
return cwnd_len;
- needed = min(skb->len, window);
return needed - needed % mss_now;
}
}
}
+EXPORT_SYMBOL(tcp_select_initial_window);
EXPORT_SYMBOL(tcp_connect);
EXPORT_SYMBOL(tcp_make_synack);
EXPORT_SYMBOL(tcp_simple_retransmit);
struct sctp_association *asoc,
struct sctp_transport *t)
{
- SCTP_DEBUG_PRINTK("%s\n", __FUNCTION__);
+ SCTP_DEBUG_PRINTK("%s\n", __func__);
sctp_do_sm(SCTP_EVENT_T_OTHER,
SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
static struct sctp_association *__sctp_rcv_asconf_lookup(
sctp_chunkhdr_t *ch,
const union sctp_addr *laddr,
- __be32 peer_port,
+ __be16 peer_port,
struct sctp_transport **transportp)
{
sctp_addip_chunk_t *asconf = (struct sctp_addip_chunk *)ch;
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
+ int found = 0;
switch (ev) {
case NETDEV_UP:
&sctp_local_addr_list, list) {
if (ipv6_addr_equal(&addr->a.v6.sin6_addr,
&ifa->addr)) {
+ found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
break;
}
}
spin_unlock_bh(&sctp_local_addr_lock);
- if (addr && !addr->valid)
+ if (found)
call_rcu(&addr->rcu, sctp_local_addr_free);
break;
}
SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
"src:" NIP6_FMT " dst:" NIP6_FMT "\n",
- __FUNCTION__, skb, skb->len,
+ __func__, skb, skb->len,
NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
- __FUNCTION__, NIP6(fl.fl6_dst));
+ __func__, NIP6(fl.fl6_dst));
if (saddr) {
ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
NIP6(fl.fl6_src));
}
- dst = ip6_route_output(NULL, &fl);
+ dst = ip6_route_output(&init_net, NULL, &fl);
if (!dst->error) {
struct rt6_info *rt;
rt = (struct rt6_info *)dst;
SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
"daddr:" NIP6_FMT " ",
- __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr));
+ __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));
if (!asoc) {
- ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr);
+ ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL,
+ &daddr->v6.sin6_addr, &saddr->v6.sin6_addr);
SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n",
NIP6(saddr->v6.sin6_addr));
return;
} else {
printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
"address for the dest:" NIP6_FMT "\n",
- __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
+ __func__, asoc, NIP6(daddr->v6.sin6_addr));
}
rcu_read_unlock();
static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port)
{
addr->v4.sin_family = AF_INET;
- addr->v4.sin_addr.s_addr = INADDR_ANY;
+ addr->v4.sin_addr.s_addr = htonl(INADDR_ANY);
addr->v4.sin_port = port;
}
/* Is this a wildcard address? */
static int sctp_v4_is_any(const union sctp_addr *addr)
{
- return INADDR_ANY == addr->v4.sin_addr.s_addr;
+ return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr;
}
/* This function checks if the address is a valid address to be used for
return 0;
/* Is this a broadcast address? */
- if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
+ if (skb && skb->rtable->rt_flags & RTCF_BROADCAST)
return 0;
return 1;
int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
- if (addr->v4.sin_addr.s_addr != INADDR_ANY &&
+ if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
ret != RTN_LOCAL &&
!sp->inet.freebind &&
!sysctl_ip_nonlocal_bind)
fl.fl4_src = saddr->v4.sin_addr.s_addr;
SCTP_DEBUG_PRINTK("%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - ",
- __FUNCTION__, NIPQUAD(fl.fl4_dst),
+ __func__, NIPQUAD(fl.fl4_dst),
NIPQUAD(fl.fl4_src));
if (!ip_route_output_key(&init_net, &rt, &fl)) {
/* What interface did this skb arrive on? */
static int sctp_v4_skb_iif(const struct sk_buff *skb)
{
- return ((struct rtable *)skb->dst)->rt_iif;
+ return skb->rtable->rt_iif;
}
/* Was this packet marked by Explicit Congestion Notification? */
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
+ int found = 0;
+ if (ifa->ifa_dev->dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
switch (ev) {
case NETDEV_UP:
addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
list_for_each_entry_safe(addr, temp,
&sctp_local_addr_list, list) {
if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) {
+ found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
break;
}
}
spin_unlock_bh(&sctp_local_addr_lock);
- if (addr && !addr->valid)
+ if (found)
call_rcu(&addr->rcu, sctp_local_addr_free);
break;
}
/* PF_INET only supports AF_INET addresses. */
if (addr1->sa.sa_family != addr2->sa.sa_family)
return 0;
- if (INADDR_ANY == addr1->v4.sin_addr.s_addr ||
- INADDR_ANY == addr2->v4.sin_addr.s_addr)
+ if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr ||
+ htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr)
return 1;
if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr)
return 1;
{
SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
"src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
- __FUNCTION__, skb, skb->len,
- NIPQUAD(((struct rtable *)skb->dst)->rt_src),
- NIPQUAD(((struct rtable *)skb->dst)->rt_dst));
+ __func__, skb, skb->len,
+ NIPQUAD(skb->rtable->rt_src),
+ NIPQUAD(skb->rtable->rt_dst));
SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
return ip_queue_xmit(skb, ipfragok);
ep = sp->ep;
SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
- __FUNCTION__, sk, addrs, addrcnt);
+ __func__, sk, addrs, addrcnt);
list_for_each(pos, &ep->asocs) {
asoc = list_entry(pos, struct sctp_association, asocs);
ep = sp->ep;
SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
- __FUNCTION__, sk, addrs, addrcnt);
+ __func__, sk, addrs, addrcnt);
list_for_each(pos, &ep->asocs) {
asoc = list_entry(pos, struct sctp_association, asocs);
struct sockaddr *kaddrs;
SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
- __FUNCTION__, sk, addrs, addrs_size);
+ __func__, sk, addrs, addrs_size);
if (unlikely(addrs_size <= 0))
return -EINVAL;
char __user *optval,
int optlen)
{
+ struct sctp_assoc_value params;
+ struct sctp_sock *sp;
+ struct sctp_association *asoc;
int val;
+ int assoc_id = 0;
- if (optlen != sizeof(int))
+ if (optlen < sizeof(int))
return -EINVAL;
- if (get_user(val, (int __user *)optval))
- return -EFAULT;
- if (val < 0)
+ if (optlen == sizeof(int)) {
+ printk(KERN_WARNING
+ "SCTP: Use of int in max_burst socket option deprecated\n");
+ printk(KERN_WARNING
+ "SCTP: Use struct sctp_assoc_value instead\n");
+ if (copy_from_user(&val, optval, optlen))
+ return -EFAULT;
+ } else if (optlen == sizeof(struct sctp_assoc_value)) {
+ if (copy_from_user(¶ms, optval, optlen))
+ return -EFAULT;
+ val = params.assoc_value;
+ assoc_id = params.assoc_id;
+ } else
return -EINVAL;
- sctp_sk(sk)->max_burst = val;
+ sp = sctp_sk(sk);
+
+ if (assoc_id != 0) {
+ asoc = sctp_id2assoc(sk, assoc_id);
+ if (!asoc)
+ return -EINVAL;
+ asoc->max_burst = val;
+ } else
+ sp->max_burst = val;
return 0;
}
sctp_lock_sock(sk);
SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
- __FUNCTION__, sk, addr, addr_len);
+ __func__, sk, addr, addr_len);
/* Validate addr_len before calling common connect/connectx routine. */
af = sctp_get_af_specific(addr->sa_family);
goto out;
}
- SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __FUNCTION__, sk, asoc);
+ SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __func__, sk, asoc);
retval = sctp_do_peeloff(asoc, &newsock);
if (retval < 0)
}
SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p newsk: %p sd: %d\n",
- __FUNCTION__, sk, asoc, newsock->sk, retval);
+ __func__, sk, asoc, newsock->sk, retval);
/* Return the fd mapped to the new socket. */
peeloff.sd = retval;
char __user *optval,
int __user *optlen)
{
- int val;
+ struct sctp_assoc_value params;
+ struct sctp_sock *sp;
+ struct sctp_association *asoc;
if (len < sizeof(int))
return -EINVAL;
- len = sizeof(int);
+ if (len == sizeof(int)) {
+ printk(KERN_WARNING
+ "SCTP: Use of int in max_burst socket option deprecated\n");
+ printk(KERN_WARNING
+ "SCTP: Use struct sctp_assoc_value instead\n");
+ params.assoc_id = 0;
+ } else if (len == sizeof (struct sctp_assoc_value)) {
+ if (copy_from_user(¶ms, optval, len))
+ return -EFAULT;
+ } else
+ return -EINVAL;
- val = sctp_sk(sk)->max_burst;
- if (put_user(len, optlen))
- return -EFAULT;
- if (copy_to_user(optval, &val, len))
- return -EFAULT;
+ sp = sctp_sk(sk);
+
+ if (params.assoc_id != 0) {
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc)
+ return -EINVAL;
+ params.assoc_value = asoc->max_burst;
+ } else
+ params.assoc_value = sp->max_burst;
+
+ if (len == sizeof(int)) {
+ if (copy_to_user(optval, ¶ms.assoc_value, len))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(optval, ¶ms, len))
+ return -EFAULT;
+ }
+
+ return 0;
- return -ENOTSUPP;
}
static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
long current_timeo = *timeo_p;
DEFINE_WAIT(wait);
- SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc,
+ SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __func__, asoc,
(long)(*timeo_p));
/* Increment the association's refcnt. */