Fix rt2x00 compilation and upgrade to the current mainline version (2.6.24)

SVN-Revision: 10573
This commit is contained in:
Florian Fainelli 2008-03-09 10:55:19 +00:00
parent 3d66117ef0
commit fef15a956c
27 changed files with 6901 additions and 5202 deletions

View file

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=rt2x00
PKG_VERSION:=cvs-20070712
PKG_VERSION:=$(KERNEL_VERSION)
include $(INCLUDE_DIR)/package.mk
@ -109,6 +109,7 @@ PKG_EXTRA_KCONFIG:= \
CONFIG_MAC80211=y \
CONFIG_RT2X00=y \
CONFIG_RT2X00_DEBUG=y \
CONFIG_RT2X00_LIB_FIRMWARE=y \
ifneq ($(CONFIG_PACKAGE_kmod-rt2x00-pci),)
PKG_EXTRA_KCONFIG+= CONFIG_RT2X00PCI=y

View file

@ -62,7 +62,7 @@ ifeq ($(CONFIG_RT2400PCI),y)
obj-m += rt2400pci.o
ifeq ($(CONFIG_RT2400PCI_RFKILL),y)
rt2x00lib-objs += rt2x00rfkill.o
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
endif
endif
@ -70,7 +70,7 @@ ifeq ($(CONFIG_RT2500PCI),y)
obj-m += rt2500pci.o
ifeq ($(CONFIG_RT2500PCI_RFKILL),y)
rt2x00lib-objs += rt2x00rfkill.o
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
endif
endif
@ -79,17 +79,17 @@ ifeq ($(CONFIG_RT2500USB),y)
endif
ifeq ($(CONFIG_RT61PCI),y)
CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
rt2x00lib-objs += rt2x00firmware.o
obj-m += rt61pci.o
ifeq ($(CONFIG_RT61PCI_RFKILL),y)
rt2x00lib-objs += rt2x00rfkill.o
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
endif
endif
ifeq ($(CONFIG_RT73USB),y)
CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
rt2x00lib-objs += rt2x00firmware.o
obj-m += rt73usb.o
endif
@ -97,7 +97,7 @@ endif
endif
MAKEFLAGS += --no-print-directory
CFLAGS := -include $(SUBDIRS)/rt2x00_compat.h $(CFLAGS)
EXTRA_CFLAGS := -include $(SUBDIRS)/rt2x00_compat.h $(CFLAGS)
all: default

File diff suppressed because it is too large Load diff

View file

@ -35,9 +35,10 @@
/*
* Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 100
/*
@ -48,6 +49,7 @@
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100
#define BBP_SIZE 0x0020
#define RF_SIZE 0x0010
/*
* Control/Status Registers(CSR).
@ -544,7 +546,6 @@
*/
#define MACCSR0 0x00e0
/*
* MACCSR1: MAC configuration register 1.
* KICK_RX: Kick one-shot rx in one-shot rx mode.
@ -716,10 +717,33 @@
#define ARCSR5_SERVICE FIELD32(0x0000ff00)
#define ARCSR5_LENGTH FIELD32(0xffff0000)
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R1: TX antenna control
*/
#define BBP_R1_TX_ANTENNA FIELD8(0x03)
/*
* R4: RX antenna control
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x06)
/*
* RF registers
*/
/*
* RF 1
*/
#define RF1_TUNER FIELD32(0x00020000)
/*
* RF 3
*/
#define RF3_TUNER FIELD32(0x00000100)
#define RF3_TXPOWER FIELD32(0x00003e00)
@ -776,21 +800,6 @@
#define EEPROM_TXPOWER_1 FIELD16(0x00ff)
#define EEPROM_TXPOWER_2 FIELD16(0xff00)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R1: TX antenna control
*/
#define BBP_R1_TX_ANTENNA FIELD8(0x03)
/*
* BBP_R4: RX antenna control
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x06)
/*
* DMA descriptor defines.
*/
@ -867,7 +876,7 @@
#define RXD_W0_MULTICAST FIELD32(0x00000004)
#define RXD_W0_BROADCAST FIELD32(0x00000008)
#define RXD_W0_MY_BSS FIELD32(0x00000010)
#define RXD_W0_CRC FIELD32(0x00000020)
#define RXD_W0_CRC_ERROR FIELD32(0x00000020)
#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080)
#define RXD_W0_DATABYTE_COUNT FIELD32(0xffff0000)

File diff suppressed because it is too large Load diff

View file

@ -46,9 +46,10 @@
/*
* Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 121
/*
@ -59,6 +60,7 @@
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0200
#define BBP_SIZE 0x0040
#define RF_SIZE 0x0014
/*
* Control/Status Registers(CSR).
@ -438,16 +440,16 @@
/*
* TXCSR8: CCK Tx BBP register.
* CCK_SIGNAL: BBP rate field address for CCK.
* CCK_SERVICE: BBP service field address for CCK.
* CCK_LENGTH_LOW: BBP length low byte address for CCK.
* CCK_LENGTH_HIGH: BBP length high byte address for CCK.
*/
#define TXCSR8 0x0098
#define TXCSR8_CCK_SIGNAL FIELD32(0x000000ff)
#define TXCSR8_CCK_SERVICE FIELD32(0x0000ff00)
#define TXCSR8_CCK_LENGTH_LOW FIELD32(0x00ff0000)
#define TXCSR8_CCK_LENGTH_HIGH FIELD32(0xff000000)
#define TXCSR8_BBP_ID0 FIELD32(0x0000007f)
#define TXCSR8_BBP_ID0_VALID FIELD32(0x00000080)
#define TXCSR8_BBP_ID1 FIELD32(0x00007f00)
#define TXCSR8_BBP_ID1_VALID FIELD32(0x00008000)
#define TXCSR8_BBP_ID2 FIELD32(0x007f0000)
#define TXCSR8_BBP_ID2_VALID FIELD32(0x00800000)
#define TXCSR8_BBP_ID3 FIELD32(0x7f000000)
#define TXCSR8_BBP_ID3_VALID FIELD32(0x80000000)
/*
* TXCSR9: OFDM TX BBP registers
@ -862,14 +864,32 @@
#define ARCSR5_LENGTH FIELD32(0xffff0000)
/*
* ACK/CTS payload consumed time registers.
* ARTCSR0: CCK ACK/CTS payload consumed time for 1/2/5.5/11 mbps.
* ARTCSR1: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
* ARTCSR2: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
*/
#define ARTCSR0 0x014c
#define ARTCSR0_ACK_CTS_11MBS FIELD32(0x000000ff)
#define ARTCSR0_ACK_CTS_5_5MBS FIELD32(0x0000ff00)
#define ARTCSR0_ACK_CTS_2MBS FIELD32(0x00ff0000)
#define ARTCSR0_ACK_CTS_1MBS FIELD32(0xff000000)
/*
* ARTCSR1: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
*/
#define ARTCSR1 0x0150
#define ARTCSR1_ACK_CTS_6MBS FIELD32(0x000000ff)
#define ARTCSR1_ACK_CTS_9MBS FIELD32(0x0000ff00)
#define ARTCSR1_ACK_CTS_12MBS FIELD32(0x00ff0000)
#define ARTCSR1_ACK_CTS_18MBS FIELD32(0xff000000)
/*
* ARTCSR2: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
*/
#define ARTCSR2 0x0154
#define ARTCSR2_ACK_CTS_24MBS FIELD32(0x000000ff)
#define ARTCSR2_ACK_CTS_36MBS FIELD32(0x0000ff00)
#define ARTCSR2_ACK_CTS_48MBS FIELD32(0x00ff0000)
#define ARTCSR2_ACK_CTS_54MBS FIELD32(0xff000000)
/*
* SECCSR1_RT2509: WEP control register.
@ -945,10 +965,40 @@
#define UART2CSR3 0x0198
#define UART2CSR4 0x019c
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R2: TX antenna control
*/
#define BBP_R2_TX_ANTENNA FIELD8(0x03)
#define BBP_R2_TX_IQ_FLIP FIELD8(0x04)
/*
* R14: RX antenna control
*/
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
/*
* BBP_R70
*/
#define BBP_R70_JAPAN_FILTER FIELD8(0x08)
/*
* RF registers
*/
/*
* RF 1
*/
#define RF1_TUNER FIELD32(0x00020000)
/*
* RF 3
*/
#define RF3_TUNER FIELD32(0x00000100)
#define RF3_TXPOWER FIELD32(0x00003e00)
@ -1029,28 +1079,6 @@
#define EEPROM_CALIBRATE_OFFSET 0x3e
#define EEPROM_CALIBRATE_OFFSET_RSSI FIELD16(0x00ff)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R2: TX antenna control
*/
#define BBP_R2_TX_ANTENNA FIELD8(0x03)
#define BBP_R2_TX_IQ_FLIP FIELD8(0x04)
/*
* BBP_R14: RX antenna control
*/
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
/*
* BBP_R70
*/
#define BBP_R70_JAPAN_FILTER FIELD8(0x08)
/*
* DMA descriptor defines.
*/
@ -1135,7 +1163,7 @@
#define RXD_W0_MULTICAST FIELD32(0x00000004)
#define RXD_W0_BROADCAST FIELD32(0x00000008)
#define RXD_W0_MY_BSS FIELD32(0x00000010)
#define RXD_W0_CRC FIELD32(0x00000020)
#define RXD_W0_CRC_ERROR FIELD32(0x00000020)
#define RXD_W0_OFDM FIELD32(0x00000040)
#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080)
#define RXD_W0_CIPHER_OWNER FIELD32(0x00000100)

File diff suppressed because it is too large Load diff

View file

@ -46,9 +46,10 @@
/*
* Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 120
/*
@ -59,6 +60,7 @@
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x006a
#define BBP_SIZE 0x0060
#define RF_SIZE 0x0014
/*
* Control/Status Registers(CSR).
@ -72,8 +74,14 @@
/*
* MAC_CSR1: System control.
* SOFT_RESET: Software reset, 1: reset, 0: normal.
* BBP_RESET: Hardware reset, 1: reset, 0, release.
* HOST_READY: Host ready after initialization.
*/
#define MAC_CSR1 0x0402
#define MAC_CSR1_SOFT_RESET FIELD16(0x00000001)
#define MAC_CSR1_BBP_RESET FIELD16(0x00000002)
#define MAC_CSR1_HOST_READY FIELD16(0x00000004)
/*
* MAC_CSR2: STA MAC register 0.
@ -246,8 +254,8 @@
#define TXRX_CSR2_DROP_NOT_TO_ME FIELD16(0x0010)
#define TXRX_CSR2_DROP_TODS FIELD16(0x0020)
#define TXRX_CSR2_DROP_VERSION_ERROR FIELD16(0x0040)
#define TXRX_CSR2_DROP_MCAST FIELD16(0x0200)
#define TXRX_CSR2_DROP_BCAST FIELD16(0x0400)
#define TXRX_CSR2_DROP_MULTICAST FIELD16(0x0200)
#define TXRX_CSR2_DROP_BROADCAST FIELD16(0x0400)
/*
* RX BBP ID registers
@ -258,16 +266,40 @@
#define TXRX_CSR4 0x0448
/*
* TX BBP ID registers
* TXRX_CSR5: CCK TX BBP ID0.
* TXRX_CSR5: CCK TX BBP ID1.
* TXRX_CSR5: OFDM TX BBP ID0.
* TXRX_CSR5: OFDM TX BBP ID1.
*/
#define TXRX_CSR5 0x044a
#define TXRX_CSR5_BBP_ID0 FIELD16(0x007f)
#define TXRX_CSR5_BBP_ID0_VALID FIELD16(0x0080)
#define TXRX_CSR5_BBP_ID1 FIELD16(0x7f00)
#define TXRX_CSR5_BBP_ID1_VALID FIELD16(0x8000)
/*
* TXRX_CSR6: CCK TX BBP ID1.
*/
#define TXRX_CSR6 0x044c
#define TXRX_CSR6_BBP_ID0 FIELD16(0x007f)
#define TXRX_CSR6_BBP_ID0_VALID FIELD16(0x0080)
#define TXRX_CSR6_BBP_ID1 FIELD16(0x7f00)
#define TXRX_CSR6_BBP_ID1_VALID FIELD16(0x8000)
/*
* TXRX_CSR7: OFDM TX BBP ID0.
*/
#define TXRX_CSR7 0x044e
#define TXRX_CSR7_BBP_ID0 FIELD16(0x007f)
#define TXRX_CSR7_BBP_ID0_VALID FIELD16(0x0080)
#define TXRX_CSR7_BBP_ID1 FIELD16(0x7f00)
#define TXRX_CSR7_BBP_ID1_VALID FIELD16(0x8000)
/*
* TXRX_CSR5: OFDM TX BBP ID1.
*/
#define TXRX_CSR8 0x0450
#define TXRX_CSR8_BBP_ID0 FIELD16(0x007f)
#define TXRX_CSR8_BBP_ID0_VALID FIELD16(0x0080)
#define TXRX_CSR8_BBP_ID1 FIELD16(0x7f00)
#define TXRX_CSR8_BBP_ID1_VALID FIELD16(0x8000)
/*
* TXRX_CSR9: TX ACK time-out.
@ -408,6 +440,7 @@
* PHY_CSR4: Interface configuration.
*/
#define PHY_CSR4 0x04c8
#define PHY_CSR4_LOW_RF_LE FIELD16(0x0001)
/*
* BBP pre-TX registers.
@ -473,28 +506,70 @@
#define STA_CSR0_FCS_ERROR FIELD16(0xffff)
/*
* Statistic Register.
* STA_CSR1: PLCP error.
* STA_CSR2: LONG error.
* STA_CSR3: CCA false alarm.
* STA_CSR4: RX FIFO overflow.
* STA_CSR5: Beacon sent counter.
* STA_CSR1: PLCP error count.
*/
#define STA_CSR1 0x04e2
/*
* STA_CSR2: LONG error count.
*/
#define STA_CSR2 0x04e4
/*
* STA_CSR3: CCA false alarm.
* FALSE_CCA_ERROR: False CCA error count, cleared when read.
*/
#define STA_CSR3 0x04e6
#define STA_CSR3_FALSE_CCA_ERROR FIELD16(0xffff)
/*
* STA_CSR4: RX FIFO overflow.
*/
#define STA_CSR4 0x04e8
/*
* STA_CSR5: Beacon sent counter.
*/
#define STA_CSR5 0x04ea
/*
* Statistics registers
*/
#define STA_CSR6 0x04ec
#define STA_CSR7 0x04ee
#define STA_CSR8 0x04f0
#define STA_CSR9 0x04f2
#define STA_CSR10 0x04f4
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R2: TX antenna control
*/
#define BBP_R2_TX_ANTENNA FIELD8(0x03)
#define BBP_R2_TX_IQ_FLIP FIELD8(0x04)
/*
* R14: RX antenna control
*/
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
/*
* RF registers.
*/
/*
* RF 1
*/
#define RF1_TUNER FIELD32(0x00020000)
/*
* RF 3
*/
#define RF3_TUNER FIELD32(0x00000100)
#define RF3_TXPOWER FIELD32(0x00003e00)
@ -614,23 +689,6 @@
#define EEPROM_CALIBRATE_OFFSET 0x0036
#define EEPROM_CALIBRATE_OFFSET_RSSI FIELD16(0x00ff)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R2: TX antenna control
*/
#define BBP_R2_TX_ANTENNA FIELD8(0x03)
#define BBP_R2_TX_IQ_FLIP FIELD8(0x04)
/*
* BBP_R14: RX antenna control
*/
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
/*
* DMA descriptor defines.
*/
@ -693,11 +751,11 @@
#define RXD_W0_MULTICAST FIELD32(0x00000004)
#define RXD_W0_BROADCAST FIELD32(0x00000008)
#define RXD_W0_MY_BSS FIELD32(0x00000010)
#define RXD_W0_CRC FIELD32(0x00000020)
#define RXD_W0_CRC_ERROR FIELD32(0x00000020)
#define RXD_W0_OFDM FIELD32(0x00000040)
#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080)
#define RXD_W0_CIPHER FIELD32(0x00000100)
#define RXD_W0_CI_ERROR FIELD32(0x00000200)
#define RXD_W0_CIPHER_ERROR FIELD32(0x00000200)
#define RXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000)
/*

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,205 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
Module: rt2x00lib
Abstract: rt2x00 generic configuration routines.
*/
/*
* Set enviroment defines for rt2x00.h
*/
#define DRV_NAME "rt2x00lib"
#include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
/*
* 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.
*
* Also note that when NULL is passed as address the
* we will send 00:00:00:00:00 to the device to clear the address.
* This will prevent the device being confused when it wants
* to ACK frames or consideres itself associated.
*/
void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac)
{
__le32 reg[2];
memset(&reg, 0, sizeof(reg));
if (mac)
memcpy(&reg, mac, ETH_ALEN);
rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, &reg[0]);
}
void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
{
__le32 reg[2];
memset(&reg, 0, sizeof(reg));
if (bssid)
memcpy(&reg, bssid, ETH_ALEN);
rt2x00dev->ops->lib->config_bssid(rt2x00dev, &reg[0]);
}
void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type)
{
int tsf_sync;
switch (type) {
case IEEE80211_IF_TYPE_IBSS:
case IEEE80211_IF_TYPE_AP:
tsf_sync = TSF_SYNC_BEACON;
break;
case IEEE80211_IF_TYPE_STA:
tsf_sync = TSF_SYNC_INFRA;
break;
default:
tsf_sync = TSF_SYNC_NONE;
break;
}
rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync);
}
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config)
{
struct rt2x00lib_conf libconf;
struct ieee80211_hw_mode *mode;
struct ieee80211_rate *rate;
int flags = 0;
int short_slot_time;
/*
* In some situations we want to force all configurations
* to be reloaded (When resuming for instance).
*/
if (force_config) {
flags = CONFIG_UPDATE_ALL;
goto config;
}
/*
* Check which configuration options have been
* updated and should be send to the device.
*/
if (rt2x00dev->rx_status.phymode != conf->phymode)
flags |= CONFIG_UPDATE_PHYMODE;
if (rt2x00dev->rx_status.channel != conf->channel)
flags |= CONFIG_UPDATE_CHANNEL;
if (rt2x00dev->tx_power != conf->power_level)
flags |= CONFIG_UPDATE_TXPOWER;
if (rt2x00dev->rx_status.antenna == conf->antenna_sel_rx)
flags |= CONFIG_UPDATE_ANTENNA;
/*
* The following configuration options are never
* stored anywhere and will always be updated.
*/
flags |= CONFIG_UPDATE_SLOT_TIME;
flags |= CONFIG_UPDATE_BEACON_INT;
/*
* We have determined what options should be updated,
* now precalculate device configuration values depending
* on what configuration options need to be updated.
*/
config:
memset(&libconf, 0, sizeof(libconf));
if (flags & CONFIG_UPDATE_PHYMODE) {
switch (conf->phymode) {
case MODE_IEEE80211A:
libconf.phymode = HWMODE_A;
break;
case MODE_IEEE80211B:
libconf.phymode = HWMODE_B;
break;
case MODE_IEEE80211G:
libconf.phymode = HWMODE_G;
break;
default:
ERROR(rt2x00dev,
"Attempt to configure unsupported mode (%d)"
"Defaulting to 802.11b", conf->phymode);
libconf.phymode = HWMODE_B;
}
mode = &rt2x00dev->hwmodes[libconf.phymode];
rate = &mode->rates[mode->num_rates - 1];
libconf.basic_rates =
DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK;
}
if (flags & CONFIG_UPDATE_CHANNEL) {
memcpy(&libconf.rf,
&rt2x00dev->spec.channels[conf->channel_val],
sizeof(libconf.rf));
}
if (flags & CONFIG_UPDATE_SLOT_TIME) {
short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
libconf.slot_time =
short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
libconf.sifs = SIFS;
libconf.pifs = short_slot_time ? SHORT_PIFS : PIFS;
libconf.difs = short_slot_time ? SHORT_DIFS : DIFS;
libconf.eifs = EIFS;
}
libconf.conf = conf;
/*
* Start configuration.
*/
rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf);
/*
* Some configuration changes affect the link quality
* which means we need to reset the link tuner.
*/
if (flags & (CONFIG_UPDATE_CHANNEL | CONFIG_UPDATE_ANTENNA))
rt2x00lib_reset_link_tuner(rt2x00dev);
rt2x00dev->curr_hwmode = libconf.phymode;
rt2x00dev->rx_status.phymode = conf->phymode;
rt2x00dev->rx_status.freq = conf->freq;
rt2x00dev->rx_status.channel = conf->channel;
rt2x00dev->tx_power = conf->power_level;
rt2x00dev->rx_status.antenna = conf->antenna_sel_rx;
}

View file

@ -21,22 +21,22 @@
/*
Module: rt2x00lib
Abstract: rt2x00 debugfs specific routines.
Supported chipsets: RT2460, RT2560, RT2570,
rt2561, rt2561s, rt2661, rt2571W & rt2671.
*/
#include <linux/debugfs.h>
/*
* Set enviroment defines for rt2x00.h
*/
#define DRV_NAME "rt2x00lib"
#include <asm/uaccess.h>
#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include "rt2x00.h"
#include "rt2x00debug.h"
#include "rt2x00lib.h"
#define PRINT_REG8_STR ( "0x%.2x\n" )
#define PRINT_REG16_STR ( "0x%.4x\n" )
#define PRINT_REG32_STR ( "0x%.8x\n" )
#define PRINT_REG_LEN_MAX ( 16 )
#define PRINT_LINE_LEN_MAX ( 32 )
#define PRINT_LINE_LEN_MAX 32
struct rt2x00debug_intf {
/*
@ -57,19 +57,24 @@ struct rt2x00debug_intf {
* - driver folder
* - driver file
* - chipset file
* - device flags file
* - register offset/value files
* - eeprom offset/value files
* - bbp offset/value files
* - rf offset/value files
*/
struct dentry *driver_folder;
struct dentry *driver_entry;
struct dentry *chipset_entry;
struct dentry *dev_flags;
struct dentry *csr_off_entry;
struct dentry *csr_val_entry;
struct dentry *eeprom_off_entry;
struct dentry *eeprom_val_entry;
struct dentry *bbp_off_entry;
struct dentry *bbp_val_entry;
struct dentry *rf_off_entry;
struct dentry *rf_val_entry;
/*
* Driver and chipset files will use a data buffer
@ -85,6 +90,7 @@ struct rt2x00debug_intf {
unsigned int offset_csr;
unsigned int offset_eeprom;
unsigned int offset_bbp;
unsigned int offset_rf;
};
static int rt2x00debug_file_open(struct inode *inode, struct file *file)
@ -108,127 +114,120 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
return 0;
}
static ssize_t rt2x00debug_file_read(void *device, char __user *buf,
loff_t *offset, unsigned int word, const struct rt2x00debug_reg *reg)
#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
static ssize_t rt2x00debug_read_##__name(struct file *file, \
char __user *buf, \
size_t length, \
loff_t *offset) \
{ \
struct rt2x00debug_intf *intf = file->private_data; \
const struct rt2x00debug *debug = intf->debug; \
char line[16]; \
size_t size; \
__type value; \
\
if (*offset) \
return 0; \
\
if (intf->offset_##__name >= debug->__name.word_count) \
return -EINVAL; \
\
debug->__name.read(intf->rt2x00dev, \
intf->offset_##__name, &value); \
\
size = sprintf(line, __format, value); \
\
if (copy_to_user(buf, line, size)) \
return -EFAULT; \
\
*offset += size; \
return size; \
}
#define RT2X00DEBUGFS_OPS_WRITE(__name, __type) \
static ssize_t rt2x00debug_write_##__name(struct file *file, \
const char __user *buf,\
size_t length, \
loff_t *offset) \
{ \
struct rt2x00debug_intf *intf = file->private_data; \
const struct rt2x00debug *debug = intf->debug; \
char line[16]; \
size_t size; \
__type value; \
\
if (*offset) \
return 0; \
\
if (!capable(CAP_NET_ADMIN)) \
return -EPERM; \
\
if (intf->offset_##__name >= debug->__name.word_count) \
return -EINVAL; \
\
if (copy_from_user(line, buf, length)) \
return -EFAULT; \
\
size = strlen(line); \
value = simple_strtoul(line, NULL, 0); \
\
debug->__name.write(intf->rt2x00dev, \
intf->offset_##__name, value); \
\
*offset += size; \
return size; \
}
#define RT2X00DEBUGFS_OPS(__name, __format, __type) \
RT2X00DEBUGFS_OPS_READ(__name, __format, __type); \
RT2X00DEBUGFS_OPS_WRITE(__name, __type); \
\
static const struct file_operations rt2x00debug_fop_##__name = {\
.owner = THIS_MODULE, \
.read = rt2x00debug_read_##__name, \
.write = rt2x00debug_write_##__name, \
.open = rt2x00debug_file_open, \
.release = rt2x00debug_file_release, \
};
RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
static ssize_t rt2x00debug_read_dev_flags(struct file *file,
char __user *buf,
size_t length,
loff_t *offset)
{
unsigned long value;
unsigned int size;
char *line;
struct rt2x00debug_intf *intf = file->private_data;
char line[16];
size_t size;
if (*offset)
return 0;
line = kzalloc(PRINT_REG_LEN_MAX, GFP_KERNEL);
if (!line)
return -ENOMEM;
reg->read(device, word, &value);
if (reg->word_size == sizeof(u8))
size = sprintf(line, PRINT_REG8_STR, (u8)value);
else if (reg->word_size == sizeof(u16))
size = sprintf(line, PRINT_REG16_STR, (u16)value);
else
size = sprintf(line, PRINT_REG32_STR, (u32)value);
size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
if (copy_to_user(buf, line, size))
goto exit;
kfree(line);
return -EFAULT;
*offset += size;
return size;
exit:
kfree(line);
return -EFAULT;
}
static ssize_t rt2x00debug_file_write(void *device, const char __user *buf,
loff_t *offset, unsigned int word, unsigned int length,
const struct rt2x00debug_reg *reg)
{
unsigned long value;
int size;
char *line;
line = kzalloc(length, GFP_KERNEL);
if (!line)
return -ENOMEM;
if (copy_from_user(line, buf, length))
goto exit;
size = strlen(line);
value = simple_strtoul(line, NULL, 0);
reg->write(device, word, &value);
kfree(line);
*offset += size;
return size;
exit:
kfree(line);
return -EFAULT;
}
#define RT2X00DEBUGFS_OPS_READ(__name) \
static ssize_t rt2x00debug_read_##__name(struct file *file, \
char __user *buf, size_t length, loff_t *offset) \
{ \
struct rt2x00debug_intf *intf = file->private_data; \
const struct rt2x00debug *debug = intf->debug; \
const struct rt2x00debug_reg *reg = &debug->reg_##__name;\
\
if (intf->offset_##__name > reg->word_count) \
return -EINVAL; \
\
return rt2x00debug_file_read(intf->rt2x00dev, buf, \
offset, intf->offset_##__name, reg); \
}
RT2X00DEBUGFS_OPS_READ(csr);
RT2X00DEBUGFS_OPS_READ(eeprom);
RT2X00DEBUGFS_OPS_READ(bbp);
#define RT2X00DEBUGFS_OPS_WRITE(__name) \
static ssize_t rt2x00debug_write_##__name(struct file *file, \
const char __user *buf, size_t length, loff_t *offset) \
{ \
struct rt2x00debug_intf *intf = file->private_data; \
const struct rt2x00debug *debug = intf->debug; \
const struct rt2x00debug_reg *reg = &debug->reg_##__name;\
\
if (intf->offset_##__name > reg->word_count) \
return -EINVAL; \
\
return rt2x00debug_file_write(intf->rt2x00dev, buf, \
offset, intf->offset_##__name, length, reg); \
}
RT2X00DEBUGFS_OPS_WRITE(csr);
RT2X00DEBUGFS_OPS_WRITE(eeprom);
RT2X00DEBUGFS_OPS_WRITE(bbp);
#define RT2X00DEBUGFS_OPS(__name) \
static const struct file_operations rt2x00debug_fop_##__name = {\
.owner = THIS_MODULE, \
.read = rt2x00debug_read_##__name, \
.write = rt2x00debug_write_##__name, \
.open = rt2x00debug_file_open, \
.release = rt2x00debug_file_release, \
};
RT2X00DEBUGFS_OPS(csr);
RT2X00DEBUGFS_OPS(eeprom);
RT2X00DEBUGFS_OPS(bbp);
static const struct file_operations rt2x00debug_fop_dev_flags = {
.owner = THIS_MODULE,
.read = rt2x00debug_read_dev_flags,
.open = rt2x00debug_file_open,
.release = rt2x00debug_file_release,
};
static struct dentry *rt2x00debug_create_file_driver(const char *name,
struct rt2x00debug_intf *intf, struct debugfs_blob_wrapper *blob)
struct rt2x00debug_intf
*intf,
struct debugfs_blob_wrapper
*blob)
{
char *data;
@ -246,20 +245,24 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
}
static struct dentry *rt2x00debug_create_file_chipset(const char *name,
struct rt2x00debug_intf *intf, struct debugfs_blob_wrapper *blob)
struct rt2x00debug_intf
*intf,
struct
debugfs_blob_wrapper
*blob)
{
const struct rt2x00debug *debug = intf->debug;
char *data;
data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
data = kzalloc(4 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
if (!data)
return NULL;
blob->data = data;
data += sprintf(data, "csr length: %d\n", debug->reg_csr.word_count);
data += sprintf(data, "eeprom length: %d\n",
debug->reg_eeprom.word_count);
data += sprintf(data, "bbp length: %d\n", debug->reg_bbp.word_count);
data += sprintf(data, "csr length: %d\n", debug->csr.word_count);
data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count);
data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count);
data += sprintf(data, "rf length: %d\n", debug->rf.word_count);
blob->size = strlen(blob->data);
return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
@ -280,53 +283,54 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf->rt2x00dev = rt2x00dev;
rt2x00dev->debugfs_intf = intf;
intf->driver_folder = debugfs_create_dir(intf->rt2x00dev->ops->name,
rt2x00dev->hw->wiphy->debugfsdir);
intf->driver_folder =
debugfs_create_dir(intf->rt2x00dev->ops->name,
rt2x00dev->hw->wiphy->debugfsdir);
if (IS_ERR(intf->driver_folder))
goto exit;
intf->driver_entry = rt2x00debug_create_file_driver("driver",
intf, &intf->driver_blob);
intf->driver_entry =
rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
if (IS_ERR(intf->driver_entry))
goto exit;
intf->chipset_entry = rt2x00debug_create_file_chipset("chipset",
intf, &intf->chipset_blob);
intf->chipset_entry =
rt2x00debug_create_file_chipset("chipset",
intf, &intf->chipset_blob);
if (IS_ERR(intf->chipset_entry))
goto exit;
intf->csr_off_entry = debugfs_create_u32("csr_offset",
S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_csr);
if (IS_ERR(intf->csr_off_entry))
intf->dev_flags = debugfs_create_file("dev_flags", S_IRUGO,
intf->driver_folder, intf,
&rt2x00debug_fop_dev_flags);
if (IS_ERR(intf->dev_flags))
goto exit;
intf->csr_val_entry = debugfs_create_file("csr_value",
S_IRUGO | S_IWUSR, intf->driver_folder, intf,
&rt2x00debug_fop_csr);
if (IS_ERR(intf->csr_val_entry))
goto exit;
#define RT2X00DEBUGFS_CREATE_ENTRY(__intf, __name) \
({ \
(__intf)->__name##_off_entry = \
debugfs_create_u32(__stringify(__name) "_offset", \
S_IRUGO | S_IWUSR, \
(__intf)->driver_folder, \
&(__intf)->offset_##__name); \
if (IS_ERR((__intf)->__name##_off_entry)) \
goto exit; \
\
(__intf)->__name##_val_entry = \
debugfs_create_file(__stringify(__name) "_value", \
S_IRUGO | S_IWUSR, \
(__intf)->driver_folder, \
(__intf), &rt2x00debug_fop_##__name);\
if (IS_ERR((__intf)->__name##_val_entry)) \
goto exit; \
})
intf->eeprom_off_entry = debugfs_create_u32("eeprom_offset",
S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_eeprom);
if (IS_ERR(intf->eeprom_off_entry))
goto exit;
RT2X00DEBUGFS_CREATE_ENTRY(intf, csr);
RT2X00DEBUGFS_CREATE_ENTRY(intf, eeprom);
RT2X00DEBUGFS_CREATE_ENTRY(intf, bbp);
RT2X00DEBUGFS_CREATE_ENTRY(intf, rf);
intf->eeprom_val_entry = debugfs_create_file("eeprom_value",
S_IRUGO | S_IWUSR, intf->driver_folder, intf,
&rt2x00debug_fop_eeprom);
if (IS_ERR(intf->eeprom_val_entry))
goto exit;
intf->bbp_off_entry = debugfs_create_u32("bbp_offset",
S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_bbp);
if (IS_ERR(intf->bbp_off_entry))
goto exit;
intf->bbp_val_entry = debugfs_create_file("bbp_value",
S_IRUGO | S_IWUSR, intf->driver_folder, intf,
&rt2x00debug_fop_bbp);
if (IS_ERR(intf->bbp_val_entry))
goto exit;
#undef RT2X00DEBUGFS_CREATE_ENTRY
return;
@ -344,12 +348,15 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
if (unlikely(!intf))
return;
debugfs_remove(intf->rf_val_entry);
debugfs_remove(intf->rf_off_entry);
debugfs_remove(intf->bbp_val_entry);
debugfs_remove(intf->bbp_off_entry);
debugfs_remove(intf->eeprom_val_entry);
debugfs_remove(intf->eeprom_off_entry);
debugfs_remove(intf->csr_val_entry);
debugfs_remove(intf->csr_off_entry);
debugfs_remove(intf->dev_flags);
debugfs_remove(intf->chipset_entry);
debugfs_remove(intf->driver_entry);
debugfs_remove(intf->driver_folder);

View file

@ -21,23 +21,23 @@
/*
Module: rt2x00debug
Abstract: Data structures for the rt2x00debug.
Supported chipsets: RT2460, RT2560, RT2570,
rt2561, rt2561s, rt2661, rt2571W & rt2671.
*/
#ifndef RT2X00DEBUG_H
#define RT2X00DEBUG_H
typedef void (debug_access_t)(struct rt2x00_dev *rt2x00dev,
const unsigned long word, void *data);
struct rt2x00_dev;
struct rt2x00debug_reg {
debug_access_t *read;
debug_access_t *write;
unsigned int word_size;
unsigned int word_count;
};
#define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type) \
struct reg##__name { \
void (*read)(const struct rt2x00_dev *rt2x00dev, \
const unsigned int word, __type *data); \
void (*write)(const struct rt2x00_dev *rt2x00dev, \
const unsigned int word, __type data); \
\
unsigned int word_size; \
unsigned int word_count; \
} __name
struct rt2x00debug {
/*
@ -46,19 +46,12 @@ struct rt2x00debug {
struct module *owner;
/*
* Register access information.
* Register access entries.
*/
struct rt2x00debug_reg reg_csr;
struct rt2x00debug_reg reg_eeprom;
struct rt2x00debug_reg reg_bbp;
RT2X00DEBUGFS_REGISTER_ENTRY(csr, u32);
RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16);
RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8);
RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32);
};
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
#else /* CONFIG_RT2X00_LIB_DEBUGFS */
static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev){}
static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev){}
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
#endif /* RT2X00DEBUG_H */

File diff suppressed because it is too large Load diff

View file

@ -20,8 +20,7 @@
/*
Module: rt2x00lib
Abstract: rt2x00 firmware loading specific routines.
Supported chipsets: rt2561, rt2561s, rt2661, rt2571W & rt2671.
Abstract: rt2x00 firmware loading routines.
*/
/*
@ -29,24 +28,44 @@
*/
#define DRV_NAME "rt2x00lib"
#include <linux/delay.h>
#include <linux/crc-itu-t.h>
#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
#include "rt2x00firmware.h"
static void rt2x00lib_load_firmware_continued(const struct firmware *fw,
void *context)
static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
{
struct rt2x00_dev *rt2x00dev = context;
struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
const struct firmware *fw;
char *fw_name;
int retval;
u16 crc;
u16 tmp;
/*
* Read correct firmware from harddisk.
*/
fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
if (!fw_name) {
ERROR(rt2x00dev,
"Invalid firmware filename.\n"
"Please file bug report to %s.\n", DRV_PROJECT);
return -EINVAL;
}
INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
retval = request_firmware(&fw, fw_name, device);
if (retval) {
ERROR(rt2x00dev, "Failed to request Firmware.\n");
return retval;
}
if (!fw || !fw->size || !fw->data) {
ERROR(rt2x00dev, "Failed to read Firmware.\n");
goto exit_failed;
return -ENOENT;
}
/*
@ -57,75 +76,49 @@ static void rt2x00lib_load_firmware_continued(const struct firmware *fw,
*/
tmp = 0;
crc = crc_itu_t(0, fw->data, fw->size - 2);
crc = crc_itu_t(crc, (u8*)&tmp, 2);
crc = crc_itu_t(crc, (u8 *)&tmp, 2);
if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
ERROR(rt2x00dev, "Firmware CRC error.\n");
goto exit_failed;
retval = -ENOENT;
goto exit;
}
INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
fw->data[fw->size - 4], fw->data[fw->size - 3]);
rt2x00dev->fw = fw;
return 0;
exit:
release_firmware(fw);
return retval;
}
int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
{
int retval;
if (!rt2x00dev->fw) {
retval = rt2x00lib_request_firmware(rt2x00dev);
if (retval)
return retval;
}
/*
* Send firmware to the device.
*/
if (rt2x00dev->ops->lib->load_firmware(rt2x00dev, fw->data, fw->size))
goto exit_failed;
INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
fw->data[fw->size - 4], fw->data[fw->size - 3]);
__set_bit(FIRMWARE_LOADED, &rt2x00dev->flags);
return;
exit_failed:
rt2x00debug_deregister(rt2x00dev);
__set_bit(FIRMWARE_FAILED, &rt2x00dev->flags);
retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev,
rt2x00dev->fw->data,
rt2x00dev->fw->size);
return retval;
}
int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
{
char *fw_name;
int status = -EINVAL;
/*
* Read correct firmware from harddisk.
*/
fw_name = rt2x00dev->ops->lib->get_fw_name(rt2x00dev);
if (!fw_name) {
ERROR(rt2x00dev,
"Invalid firmware filename.\n"
"Please file bug report to %s.\n", DRV_PROJECT);
return -EINVAL;
}
INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
status = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
fw_name, wiphy_dev(rt2x00dev->hw->wiphy), rt2x00dev,
&rt2x00lib_load_firmware_continued);
if (status)
ERROR(rt2x00dev, "Failed to request Firmware.\n");
return status;
release_firmware(rt2x00dev->fw);
rt2x00dev->fw = NULL;
}
int rt2x00lib_load_firmware_wait(struct rt2x00_dev *rt2x00dev)
{
unsigned int i;
if (!test_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags))
return 0;
for (i = 0; i < 150; i++) {
if (test_bit(FIRMWARE_FAILED, &rt2x00dev->flags))
return -EIO;
if (test_bit(FIRMWARE_LOADED, &rt2x00dev->flags))
return 0;
msleep(20);
}
ERROR(rt2x00dev, "Firmware loading timed out.\n");
return -ETIMEDOUT;
}

View file

@ -20,62 +20,100 @@
/*
Module: rt2x00lib
Abstract: Data structures for the rt2x00lib module.
Supported chipsets: RT2460, RT2560, RT2570,
rt2561, rt2561s, rt2661, rt2571W & rt2671.
Abstract: Data structures and definitions for the rt2x00lib module.
*/
#ifndef RT2X00LIB_H
#define RT2X00LIB_H
/*
* Driver allocation handlers.
* Interval defines
* Both the link tuner as the rfkill will be called once per second.
*/
int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev);
#define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) )
#define RFKILL_POLL_INTERVAL ( 1000 )
/*
* Driver status handlers.
* Radio control handlers.
*/
int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state);
int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev);
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state);
void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev);
/*
* Interrupt context handlers.
* Initialization handlers.
*/
void rt2x00lib_txdone(struct data_entry *entry,
const int status, const int retry);
void rt2x00lib_rxdone(struct data_entry *entry, char *data,
const int size, const int signal, const int rssi, const int ofdm);
int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev);
/*
* TX descriptor initializer
* Configuration handlers.
*/
void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry, struct data_desc *txd,
struct ieee80211_hdr *ieee80211hdr, unsigned int length,
struct ieee80211_tx_control *control);
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(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config);
/*
* mac80211 handlers.
* Firmware handlers.
*/
int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control);
int rt2x00lib_reset(struct ieee80211_hw *hw);
int rt2x00lib_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf);
void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf);
int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
struct ieee80211_if_conf *conf);
void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw,
unsigned short flags, int mc_count);
int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats);
int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params);
#ifdef CONFIG_RT2X00_LIB_FIRMWARE
int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev);
#else
static inline int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
{
return 0;
}
static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
{
}
#endif /* CONFIG_RT2X00_LIB_FIRMWARE */
#include "rt2x00debug.h"
/*
* Debugfs handlers.
*/
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
#else
static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
{
}
static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
{
}
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
* RFkill handlers.
*/
#ifdef CONFIG_RT2X00_LIB_RFKILL
int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev);
int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev);
#else
static inline int 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)
{
return 0;
}
static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
{
}
#endif /* CONFIG_RT2X00_LIB_RFKILL */
#endif /* RT2X00LIB_H */

View file

@ -19,10 +19,8 @@
*/
/*
Module: rt2x00lib
Module: rt2x00mac
Abstract: rt2x00 generic mac80211 routines.
Supported chipsets: RT2460, RT2560, RT2570,
rt2561, rt2561s, rt2661, rt2571W & rt2671.
*/
/*
@ -30,15 +28,16 @@
*/
#define DRV_NAME "rt2x00lib"
#include <linux/netdevice.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
#include "rt2x00dev.h"
static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *frag_skb,
struct ieee80211_tx_control *control)
static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring,
struct sk_buff *frag_skb,
struct ieee80211_tx_control *control)
{
struct sk_buff *skb;
int size;
@ -58,13 +57,13 @@ static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
skb_put(skb, size);
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
ieee80211_ctstoself_get(rt2x00dev->hw,
frag_skb->data, frag_skb->len, control,
(struct ieee80211_cts*)(skb->data));
ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id,
frag_skb->data, frag_skb->len, control,
(struct ieee80211_cts *)(skb->data));
else
ieee80211_rts_get(rt2x00dev->hw,
frag_skb->data, frag_skb->len, control,
(struct ieee80211_rts*)(skb->data));
ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id,
frag_skb->data, frag_skb->len, control,
(struct ieee80211_rts *)(skb->data));
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
@ -74,23 +73,34 @@ static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
return NETDEV_TX_OK;
}
int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
struct data_ring *ring;
u16 frame_control;
/*
* Mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
* Note that we can only stop the TX queues inside the TX path
* due to possible race conditions in mac80211.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) {
ieee80211_stop_queues(hw);
return 0;
}
/*
* Determine which ring to put packet on.
*/
ring = rt2x00_get_ring(rt2x00dev, control->queue);
ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
if (unlikely(!ring)) {
ERROR(rt2x00dev,
"Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
"Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@ -102,12 +112,13 @@ int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
* frame as well as the data frame.
*/
frame_control = le16_to_cpu(ieee80211hdr->frame_control);
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS &&
!is_cts_frame(frame_control) && !is_rts_frame(frame_control)) {
if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
(control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
IEEE80211_TXCTL_USE_CTS_PROTECT))) {
if (rt2x00_ring_free(ring) <= 1)
return NETDEV_TX_BUSY;
if (rt2x00_tx_rts_cts(rt2x00dev, ring, skb, control))
if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control))
return NETDEV_TX_BUSY;
}
@ -119,130 +130,148 @@ int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
return NETDEV_TX_OK;
}
EXPORT_SYMBOL_GPL(rt2x00lib_tx);
EXPORT_SYMBOL_GPL(rt2x00mac_tx);
int rt2x00lib_reset(struct ieee80211_hw *hw)
int rt2x00mac_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
rt2x00lib_disable_radio(rt2x00dev);
return rt2x00lib_enable_radio(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00lib_reset);
int rt2x00lib_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
int status;
/*
* We only support 1 non-monitor interface.
*/
if (conf->type != IEEE80211_IF_TYPE_MNTR &&
is_interface_present(intf))
return -ENOBUFS;
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
test_bit(DEVICE_STARTED, &rt2x00dev->flags))
return 0;
/*
* We support muliple monitor mode interfaces.
* All we need to do is increase the monitor_count.
* If this is the first interface which is added,
* we should load the firmware now.
*/
if (conf->type == IEEE80211_IF_TYPE_MNTR) {
intf->monitor_count++;
} else {
intf->id = conf->if_id;
intf->type = conf->type;
if (conf->type == IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
intf->promisc = 0;
}
/*
* Initialize interface, and enable the radio when this
* is the first interface that is brought up.
*/
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) {
/*
* We must wait on the firmware before
* we can safely continue.
*/
status = rt2x00lib_load_firmware_wait(rt2x00dev);
if (status)
return status;
/*
* Before initialization, the mac address should
* be configured.
*/
rt2x00dev->ops->lib->config_mac_addr(rt2x00dev,
conf->mac_addr);
/*
* Initialize the device.
*/
status = rt2x00lib_initialize(rt2x00dev);
if (status)
return status;
/*
* Enable radio.
*/
status = rt2x00lib_enable_radio(rt2x00dev);
if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
status = rt2x00lib_load_firmware(rt2x00dev);
if (status)
return status;
}
/*
* Initialize the device.
*/
status = rt2x00lib_initialize(rt2x00dev);
if (status)
return status;
/*
* Enable radio.
*/
status = rt2x00lib_enable_radio(rt2x00dev);
if (status) {
rt2x00lib_uninitialize(rt2x00dev);
return status;
}
__set_bit(DEVICE_STARTED, &rt2x00dev->flags);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00lib_add_interface);
EXPORT_SYMBOL_GPL(rt2x00mac_start);
void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
void rt2x00mac_stop(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return;
/*
* Perhaps we can add something smarter here,
* but for now just disabling the radio should do.
*/
rt2x00lib_disable_radio(rt2x00dev);
__clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
}
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
/* FIXME: Beaconing is broken in rt2x00. */
if (conf->type == IEEE80211_IF_TYPE_IBSS ||
conf->type == IEEE80211_IF_TYPE_AP) {
ERROR(rt2x00dev,
"rt2x00 does not support Adhoc or Master mode");
return -EOPNOTSUPP;
}
/*
* Don't allow interfaces to be added while
* either the device has disappeared or when
* another interface is already present.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
is_interface_present(intf))
return -ENOBUFS;
intf->id = conf->if_id;
intf->type = conf->type;
if (conf->type == IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
/*
* The MAC adddress must be configured after the device
* has been initialized. Otherwise the device can reset
* the MAC registers.
*/
rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
rt2x00lib_config_type(rt2x00dev, conf->type);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
/*
* We only support 1 non-monitor interface.
* Don't allow interfaces to be remove while
* either the device has disappeared or when
* no interface is present.
*/
if (conf->type != IEEE80211_IF_TYPE_MNTR &&
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
!is_interface_present(intf))
return;
/*
* When removing an monitor interface, decrease monitor_count.
* For non-monitor interfaces, all interface data needs to be reset.
*/
if (conf->type == IEEE80211_IF_TYPE_MNTR) {
intf->monitor_count--;
} else if (intf->type == conf->type) {
intf->id = 0;
intf->type = -EINVAL;
memset(&intf->bssid, 0x00, ETH_ALEN);
intf->promisc = 0;
}
intf->id = 0;
intf->type = INVALID_INTERFACE;
memset(&intf->bssid, 0x00, ETH_ALEN);
memset(&intf->mac, 0x00, ETH_ALEN);
/*
* If this was the last interface,
* this is the time to disable the radio.
* If this is not the last interface, then we should
* check if we should switch completely to monitor
* mode or completely switch to the non-monitor mode.
* Make sure the bssid and mac address registers
* are cleared to prevent false ACKing of frames.
*/
if (!is_monitor_present(intf) && !is_interface_present(intf))
rt2x00lib_disable_radio(rt2x00dev);
else if (is_monitor_present(intf) ^ is_interface_present(intf))
rt2x00lib_config_type(rt2x00dev,
is_interface_present(intf) ?
intf->type : IEEE80211_IF_TYPE_MNTR);
rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
rt2x00lib_config_type(rt2x00dev, intf->type);
}
EXPORT_SYMBOL_GPL(rt2x00lib_remove_interface);
EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
/*
* Mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return 0;
/*
* Check if we need to disable the radio,
* if this is not the case, at least the RX must be disabled.
@ -251,46 +280,42 @@ int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
if (!conf->radio_enabled)
rt2x00lib_disable_radio(rt2x00dev);
else
rt2x00lib_toggle_rx(rt2x00dev, 0);
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
}
rt2x00lib_config_phymode(rt2x00dev, conf->phymode);
rt2x00lib_config_channel(rt2x00dev, conf->channel_val,
conf->channel, conf->freq, conf->power_level);
rt2x00lib_config_txpower(rt2x00dev, conf->power_level);
rt2x00lib_config_antenna(rt2x00dev,
conf->antenna_sel_tx, conf->antenna_sel_rx);
rt2x00dev->ops->lib->config_duration(rt2x00dev,
(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME),
conf->beacon_int);
rt2x00lib_config(rt2x00dev, conf, 0);
/*
* Reenable RX only if the radio should be on.
*/
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00lib_toggle_rx(rt2x00dev, 1);
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
else if (conf->radio_enabled)
return rt2x00lib_enable_radio(rt2x00dev);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00lib_config);
EXPORT_SYMBOL_GPL(rt2x00mac_config);
int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
struct ieee80211_if_conf *conf)
int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id,
struct ieee80211_if_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
int status;
/*
* Monitor mode does not need configuring.
* Mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return 0;
/*
* If the given type does not match the configured type,
* there has been a problem.
*/
if (conf->type == IEEE80211_IF_TYPE_MNTR)
return 0;
else if (conf->type != intf->type)
if (conf->type != intf->type)
return -EINVAL;
/*
@ -300,14 +325,7 @@ int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
*/
if (conf->type != IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
/*
* Enable configuration.
* For Monitor mode, promisc mode will be forced on.
*/
rt2x00lib_config_type(rt2x00dev, conf->type);
rt2x00lib_config_promisc(rt2x00dev, rt2x00dev->interface.promisc);
rt2x00dev->ops->lib->config_bssid(rt2x00dev, intf->bssid);
rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
/*
* We only need to initialize the beacon when master mode is enabled.
@ -316,65 +334,86 @@ int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
return 0;
status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
conf->beacon, conf->beacon_control);
conf->beacon,
conf->beacon_control);
if (status)
dev_kfree_skb(conf->beacon);
return status;
}
EXPORT_SYMBOL_GPL(rt2x00lib_config_interface);
EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw,
unsigned short flags, int mc_count)
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
/*
* Promisc mode is forced on for Monitor interfaces.
* The dot11ACKFailureCount, dot11RTSFailureCount and
* dot11RTSSuccessCount are updated in interrupt time.
* dot11FCSErrorCount is updated in the link tuner.
*/
if (is_monitor_present(&rt2x00dev->interface))
return;
memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats));
/*
* Check if the new state is different then the old state.
*/
if (test_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags) ==
!!(flags & IFF_PROMISC))
return;
rt2x00dev->interface.promisc = !!(flags & IFF_PROMISC);
/*
* Schedule the link tuner if this does not run
* automatically. The link tuner will be automatically
* switched off when it is not required.
*/
if (!work_pending(&rt2x00dev->link.work.work))
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work.work);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00lib_set_multicast_list);
EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);
int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats)
int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
unsigned int i;
for (i = 0; i < hw->queues; i++)
memcpy(&stats->data[i], &rt2x00dev->tx[i].stats,
sizeof(rt2x00dev->tx[i].stats));
sizeof(rt2x00dev->tx[i].stats));
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00lib_get_tx_stats);
EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats);
int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params)
void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes,
int cts_protection, int preamble)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
int short_preamble;
int ack_timeout;
int ack_consume_time;
int difs;
/*
* We only support changing preamble mode.
*/
if (!(changes & IEEE80211_ERP_CHANGE_PREAMBLE))
return;
short_preamble = !preamble;
preamble = !!(preamble) ? PREAMBLE : SHORT_PREAMBLE;
difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
SHORT_DIFS : DIFS;
ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10);
ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
if (short_preamble)
__set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
else
__clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
ack_timeout, ack_consume_time);
}
EXPORT_SYMBOL_GPL(rt2x00mac_erp_ie_changed);
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct data_ring *ring;
ring = rt2x00_get_ring(rt2x00dev, queue);
ring = rt2x00lib_get_ring(rt2x00dev, queue);
if (unlikely(!ring))
return -EINVAL;
@ -398,10 +437,10 @@ int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
ring->tx_params.aifs = 2;
INFO(rt2x00dev,
"Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
queue, ring->tx_params.cw_min, ring->tx_params.cw_max,
ring->tx_params.aifs);
"Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
queue, ring->tx_params.cw_min, ring->tx_params.cw_max,
ring->tx_params.aifs);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00lib_conf_tx);
EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);

View file

@ -21,7 +21,6 @@
/*
Module: rt2x00pci
Abstract: rt2x00 generic pci device routines.
Supported chipsets: rt2460, rt2560, rt2561, rt2561s & rt2661.
*/
/*
@ -29,29 +28,27 @@
*/
#define DRV_NAME "rt2x00pci"
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/pci.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
#include "rt2x00pci.h"
/*
* Beacon handlers.
*/
int rt2x00pci_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 data_ring *ring =
rt2x00_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
struct data_entry *entry = rt2x00_get_data_entry(ring);
/*
* Just in case the ieee80211 doesn't set this,
* Just in case mac80211 doesn't set this correctly,
* but we need this queue set for the descriptor
* initialization.
*/
@ -61,8 +58,9 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
* Update the beacon entry.
*/
memcpy(entry->data_addr, skb->data, skb->len);
rt2x00lib_write_tx_desc(rt2x00dev, entry, entry->priv,
(struct ieee80211_hdr*)skb->data, skb->len, control);
rt2x00lib_write_tx_desc(rt2x00dev, entry->priv,
(struct ieee80211_hdr *)skb->data,
skb->len, control);
/*
* Enable beacon generation.
@ -73,32 +71,14 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update);
void rt2x00pci_beacondone(struct rt2x00_dev *rt2x00dev, const int queue)
{
struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
struct data_entry *entry = rt2x00_get_data_entry(ring);
struct sk_buff *skb;
skb = ieee80211_beacon_get(rt2x00dev->hw,
rt2x00dev->interface.id, &entry->tx_status.control);
if (!skb)
return;
rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
&entry->tx_status.control);
dev_kfree_skb(skb);
}
EXPORT_SYMBOL_GPL(rt2x00pci_beacondone);
/*
* TX data handlers.
*/
int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control)
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
struct data_entry *entry = rt2x00_get_data_entry(ring);
struct data_desc *txd = entry->priv;
u32 word;
@ -113,9 +93,9 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) ||
rt2x00_get_field32(word, TXD_ENTRY_VALID)) {
ERROR(rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return -EINVAL;
}
@ -123,8 +103,8 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
entry->skb = skb;
memcpy(&entry->tx_status.control, control, sizeof(*control));
memcpy(entry->data_addr, skb->data, skb->len);
rt2x00lib_write_tx_desc(rt2x00dev, entry, txd, ieee80211hdr,
skb->len, control);
rt2x00lib_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
skb->len, control);
rt2x00_ring_index_inc(ring);
@ -143,35 +123,53 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
struct data_ring *ring = rt2x00dev->rx;
struct data_entry *entry;
struct data_desc *rxd;
u32 desc;
int signal;
int rssi;
int ofdm;
int size;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
struct rxdata_entry_desc desc;
int header_size;
int align;
u32 word;
while (1) {
entry = rt2x00_get_data_entry(ring);
rxd = entry->priv;
rt2x00_desc_read(rxd, 0, &desc);
rt2x00_desc_read(rxd, 0, &word);
if (rt2x00_get_field32(desc, RXD_ENTRY_OWNER_NIC))
if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
break;
size = rt2x00dev->ops->lib->fill_rxdone(
entry, &signal, &rssi, &ofdm);
if (size < 0)
goto skip_entry;
memset(&desc, 0x00, sizeof(desc));
rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
hdr = (struct ieee80211_hdr *)entry->data_addr;
header_size =
ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
/*
* Send the packet to upper layer.
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
rt2x00lib_rxdone(entry, entry->data_addr, size,
signal, rssi, ofdm);
align = header_size % 4;
/*
* Allocate the sk_buffer, initialize it and copy
* all data into it.
*/
skb = dev_alloc_skb(desc.size + align);
if (!skb)
return;
skb_reserve(skb, align);
memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
/*
* Send the frame to rt2x00lib for further processing.
*/
rt2x00lib_rxdone(entry, skb, &desc);
skip_entry:
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
rt2x00_set_field32(&desc, RXD_ENTRY_OWNER_NIC, 1);
rt2x00_desc_write(rxd, 0, desc);
rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1);
rt2x00_desc_write(rxd, 0, word);
}
rt2x00_ring_index_inc(ring);
@ -189,20 +187,20 @@ EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
#define data_addr_offset(__ring, __i) \
({ \
(__ring)->data_addr \
+ ((__ring)->stats.limit * (__ring)->desc_size) \
+ ((__i) * (__ring)->data_size); \
(__ring)->data_addr + \
((__ring)->stats.limit * (__ring)->desc_size) + \
((__i) * (__ring)->data_size); \
})
#define data_dma_offset(__ring, __i) \
({ \
(__ring)->data_dma \
+ ((__ring)->stats.limit * (__ring)->desc_size) \
+ ((__i) * (__ring)->data_size); \
(__ring)->data_dma + \
((__ring)->stats.limit * (__ring)->desc_size) + \
((__i) * (__ring)->data_size); \
})
static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
{
unsigned int i;
@ -210,7 +208,8 @@ static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
* Allocate DMA memory for descriptor and buffer.
*/
ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev),
rt2x00_get_ring_size(ring), &ring->data_dma);
rt2x00_get_ring_size(ring),
&ring->data_dma);
if (!ring->data_addr)
return -ENOMEM;
@ -227,6 +226,16 @@ static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
return 0;
}
static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
{
if (ring->data_addr)
pci_free_consistent(rt2x00dev_pci(rt2x00dev),
rt2x00_get_ring_size(ring),
ring->data_addr, ring->data_dma);
ring->data_addr = NULL;
}
int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
{
struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
@ -237,7 +246,7 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
* Allocate DMA
*/
ring_for_each(rt2x00dev, ring) {
status = rt2x00pci_alloc_ring(rt2x00dev, ring);
status = rt2x00pci_alloc_dma(rt2x00dev, ring);
if (status)
goto exit;
}
@ -246,10 +255,10 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
* Register interrupt handler.
*/
status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler,
IRQF_SHARED, pci_dev->driver->name, rt2x00dev);
IRQF_SHARED, pci_name(pci_dev), rt2x00dev);
if (status) {
ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
pci_dev->irq, status);
pci_dev->irq, status);
return status;
}
@ -274,43 +283,58 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
/*
* Free DMA
*/
ring_for_each(rt2x00dev, ring) {
if (ring->data_addr)
pci_free_consistent(rt2x00dev_pci(rt2x00dev),
rt2x00_get_ring_size(ring),
ring->data_addr, ring->data_dma);
ring->data_addr = NULL;
}
ring_for_each(rt2x00dev, ring)
rt2x00pci_free_dma(rt2x00dev, ring);
}
EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
/*
* PCI driver handlers.
*/
static int rt2x00pci_alloc_csr(struct rt2x00_dev *rt2x00dev)
static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
{
rt2x00dev->csr_addr = ioremap(
pci_resource_start(rt2x00dev_pci(rt2x00dev), 0),
pci_resource_len(rt2x00dev_pci(rt2x00dev), 0));
if (!rt2x00dev->csr_addr) {
ERROR(rt2x00dev, "Ioremap failed.\n");
return -ENOMEM;
}
kfree(rt2x00dev->rf);
rt2x00dev->rf = NULL;
return 0;
}
kfree(rt2x00dev->eeprom);
rt2x00dev->eeprom = NULL;
static void rt2x00pci_free_csr(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00dev->csr_addr) {
iounmap(rt2x00dev->csr_addr);
rt2x00dev->csr_addr = NULL;
}
}
static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
{
struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
rt2x00dev->csr_addr = ioremap(pci_resource_start(pci_dev, 0),
pci_resource_len(pci_dev, 0));
if (!rt2x00dev->csr_addr)
goto exit;
rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
if (!rt2x00dev->eeprom)
goto exit;
rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
if (!rt2x00dev->rf)
goto exit;
return 0;
exit:
ERROR_PROBE("Failed to allocate registers.\n");
rt2x00pci_free_reg(rt2x00dev);
return -ENOMEM;
}
int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
{
struct rt2x00_ops *ops = (struct rt2x00_ops*)id->driver_data;
struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
int retval;
@ -353,18 +377,18 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
rt2x00dev->ops = ops;
rt2x00dev->hw = hw;
retval = rt2x00pci_alloc_csr(rt2x00dev);
retval = rt2x00pci_alloc_reg(rt2x00dev);
if (retval)
goto exit_free_device;
retval = rt2x00lib_probe_dev(rt2x00dev);
if (retval)
goto exit_free_csr;
goto exit_free_reg;
return 0;
exit_free_csr:
rt2x00pci_free_csr(rt2x00dev);
exit_free_reg:
rt2x00pci_free_reg(rt2x00dev);
exit_free_device:
ieee80211_free_hw(hw);
@ -391,6 +415,7 @@ void rt2x00pci_remove(struct pci_dev *pci_dev)
* Free all allocated data.
*/
rt2x00lib_remove_dev(rt2x00dev);
rt2x00pci_free_reg(rt2x00dev);
ieee80211_free_hw(hw);
/*
@ -413,7 +438,7 @@ int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
if (retval)
return retval;
rt2x00pci_free_csr(rt2x00dev);
rt2x00pci_free_reg(rt2x00dev);
pci_save_state(pci_dev);
pci_disable_device(pci_dev);
@ -434,11 +459,20 @@ int rt2x00pci_resume(struct pci_dev *pci_dev)
return -EIO;
}
retval = rt2x00pci_alloc_csr(rt2x00dev);
retval = rt2x00pci_alloc_reg(rt2x00dev);
if (retval)
return retval;
return rt2x00lib_resume(rt2x00dev);
retval = rt2x00lib_resume(rt2x00dev);
if (retval)
goto exit_free_reg;
return 0;
exit_free_reg:
rt2x00pci_free_reg(rt2x00dev);
return retval;
}
EXPORT_SYMBOL_GPL(rt2x00pci_resume);
#endif /* CONFIG_PM */

View file

@ -21,12 +21,13 @@
/*
Module: rt2x00pci
Abstract: Data structures for the rt2x00pci module.
Supported chipsets: rt2460, rt2560, rt2561, rt2561s & rt2661.
*/
#ifndef RT2X00PCI_H
#define RT2X00PCI_H
#include <linux/io.h>
/*
* This variable should be used with the
* pci_driver structure initialization.
@ -35,9 +36,9 @@
/*
* Register defines.
* When register access attempts should be repeated
* only REGISTER_BUSY_COUNT attempts with a delay
* of REGISTER_BUSY_DELAY us should be taken.
* Some registers require multiple attempts before success,
* in those cases REGISTER_BUSY_COUNT attempts should be
* taken with a REGISTER_BUSY_DELAY interval.
*/
#define REGISTER_BUSY_COUNT 5
#define REGISTER_BUSY_DELAY 100
@ -46,6 +47,8 @@
* Descriptor availability flags.
* All PCI device descriptors have these 2 flags
* with the exact same definition.
* By storing them here we can use them inside rt2x00pci
* for some simple entry availability checking.
*/
#define TXD_ENTRY_OWNER_NIC FIELD32(0x00000001)
#define TXD_ENTRY_VALID FIELD32(0x00000002)
@ -55,27 +58,31 @@
* Register access.
*/
static inline void rt2x00pci_register_read(const struct rt2x00_dev *rt2x00dev,
const unsigned long offset, u32 *value)
const unsigned long offset,
u32 *value)
{
*value = readl(rt2x00dev->csr_addr + offset);
}
static inline void rt2x00pci_register_multiread(
const struct rt2x00_dev *rt2x00dev,
const unsigned long offset, void *value, const u16 length)
static inline void
rt2x00pci_register_multiread(const struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
void *value, const u16 length)
{
memcpy_fromio(value, rt2x00dev->csr_addr + offset, length);
}
static inline void rt2x00pci_register_write(const struct rt2x00_dev *rt2x00dev,
const unsigned long offset, u32 value)
const unsigned long offset,
u32 value)
{
writel(value, rt2x00dev->csr_addr + offset);
}
static inline void rt2x00pci_register_multiwrite(
const struct rt2x00_dev *rt2x00dev,
const unsigned long offset, void *value, const u16 length)
static inline void
rt2x00pci_register_multiwrite(const struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
void *value, const u16 length)
{
memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
}
@ -84,15 +91,14 @@ static inline void rt2x00pci_register_multiwrite(
* Beacon handlers.
*/
int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control);
void rt2x00pci_beacondone(struct rt2x00_dev *rt2x00dev, const int queue);
struct ieee80211_tx_control *control);
/*
* TX data handlers.
*/
int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control);
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control);
/*
* RX data handlers.
@ -113,6 +119,9 @@ void rt2x00pci_remove(struct pci_dev *pci_dev);
#ifdef CONFIG_PM
int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
int rt2x00pci_resume(struct pci_dev *pci_dev);
#else
#define rt2x00pci_suspend NULL
#define rt2x00pci_resume NULL
#endif /* CONFIG_PM */
#endif /* RT2X00PCI_H */

View file

@ -0,0 +1,292 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
Module: rt2x00
Abstract: rt2x00 generic register information.
*/
#ifndef RT2X00REG_H
#define RT2X00REG_H
/*
* TX result flags.
*/
enum TX_STATUS {
TX_SUCCESS = 0,
TX_SUCCESS_RETRY = 1,
TX_FAIL_RETRY = 2,
TX_FAIL_INVALID = 3,
TX_FAIL_OTHER = 4,
};
/*
* Antenna values
*/
enum antenna {
ANTENNA_SW_DIVERSITY = 0,
ANTENNA_A = 1,
ANTENNA_B = 2,
ANTENNA_HW_DIVERSITY = 3,
};
/*
* Led mode values.
*/
enum led_mode {
LED_MODE_DEFAULT = 0,
LED_MODE_TXRX_ACTIVITY = 1,
LED_MODE_SIGNAL_STRENGTH = 2,
LED_MODE_ASUS = 3,
LED_MODE_ALPHA = 4,
};
/*
* TSF sync values
*/
enum tsf_sync {
TSF_SYNC_NONE = 0,
TSF_SYNC_INFRA = 1,
TSF_SYNC_BEACON = 2,
};
/*
* Device states
*/
enum dev_state {
STATE_DEEP_SLEEP = 0,
STATE_SLEEP = 1,
STATE_STANDBY = 2,
STATE_AWAKE = 3,
/*
* Additional device states, these values are
* not strict since they are not directly passed
* into the device.
*/
STATE_RADIO_ON,
STATE_RADIO_OFF,
STATE_RADIO_RX_ON,
STATE_RADIO_RX_OFF,
STATE_RADIO_IRQ_ON,
STATE_RADIO_IRQ_OFF,
};
/*
* IFS backoff values
*/
enum ifs {
IFS_BACKOFF = 0,
IFS_SIFS = 1,
IFS_NEW_BACKOFF = 2,
IFS_NONE = 3,
};
/*
* Cipher types for hardware encryption
*/
enum cipher {
CIPHER_NONE = 0,
CIPHER_WEP64 = 1,
CIPHER_WEP128 = 2,
CIPHER_TKIP = 3,
CIPHER_AES = 4,
/*
* The following fields were added by rt61pci and rt73usb.
*/
CIPHER_CKIP64 = 5,
CIPHER_CKIP128 = 6,
CIPHER_TKIP_NO_MIC = 7,
};
/*
* Register handlers.
* We store the position of a register field inside a field structure,
* This will simplify the process of setting and reading a certain field
* inside the register while making sure the process remains byte order safe.
*/
struct rt2x00_field8 {
u8 bit_offset;
u8 bit_mask;
};
struct rt2x00_field16 {
u16 bit_offset;
u16 bit_mask;
};
struct rt2x00_field32 {
u32 bit_offset;
u32 bit_mask;
};
/*
* Power of two check, this will check
* if the mask that has been given contains
* and contiguous set of bits.
*/
#define is_power_of_two(x) ( !((x) & ((x)-1)) )
#define low_bit_mask(x) ( ((x)-1) & ~(x) )
#define is_valid_mask(x) is_power_of_two(1 + (x) + low_bit_mask(x))
#define FIELD8(__mask) \
({ \
BUILD_BUG_ON(!(__mask) || \
!is_valid_mask(__mask) || \
(__mask) != (u8)(__mask)); \
(struct rt2x00_field8) { \
__ffs(__mask), (__mask) \
}; \
})
#define FIELD16(__mask) \
({ \
BUILD_BUG_ON(!(__mask) || \
!is_valid_mask(__mask) || \
(__mask) != (u16)(__mask));\
(struct rt2x00_field16) { \
__ffs(__mask), (__mask) \
}; \
})
#define FIELD32(__mask) \
({ \
BUILD_BUG_ON(!(__mask) || \
!is_valid_mask(__mask) || \
(__mask) != (u32)(__mask));\
(struct rt2x00_field32) { \
__ffs(__mask), (__mask) \
}; \
})
static inline void rt2x00_set_field32(u32 *reg,
const struct rt2x00_field32 field,
const u32 value)
{
*reg &= ~(field.bit_mask);
*reg |= (value << field.bit_offset) & field.bit_mask;
}
static inline u32 rt2x00_get_field32(const u32 reg,
const struct rt2x00_field32 field)
{
return (reg & field.bit_mask) >> field.bit_offset;
}
static inline void rt2x00_set_field16(u16 *reg,
const struct rt2x00_field16 field,
const u16 value)
{
*reg &= ~(field.bit_mask);
*reg |= (value << field.bit_offset) & field.bit_mask;
}
static inline u16 rt2x00_get_field16(const u16 reg,
const struct rt2x00_field16 field)
{
return (reg & field.bit_mask) >> field.bit_offset;
}
static inline void rt2x00_set_field8(u8 *reg,
const struct rt2x00_field8 field,
const u8 value)
{
*reg &= ~(field.bit_mask);
*reg |= (value << field.bit_offset) & field.bit_mask;
}
static inline u8 rt2x00_get_field8(const u8 reg,
const struct rt2x00_field8 field)
{
return (reg & field.bit_mask) >> field.bit_offset;
}
/*
* Device specific rate value.
* We will have to create the device specific rate value
* passed to the ieee80211 kernel. We need to make it a consist of
* multiple fields because we want to store more then 1 device specific
* values inside the value.
* 1 - rate, stored as 100 kbit/s.
* 2 - preamble, short_preamble enabled flag.
* 3 - MASK_RATE, which rates are enabled in this mode, this mask
* corresponds with the TX register format for the current device.
* 4 - plcp, 802.11b rates are device specific,
* 802.11g rates are set according to the ieee802.11a-1999 p.14.
* The bit to enable preamble is set in a seperate define.
*/
#define DEV_RATE FIELD32(0x000007ff)
#define DEV_PREAMBLE FIELD32(0x00000800)
#define DEV_RATEMASK FIELD32(0x00fff000)
#define DEV_PLCP FIELD32(0xff000000)
/*
* Bitfields
*/
#define DEV_RATEBIT_1MB ( 1 << 0 )
#define DEV_RATEBIT_2MB ( 1 << 1 )
#define DEV_RATEBIT_5_5MB ( 1 << 2 )
#define DEV_RATEBIT_11MB ( 1 << 3 )
#define DEV_RATEBIT_6MB ( 1 << 4 )
#define DEV_RATEBIT_9MB ( 1 << 5 )
#define DEV_RATEBIT_12MB ( 1 << 6 )
#define DEV_RATEBIT_18MB ( 1 << 7 )
#define DEV_RATEBIT_24MB ( 1 << 8 )
#define DEV_RATEBIT_36MB ( 1 << 9 )
#define DEV_RATEBIT_48MB ( 1 << 10 )
#define DEV_RATEBIT_54MB ( 1 << 11 )
/*
* Bitmasks for DEV_RATEMASK
*/
#define DEV_RATEMASK_1MB ( (DEV_RATEBIT_1MB << 1) -1 )
#define DEV_RATEMASK_2MB ( (DEV_RATEBIT_2MB << 1) -1 )
#define DEV_RATEMASK_5_5MB ( (DEV_RATEBIT_5_5MB << 1) -1 )
#define DEV_RATEMASK_11MB ( (DEV_RATEBIT_11MB << 1) -1 )
#define DEV_RATEMASK_6MB ( (DEV_RATEBIT_6MB << 1) -1 )
#define DEV_RATEMASK_9MB ( (DEV_RATEBIT_9MB << 1) -1 )
#define DEV_RATEMASK_12MB ( (DEV_RATEBIT_12MB << 1) -1 )
#define DEV_RATEMASK_18MB ( (DEV_RATEBIT_18MB << 1) -1 )
#define DEV_RATEMASK_24MB ( (DEV_RATEBIT_24MB << 1) -1 )
#define DEV_RATEMASK_36MB ( (DEV_RATEBIT_36MB << 1) -1 )
#define DEV_RATEMASK_48MB ( (DEV_RATEBIT_48MB << 1) -1 )
#define DEV_RATEMASK_54MB ( (DEV_RATEBIT_54MB << 1) -1 )
/*
* Bitmask groups of bitrates
*/
#define DEV_BASIC_RATEMASK \
( DEV_RATEMASK_11MB | \
DEV_RATEBIT_6MB | DEV_RATEBIT_12MB | DEV_RATEBIT_24MB )
#define DEV_CCK_RATEMASK ( DEV_RATEMASK_11MB )
#define DEV_OFDM_RATEMASK ( DEV_RATEMASK_54MB & ~DEV_CCK_RATEMASK )
/*
* Macro's to set and get specific fields from the device specific val and val2
* fields inside the ieee80211_rate entry.
*/
#define DEVICE_SET_RATE_FIELD(__value, __mask) \
(int)( ((__value) << DEV_##__mask.bit_offset) & DEV_##__mask.bit_mask )
#define DEVICE_GET_RATE_FIELD(__value, __mask) \
(int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset )
#endif /* RT2X00REG_H */

View file

@ -19,9 +19,8 @@
*/
/*
Module: rt2x00lib
Abstract: rt2x00 rfkill specific routines.
Supported chipsets: RT2460, RT2560, rt2561, rt2561s, rt2661.
Module: rt2x00rfkill
Abstract: rt2x00 rfkill routines.
*/
/*
@ -29,101 +28,119 @@
*/
#define DRV_NAME "rt2x00lib"
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rfkill.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
static int rt2x00lib_toggle_radio(void *data, enum rfkill_state state)
static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state)
{
struct rt2x00_dev* rt2x00dev = data;
struct rt2x00_dev *rt2x00dev = data;
int retval = 0;
if (unlikely(!rt2x00dev))
return 0;
/*
* Only continue if we have an active interface,
* either monitor or non-monitor should be present.
* Only continue if there are enabled interfaces.
*/
if (!is_interface_present(&rt2x00dev->interface) &&
!is_monitor_present(&rt2x00dev->interface))
if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
return 0;
if (state == RFKILL_STATE_ON) {
INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n");
__set_bit(DEVICE_ENABLED_RADIO_HW, &rt2x00dev->flags);
__clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
retval = rt2x00lib_enable_radio(rt2x00dev);
} else if (state == RFKILL_STATE_OFF) {
INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n");
__clear_bit(DEVICE_ENABLED_RADIO_HW, &rt2x00dev->flags);
__set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
rt2x00lib_disable_radio(rt2x00dev);
}
return retval;
}
static void rt2x00lib_rfkill_poll(struct work_struct *work)
static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, rfkill_work.work);
struct rt2x00_dev *rt2x00dev = poll_dev->private;
int state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
rfkill_switch_all(rt2x00dev->rfkill->type,
rt2x00dev->ops->lib->rfkill_poll(rt2x00dev));
queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work,
RFKILL_POLL_INTERVAL);
if (rt2x00dev->rfkill->state != state)
input_report_key(poll_dev->input, KEY_WLAN, 1);
}
int rt2x00lib_register_rfkill(struct rt2x00_dev *rt2x00dev)
int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
{
int status = rfkill_register(rt2x00dev->rfkill);
if (status) {
ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
return status;
}
int retval;
rt2x00lib_rfkill_poll(&rt2x00dev->rfkill_work.work);
return !schedule_delayed_work(&rt2x00dev->rfkill_work,
RFKILL_POLL_INTERVAL);
}
void rt2x00lib_unregister_rfkill(struct rt2x00_dev *rt2x00dev)
{
if (delayed_work_pending(&rt2x00dev->rfkill_work))
cancel_rearming_delayed_workqueue(
rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work);
rfkill_unregister(rt2x00dev->rfkill);
}
int rt2x00lib_allocate_rfkill(struct rt2x00_dev *rt2x00dev)
{
struct rfkill *rfkill;
if (!test_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
return 0;
rfkill = rfkill_allocate(rt2x00dev->device, RFKILL_TYPE_WLAN);
if (!rfkill) {
ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
return -ENOMEM;
retval = rfkill_register(rt2x00dev->rfkill);
if (retval) {
ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
return retval;
}
rfkill->name = rt2x00dev->ops->name;
rfkill->data = rt2x00dev;
rfkill->toggle_radio = rt2x00lib_toggle_radio;
rt2x00dev->rfkill = rfkill;
INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00lib_rfkill_poll);
retval = input_register_polled_device(rt2x00dev->poll_dev);
if (retval) {
ERROR(rt2x00dev, "Failed to register polled device.\n");
rfkill_unregister(rt2x00dev->rfkill);
return retval;
}
return 0;
}
void rt2x00lib_free_rfkill(struct rt2x00_dev *rt2x00dev)
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
{
if (!test_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
return;
input_unregister_polled_device(rt2x00dev->poll_dev);
rfkill_unregister(rt2x00dev->rfkill);
}
int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
{
struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
return 0;
rt2x00dev->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
if (!rt2x00dev->rfkill) {
ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
return -ENOMEM;
}
rt2x00dev->rfkill->name = rt2x00dev->ops->name;
rt2x00dev->rfkill->data = rt2x00dev;
rt2x00dev->rfkill->state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio;
rt2x00dev->poll_dev = input_allocate_polled_device();
if (!rt2x00dev->poll_dev) {
ERROR(rt2x00dev, "Failed to allocate polled device.\n");
rfkill_free(rt2x00dev->rfkill);
return -ENOMEM;
}
rt2x00dev->poll_dev->private = rt2x00dev;
rt2x00dev->poll_dev->poll = rt2x00rfkill_poll;
rt2x00dev->poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
return 0;
}
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
{
if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
return;
input_free_polled_device(rt2x00dev->poll_dev);
rfkill_free(rt2x00dev->rfkill);
}

View file

@ -0,0 +1,268 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
Module: rt2x00
Abstract: rt2x00 ring datastructures and routines
*/
#ifndef RT2X00RING_H
#define RT2X00RING_H
/*
* data_desc
* Each data entry also contains a descriptor which is used by the
* device to determine what should be done with the packet and
* what the current status is.
* This structure is greatly simplified, but the descriptors
* are basically a list of little endian 32 bit values.
* Make the array by default 1 word big, this will allow us
* to use sizeof() correctly.
*/
struct data_desc {
__le32 word[1];
};
/*
* rxdata_entry_desc
* Summary of information that has been read from the
* RX frame descriptor.
*/
struct rxdata_entry_desc {
int signal;
int rssi;
int ofdm;
int size;
int flags;
};
/*
* txdata_entry_desc
* Summary of information that should be written into the
* descriptor for sending a TX frame.
*/
struct txdata_entry_desc {
unsigned long flags;
#define ENTRY_TXDONE 1
#define ENTRY_TXD_RTS_FRAME 2
#define ENTRY_TXD_OFDM_RATE 3
#define ENTRY_TXD_MORE_FRAG 4
#define ENTRY_TXD_REQ_TIMESTAMP 5
#define ENTRY_TXD_BURST 6
/*
* Queue ID. ID's 0-4 are data TX rings
*/
int queue;
#define QUEUE_MGMT 13
#define QUEUE_RX 14
#define QUEUE_OTHER 15
/*
* PLCP values.
*/
u16 length_high;
u16 length_low;
u16 signal;
u16 service;
/*
* Timing information
*/
int aifs;
int ifs;
int cw_min;
int cw_max;
};
/*
* data_entry
* The data ring is a list of data entries.
* Each entry holds a reference to the descriptor
* and the data buffer. For TX rings the reference to the
* sk_buff of the packet being transmitted is also stored here.
*/
struct data_entry {
/*
* Status flags
*/
unsigned long flags;
#define ENTRY_OWNER_NIC 1
/*
* Ring we belong to.
*/
struct data_ring *ring;
/*
* sk_buff for the packet which is being transmitted
* in this entry (Only used with TX related rings).
*/
struct sk_buff *skb;
/*
* Store a ieee80211_tx_status structure in each
* ring entry, this will optimize the txdone
* handler.
*/
struct ieee80211_tx_status tx_status;
/*
* private pointer specific to driver.
*/
void *priv;
/*
* Data address for this entry.
*/
void *data_addr;
dma_addr_t data_dma;
};
/*
* data_ring
* Data rings are used by the device to send and receive packets.
* The data_addr is the base address of the data memory.
* To determine at which point in the ring we are,
* have to use the rt2x00_ring_index_*() functions.
*/
struct data_ring {
/*
* Pointer to main rt2x00dev structure where this
* ring belongs to.
*/
struct rt2x00_dev *rt2x00dev;
/*
* Base address for the device specific data entries.
*/
struct data_entry *entry;
/*
* TX queue statistic info.
*/
struct ieee80211_tx_queue_stats_data stats;
/*
* TX Queue parameters.
*/
struct ieee80211_tx_queue_params tx_params;
/*
* Base address for data ring.
*/
dma_addr_t data_dma;
void *data_addr;
/*
* Index variables.
*/
u16 index;
u16 index_done;
/*
* Size of packet and descriptor in bytes.
*/
u16 data_size;
u16 desc_size;
};
/*
* Handlers to determine the address of the current device specific
* data entry, where either index or index_done points to.
*/
static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring)
{
return &ring->entry[ring->index];
}
static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring
*ring)
{
return &ring->entry[ring->index_done];
}
/*
* Total ring memory
*/
static inline int rt2x00_get_ring_size(struct data_ring *ring)
{
return ring->stats.limit * (ring->desc_size + ring->data_size);
}
/*
* Ring index manipulation functions.
*/
static inline void rt2x00_ring_index_inc(struct data_ring *ring)
{
ring->index++;
if (ring->index >= ring->stats.limit)
ring->index = 0;
ring->stats.len++;
}
static inline void rt2x00_ring_index_done_inc(struct data_ring *ring)
{
ring->index_done++;
if (ring->index_done >= ring->stats.limit)
ring->index_done = 0;
ring->stats.len--;
ring->stats.count++;
}
static inline void rt2x00_ring_index_clear(struct data_ring *ring)
{
ring->index = 0;
ring->index_done = 0;
ring->stats.len = 0;
ring->stats.count = 0;
}
static inline int rt2x00_ring_empty(struct data_ring *ring)
{
return ring->stats.len == 0;
}
static inline int rt2x00_ring_full(struct data_ring *ring)
{
return ring->stats.len == ring->stats.limit;
}
static inline int rt2x00_ring_free(struct data_ring *ring)
{
return ring->stats.limit - ring->stats.len;
}
/*
* TX/RX Descriptor access functions.
*/
static inline void rt2x00_desc_read(struct data_desc *desc,
const u8 word, u32 *value)
{
*value = le32_to_cpu(desc->word[word]);
}
static inline void rt2x00_desc_write(struct data_desc *desc,
const u8 word, const u32 value)
{
desc->word[word] = cpu_to_le32(value);
}
#endif /* RT2X00RING_H */

View file

@ -21,7 +21,6 @@
/*
Module: rt2x00usb
Abstract: rt2x00 generic usb device routines.
Supported chipsets: rt2570, rt2571W & rt2671.
*/
/*
@ -31,169 +30,87 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/usb.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
#include "rt2x00usb.h"
/*
* Interfacing with the HW.
*/
int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 type, const u16 offset,
u32 value, void *buffer, const u16 buffer_length, const u16 timeout)
const u8 request, const u8 requesttype,
const u16 offset, const u16 value,
void *buffer, const u16 buffer_length,
const int timeout)
{
struct usb_device *usb_dev = interface_to_usbdev(
rt2x00dev_usb(rt2x00dev));
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
int status;
unsigned int i;
unsigned int pipe =
(requesttype == USB_VENDOR_REQUEST_IN) ?
usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
status = usb_control_msg(
usb_dev,
(type == USB_VENDOR_REQUEST_IN) ?
usb_rcvctrlpipe(usb_dev, 0) :
usb_sndctrlpipe(usb_dev, 0),
request, type, value, offset, buffer, buffer_length,
timeout);
status = usb_control_msg(usb_dev, pipe, request, requesttype,
value, offset, buffer, buffer_length,
timeout);
if (status >= 0)
return 0;
/*
* Check for errors
* -ENODEV: Device has disappeared, no point continuing.
* All other errors: Try again.
*/
else if (status == -ENODEV)
break;
}
ERROR(rt2x00dev, "Vendor Request 0x%02x failed for offset 0x%04x"
" with error %d.\n", request, offset, status);
ERROR(rt2x00dev,
"Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n",
request, offset, status);
return status;
}
EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
/*
* Beacon handlers.
*/
int rt2x00usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length, const int timeout)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_ring *ring =
rt2x00_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
struct data_entry *beacon;
struct data_entry *guardian;
int length;
int status;
/*
* Just in case the ieee80211 doesn't set this,
* but we need this queue set for the descriptor
* initialization.
* Check for Cache availability.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
/*
* Obtain 2 entries, one for the guardian byte,
* the second for the actual beacon.
*/
guardian = rt2x00_get_data_entry(ring);
rt2x00_ring_index_inc(ring);
beacon = rt2x00_get_data_entry(ring);
/*
* First we create the beacon.
*/
skb_push(skb, ring->desc_size);
rt2x00lib_write_tx_desc(rt2x00dev, beacon,
(struct data_desc*)skb->data,
(struct ieee80211_hdr*)(skb->data + ring->desc_size),
skb->len - ring->desc_size,
control);
/*
* Length passed to usb_fill_urb cannot be an odd number,
* so add 1 byte to make it even.
*/
length = skb->len;
if (length % 2)
length++;
usb_fill_bulk_urb(
beacon->priv,
usb_dev,
usb_sndbulkpipe(usb_dev, 1),
skb->data,
length,
rt2x00usb_beacondone,
beacon);
beacon->skb = skb;
/*
* Second we need to create the guardian byte.
* We only need a single byte, so lets recycle
* the 'flags' field we are not using for beacons.
*/
guardian->flags = 0;
usb_fill_bulk_urb(
guardian->priv,
usb_dev,
usb_sndbulkpipe(usb_dev, 1),
&guardian->flags,
1,
rt2x00usb_beacondone,
guardian);
/*
* Send out the guardian byte.
*/
usb_submit_urb(guardian->priv, GFP_ATOMIC);
/*
* Enable beacon generation.
*/
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00usb_beacon_update);
void rt2x00usb_beacondone(struct urb *urb)
{
struct data_entry *entry = (struct data_entry*)urb->context;
struct data_ring *ring = entry->ring;
if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags))
return;
/*
* Check if this was the guardian beacon,
* if that was the case we need to send the real beacon now.
* Otherwise we should free the sk_buffer, the device
* should be doing the rest of the work now.
*/
if (ring->index == 1) {
rt2x00_ring_index_done_inc(ring);
entry = rt2x00_get_data_entry(ring);
usb_submit_urb(entry->priv, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
} else if (ring->index_done == 1) {
entry = rt2x00_get_data_entry_done(ring);
if (entry->skb) {
dev_kfree_skb(entry->skb);
entry->skb = NULL;
}
rt2x00_ring_index_done_inc(ring);
if (unlikely(!rt2x00dev->csr_cache || buffer_length > CSR_CACHE_SIZE)) {
ERROR(rt2x00dev, "CSR cache not available.\n");
return -ENOMEM;
}
if (requesttype == USB_VENDOR_REQUEST_OUT)
memcpy(rt2x00dev->csr_cache, buffer, buffer_length);
status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
offset, 0, rt2x00dev->csr_cache,
buffer_length, timeout);
if (!status && requesttype == USB_VENDOR_REQUEST_IN)
memcpy(buffer, rt2x00dev->csr_cache, buffer_length);
return status;
}
EXPORT_SYMBOL_GPL(rt2x00usb_beacondone);
EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
/*
* TX data handlers.
*/
static void rt2x00usb_interrupt_txdone(struct urb *urb)
{
struct data_entry *entry = (struct data_entry*)urb->context;
struct data_entry *entry = (struct data_entry *)urb->context;
struct data_ring *ring = entry->ring;
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
struct data_desc *txd = (struct data_desc *)entry->skb->data;
@ -231,19 +148,18 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
*/
if (!rt2x00_ring_full(ring))
ieee80211_wake_queue(rt2x00dev->hw,
entry->tx_status.control.queue);
entry->tx_status.control.queue);
}
int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control)
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_entry *entry = rt2x00_get_data_entry(ring);
struct data_desc *txd;
u32 length = skb->len;
int pipe = usb_sndbulkpipe(usb_dev, 1);
u32 length;
if (rt2x00_ring_full(ring)) {
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
@ -252,37 +168,39 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) {
ERROR(rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
ieee80211_stop_queue( rt2x00dev->hw, control->queue);
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return -EINVAL;
}
skb_push(skb, rt2x00dev->hw->extra_tx_headroom);
txd = (struct data_desc*)skb->data;
rt2x00lib_write_tx_desc(rt2x00dev, entry, txd, ieee80211hdr,
length, control);
/*
* Add the descriptor in front of the skb.
*/
skb_push(skb, ring->desc_size);
memset(skb->data, 0, ring->desc_size);
rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
(struct ieee80211_hdr *)(skb->data +
ring->desc_size),
skb->len - ring->desc_size, control);
memcpy(&entry->tx_status.control, control, sizeof(*control));
entry->skb = skb;
/*
* Length passed to usb_fill_urb cannot be an odd number,
* so add 1 byte to make it even.
* USB devices cannot blindly pass the skb->len as the
* length of the data to usb_fill_bulk_urb. Pass the skb
* to the driver to determine what the length should be.
*/
length += rt2x00dev->hw->extra_tx_headroom;
if (length % 2)
length++;
length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, skb);
/*
* Initialize URB and send the frame to the device.
*/
__set_bit(ENTRY_OWNER_NIC, &entry->flags);
usb_fill_bulk_urb(
entry->priv,
usb_dev,
usb_sndbulkpipe(usb_dev, 1),
skb->data,
length,
rt2x00usb_interrupt_txdone,
entry);
usb_fill_bulk_urb(entry->priv, usb_dev, pipe,
skb->data, length, rt2x00usb_interrupt_txdone, entry);
usb_submit_urb(entry->priv, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
@ -299,13 +217,14 @@ EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
*/
static void rt2x00usb_interrupt_rxdone(struct urb *urb)
{
struct data_entry *entry = (struct data_entry*)urb->context;
struct data_entry *entry = (struct data_entry *)urb->context;
struct data_ring *ring = entry->ring;
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
int signal;
int rssi;
int ofdm;
int size;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
struct rxdata_entry_desc desc;
int header_size;
int frame_size;
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
!test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
@ -319,21 +238,56 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
if (urb->actual_length < entry->ring->desc_size || urb->status)
goto skip_entry;
size = rt2x00dev->ops->lib->fill_rxdone(entry, &signal, &rssi, &ofdm);
if (size < 0)
memset(&desc, 0x00, sizeof(desc));
rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
/*
* Allocate a new sk buffer to replace the current one.
* If allocation fails, we should drop the current frame
* so we can recycle the existing sk buffer for the new frame.
* As alignment we use 2 and not NET_IP_ALIGN because we need
* to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
* can be 0 on some hardware). We use these 2 bytes for frame
* alignment later, we assume that the chance that
* header_size % 4 == 2 is bigger then header_size % 2 == 0
* and thus optimize alignment by reserving the 2 bytes in
* advance.
*/
frame_size = entry->ring->data_size + entry->ring->desc_size;
skb = dev_alloc_skb(frame_size + 2);
if (!skb)
goto skip_entry;
/*
* Trim the skb_buffer to only contain the valid
* frame data (so ignore the device's descriptor).
*/
skb_trim(entry->skb, size);
skb_reserve(skb, 2);
skb_put(skb, frame_size);
/*
* Send the packet to upper layer, and update urb.
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
* After that trim the entire buffer down to only
* contain the valid frame data excluding the device
* descriptor.
*/
rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size,
signal, rssi, ofdm);
hdr = (struct ieee80211_hdr *)entry->skb->data;
header_size =
ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
if (header_size % 4 == 0) {
skb_push(entry->skb, 2);
memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
}
skb_trim(entry->skb, desc.size);
/*
* Send the frame to rt2x00lib for further processing.
*/
rt2x00lib_rxdone(entry, entry->skb, &desc);
/*
* Replace current entry's skb with the newly allocated one,
* and reinitialize the urb.
*/
entry->skb = skb;
urb->transfer_buffer = entry->skb->data;
urb->transfer_buffer_length = entry->skb->len;
@ -352,7 +306,7 @@ skip_entry:
void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
{
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_ring *ring;
struct data_entry *entry;
unsigned int i;
@ -375,14 +329,10 @@ void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
entry = &rt2x00dev->rx->entry[i];
usb_fill_bulk_urb(
entry->priv,
usb_dev,
usb_rcvbulkpipe(usb_dev, 1),
entry->skb->data,
entry->skb->len,
rt2x00usb_interrupt_rxdone,
entry);
usb_fill_bulk_urb(entry->priv, usb_dev,
usb_rcvbulkpipe(usb_dev, 1),
entry->skb->data, entry->skb->len,
rt2x00usb_interrupt_rxdone, entry);
__set_bit(ENTRY_OWNER_NIC, &entry->flags);
usb_submit_urb(entry->priv, GFP_ATOMIC);
@ -395,8 +345,8 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
struct data_ring *ring;
unsigned int i;
rt2x00usb_vendor_request(rt2x00dev, USB_RX_CONTROL,
USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0, REGISTER_TIMEOUT);
rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000,
REGISTER_TIMEOUT);
/*
* Cancel all rings.
@ -411,8 +361,8 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
/*
* Device initialization handlers.
*/
static int rt2x00usb_alloc_ring(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
{
unsigned int i;
@ -428,6 +378,22 @@ static int rt2x00usb_alloc_ring(struct rt2x00_dev *rt2x00dev,
return 0;
}
static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
{
unsigned int i;
if (!ring->entry)
return;
for (i = 0; i < ring->stats.limit; i++) {
usb_kill_urb(ring->entry[i].priv);
usb_free_urb(ring->entry[i].priv);
if (ring->entry[i].skb)
kfree_skb(ring->entry[i].skb);
}
}
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
@ -440,7 +406,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
* Allocate DMA
*/
ring_for_each(rt2x00dev, ring) {
status = rt2x00usb_alloc_ring(rt2x00dev, ring);
status = rt2x00usb_alloc_urb(rt2x00dev, ring);
if (status)
goto exit;
}
@ -448,7 +414,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
/*
* For the RX ring, skb's should be allocated.
*/
entry_size = ring->data_size + ring->desc_size;
entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size;
for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
skb = dev_alloc_skb(NET_IP_ALIGN + entry_size);
if (!skb)
@ -472,30 +438,56 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize);
void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
unsigned int i;
ring_for_each(rt2x00dev, ring) {
if (!ring->entry)
continue;
for (i = 0; i < ring->stats.limit; i++) {
usb_kill_urb(ring->entry[i].priv);
usb_free_urb(ring->entry[i].priv);
if (ring->entry[i].skb)
kfree_skb(ring->entry[i].skb);
}
}
ring_for_each(rt2x00dev, ring)
rt2x00usb_free_urb(rt2x00dev, ring);
}
EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
/*
* USB driver handlers.
*/
static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)
{
kfree(rt2x00dev->rf);
rt2x00dev->rf = NULL;
kfree(rt2x00dev->eeprom);
rt2x00dev->eeprom = NULL;
kfree(rt2x00dev->csr_cache);
rt2x00dev->csr_cache = NULL;
}
static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
{
rt2x00dev->csr_cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
if (!rt2x00dev->csr_cache)
goto exit;
rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
if (!rt2x00dev->eeprom)
goto exit;
rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
if (!rt2x00dev->rf)
goto exit;
return 0;
exit:
ERROR_PROBE("Failed to allocate registers.\n");
rt2x00usb_free_reg(rt2x00dev);
return -ENOMEM;
}
int rt2x00usb_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id)
const struct usb_device_id *id)
{
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
struct rt2x00_ops *ops = (struct rt2x00_ops*)id->driver_info;
struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
int retval;
@ -516,12 +508,24 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
rt2x00dev->ops = ops;
rt2x00dev->hw = hw;
retval = rt2x00lib_probe_dev(rt2x00dev);
rt2x00dev->usb_maxpacket =
usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
if (!rt2x00dev->usb_maxpacket)
rt2x00dev->usb_maxpacket = 1;
retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
goto exit_free_device;
retval = rt2x00lib_probe_dev(rt2x00dev);
if (retval)
goto exit_free_reg;
return 0;
exit_free_reg:
rt2x00usb_free_reg(rt2x00dev);
exit_free_device:
ieee80211_free_hw(hw);
@ -543,6 +547,7 @@ void rt2x00usb_disconnect(struct usb_interface *usb_intf)
* Free all allocated data.
*/
rt2x00lib_remove_dev(rt2x00dev);
rt2x00usb_free_reg(rt2x00dev);
ieee80211_free_hw(hw);
/*
@ -564,6 +569,8 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
if (retval)
return retval;
rt2x00usb_free_reg(rt2x00dev);
/*
* Decrease usbdev refcount.
*/
@ -577,10 +584,24 @@ int rt2x00usb_resume(struct usb_interface *usb_intf)
{
struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
struct rt2x00_dev *rt2x00dev = hw->priv;
int retval;
usb_get_dev(interface_to_usbdev(usb_intf));
return rt2x00lib_resume(rt2x00dev);
retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
return retval;
retval = rt2x00lib_resume(rt2x00dev);
if (retval)
goto exit_free_reg;
return 0;
exit_free_reg:
rt2x00usb_free_reg(rt2x00dev);
return retval;
}
EXPORT_SYMBOL_GPL(rt2x00usb_resume);
#endif /* CONFIG_PM */

View file

@ -21,7 +21,6 @@
/*
Module: rt2x00usb
Abstract: Data structures for the rt2x00usb module.
Supported chipsets: rt2570, rt2571W & rt2671.
*/
#ifndef RT2X00USB_H
@ -35,19 +34,25 @@
/*
* Register defines.
* When register access attempts should be repeated
* only REGISTER_BUSY_COUNT attempts with a delay
* of REGISTER_BUSY_DELAY us should be taken.
* Some registers require multiple attempts before success,
* in those cases REGISTER_BUSY_COUNT attempts should be
* taken with a REGISTER_BUSY_DELAY interval.
* For USB vendor requests we need to pass a timeout
* time in ms, for this we use the REGISTER_TIMEOUT,
* however when loading firmware a higher value is
* required. For that we use the REGISTER_TIMEOUT_FIRMWARE.
* required. In that case we use the REGISTER_TIMEOUT_FIRMWARE.
*/
#define REGISTER_BUSY_COUNT 5
#define REGISTER_BUSY_DELAY 100
#define REGISTER_TIMEOUT 20
#define REGISTER_TIMEOUT 500
#define REGISTER_TIMEOUT_FIRMWARE 1000
/*
* Cache size
*/
#define CSR_CACHE_SIZE 8
#define CSR_CACHE_SIZE_FIRMWARE 64
/*
* USB request types.
*/
@ -80,17 +85,64 @@
#define USB_MODE_WAKEUP 0x09 /* RT73USB */
/*
* USB devices need an additional Beacon (guardian beacon) to be generated.
*/
#undef BEACON_ENTRIES
#define BEACON_ENTRIES 2
/*
* Interfacing with the HW.
* Used to read/write from/to the device.
* This is the main function to communicate with the device,
* the buffer argument _must_ either be NULL or point to
* a buffer allocated by kmalloc. Failure to do so can lead
* to unexpected behavior depending on the architecture.
*/
int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 type, const u16 offset,
u32 value, void *buffer, const u16 buffer_length, const u16 timeout);
const u8 request, const u8 requesttype,
const u16 offset, const u16 value,
void *buffer, const u16 buffer_length,
const int timeout);
/*
* Used to read/write from/to the device.
* This function will use a previously with kmalloc allocated cache
* to communicate with the device. The contents of the buffer pointer
* will be copied to this cache when writing, or read from the cache
* when reading.
* Buffers send to rt2x00usb_vendor_request _must_ be allocated with
* kmalloc. Hence the reason for using a previously allocated cache
* which has been allocated properly.
*/
int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length, const int timeout);
/*
* Simple wrapper around rt2x00usb_vendor_request to write a single
* command to the device. Since we don't use the buffer argument we
* don't have to worry about kmalloc here.
*/
static inline int rt2x00usb_vendor_request_sw(const struct rt2x00_dev
*rt2x00dev,
const u8 request,
const u16 offset,
const u16 value,
const int timeout)
{
return rt2x00usb_vendor_request(rt2x00dev, request,
USB_VENDOR_REQUEST_OUT, offset,
value, NULL, 0, timeout);
}
/*
* Simple wrapper around rt2x00usb_vendor_request to read the eeprom
* from the device. Note that the eeprom argument _must_ be allocated using
* kmalloc for correct handling inside the kernel USB layer.
*/
static inline int rt2x00usb_eeprom_read(const struct rt2x00_dev *rt2x00dev,
__le16 *eeprom, const u16 lenght)
{
int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
USB_VENDOR_REQUEST_IN, 0x0000,
0x0000, eeprom, lenght, timeout);
}
/*
* Radio handlers
@ -98,19 +150,12 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
/*
* Beacon handlers.
*/
int rt2x00usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control);
void rt2x00usb_beacondone(struct urb *urb);
/*
* TX data handlers.
*/
int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control);
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control);
/*
* Device initialization handlers.
@ -122,11 +167,14 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
* USB driver handlers.
*/
int rt2x00usb_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id);
const struct usb_device_id *id);
void rt2x00usb_disconnect(struct usb_interface *usb_intf);
#ifdef CONFIG_PM
int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
int rt2x00usb_resume(struct usb_interface *usb_intf);
#else
#define rt2x00usb_suspend NULL
#define rt2x00usb_resume NULL
#endif /* CONFIG_PM */
#endif /* RT2X00USB_H */

File diff suppressed because it is too large Load diff

View file

@ -37,9 +37,10 @@
/*
* Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 120
/*
@ -50,6 +51,7 @@
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100
#define BBP_SIZE 0x0080
#define RF_SIZE 0x0014
/*
* PCI registers.
@ -260,7 +262,7 @@ struct hw_pairwise_ta_entry {
* MAC_CSR6: Maximum frame length register.
*/
#define MAC_CSR6 0x3018
#define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x000007ff)
#define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x00000fff)
/*
* MAC_CSR7: Reserved
@ -330,6 +332,11 @@ struct hw_pairwise_ta_entry {
#define MAC_CSR13_BIT5 FIELD32(0x00000020)
#define MAC_CSR13_BIT6 FIELD32(0x00000040)
#define MAC_CSR13_BIT7 FIELD32(0x00000080)
#define MAC_CSR13_BIT8 FIELD32(0x00000100)
#define MAC_CSR13_BIT9 FIELD32(0x00000200)
#define MAC_CSR13_BIT10 FIELD32(0x00000400)
#define MAC_CSR13_BIT11 FIELD32(0x00000800)
#define MAC_CSR13_BIT12 FIELD32(0x00001000)
/*
* MAC_CSR14: LED control register.
@ -392,16 +399,40 @@ struct hw_pairwise_ta_entry {
* TXRX_CSR1
*/
#define TXRX_CSR1 0x3044
#define TXRX_CSR1_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR1_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR1_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR1_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR1_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR1_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR1_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR1_BBP_ID3_VALID FIELD32(0x80000000)
/*
* TXRX_CSR2
*/
#define TXRX_CSR2 0x3048
#define TXRX_CSR2_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR2_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR2_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR2_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR2_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR2_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR2_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR2_BBP_ID3_VALID FIELD32(0x80000000)
/*
* TXRX_CSR3
*/
#define TXRX_CSR3 0x304c
#define TXRX_CSR3_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR3_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR3_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR3_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR3_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR3_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR3_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR3_BBP_ID3_VALID FIELD32(0x80000000)
/*
* TXRX_CSR4: Auto-Responder/Tx-retry register.
@ -428,11 +459,27 @@ struct hw_pairwise_ta_entry {
#define TXRX_CSR5 0x3054
/*
* ACK/CTS payload consumed time registers.
* TXRX_CSR6: ACK/CTS payload consumed time
*/
#define TXRX_CSR6 0x3058
/*
* TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
*/
#define TXRX_CSR7 0x305c
#define TXRX_CSR7_ACK_CTS_6MBS FIELD32(0x000000ff)
#define TXRX_CSR7_ACK_CTS_9MBS FIELD32(0x0000ff00)
#define TXRX_CSR7_ACK_CTS_12MBS FIELD32(0x00ff0000)
#define TXRX_CSR7_ACK_CTS_18MBS FIELD32(0xff000000)
/*
* TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
*/
#define TXRX_CSR8 0x3060
#define TXRX_CSR8_ACK_CTS_24MBS FIELD32(0x000000ff)
#define TXRX_CSR8_ACK_CTS_36MBS FIELD32(0x0000ff00)
#define TXRX_CSR8_ACK_CTS_48MBS FIELD32(0x00ff0000)
#define TXRX_CSR8_ACK_CTS_54MBS FIELD32(0xff000000)
/*
* TXRX_CSR9: Synchronization control register.
@ -481,7 +528,6 @@ struct hw_pairwise_ta_entry {
*/
#define TXRX_CSR15 0x307c
/*
* PHY control registers.
* Some values are set in TU, whereas 1 TU == 1024 us.
@ -536,11 +582,13 @@ struct hw_pairwise_ta_entry {
* PHY_CSR5: RX to TX signal switch timing control.
*/
#define PHY_CSR5 0x3094
#define PHY_CSR5_IQ_FLIP FIELD32(0x00000004)
/*
* PHY_CSR6: TX to RX signal timing control.
*/
#define PHY_CSR6 0x3098
#define PHY_CSR6_IQ_FLIP FIELD32(0x00000004)
/*
* PHY_CSR7: TX DAC switching timing control.
@ -555,6 +603,22 @@ struct hw_pairwise_ta_entry {
* SEC_CSR0: Shared key table control.
*/
#define SEC_CSR0 0x30a0
#define SEC_CSR0_BSS0_KEY0_VALID FIELD32(0x00000001)
#define SEC_CSR0_BSS0_KEY1_VALID FIELD32(0x00000002)
#define SEC_CSR0_BSS0_KEY2_VALID FIELD32(0x00000004)
#define SEC_CSR0_BSS0_KEY3_VALID FIELD32(0x00000008)
#define SEC_CSR0_BSS1_KEY0_VALID FIELD32(0x00000010)
#define SEC_CSR0_BSS1_KEY1_VALID FIELD32(0x00000020)
#define SEC_CSR0_BSS1_KEY2_VALID FIELD32(0x00000040)
#define SEC_CSR0_BSS1_KEY3_VALID FIELD32(0x00000080)
#define SEC_CSR0_BSS2_KEY0_VALID FIELD32(0x00000100)
#define SEC_CSR0_BSS2_KEY1_VALID FIELD32(0x00000200)
#define SEC_CSR0_BSS2_KEY2_VALID FIELD32(0x00000400)
#define SEC_CSR0_BSS2_KEY3_VALID FIELD32(0x00000800)
#define SEC_CSR0_BSS3_KEY0_VALID FIELD32(0x00001000)
#define SEC_CSR0_BSS3_KEY1_VALID FIELD32(0x00002000)
#define SEC_CSR0_BSS3_KEY2_VALID FIELD32(0x00004000)
#define SEC_CSR0_BSS3_KEY3_VALID FIELD32(0x00008000)
/*
* SEC_CSR1: Shared key table security mode register.
@ -768,9 +832,15 @@ struct hw_pairwise_ta_entry {
#define CWMAX_CSR_CWMAX3 FIELD32(0x0000f000)
/*
* TX_DMA_DST_CSR
* TX_DMA_DST_CSR: TX DMA destination
* 0: TX ring0, 1: TX ring1, 2: TX ring2 3: invalid
*/
#define TX_DMA_DST_CSR 0x342c
#define TX_DMA_DST_CSR_DEST_AC0 FIELD32(0x00000003)
#define TX_DMA_DST_CSR_DEST_AC1 FIELD32(0x0000000c)
#define TX_DMA_DST_CSR_DEST_AC2 FIELD32(0x00000030)
#define TX_DMA_DST_CSR_DEST_AC3 FIELD32(0x000000c0)
#define TX_DMA_DST_CSR_DEST_MGMT FIELD32(0x00000300)
/*
* TX_CNTL_CSR: KICK/Abort TX.
@ -796,9 +866,14 @@ struct hw_pairwise_ta_entry {
#define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000)
/*
* LOAD_TX_RING_CSR
* LOAD_TX_RING_CSR: Load RX de
*/
#define LOAD_TX_RING_CSR 0x3434
#define LOAD_TX_RING_CSR_LOAD_TXD_AC0 FIELD32(0x00000001)
#define LOAD_TX_RING_CSR_LOAD_TXD_AC1 FIELD32(0x00000002)
#define LOAD_TX_RING_CSR_LOAD_TXD_AC2 FIELD32(0x00000004)
#define LOAD_TX_RING_CSR_LOAD_TXD_AC3 FIELD32(0x00000008)
#define LOAD_TX_RING_CSR_LOAD_TXD_MGMT FIELD32(0x00000010)
/*
* Several read-only registers, for debugging.
@ -828,6 +903,8 @@ struct hw_pairwise_ta_entry {
* RX_CNTL_CSR
*/
#define RX_CNTL_CSR 0x3458
#define RX_CNTL_CSR_ENABLE_RX_DMA FIELD32(0x00000001)
#define RX_CNTL_CSR_LOAD_RXD FIELD32(0x00000002)
/*
* RXPTR_CSR: Read-only, for debugging.
@ -981,10 +1058,45 @@ struct hw_pairwise_ta_entry {
#define FIRMWARE_RT2661 "rt2661.bin"
#define FIRMWARE_IMAGE_BASE 0x4000
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R2
*/
#define BBP_R2_BG_MODE FIELD8(0x20)
/*
* R3
*/
#define BBP_R3_SMART_MODE FIELD8(0x01)
/*
* R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x20)
/*
* R77
*/
#define BBP_R77_PAIR FIELD8(0x03)
/*
* RF registers
*/
/*
* RF 3
*/
#define RF3_TXPOWER FIELD32(0x00003e00)
/*
* RF 4
*/
#define RF4_FREQ_OFFSET FIELD32(0x0003f000)
/*
@ -1117,34 +1229,6 @@ struct hw_pairwise_ta_entry {
#define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff)
#define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R2
*/
#define BBP_R2_BG_MODE FIELD8(0x20)
/*
* BBP_R3
*/
#define BBP_R3_SMART_MODE FIELD8(0x01)
/*
* BBP_R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x10)
#define BBP_R4_RX_BG_MODE FIELD8(0x20)
/*
* BBP_R77
*/
#define BBP_R77_PAIR FIELD8(0x03)
/*
* MCU mailbox commands.
*/
@ -1290,7 +1374,7 @@ struct hw_pairwise_ta_entry {
#define RXD_W0_MULTICAST FIELD32(0x00000008)
#define RXD_W0_BROADCAST FIELD32(0x00000010)
#define RXD_W0_MY_BSS FIELD32(0x00000020)
#define RXD_W0_CRC FIELD32(0x00000040)
#define RXD_W0_CRC_ERROR FIELD32(0x00000040)
#define RXD_W0_OFDM FIELD32(0x00000080)
#define RXD_W0_CIPHER_ERROR FIELD32(0x00000300)
#define RXD_W0_KEY_INDEX FIELD32(0x0000fc00)

File diff suppressed because it is too large Load diff

View file

@ -37,9 +37,10 @@
/*
* Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 120
/*
@ -50,6 +51,7 @@
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100
#define BBP_SIZE 0x0080
#define RF_SIZE 0x0014
/*
* USB registers.
@ -172,7 +174,7 @@ struct hw_pairwise_ta_entry {
* MAC_CSR6: Maximum frame length register.
*/
#define MAC_CSR6 0x3018
#define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x000007ff)
#define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x00000fff)
/*
* MAC_CSR7: Reserved
@ -288,7 +290,7 @@ struct hw_pairwise_ta_entry {
#define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000)
#define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000)
#define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000)
#define TXRX_CSR0_DROP_BORADCAST FIELD32(0x01000000)
#define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000)
#define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000)
#define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000)
@ -296,16 +298,40 @@ struct hw_pairwise_ta_entry {
* TXRX_CSR1
*/
#define TXRX_CSR1 0x3044
#define TXRX_CSR1_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR1_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR1_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR1_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR1_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR1_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR1_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR1_BBP_ID3_VALID FIELD32(0x80000000)
/*
* TXRX_CSR2
*/
#define TXRX_CSR2 0x3048
#define TXRX_CSR2_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR2_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR2_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR2_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR2_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR2_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR2_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR2_BBP_ID3_VALID FIELD32(0x80000000)
/*
* TXRX_CSR3
*/
#define TXRX_CSR3 0x304c
#define TXRX_CSR3_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR3_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR3_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR3_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR3_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR3_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR3_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR3_BBP_ID3_VALID FIELD32(0x80000000)
/*
* TXRX_CSR4: Auto-Responder/Tx-retry register.
@ -332,11 +358,27 @@ struct hw_pairwise_ta_entry {
#define TXRX_CSR5 0x3054
/*
* ACK/CTS payload consumed time registers.
* TXRX_CSR6: ACK/CTS payload consumed time
*/
#define TXRX_CSR6 0x3058
/*
* TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
*/
#define TXRX_CSR7 0x305c
#define TXRX_CSR7_ACK_CTS_6MBS FIELD32(0x000000ff)
#define TXRX_CSR7_ACK_CTS_9MBS FIELD32(0x0000ff00)
#define TXRX_CSR7_ACK_CTS_12MBS FIELD32(0x00ff0000)
#define TXRX_CSR7_ACK_CTS_18MBS FIELD32(0xff000000)
/*
* TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
*/
#define TXRX_CSR8 0x3060
#define TXRX_CSR8_ACK_CTS_24MBS FIELD32(0x000000ff)
#define TXRX_CSR8_ACK_CTS_36MBS FIELD32(0x0000ff00)
#define TXRX_CSR8_ACK_CTS_48MBS FIELD32(0x00ff0000)
#define TXRX_CSR8_ACK_CTS_54MBS FIELD32(0xff000000)
/*
* TXRX_CSR9: Synchronization control register.
@ -403,7 +445,6 @@ struct hw_pairwise_ta_entry {
#define PHY_CSR1 0x3084
#define PHY_CSR1_RF_RPI FIELD32(0x00010000)
/*
* PHY_CSR2: Pre-TX BBP control.
*/
@ -441,11 +482,13 @@ struct hw_pairwise_ta_entry {
* PHY_CSR5: RX to TX signal switch timing control.
*/
#define PHY_CSR5 0x3094
#define PHY_CSR5_IQ_FLIP FIELD32(0x00000004)
/*
* PHY_CSR6: TX to RX signal timing control.
*/
#define PHY_CSR6 0x3098
#define PHY_CSR6_IQ_FLIP FIELD32(0x00000004)
/*
* PHY_CSR7: TX DAC switching timing control.
@ -460,6 +503,22 @@ struct hw_pairwise_ta_entry {
* SEC_CSR0: Shared key table control.
*/
#define SEC_CSR0 0x30a0
#define SEC_CSR0_BSS0_KEY0_VALID FIELD32(0x00000001)
#define SEC_CSR0_BSS0_KEY1_VALID FIELD32(0x00000002)
#define SEC_CSR0_BSS0_KEY2_VALID FIELD32(0x00000004)
#define SEC_CSR0_BSS0_KEY3_VALID FIELD32(0x00000008)
#define SEC_CSR0_BSS1_KEY0_VALID FIELD32(0x00000010)
#define SEC_CSR0_BSS1_KEY1_VALID FIELD32(0x00000020)
#define SEC_CSR0_BSS1_KEY2_VALID FIELD32(0x00000040)
#define SEC_CSR0_BSS1_KEY3_VALID FIELD32(0x00000080)
#define SEC_CSR0_BSS2_KEY0_VALID FIELD32(0x00000100)
#define SEC_CSR0_BSS2_KEY1_VALID FIELD32(0x00000200)
#define SEC_CSR0_BSS2_KEY2_VALID FIELD32(0x00000400)
#define SEC_CSR0_BSS2_KEY3_VALID FIELD32(0x00000800)
#define SEC_CSR0_BSS3_KEY0_VALID FIELD32(0x00001000)
#define SEC_CSR0_BSS3_KEY1_VALID FIELD32(0x00002000)
#define SEC_CSR0_BSS3_KEY2_VALID FIELD32(0x00004000)
#define SEC_CSR0_BSS3_KEY3_VALID FIELD32(0x00008000)
/*
* SEC_CSR1: Shared key table security mode register.
@ -635,10 +694,45 @@ struct hw_pairwise_ta_entry {
#define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff)
#define AC_TXOP_CSR1_AC3_TX_OP FIELD32(0xffff0000)
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R2
*/
#define BBP_R2_BG_MODE FIELD8(0x20)
/*
* R3
*/
#define BBP_R3_SMART_MODE FIELD8(0x01)
/*
* R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x20)
/*
* R77
*/
#define BBP_R77_PAIR FIELD8(0x03)
/*
* RF registers
*/
/*
* RF 3
*/
#define RF3_TXPOWER FIELD32(0x00003e00)
/*
* RF 4
*/
#define RF4_FREQ_OFFSET FIELD32(0x0003f000)
/*
@ -763,34 +857,6 @@ struct hw_pairwise_ta_entry {
#define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff)
#define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R2
*/
#define BBP_R2_BG_MODE FIELD8(0x20)
/*
* BBP_R3
*/
#define BBP_R3_SMART_MODE FIELD8(0x01)
/*
* BBP_R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x10)
#define BBP_R4_RX_BG_MODE FIELD8(0x20)
/*
* BBP_R77
*/
#define BBP_R77_PAIR FIELD8(0x03)
/*
* DMA descriptor defines.
*/
@ -888,7 +954,7 @@ struct hw_pairwise_ta_entry {
#define RXD_W0_MULTICAST FIELD32(0x00000008)
#define RXD_W0_BROADCAST FIELD32(0x00000010)
#define RXD_W0_MY_BSS FIELD32(0x00000020)
#define RXD_W0_CRC FIELD32(0x00000040)
#define RXD_W0_CRC_ERROR FIELD32(0x00000040)
#define RXD_W0_OFDM FIELD32(0x00000080)
#define RXD_W0_CIPHER_ERROR FIELD32(0x00000300)
#define RXD_W0_KEY_INDEX FIELD32(0x0000fc00)