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

This commit is contained in:
David S. Miller 2008-02-29 13:41:25 -08:00
Родитель 03a64c93b6 e486182907
Коммит 4a80f27889
147 изменённых файлов: 10673 добавлений и 8341 удалений

Просмотреть файл

@ -147,10 +147,13 @@ config IPW2100
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
If you want to compile the driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.txt>.
The module will be called ipw2100.ko.
It is recommended that you compile this driver as a module (M)
rather than built-in (Y). This driver requires firmware at device
initialization time, and when built-in this typically happens
before the filesystem is accessible (hence firmware will be
unavailable and initialization will fail). If you do choose to build
this driver into your kernel image, you can avoid this problem by
including the firmware and a firmware loader in an initramfs.
config IPW2100_MONITOR
bool "Enable promiscuous mode"
@ -202,10 +205,13 @@ config IPW2200
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
If you want to compile the driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.txt>.
The module will be called ipw2200.ko.
It is recommended that you compile this driver as a module (M)
rather than built-in (Y). This driver requires firmware at device
initialization time, and when built-in this typically happens
before the filesystem is accessible (hence firmware will be
unavailable and initialization will fail). If you do choose to build
this driver into your kernel image, you can avoid this problem by
including the firmware and a firmware loader in an initramfs.
config IPW2200_MONITOR
bool "Enable promiscuous mode"
@ -732,23 +738,7 @@ config P54_PCI
If you choose to build a module, it'll be called p54pci.
config ATH5K
tristate "Atheros 5xxx wireless cards support"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
---help---
This module adds support for wireless adapters based on
Atheros 5xxx chipset.
Currently the following chip versions are supported:
MAC: AR5211 AR5212
PHY: RF5111/2111 RF5112/2112 RF5413/2413
This driver uses the kernel's mac80211 subsystem.
If you choose to build a module, it'll be called ath5k. Say M if
unsure.
source "drivers/net/wireless/ath5k/Kconfig"
source "drivers/net/wireless/iwlwifi/Kconfig"
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"

Просмотреть файл

@ -48,6 +48,32 @@ static struct pci_device_id adm8211_pci_id_table[] __devinitdata = {
{ 0 }
};
static struct ieee80211_rate adm8211_rates[] = {
{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */
};
static const struct ieee80211_channel adm8211_channels[] = {
{ .center_freq = 2412},
{ .center_freq = 2417},
{ .center_freq = 2422},
{ .center_freq = 2427},
{ .center_freq = 2432},
{ .center_freq = 2437},
{ .center_freq = 2442},
{ .center_freq = 2447},
{ .center_freq = 2452},
{ .center_freq = 2457},
{ .center_freq = 2462},
{ .center_freq = 2467},
{ .center_freq = 2472},
{ .center_freq = 2484},
};
static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom)
{
struct adm8211_priv *priv = eeprom->data;
@ -155,17 +181,17 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev)
printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n",
pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max);
priv->modes[0].num_channels = chan_range.max - chan_range.min + 1;
priv->modes[0].channels = priv->channels;
BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels));
memcpy(priv->channels, adm8211_channels, sizeof(adm8211_channels));
memcpy(priv->channels, adm8211_channels, sizeof(priv->channels));
priv->band.channels = priv->channels;
priv->band.n_channels = ARRAY_SIZE(adm8211_channels);
priv->band.bitrates = adm8211_rates;
priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates);
for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++)
if (i >= chan_range.min && i <= chan_range.max)
priv->channels[i - 1].flag =
IEEE80211_CHAN_W_SCAN |
IEEE80211_CHAN_W_ACTIVE_SCAN |
IEEE80211_CHAN_W_IBSS;
if (i < chan_range.min || i > chan_range.max)
priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED;
switch (priv->eeprom->specific_bbptype) {
case ADM8211_BBP_RFMD3000:
@ -347,7 +373,6 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
unsigned int pktlen;
struct sk_buff *skb, *newskb;
unsigned int limit = priv->rx_ring_size;
static const u8 rate_tbl[] = {10, 20, 55, 110, 220};
u8 rssi, rate;
while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) {
@ -425,12 +450,10 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
else
rx_status.ssi = 100 - rssi;
if (rate <= 4)
rx_status.rate = rate_tbl[rate];
rx_status.rate_idx = rate;
rx_status.channel = priv->channel;
rx_status.freq = adm8211_channels[priv->channel - 1].freq;
rx_status.phymode = MODE_IEEE80211B;
rx_status.freq = adm8211_channels[priv->channel - 1].center_freq;
rx_status.band = IEEE80211_BAND_2GHZ;
ieee80211_rx_irqsafe(dev, skb, &rx_status);
}
@ -1054,7 +1077,7 @@ static int adm8211_set_rate(struct ieee80211_hw *dev)
if (priv->pdev->revision != ADM8211_REV_BA) {
rate_buf[0] = ARRAY_SIZE(adm8211_rates);
for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++)
rate_buf[i + 1] = (adm8211_rates[i].rate / 5) | 0x80;
rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80;
} else {
/* workaround for rev BA specific bug */
rate_buf[0] = 0x04;
@ -1086,7 +1109,7 @@ static void adm8211_hw_init(struct ieee80211_hw *dev)
u32 reg;
u8 cline;
reg = le32_to_cpu(ADM8211_CSR_READ(PAR));
reg = ADM8211_CSR_READ(PAR);
reg |= ADM8211_PAR_MRLE | ADM8211_PAR_MRME;
reg &= ~(ADM8211_PAR_BAR | ADM8211_PAR_CAL);
@ -1303,9 +1326,10 @@ static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len)
static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
struct adm8211_priv *priv = dev->priv;
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
if (conf->channel != priv->channel) {
priv->channel = conf->channel;
if (channel != priv->channel) {
priv->channel = channel;
adm8211_rf_set_channel(dev, priv->channel);
}
@ -1678,13 +1702,9 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
int plcp, dur, len, plcp_signal, short_preamble;
struct ieee80211_hdr *hdr;
if (control->tx_rate < 0) {
short_preamble = 1;
plcp_signal = -control->tx_rate;
} else {
short_preamble = 0;
plcp_signal = control->tx_rate;
}
short_preamble = !!(control->tx_rate->flags &
IEEE80211_TXCTL_SHORT_PREAMBLE);
plcp_signal = control->tx_rate->bitrate;
hdr = (struct ieee80211_hdr *)skb->data;
fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED;
@ -1880,18 +1900,11 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
SET_IEEE80211_PERM_ADDR(dev, perm_addr);
dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
dev->flags = IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
/* IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
dev->channel_change_time = 1000;
dev->max_rssi = 100; /* FIXME: find better value */
priv->modes[0].mode = MODE_IEEE80211B;
/* channel info filled in by adm8211_read_eeprom */
memcpy(priv->rates, adm8211_rates, sizeof(adm8211_rates));
priv->modes[0].num_rates = ARRAY_SIZE(adm8211_rates);
priv->modes[0].rates = priv->rates;
dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */
priv->retry_limit = 3;
@ -1917,14 +1930,9 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
goto err_free_desc;
}
priv->channel = priv->modes[0].channels[0].chan;
priv->channel = 1;
err = ieee80211_register_hwmode(dev, &priv->modes[0]);
if (err) {
printk(KERN_ERR "%s (adm8211): Can't register hwmode\n",
pci_name(pdev));
goto err_free_desc;
}
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
err = ieee80211_register_hw(dev);
if (err) {

Просмотреть файл

@ -534,61 +534,6 @@ struct adm8211_eeprom {
u8 cis_data[0]; /* 0x80, 384 bytes */
} __attribute__ ((packed));
static const struct ieee80211_rate adm8211_rates[] = {
{ .rate = 10,
.val = 10,
.val2 = -10,
.flags = IEEE80211_RATE_CCK_2 },
{ .rate = 20,
.val = 20,
.val2 = -20,
.flags = IEEE80211_RATE_CCK_2 },
{ .rate = 55,
.val = 55,
.val2 = -55,
.flags = IEEE80211_RATE_CCK_2 },
{ .rate = 110,
.val = 110,
.val2 = -110,
.flags = IEEE80211_RATE_CCK_2 }
};
struct ieee80211_chan_range {
u8 min;
u8 max;
};
static const struct ieee80211_channel adm8211_channels[] = {
{ .chan = 1,
.freq = 2412},
{ .chan = 2,
.freq = 2417},
{ .chan = 3,
.freq = 2422},
{ .chan = 4,
.freq = 2427},
{ .chan = 5,
.freq = 2432},
{ .chan = 6,
.freq = 2437},
{ .chan = 7,
.freq = 2442},
{ .chan = 8,
.freq = 2447},
{ .chan = 9,
.freq = 2452},
{ .chan = 10,
.freq = 2457},
{ .chan = 11,
.freq = 2462},
{ .chan = 12,
.freq = 2467},
{ .chan = 13,
.freq = 2472},
{ .chan = 14,
.freq = 2484},
};
struct adm8211_priv {
struct pci_dev *pdev;
spinlock_t lock;
@ -603,9 +548,8 @@ struct adm8211_priv {
unsigned int cur_tx, dirty_tx, cur_rx;
struct ieee80211_low_level_stats stats;
struct ieee80211_hw_mode modes[1];
struct ieee80211_channel channels[ARRAY_SIZE(adm8211_channels)];
struct ieee80211_rate rates[ARRAY_SIZE(adm8211_rates)];
struct ieee80211_supported_band band;
struct ieee80211_channel channels[14];
int mode;
int channel;
@ -643,6 +587,11 @@ struct adm8211_priv {
} transceiver_type;
};
struct ieee80211_chan_range {
u8 min;
u8 max;
};
static const struct ieee80211_chan_range cranges[] = {
{1, 11}, /* FCC */
{1, 11}, /* IC */

Просмотреть файл

@ -0,0 +1,37 @@
config ATH5K
tristate "Atheros 5xxx wireless cards support"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
---help---
This module adds support for wireless adapters based on
Atheros 5xxx chipset.
Currently the following chip versions are supported:
MAC: AR5211 AR5212
PHY: RF5111/2111 RF5112/2112 RF5413/2413
This driver uses the kernel's mac80211 subsystem.
If you choose to build a module, it'll be called ath5k. Say M if
unsure.
config ATH5K_DEBUG
bool "Atheros 5xxx debugging"
depends on ATH5K
---help---
Atheros 5xxx debugging messages.
Say Y, if and you will get debug options for ath5k.
To use this, you need to mount debugfs:
mkdir /debug/
mount -t debugfs debug /debug/
You will get access to files under:
/debug/ath5k/phy0/
To enable debug, pass the debug level to the debug module
parameter. For example:
modprobe ath5k debug=0x00000400

Просмотреть файл

@ -1,2 +1,6 @@
ath5k-objs = base.o hw.o regdom.o initvals.o phy.o debug.o
ath5k-y += base.o
ath5k-y += hw.o
ath5k-y += initvals.o
ath5k-y += phy.o
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
obj-$(CONFIG_ATH5K) += ath5k.o

Просмотреть файл

@ -30,7 +30,6 @@
#include <net/mac80211.h>
#include "hw.h"
#include "regdom.h"
/* PCI IDs */
#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
@ -251,19 +250,23 @@ struct ath5k_srev_name {
*/
#define MODULATION_TURBO 0x00000080
enum ath5k_vendor_mode {
MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1,
MODE_ATHEROS_TURBOG
enum ath5k_driver_mode {
AR5K_MODE_11A = 0,
AR5K_MODE_11A_TURBO = 1,
AR5K_MODE_11B = 2,
AR5K_MODE_11G = 3,
AR5K_MODE_11G_TURBO = 4,
AR5K_MODE_XR = 0,
AR5K_MODE_MAX = 5
};
/* Number of supported mac80211 enum ieee80211_phymode modes by this driver */
#define NUM_DRIVER_MODES 3
/* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
#define AR5K_SET_SHORT_PREAMBLE 0x04
#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_CCK_2)
#define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
#define HAS_SHPREAMBLE(_ix) \
(rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE)
#define SHPREAMBLE_FLAG(_ix) \
(HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
/****************\
TX DEFINITIONS
@ -560,8 +563,8 @@ struct ath5k_desc {
* Used internaly in OpenHAL (ar5211.c/ar5212.c
* for reset_tx_queue). Also see struct struct ieee80211_channel.
*/
#define IS_CHAN_XR(_c) ((_c.val & CHANNEL_XR) != 0)
#define IS_CHAN_B(_c) ((_c.val & CHANNEL_B) != 0)
#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0)
#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0)
/*
* The following structure will be used to map 2GHz channels to
@ -584,7 +587,7 @@ struct ath5k_athchan_2ghz {
/**
* struct ath5k_rate - rate structure
* @valid: is this a valid rate for the current mode
* @valid: is this a valid rate for rate control (remove)
* @modulation: respective mac80211 modulation
* @rate_kbps: rate in kbit/s
* @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
@ -643,47 +646,48 @@ struct ath5k_rate_table {
/*
* Rate tables...
* TODO: CLEAN THIS !!!
*/
#define AR5K_RATES_11A { 8, { \
255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
255, 255, 255, 255, 255, 255, 255, 255 }, { \
{ 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 0 }, \
{ 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 }, \
{ 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 }, \
{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 }, \
{ 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 }, \
{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 }, \
{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 }, \
{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } } \
{ 1, 0, 6000, 11, 140, 0 }, \
{ 1, 0, 9000, 15, 18, 0 }, \
{ 1, 0, 12000, 10, 152, 2 }, \
{ 1, 0, 18000, 14, 36, 2 }, \
{ 1, 0, 24000, 9, 176, 4 }, \
{ 1, 0, 36000, 13, 72, 4 }, \
{ 1, 0, 48000, 8, 96, 4 }, \
{ 1, 0, 54000, 12, 108, 4 } } \
}
#define AR5K_RATES_11B { 4, { \
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
3, 2, 1, 0, 255, 255, 255, 255 }, { \
{ 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 }, \
{ 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 }, \
{ 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 }, \
{ 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } } \
{ 1, 0, 1000, 27, 130, 0 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 132, 1 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 139, 1 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 150, 1 } } \
}
#define AR5K_RATES_11G { 12, { \
255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \
11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
3, 2, 1, 0, 255, 255, 255, 255 }, { \
{ 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 }, \
{ 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 }, \
{ 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 }, \
{ 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 }, \
{ 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 }, \
{ 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
{ 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 }, \
{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
{ 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 }, \
{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
{ 1, 0, 1000, 27, 2, 0 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 4, 1 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 11, 1 }, \
{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 22, 1 }, \
{ 0, 0, 6000, 11, 12, 4 }, \
{ 0, 0, 9000, 15, 18, 4 }, \
{ 1, 0, 12000, 10, 24, 6 }, \
{ 1, 0, 18000, 14, 36, 6 }, \
{ 1, 0, 24000, 9, 48, 8 }, \
{ 1, 0, 36000, 13, 72, 8 }, \
{ 1, 0, 48000, 8, 96, 8 }, \
{ 1, 0, 54000, 12, 108, 8 } } \
}
#define AR5K_RATES_TURBO { 8, { \
@ -708,14 +712,14 @@ struct ath5k_rate_table {
{ 1, MODULATION_XR, 1000, 2, 139, 1 }, \
{ 1, MODULATION_XR, 2000, 6, 150, 2 }, \
{ 1, MODULATION_XR, 3000, 1, 150, 3 }, \
{ 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 }, \
{ 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
{ 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 }, \
{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
{ 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 }, \
{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
{ 1, 0, 6000, 11, 140, 4 }, \
{ 1, 0, 9000, 15, 18, 4 }, \
{ 1, 0, 12000, 10, 152, 6 }, \
{ 1, 0, 18000, 14, 36, 6 }, \
{ 1, 0, 24000, 9, 176, 8 }, \
{ 1, 0, 36000, 13, 72, 8 }, \
{ 1, 0, 48000, 8, 96, 8 }, \
{ 1, 0, 54000, 12, 108, 8 } } \
}
/*
@ -890,12 +894,14 @@ enum ath5k_capability_type {
AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
};
/* XXX: we *may* move cap_range stuff to struct wiphy */
struct ath5k_capabilities {
/*
* Supported PHY modes
* (ie. CHANNEL_A, CHANNEL_B, ...)
*/
DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES);
DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
/*
* Frequency range (without regulation restrictions)
@ -907,14 +913,6 @@ struct ath5k_capabilities {
u16 range_5ghz_max;
} cap_range;
/*
* Active regulation domain settings
*/
struct {
enum ath5k_regdom reg_current;
enum ath5k_regdom reg_hw;
} cap_regdomain;
/*
* Values stored in the EEPROM (some of them...)
*/
@ -1129,8 +1127,6 @@ extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
/* Regulatory Domain/Channels Setup */
extern u16 ath5k_get_regdomain(struct ath5k_hw *ah);
/* Misc functions */
extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);

Просмотреть файл

@ -80,7 +80,7 @@ MODULE_AUTHOR("Nick Kossifidis");
MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION("0.1.1 (EXPERIMENTAL)");
MODULE_VERSION("0.5.0 (EXPERIMENTAL)");
/* Known PCI ids */
@ -240,6 +240,8 @@ static int ath5k_chan_set(struct ath5k_softc *sc,
static void ath5k_setcurmode(struct ath5k_softc *sc,
unsigned int mode);
static void ath5k_mode_setup(struct ath5k_softc *sc);
static void ath5k_set_total_hw_rates(struct ath5k_softc *sc);
/* Descriptor setup */
static int ath5k_desc_alloc(struct ath5k_softc *sc,
struct pci_dev *pdev);
@ -511,34 +513,45 @@ ath5k_pci_probe(struct pci_dev *pdev,
sc->ah->ah_mac_srev,
sc->ah->ah_phy_revision);
if(!sc->ah->ah_single_chip){
if (!sc->ah->ah_single_chip) {
/* Single chip radio (!RF5111) */
if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) {
if (sc->ah->ah_radio_5ghz_revision &&
!sc->ah->ah_radio_2ghz_revision) {
/* No 5GHz support -> report 2GHz radio */
if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){
if (!test_bit(AR5K_MODE_11A,
sc->ah->ah_capabilities.cap_mode)) {
ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
ath5k_chip_name(AR5K_VERSION_RAD,
sc->ah->ah_radio_5ghz_revision),
sc->ah->ah_radio_5ghz_revision);
/* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */
} else if(!test_bit(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){
/* No 2GHz support (5110 and some
* 5Ghz only cards) -> report 5Ghz radio */
} else if (!test_bit(AR5K_MODE_11B,
sc->ah->ah_capabilities.cap_mode)) {
ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
ath5k_chip_name(AR5K_VERSION_RAD,
sc->ah->ah_radio_5ghz_revision),
sc->ah->ah_radio_5ghz_revision);
/* Multiband radio */
} else {
ATH5K_INFO(sc, "RF%s multiband radio found"
" (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
ath5k_chip_name(AR5K_VERSION_RAD,
sc->ah->ah_radio_5ghz_revision),
sc->ah->ah_radio_5ghz_revision);
}
}
/* Multi chip radio (RF5111 - RF2111) -> report both 2GHz/5GHz radios */
else if(sc->ah->ah_radio_5ghz_revision && sc->ah->ah_radio_2ghz_revision){
/* Multi chip radio (RF5111 - RF2111) ->
* report both 2GHz/5GHz radios */
else if (sc->ah->ah_radio_5ghz_revision &&
sc->ah->ah_radio_2ghz_revision){
ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
ath5k_chip_name(AR5K_VERSION_RAD,
sc->ah->ah_radio_5ghz_revision),
sc->ah->ah_radio_5ghz_revision);
ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_2ghz_revision),
ath5k_chip_name(AR5K_VERSION_RAD,
sc->ah->ah_radio_2ghz_revision),
sc->ah->ah_radio_2ghz_revision);
}
}
@ -693,11 +706,14 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
goto err;
}
/* Set *_rates so we can map hw rate index */
ath5k_set_total_hw_rates(sc);
/* NB: setup here so ath5k_rate_update is happy */
if (test_bit(MODE_IEEE80211A, ah->ah_modes))
ath5k_setcurmode(sc, MODE_IEEE80211A);
if (test_bit(AR5K_MODE_11A, ah->ah_modes))
ath5k_setcurmode(sc, AR5K_MODE_11A);
else
ath5k_setcurmode(sc, MODE_IEEE80211B);
ath5k_setcurmode(sc, AR5K_MODE_11B);
/*
* Allocate tx+rx descriptors and populate the lists.
@ -837,12 +853,9 @@ ath5k_copy_rates(struct ieee80211_rate *rates,
return 0;
for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
if (!rt->rates[i].valid)
continue;
rates->rate = rt->rates[i].rate_kbps / 100;
rates->val = rt->rates[i].rate_code;
rates->flags = rt->rates[i].modulation;
rates++;
rates[count].bitrate = rt->rates[i].rate_kbps / 100;
rates[count].hw_value = rt->rates[i].rate_code;
rates[count].flags = rt->rates[i].modulation;
count++;
max--;
}
@ -856,43 +869,22 @@ ath5k_copy_channels(struct ath5k_hw *ah,
unsigned int mode,
unsigned int max)
{
static const struct { unsigned int mode, mask, chan; } map[] = {
[MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A },
[MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T },
[MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B },
[MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G },
[MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG },
};
static const struct ath5k_regchannel chans_2ghz[] =
IEEE80211_CHANNELS_2GHZ;
static const struct ath5k_regchannel chans_5ghz[] =
IEEE80211_CHANNELS_5GHZ;
const struct ath5k_regchannel *chans;
enum ath5k_regdom dmn;
unsigned int i, count, size, chfreq, all, f, ch;
unsigned int i, count, size, chfreq, freq, ch;
if (!test_bit(mode, ah->ah_modes))
return 0;
all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1;
switch (mode) {
case MODE_IEEE80211A:
case MODE_ATHEROS_TURBO:
case AR5K_MODE_11A:
case AR5K_MODE_11A_TURBO:
/* 1..220, but 2GHz frequencies are filtered by check_channel */
size = all ? 220 : ARRAY_SIZE(chans_5ghz);
chans = chans_5ghz;
dmn = ath5k_regdom2flag(ah->ah_regdomain,
IEEE80211_CHANNELS_5GHZ_MIN);
size = 220 ;
chfreq = CHANNEL_5GHZ;
break;
case MODE_IEEE80211B:
case MODE_IEEE80211G:
case MODE_ATHEROS_TURBOG:
size = all ? 26 : ARRAY_SIZE(chans_2ghz);
chans = chans_2ghz;
dmn = ath5k_regdom2flag(ah->ah_regdomain,
IEEE80211_CHANNELS_2GHZ_MIN);
case AR5K_MODE_11B:
case AR5K_MODE_11G:
case AR5K_MODE_11G_TURBO:
size = 26;
chfreq = CHANNEL_2GHZ;
break;
default:
@ -901,25 +893,31 @@ ath5k_copy_channels(struct ath5k_hw *ah,
}
for (i = 0, count = 0; i < size && max > 0; i++) {
ch = all ? i + 1 : chans[i].chan;
f = ath5k_ieee2mhz(ch);
ch = i + 1 ;
freq = ath5k_ieee2mhz(ch);
/* Check if channel is supported by the chipset */
if (!ath5k_channel_ok(ah, f, chfreq))
if (!ath5k_channel_ok(ah, freq, chfreq))
continue;
/* Match regulation domain */
if (!all && !(IEEE80211_DMN(chans[i].domain) &
IEEE80211_DMN(dmn)))
continue;
/* Write channel info and increment counter */
channels[count].center_freq = freq;
channels[count].band = (chfreq == CHANNEL_2GHZ) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
switch (mode) {
case AR5K_MODE_11A:
case AR5K_MODE_11G:
channels[count].hw_value = chfreq | CHANNEL_OFDM;
break;
case AR5K_MODE_11A_TURBO:
case AR5K_MODE_11G_TURBO:
channels[count].hw_value = chfreq |
CHANNEL_OFDM | CHANNEL_TURBO;
break;
case AR5K_MODE_11B:
channels[count].hw_value = CHANNEL_B;
}
if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode)
continue;
/* Write channel and increment counter */
channels->chan = ch;
channels->freq = f;
channels->val = map[mode].chan;
channels++;
count++;
max--;
}
@ -927,95 +925,78 @@ ath5k_copy_channels(struct ath5k_hw *ah,
return count;
}
/* Only tries to register modes our EEPROM says it can support */
#define REGISTER_MODE(m) do { \
ret = ath5k_register_mode(hw, m); \
if (ret) \
return ret; \
} while (0) \
static inline int
ath5k_register_mode(struct ieee80211_hw *hw, u8 m)
{
struct ath5k_softc *sc = hw->priv;
struct ieee80211_hw_mode *modes = sc->modes;
unsigned int i;
int ret;
if (!test_bit(m, sc->ah->ah_capabilities.cap_mode))
return 0;
for (i = 0; i < NUM_DRIVER_MODES; i++) {
if (modes[i].mode != m || !modes[i].num_channels)
continue;
ret = ieee80211_register_hwmode(hw, &modes[i]);
if (ret) {
ATH5K_ERR(sc, "can't register hwmode %u\n", m);
return ret;
}
return 0;
}
BUG();
}
static int
ath5k_getchannels(struct ieee80211_hw *hw)
{
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
struct ieee80211_hw_mode *modes = sc->modes;
unsigned int i, max_r, max_c;
int ret;
struct ieee80211_supported_band *sbands = sc->sbands;
const struct ath5k_rate_table *hw_rates;
unsigned int max_r, max_c, count_r, count_c;
int mode2g = AR5K_MODE_11G;
BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
/* The order here does not matter */
modes[0].mode = MODE_IEEE80211G;
modes[1].mode = MODE_IEEE80211B;
modes[2].mode = MODE_IEEE80211A;
BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
max_r = ARRAY_SIZE(sc->rates);
max_c = ARRAY_SIZE(sc->channels);
count_r = count_c = 0;
for (i = 0; i < NUM_DRIVER_MODES; i++) {
struct ieee80211_hw_mode *mode = &modes[i];
const struct ath5k_rate_table *hw_rates;
if (i == 0) {
modes[0].rates = sc->rates;
modes->channels = sc->channels;
} else {
struct ieee80211_hw_mode *prev_mode = &modes[i-1];
int prev_num_r = prev_mode->num_rates;
int prev_num_c = prev_mode->num_channels;
mode->rates = &prev_mode->rates[prev_num_r];
mode->channels = &prev_mode->channels[prev_num_c];
/* 2GHz band */
if (!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
mode2g = AR5K_MODE_11B;
if (!test_bit(AR5K_MODE_11B,
sc->ah->ah_capabilities.cap_mode))
mode2g = -1;
}
hw_rates = ath5k_hw_get_rate_table(ah, mode->mode);
mode->num_rates = ath5k_copy_rates(mode->rates, hw_rates,
max_r);
mode->num_channels = ath5k_copy_channels(ah, mode->channels,
mode->mode, max_c);
max_r -= mode->num_rates;
max_c -= mode->num_channels;
if (mode2g > 0) {
struct ieee80211_supported_band *sband =
&sbands[IEEE80211_BAND_2GHZ];
sband->bitrates = sc->rates;
sband->channels = sc->channels;
sband->band = IEEE80211_BAND_2GHZ;
sband->n_channels = ath5k_copy_channels(ah, sband->channels,
mode2g, max_c);
hw_rates = ath5k_hw_get_rate_table(ah, mode2g);
sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
hw_rates, max_r);
count_c = sband->n_channels;
count_r = sband->n_bitrates;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
max_r -= count_r;
max_c -= count_c;
}
/* We try to register all modes this driver supports. We don't bother
* with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts
* for that as per mac80211. Then, REGISTER_MODE() will will actually
* check the eeprom reading for more reliable capability information.
* Order matters here as per mac80211's latest preference. This will
* all hopefullly soon go away. */
/* 5GHz band */
REGISTER_MODE(MODE_IEEE80211G);
if (ah->ah_version != AR5K_AR5212)
REGISTER_MODE(MODE_IEEE80211B);
REGISTER_MODE(MODE_IEEE80211A);
if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
struct ieee80211_supported_band *sband =
&sbands[IEEE80211_BAND_5GHZ];
ath5k_debug_dump_modes(sc, modes);
sband->bitrates = &sc->rates[count_r];
sband->channels = &sc->channels[count_c];
return ret;
sband->band = IEEE80211_BAND_5GHZ;
sband->n_channels = ath5k_copy_channels(ah, sband->channels,
AR5K_MODE_11A, max_c);
hw_rates = ath5k_hw_get_rate_table(ah, AR5K_MODE_11A);
sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
hw_rates, max_r);
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
}
ath5k_debug_dump_bands(sc);
return 0;
}
/*
@ -1030,11 +1011,15 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
struct ath5k_hw *ah = sc->ah;
int ret;
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n",
sc->curchan->chan, sc->curchan->freq,
chan->chan, chan->freq);
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
sc->curchan->center_freq, chan->center_freq);
if (chan->center_freq != sc->curchan->center_freq ||
chan->hw_value != sc->curchan->hw_value) {
sc->curchan = chan;
sc->curband = &sc->sbands[chan->band];
if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) {
/*
* To switch channels clear any pending DMA operations;
* wait long enough for the RX fifo to drain, reset the
@ -1044,13 +1029,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
ath5k_hw_set_intr(ah, 0); /* disable interrupts */
ath5k_txq_cleanup(sc); /* clear pending tx frames */
ath5k_rx_stop(sc); /* turn off frame recv */
ret = ath5k_hw_reset(ah, sc->opmode, chan, true);
ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
if (ret) {
ATH5K_ERR(sc, "%s: unable to reset channel %u "
"(%u Mhz)\n", __func__, chan->chan, chan->freq);
ATH5K_ERR(sc, "%s: unable to reset channel "
"(%u Mhz)\n", __func__, chan->center_freq);
return ret;
}
sc->curchan = chan;
ath5k_hw_set_txpower_limit(sc->ah, 0);
/*
@ -1081,6 +1066,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
return 0;
}
/*
* TODO: CLEAN THIS !!!
*/
static void
ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
{
@ -1121,10 +1109,6 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
continue;
}
sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation ==
IEEE80211_RATE_OFDM)
sc->hwmap[i].txflags |=
IEEE80211_RADIOTAP_F_SHORTPRE;
/* receive frames include FCS */
sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
IEEE80211_RADIOTAP_F_FCS;
@ -1142,6 +1126,12 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
}
sc->curmode = mode;
if (mode == AR5K_MODE_11A) {
sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
} else {
sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
}
}
static void
@ -1164,6 +1154,72 @@ ath5k_mode_setup(struct ath5k_softc *sc)
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
}
/*
* Match the hw provided rate index (through descriptors)
* to an index for sc->curband->bitrates, so it can be used
* by the stack.
*
* This one is a little bit tricky but i think i'm right
* about this...
*
* We have 4 rate tables in the following order:
* XR (4 rates)
* 802.11a (8 rates)
* 802.11b (4 rates)
* 802.11g (12 rates)
* that make the hw rate table.
*
* Lets take a 5211 for example that supports a and b modes only.
* First comes the 802.11a table and then 802.11b (total 12 rates).
* When hw returns eg. 11 it points to the last 802.11b rate (11Mbit),
* if it returns 2 it points to the second 802.11a rate etc.
*
* Same goes for 5212 who has xr/a/b/g support (total 28 rates).
* First comes the XR table, then 802.11a, 802.11b and 802.11g.
* When hw returns eg. 27 it points to the last 802.11g rate (54Mbits) etc
*/
static void
ath5k_set_total_hw_rates(struct ath5k_softc *sc) {
struct ath5k_hw *ah = sc->ah;
if (test_bit(AR5K_MODE_11A, ah->ah_modes))
sc->a_rates = 8;
if (test_bit(AR5K_MODE_11B, ah->ah_modes))
sc->b_rates = 4;
if (test_bit(AR5K_MODE_11G, ah->ah_modes))
sc->g_rates = 12;
/* XXX: Need to see what what happens when
xr disable bits in eeprom are set */
if (ah->ah_version >= AR5K_AR5212)
sc->xr_rates = 4;
}
static inline int
ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) {
int mac80211_rix;
if(sc->curband->band == IEEE80211_BAND_2GHZ) {
/* We setup a g ratetable for both b/g modes */
mac80211_rix =
hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates;
} else {
mac80211_rix = hw_rix - sc->xr_rates;
}
/* Something went wrong, fallback to basic rate for this band */
if ((mac80211_rix >= sc->curband->n_bitrates) ||
(mac80211_rix <= 0 ))
mac80211_rix = 1;
return mac80211_rix;
}
@ -1268,7 +1324,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
(ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0);
(sc->power_level * 2), ctl->tx_rate->hw_value,
ctl->retry_limit, keyidx, 0, flags, 0, 0);
if (ret)
goto err_unmap;
@ -1660,11 +1717,11 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
u32 hw_tu;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
if ((mgmt->frame_control & IEEE80211_FCTL_FTYPE) ==
if ((le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_FTYPE) ==
IEEE80211_FTYPE_MGMT &&
(mgmt->frame_control & IEEE80211_FCTL_STYPE) ==
(le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) ==
IEEE80211_STYPE_BEACON &&
mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS &&
le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
/*
* Received an IBSS beacon with the same BSSID. Hardware might
@ -1673,7 +1730,7 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
if (hw_tu >= sc->nexttbtt) {
ath5k_beacon_update_timers(sc,
mgmt->u.beacon.timestamp);
le64_to_cpu(mgmt->u.beacon.timestamp));
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
"detected HW merge from received beacon\n");
}
@ -1791,9 +1848,8 @@ accept:
rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
rxs.flag |= RX_FLAG_TSFT;
rxs.freq = sc->curchan->freq;
rxs.channel = sc->curchan->chan;
rxs.phymode = sc->curmode;
rxs.freq = sc->curchan->center_freq;
rxs.band = sc->curband->band;
/*
* signal quality:
@ -1811,7 +1867,8 @@ accept:
rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
rxs.antenna = ds->ds_rxstat.rs_antenna;
rxs.rate = ds->ds_rxstat.rs_rate;
rxs.rate_idx = ath5k_hw_to_driver_rix(sc,
ds->ds_rxstat.rs_rate);
rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
ath5k_debug_dump_skb(sc, skb, "RX ", 0);
@ -1958,8 +2015,9 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
ds->ds_data = bf->skbaddr;
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
ieee80211_get_hdrlen_from_skb(skb),
AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1,
AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
ctl->tx_rate->hw_value, 1, AR5K_TXKEYIX_INVALID,
antenna, flags, 0, 0);
if (ret)
goto err_unmap;
@ -2211,7 +2269,8 @@ ath5k_init(struct ath5k_softc *sc)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
sc->curchan = sc->hw->conf.chan;
sc->curchan = sc->hw->conf.channel;
sc->curband = &sc->sbands[sc->curchan->band];
ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false);
if (ret) {
ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
@ -2448,7 +2507,8 @@ ath5k_calibrate(unsigned long data)
struct ath5k_hw *ah = sc->ah;
ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
sc->curchan->chan, sc->curchan->val);
ieee80211_frequency_to_channel(sc->curchan->center_freq),
sc->curchan->hw_value);
if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) {
/*
@ -2460,7 +2520,8 @@ ath5k_calibrate(unsigned long data)
}
if (ath5k_hw_phy_calibrate(ah, sc->curchan))
ATH5K_ERR(sc, "calibration of channel %u failed\n",
sc->curchan->chan);
ieee80211_frequency_to_channel(
sc->curchan->center_freq));
mod_timer(&sc->calib_tim, round_jiffies(jiffies +
msecs_to_jiffies(ath5k_calinterval * 1000)));
@ -2558,7 +2619,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
memmove(skb->data, skb->data+pad, hdrlen);
}
sc->led_txrate = ctl->tx_rate;
sc->led_txrate = ctl->tx_rate->hw_value;
spin_lock_irqsave(&sc->txbuflock, flags);
if (list_empty(&sc->txbuf)) {
@ -2597,11 +2658,6 @@ ath5k_reset(struct ieee80211_hw *hw)
int ret;
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
/*
* Convert to a hw channel description with the flags
* constrained to reflect the current operating mode.
*/
sc->curchan = hw->conf.chan;
ath5k_hw_set_intr(ah, 0);
ath5k_txq_cleanup(sc);
@ -2692,6 +2748,9 @@ end:
mutex_unlock(&sc->lock);
}
/*
* TODO: Phy disable/diversity etc
*/
static int
ath5k_config(struct ieee80211_hw *hw,
struct ieee80211_conf *conf)
@ -2699,9 +2758,9 @@ ath5k_config(struct ieee80211_hw *hw,
struct ath5k_softc *sc = hw->priv;
sc->bintval = conf->beacon_int;
ath5k_setcurmode(sc, conf->phymode);
sc->power_level = conf->power_level;
return ath5k_chan_set(sc, conf->chan);
return ath5k_chan_set(sc, conf->channel);
}
static int
@ -2869,7 +2928,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch(key->alg) {
case ALG_WEP:
break;
/* XXX: fix hardware encryption, its not working. For now
* allow software encryption */
/* break; */
case ALG_TKIP:
case ALG_CCMP:
return -EOPNOTSUPP;

Просмотреть файл

@ -83,7 +83,7 @@ struct ath5k_txq {
#if CHAN_DEBUG
#define ATH_CHAN_MAX (26+26+26+200+200)
#else
#define ATH_CHAN_MAX (14+14+14+252+20) /* XXX what's the max? */
#define ATH_CHAN_MAX (14+14+14+252+20)
#endif
/* Software Carrier, keeps track of the driver state
@ -95,15 +95,22 @@ struct ath5k_softc {
struct ieee80211_tx_queue_stats tx_stats;
struct ieee80211_low_level_stats ll_stats;
struct ieee80211_hw *hw; /* IEEE 802.11 common */
struct ieee80211_hw_mode modes[NUM_DRIVER_MODES];
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ieee80211_channel channels[ATH_CHAN_MAX];
struct ieee80211_rate rates[AR5K_MAX_RATES * NUM_DRIVER_MODES];
struct ieee80211_rate rates[AR5K_MAX_RATES * IEEE80211_NUM_BANDS];
enum ieee80211_if_types opmode;
struct ath5k_hw *ah; /* Atheros HW */
#if ATH5K_DEBUG
struct ieee80211_supported_band *curband;
u8 a_rates;
u8 b_rates;
u8 g_rates;
u8 xr_rates;
#ifdef CONFIG_ATH5K_DEBUG
struct ath5k_dbg_info debug; /* debug info */
#endif
#endif /* CONFIG_ATH5K_DEBUG */
struct ath5k_buf *bufptr; /* allocated buffer ptr */
struct ath5k_desc *desc; /* TX/RX descriptors */
@ -169,6 +176,7 @@ struct ath5k_softc {
unsigned int nexttbtt; /* next beacon time in TU */
struct timer_list calib_tim; /* calibration timer */
int power_level; /* Requested tx power in dbm */
};
#define ath5k_hw_hasbssidmask(_ah) \

Просмотреть файл

@ -65,7 +65,7 @@ static unsigned int ath5k_debug;
module_param_named(debug, ath5k_debug, uint, 0);
#if ATH5K_DEBUG
#ifdef CONFIG_ATH5K_DEBUG
#include <linux/seq_file.h>
#include "reg.h"
@ -340,7 +340,7 @@ static struct {
{ ATH5K_DEBUG_LED, "led", "LED mamagement" },
{ ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" },
{ ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" },
{ ATH5K_DEBUG_DUMPMODES, "dumpmodes", "dump modes" },
{ ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
{ ATH5K_DEBUG_TRACE, "trace", "trace function calls" },
{ ATH5K_DEBUG_ANY, "all", "show all debug levels" },
};
@ -452,30 +452,47 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
/* functions used in other places */
void
ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes)
ath5k_debug_dump_bands(struct ath5k_softc *sc)
{
unsigned int m, i;
unsigned int b, i;
if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES)))
if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
return;
for (m = 0; m < NUM_DRIVER_MODES; m++) {
printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m,
modes[m].num_channels, modes[m].num_rates);
BUG_ON(!sc->sbands);
for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
struct ieee80211_supported_band *band = &sc->sbands[b];
char bname[5];
switch (band->band) {
case IEEE80211_BAND_2GHZ:
strcpy(bname, "2 GHz");
break;
case IEEE80211_BAND_5GHZ:
strcpy(bname, "5 GHz");
break;
default:
printk(KERN_DEBUG "Band not supported: %d\n",
band->band);
return;
}
printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
band->n_channels, band->n_bitrates);
printk(KERN_DEBUG " channels:\n");
for (i = 0; i < modes[m].num_channels; i++)
for (i = 0; i < band->n_channels; i++)
printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
modes[m].channels[i].chan,
modes[m].channels[i].freq,
modes[m].channels[i].val,
modes[m].channels[i].flag);
ieee80211_frequency_to_channel(
band->channels[i].center_freq),
band->channels[i].center_freq,
band->channels[i].hw_value,
band->channels[i].flags);
printk(KERN_DEBUG " rates:\n");
for (i = 0; i < modes[m].num_rates; i++)
for (i = 0; i < band->n_bitrates; i++)
printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
modes[m].rates[i].rate,
modes[m].rates[i].val,
modes[m].rates[i].flags,
modes[m].rates[i].val2);
band->bitrates[i].bitrate,
band->bitrates[i].hw_value,
band->bitrates[i].flags,
band->bitrates[i].hw_value_short);
}
}
@ -548,4 +565,4 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc,
!done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
}
#endif /* if ATH5K_DEBUG */
#endif /* ifdef CONFIG_ATH5K_DEBUG */

Просмотреть файл

@ -61,11 +61,6 @@
#ifndef _ATH5K_DEBUG_H
#define _ATH5K_DEBUG_H
/* set this to 1 for debugging output */
#ifndef ATH5K_DEBUG
#define ATH5K_DEBUG 0
#endif
struct ath5k_softc;
struct ath5k_hw;
struct ieee80211_hw_mode;
@ -96,7 +91,7 @@ struct ath5k_dbg_info {
* @ATH5K_DEBUG_LED: led management
* @ATH5K_DEBUG_DUMP_RX: print received skb content
* @ATH5K_DEBUG_DUMP_TX: print transmit skb content
* @ATH5K_DEBUG_DUMPMODES: dump modes
* @ATH5K_DEBUG_DUMPBANDS: dump bands
* @ATH5K_DEBUG_TRACE: trace function calls
* @ATH5K_DEBUG_ANY: show at any debug level
*
@ -118,12 +113,12 @@ enum ath5k_debug_level {
ATH5K_DEBUG_LED = 0x00000080,
ATH5K_DEBUG_DUMP_RX = 0x00000100,
ATH5K_DEBUG_DUMP_TX = 0x00000200,
ATH5K_DEBUG_DUMPMODES = 0x00000400,
ATH5K_DEBUG_DUMPBANDS = 0x00000400,
ATH5K_DEBUG_TRACE = 0x00001000,
ATH5K_DEBUG_ANY = 0xffffffff
};
#if ATH5K_DEBUG
#ifdef CONFIG_ATH5K_DEBUG
#define ATH5K_TRACE(_sc) do { \
if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
@ -158,8 +153,7 @@ void
ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
void
ath5k_debug_dump_modes(struct ath5k_softc *sc,
struct ieee80211_hw_mode *modes);
ath5k_debug_dump_bands(struct ath5k_softc *sc);
void
ath5k_debug_dump_skb(struct ath5k_softc *sc,
@ -171,7 +165,9 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc,
#else /* no debugging */
#define ATH5K_TRACE(_sc) /* empty */
#include <linux/compiler.h>
#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
static inline void __attribute__ ((format (printf, 3, 4)))
ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
@ -196,8 +192,7 @@ static inline void
ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
static inline void
ath5k_debug_dump_modes(struct ath5k_softc *sc,
struct ieee80211_hw_mode *modes) {}
ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
static inline void
ath5k_debug_dump_skb(struct ath5k_softc *sc,
@ -207,6 +202,6 @@ static inline void
ath5k_debug_printtxbuf(struct ath5k_softc *sc,
struct ath5k_buf *bf, int done) {}
#endif /* if ATH5K_DEBUG */
#endif /* ifdef CONFIG_ATH5K_DEBUG */
#endif /* ifndef _ATH5K_DEBUG_H */

Просмотреть файл

@ -140,9 +140,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
* HW information
*/
/* Get reg domain from eeprom */
ath5k_get_regdomain(ah);
ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
ah->ah_turbo = false;
@ -405,15 +402,15 @@ const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah,
/* Get rate tables */
switch (mode) {
case MODE_IEEE80211A:
case AR5K_MODE_11A:
return &ath5k_rt_11a;
case MODE_ATHEROS_TURBO:
case AR5K_MODE_11A_TURBO:
return &ath5k_rt_turbo;
case MODE_IEEE80211B:
case AR5K_MODE_11B:
return &ath5k_rt_11b;
case MODE_IEEE80211G:
case AR5K_MODE_11G:
return &ath5k_rt_11g;
case MODE_ATHEROS_TURBOG:
case AR5K_MODE_11G_TURBO:
return &ath5k_rt_xr;
}
@ -457,15 +454,15 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
ds_coef_exp, ds_coef_man, clock;
if (!(ah->ah_version == AR5K_AR5212) ||
!(channel->val & CHANNEL_OFDM))
!(channel->hw_value & CHANNEL_OFDM))
BUG();
/* Seems there are two PLLs, one for baseband sampling and one
* for tuning. Tuning basebands are 40 MHz or 80MHz when in
* turbo. */
clock = channel->val & CHANNEL_TURBO ? 80 : 40;
clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
coef_scaled = ((5 * (clock << 24)) / 2) /
channel->freq;
channel->center_freq;
for (coef_exp = 31; coef_exp > 0; coef_exp--)
if ((coef_scaled >> coef_exp) & 0x1)
@ -492,8 +489,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
* ath5k_hw_write_rate_duration - set rate duration during hw resets
*
* @ah: the &struct ath5k_hw
* @driver_mode: one of enum ieee80211_phymode or our one of our own
* vendor modes
* @mode: one of enum ath5k_driver_mode
*
* Write the rate duration table for the current mode upon hw reset. This
* is a helper for ath5k_hw_reset(). It seems all this is doing is setting
@ -504,19 +500,20 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
*
*/
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
unsigned int driver_mode)
unsigned int mode)
{
struct ath5k_softc *sc = ah->ah_sc;
const struct ath5k_rate_table *rt;
struct ieee80211_rate srate = {};
unsigned int i;
/* Get rate table for the current operating mode */
rt = ath5k_hw_get_rate_table(ah,
driver_mode);
rt = ath5k_hw_get_rate_table(ah, mode);
/* Write rate duration table */
for (i = 0; i < rt->rate_count; i++) {
const struct ath5k_rate *rate, *control_rate;
u32 reg;
u16 tx_time;
@ -526,14 +523,16 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
/* Set ACK timeout */
reg = AR5K_RATE_DUR(rate->rate_code);
srate.bitrate = control_rate->rate_kbps/100;
/* An ACK frame consists of 10 bytes. If you add the FCS,
* which ieee80211_generic_frame_duration() adds,
* its 14 bytes. Note we use the control rate and not the
* actual rate for this rate. See mac80211 tx.c
* ieee80211_duration() for a brief description of
* what rate we should choose to TX ACKs. */
tx_time = ieee80211_generic_frame_duration(sc->hw,
sc->vif, 10, control_rate->rate_kbps/100);
tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
sc->vif, 10, &srate));
ath5k_hw_reg_write(ah, tx_time, reg);
@ -567,7 +566,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
{
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
u32 data, s_seq, s_ant, s_led[3];
unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
unsigned int i, mode, freq, ee_mode, ant[2];
int ret;
ATH5K_TRACE(ah->ah_sc);
@ -602,7 +601,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
/*Wakeup the device*/
ret = ath5k_hw_nic_wakeup(ah, channel->val, false);
ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
if (ret)
return ret;
@ -624,37 +623,32 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
return -EINVAL;
}
switch (channel->val & CHANNEL_MODES) {
switch (channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
mode = AR5K_INI_VAL_11A;
mode = AR5K_MODE_11A;
freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A;
driver_mode = MODE_IEEE80211A;
break;
case CHANNEL_G:
mode = AR5K_INI_VAL_11G;
mode = AR5K_MODE_11G;
freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11G;
driver_mode = MODE_IEEE80211G;
break;
case CHANNEL_B:
mode = AR5K_INI_VAL_11B;
mode = AR5K_MODE_11B;
freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11B;
driver_mode = MODE_IEEE80211B;
break;
case CHANNEL_T:
mode = AR5K_INI_VAL_11A_TURBO;
mode = AR5K_MODE_11A_TURBO;
freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A;
driver_mode = MODE_ATHEROS_TURBO;
break;
/*Is this ok on 5211 too ?*/
case CHANNEL_TG:
mode = AR5K_INI_VAL_11G_TURBO;
mode = AR5K_MODE_11G_TURBO;
freq = AR5K_INI_RFGAIN_2GHZ;
ee_mode = AR5K_EEPROM_MODE_11G;
driver_mode = MODE_ATHEROS_TURBOG;
break;
case CHANNEL_XR:
if (ah->ah_version == AR5K_AR5211) {
@ -662,14 +656,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
"XR mode not available on 5211");
return -EINVAL;
}
mode = AR5K_INI_VAL_XR;
mode = AR5K_MODE_XR;
freq = AR5K_INI_RFGAIN_5GHZ;
ee_mode = AR5K_EEPROM_MODE_11A;
driver_mode = MODE_IEEE80211A;
break;
default:
ATH5K_ERR(ah->ah_sc,
"invalid channel: %d\n", channel->freq);
"invalid channel: %d\n", channel->center_freq);
return -EINVAL;
}
@ -702,7 +695,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */
ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
if (channel->val == CHANNEL_G)
if (channel->hw_value == CHANNEL_G)
ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */
else
ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83));
@ -720,7 +713,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
AR5K_SREV_RAD_5112A) {
ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
AR5K_PHY_CCKTXCTL);
if (channel->val & CHANNEL_5GHZ)
if (channel->hw_value & CHANNEL_5GHZ)
data = 0xffb81020;
else
data = 0xffb80d20;
@ -740,7 +733,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
* mac80211 are integrated */
if (ah->ah_version == AR5K_AR5212 &&
ah->ah_sc->vif != NULL)
ath5k_hw_write_rate_duration(ah, driver_mode);
ath5k_hw_write_rate_duration(ah, mode);
/*
* Write RF registers
@ -756,7 +749,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
/* Write OFDM timings on 5212*/
if (ah->ah_version == AR5K_AR5212 &&
channel->val & CHANNEL_OFDM) {
channel->hw_value & CHANNEL_OFDM) {
ret = ath5k_hw_write_ofdm_timings(ah, channel);
if (ret)
return ret;
@ -765,7 +758,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
/*Enable/disable 802.11b mode on 5111
(enable 2111 frequency converter + CCK)*/
if (ah->ah_radio == AR5K_RF5111) {
if (driver_mode == MODE_IEEE80211B)
if (mode == AR5K_MODE_11B)
AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
AR5K_TXCFG_B_MODE);
else
@ -903,7 +896,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
if (ah->ah_version != AR5K_AR5210) {
data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
AR5K_PHY_RX_DELAY_M;
data = (channel->val & CHANNEL_CCK) ?
data = (channel->hw_value & CHANNEL_CCK) ?
((data << 2) / 22) : (data / 10);
udelay(100 + data);
@ -920,11 +913,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_CAL, 0, false)) {
ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
channel->freq);
channel->center_freq);
return -EAGAIN;
}
ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
if (ret)
return ret;
@ -932,7 +925,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
/* A and G modes can use QAM modulation which requires enabling
* I and Q calibration. Don't bother in B mode. */
if (!(driver_mode == MODE_IEEE80211B)) {
if (!(mode == AR5K_MODE_11B)) {
ah->ah_calibration = true;
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
@ -1590,9 +1583,10 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
/*
* Write to eeprom - currently disabled, use at your own risk
*/
#if 0
static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
{
#if 0
u32 status, timeout;
ATH5K_TRACE(ah->ah_sc);
@ -1634,10 +1628,11 @@ static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
}
udelay(15);
}
#endif
ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
return -EIO;
}
#endif
/*
* Translate binary channel representation in EEPROM to frequency
@ -2042,50 +2037,6 @@ static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
return 0;
}
/*
* Read/Write regulatory domain
*/
static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write,
enum ath5k_regdom *regdomain)
{
u16 ee_regdomain;
/* Read current value */
if (write != true) {
ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain;
*regdomain = ath5k_regdom_to_ieee(ee_regdomain);
return true;
}
ee_regdomain = ath5k_regdom_from_ieee(*regdomain);
/* Try to write a new value */
if (ah->ah_capabilities.cap_eeprom.ee_protect &
AR5K_EEPROM_PROTECT_WR_128_191)
return false;
if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0)
return false;
ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
return true;
}
/*
* Use the above to write a new regulatory domain
*/
int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain)
{
enum ath5k_regdom ieee_regdomain;
ieee_regdomain = ath5k_regdom_to_ieee(regdomain);
if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true)
return 0;
return -EIO;
}
/*
* Fill the capabilities struct
*/
@ -2108,8 +2059,8 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
ah->ah_capabilities.cap_range.range_2ghz_max = 0;
/* Set supported modes */
__set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode);
__set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode);
__set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
__set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
} else {
/*
* XXX The tranceiver supports frequencies from 4920 to 6100GHz
@ -2131,12 +2082,12 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
/* Set supported modes */
__set_bit(MODE_IEEE80211A,
__set_bit(AR5K_MODE_11A,
ah->ah_capabilities.cap_mode);
__set_bit(MODE_ATHEROS_TURBO,
__set_bit(AR5K_MODE_11A_TURBO,
ah->ah_capabilities.cap_mode);
if (ah->ah_version == AR5K_AR5212)
__set_bit(MODE_ATHEROS_TURBOG,
__set_bit(AR5K_MODE_11G_TURBO,
ah->ah_capabilities.cap_mode);
}
@ -2148,11 +2099,11 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
if (AR5K_EEPROM_HDR_11B(ee_header))
__set_bit(MODE_IEEE80211B,
__set_bit(AR5K_MODE_11B,
ah->ah_capabilities.cap_mode);
if (AR5K_EEPROM_HDR_11G(ee_header))
__set_bit(MODE_IEEE80211G,
__set_bit(AR5K_MODE_11G,
ah->ah_capabilities.cap_mode);
}
}
@ -4248,35 +4199,6 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
}
/*********************************\
Regulatory Domain/Channels Setup
\*********************************/
u16 ath5k_get_regdomain(struct ath5k_hw *ah)
{
u16 regdomain;
enum ath5k_regdom ieee_regdomain;
#ifdef COUNTRYCODE
u16 code;
#endif
ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain);
ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
#ifdef COUNTRYCODE
/*
* Get the regulation domain by country code. This will ignore
* the settings found in the EEPROM.
*/
code = ieee80211_name2countrycode(COUNTRYCODE);
ieee_regdomain = ieee80211_countrycode2regdomain(code);
#endif
regdomain = ath5k_regdom_from_ieee(ieee_regdomain);
ah->ah_capabilities.cap_regdomain.reg_current = regdomain;
return regdomain;
}
/****************\

Просмотреть файл

@ -1317,8 +1317,10 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
/* For AR5211 */
} else if (ah->ah_version == AR5K_AR5211) {
if(mode > 2){ /* AR5K_INI_VAL_11B */
ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode);
/* AR5K_MODE_11B */
if (mode > 2) {
ATH5K_ERR(ah->ah_sc,
"unsupported channel mode: %d\n", mode);
return -EINVAL;
}

Просмотреть файл

@ -1018,7 +1018,7 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
int obdb = -1, bank = -1;
u32 ee_mode;
AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
rf = ah->ah_rf_banks;
@ -1038,8 +1038,8 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
}
/* Modify bank 0 */
if (channel->val & CHANNEL_2GHZ) {
if (channel->val & CHANNEL_CCK)
if (channel->hw_value & CHANNEL_2GHZ) {
if (channel->hw_value & CHANNEL_CCK)
ee_mode = AR5K_EEPROM_MODE_11B;
else
ee_mode = AR5K_EEPROM_MODE_11G;
@ -1058,10 +1058,10 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
} else {
/* For 11a, Turbo and XR */
ee_mode = AR5K_EEPROM_MODE_11A;
obdb = channel->freq >= 5725 ? 3 :
(channel->freq >= 5500 ? 2 :
(channel->freq >= 5260 ? 1 :
(channel->freq > 4000 ? 0 : -1)));
obdb = channel->center_freq >= 5725 ? 3 :
(channel->center_freq >= 5500 ? 2 :
(channel->center_freq >= 5260 ? 1 :
(channel->center_freq > 4000 ? 0 : -1)));
if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
ee->ee_pwd_84, 1, 51, 3, true))
@ -1119,12 +1119,12 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
int obdb = -1, bank = -1;
u32 ee_mode;
AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
rf = ah->ah_rf_banks;
if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A
&& !test_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode)){
&& !test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) {
rf_ini = rfregs_2112a;
rf_size = ARRAY_SIZE(rfregs_5112a);
if (mode < 2) {
@ -1156,8 +1156,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
}
/* Modify bank 6 */
if (channel->val & CHANNEL_2GHZ) {
if (channel->val & CHANNEL_OFDM)
if (channel->hw_value & CHANNEL_2GHZ) {
if (channel->hw_value & CHANNEL_OFDM)
ee_mode = AR5K_EEPROM_MODE_11G;
else
ee_mode = AR5K_EEPROM_MODE_11B;
@ -1173,10 +1173,13 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
} else {
/* For 11a, Turbo and XR */
ee_mode = AR5K_EEPROM_MODE_11A;
obdb = channel->freq >= 5725 ? 3 :
(channel->freq >= 5500 ? 2 :
(channel->freq >= 5260 ? 1 :
(channel->freq > 4000 ? 0 : -1)));
obdb = channel->center_freq >= 5725 ? 3 :
(channel->center_freq >= 5500 ? 2 :
(channel->center_freq >= 5260 ? 1 :
(channel->center_freq > 4000 ? 0 : -1)));
if (obdb == -1)
return -EINVAL;
if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
ee->ee_ob[ee_mode][obdb], 3, 279, 0, true))
@ -1219,7 +1222,7 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
unsigned int rf_size, i;
int bank = -1;
AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
rf = ah->ah_rf_banks;
@ -1445,9 +1448,10 @@ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
* newer chipsets like the AR5212A who have a completely
* different RF/PHY part.
*/
athchan = (ath5k_hw_bitswap((channel->chan - 24) / 2, 5) << 1) |
(1 << 6) | 0x1;
athchan = (ath5k_hw_bitswap(
(ieee80211_frequency_to_channel(
channel->center_freq) - 24) / 2, 5)
<< 1) | (1 << 6) | 0x1;
return athchan;
}
@ -1506,7 +1510,8 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
struct ieee80211_channel *channel)
{
struct ath5k_athchan_2ghz ath5k_channel_2ghz;
unsigned int ath5k_channel = channel->chan;
unsigned int ath5k_channel =
ieee80211_frequency_to_channel(channel->center_freq);
u32 data0, data1, clock;
int ret;
@ -1515,9 +1520,10 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
*/
data0 = data1 = 0;
if (channel->val & CHANNEL_2GHZ) {
if (channel->hw_value & CHANNEL_2GHZ) {
/* Map 2GHz channel to 5GHz Atheros channel ID */
ret = ath5k_hw_rf5111_chan2athchan(channel->chan,
ret = ath5k_hw_rf5111_chan2athchan(
ieee80211_frequency_to_channel(channel->center_freq),
&ath5k_channel_2ghz);
if (ret)
return ret;
@ -1555,7 +1561,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
u16 c;
data = data0 = data1 = data2 = 0;
c = channel->freq;
c = channel->center_freq;
/*
* Set the channel on the RF5112 or newer
@ -1599,18 +1605,16 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
{
int ret;
/*
* Check bounds supported by the PHY
* (don't care about regulation restrictions at this point)
*/
if ((channel->freq < ah->ah_capabilities.cap_range.range_2ghz_min ||
channel->freq > ah->ah_capabilities.cap_range.range_2ghz_max) &&
(channel->freq < ah->ah_capabilities.cap_range.range_5ghz_min ||
channel->freq > ah->ah_capabilities.cap_range.range_5ghz_max)) {
* Check bounds supported by the PHY (we don't care about regultory
* restrictions at this point). Note: hw_value already has the band
* (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
* of the band by that */
if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
ATH5K_ERR(ah->ah_sc,
"channel out of supported range (%u MHz)\n",
channel->freq);
"channel frequency (%u MHz) out of supported "
"band range\n",
channel->center_freq);
return -EINVAL;
}
@ -1632,9 +1636,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
if (ret)
return ret;
ah->ah_current_channel.freq = channel->freq;
ah->ah_current_channel.val = channel->val;
ah->ah_turbo = channel->val == CHANNEL_T ? true : false;
ah->ah_current_channel.center_freq = channel->center_freq;
ah->ah_current_channel.hw_value = channel->hw_value;
ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
return 0;
}
@ -1797,11 +1801,11 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
if (ret) {
ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
channel->freq);
channel->center_freq);
return ret;
}
ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
if (ret)
return ret;
@ -1848,10 +1852,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
done:
ath5k_hw_noise_floor_calibration(ah, channel->freq);
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
/* Request RF gain */
if (channel->val & CHANNEL_5GHZ) {
if (channel->hw_value & CHANNEL_5GHZ) {
ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max,
AR5K_PHY_PAPD_PROBE_TXPOWER) |
AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);

Просмотреть файл

@ -66,6 +66,7 @@
#include <linux/device.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/jiffies.h>
#include <net/ieee80211.h>
#include "atmel.h"
@ -516,7 +517,7 @@ struct atmel_private {
SITE_SURVEY_IN_PROGRESS,
SITE_SURVEY_COMPLETED
} site_survey_state;
time_t last_survey;
unsigned long last_survey;
int station_was_associated, station_is_associated;
int fast_scan;
@ -2283,7 +2284,7 @@ static int atmel_set_scan(struct net_device *dev,
return -EAGAIN;
/* Timeout old surveys. */
if ((jiffies - priv->last_survey) > (20 * HZ))
if (time_after(jiffies, priv->last_survey + 20 * HZ))
priv->site_survey_state = SITE_SURVEY_IDLE;
priv->last_survey = jiffies;

Просмотреть файл

@ -144,7 +144,8 @@ enum {
#define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */
#define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */
#define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */
#define B43_SHM_SH_HOSTFHI 0x0060 /* Hostflags for ucode options (high) */
#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */
#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */
#define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */
#define B43_SHM_SH_RADAR 0x0066 /* Radar register */
#define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */
@ -232,31 +233,41 @@ enum {
#define B43_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
/* HostFlags. See b43_hf_read/write() */
#define B43_HF_ANTDIVHELP 0x00000001 /* ucode antenna div helper */
#define B43_HF_SYMW 0x00000002 /* G-PHY SYM workaround */
#define B43_HF_RXPULLW 0x00000004 /* RX pullup workaround */
#define B43_HF_CCKBOOST 0x00000008 /* 4dB CCK power boost (exclusive with OFDM boost) */
#define B43_HF_BTCOEX 0x00000010 /* Bluetooth coexistance */
#define B43_HF_GDCW 0x00000020 /* G-PHY DV canceller filter bw workaround */
#define B43_HF_OFDMPABOOST 0x00000040 /* Enable PA gain boost for OFDM */
#define B43_HF_ACPR 0x00000080 /* Disable for Japan, channel 14 */
#define B43_HF_EDCF 0x00000100 /* on if WME and MAC suspended */
#define B43_HF_TSSIRPSMW 0x00000200 /* TSSI reset PSM ucode workaround */
#define B43_HF_DSCRQ 0x00000400 /* Disable slow clock request in ucode */
#define B43_HF_ACIW 0x00000800 /* ACI workaround: shift bits by 2 on PHY CRS */
#define B43_HF_2060W 0x00001000 /* 2060 radio workaround */
#define B43_HF_RADARW 0x00002000 /* Radar workaround */
#define B43_HF_USEDEFKEYS 0x00004000 /* Enable use of default keys */
#define B43_HF_BT4PRIOCOEX 0x00010000 /* Bluetooth 2-priority coexistance */
#define B43_HF_FWKUP 0x00020000 /* Fast wake-up ucode */
#define B43_HF_VCORECALC 0x00040000 /* Force VCO recalculation when powering up synthpu */
#define B43_HF_PCISCW 0x00080000 /* PCI slow clock workaround */
#define B43_HF_4318TSSI 0x00200000 /* 4318 TSSI */
#define B43_HF_FBCMCFIFO 0x00400000 /* Flush bcast/mcast FIFO immediately */
#define B43_HF_HWPCTL 0x00800000 /* Enable hardwarre power control */
#define B43_HF_BTCOEXALT 0x01000000 /* Bluetooth coexistance in alternate pins */
#define B43_HF_TXBTCHECK 0x02000000 /* Bluetooth check during transmission */
#define B43_HF_SKCFPUP 0x04000000 /* Skip CFP update */
#define B43_HF_ANTDIVHELP 0x000000000001ULL /* ucode antenna div helper */
#define B43_HF_SYMW 0x000000000002ULL /* G-PHY SYM workaround */
#define B43_HF_RXPULLW 0x000000000004ULL /* RX pullup workaround */
#define B43_HF_CCKBOOST 0x000000000008ULL /* 4dB CCK power boost (exclusive with OFDM boost) */
#define B43_HF_BTCOEX 0x000000000010ULL /* Bluetooth coexistance */
#define B43_HF_GDCW 0x000000000020ULL /* G-PHY DC canceller filter bw workaround */
#define B43_HF_OFDMPABOOST 0x000000000040ULL /* Enable PA gain boost for OFDM */
#define B43_HF_ACPR 0x000000000080ULL /* Disable for Japan, channel 14 */
#define B43_HF_EDCF 0x000000000100ULL /* on if WME and MAC suspended */
#define B43_HF_TSSIRPSMW 0x000000000200ULL /* TSSI reset PSM ucode workaround */
#define B43_HF_20IN40IQW 0x000000000200ULL /* 20 in 40 MHz I/Q workaround (rev >= 13 only) */
#define B43_HF_DSCRQ 0x000000000400ULL /* Disable slow clock request in ucode */
#define B43_HF_ACIW 0x000000000800ULL /* ACI workaround: shift bits by 2 on PHY CRS */
#define B43_HF_2060W 0x000000001000ULL /* 2060 radio workaround */
#define B43_HF_RADARW 0x000000002000ULL /* Radar workaround */
#define B43_HF_USEDEFKEYS 0x000000004000ULL /* Enable use of default keys */
#define B43_HF_AFTERBURNER 0x000000008000ULL /* Afterburner enabled */
#define B43_HF_BT4PRIOCOEX 0x000000010000ULL /* Bluetooth 4-priority coexistance */
#define B43_HF_FWKUP 0x000000020000ULL /* Fast wake-up ucode */
#define B43_HF_VCORECALC 0x000000040000ULL /* Force VCO recalculation when powering up synthpu */
#define B43_HF_PCISCW 0x000000080000ULL /* PCI slow clock workaround */
#define B43_HF_4318TSSI 0x000000200000ULL /* 4318 TSSI */
#define B43_HF_FBCMCFIFO 0x000000400000ULL /* Flush bcast/mcast FIFO immediately */
#define B43_HF_HWPCTL 0x000000800000ULL /* Enable hardwarre power control */
#define B43_HF_BTCOEXALT 0x000001000000ULL /* Bluetooth coexistance in alternate pins */
#define B43_HF_TXBTCHECK 0x000002000000ULL /* Bluetooth check during transmission */
#define B43_HF_SKCFPUP 0x000004000000ULL /* Skip CFP update */
#define B43_HF_N40W 0x000008000000ULL /* N PHY 40 MHz workaround (rev >= 13 only) */
#define B43_HF_ANTSEL 0x000020000000ULL /* Antenna selection (for testing antenna div.) */
#define B43_HF_BT3COEXT 0x000020000000ULL /* Bluetooth 3-wire coexistence (rev >= 13 only) */
#define B43_HF_BTCANT 0x000040000000ULL /* Bluetooth coexistence (antenna mode) (rev >= 13 only) */
#define B43_HF_ANTSELEN 0x000100000000ULL /* Antenna selection enabled (rev >= 13 only) */
#define B43_HF_ANTSELMODE 0x000200000000ULL /* Antenna selection mode (rev >= 13 only) */
#define B43_HF_MLADVW 0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
#define B43_HF_PR45960W 0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
/* MacFilter offsets. */
#define B43_MACFILTER_SELF 0x0000
@ -458,20 +469,13 @@ struct b43_iv {
} __attribute__((__packed__));
#define B43_PHYMODE(phytype) (1 << (phytype))
#define B43_PHYMODE_A B43_PHYMODE(B43_PHYTYPE_A)
#define B43_PHYMODE_B B43_PHYMODE(B43_PHYTYPE_B)
#define B43_PHYMODE_G B43_PHYMODE(B43_PHYTYPE_G)
struct b43_phy {
/* Possible PHYMODEs on this PHY */
u8 possible_phymodes;
/* Band support flags. */
bool supports_2ghz;
bool supports_5ghz;
/* GMODE bit enabled? */
bool gmode;
/* Possible ieee80211 subsystem hwmodes for this PHY.
* Which mode is selected, depends on thr GMODE enabled bit */
#define B43_MAX_PHYHWMODES 2
struct ieee80211_hw_mode hwmodes[B43_MAX_PHYHWMODES];
/* Analog Type */
u8 analog;
@ -727,7 +731,6 @@ struct b43_wldev {
bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
bool short_preamble; /* TRUE, if short preamble is enabled. */
bool short_slot; /* TRUE, if short slot timing is enabled. */
bool radio_hw_enable; /* saved state of radio hardware enabled state */
bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */

Просмотреть файл

@ -97,24 +97,28 @@ MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
* get concurrency issues */
#define RATETAB_ENT(_rateid, _flags) \
{ \
.rate = B43_RATE_TO_BASE100KBPS(_rateid), \
.val = (_rateid), \
.val2 = (_rateid), \
.bitrate = B43_RATE_TO_BASE100KBPS(_rateid), \
.hw_value = (_rateid), \
.flags = (_flags), \
}
/*
* NOTE: When changing this, sync with xmit.c's
* b43_plcp_get_bitrate_idx_* functions!
*/
static struct ieee80211_rate __b43_ratetable[] = {
RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK),
RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43_CCK_RATE_1MB, 0),
RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
RATETAB_ENT(B43_OFDM_RATE_6MB, 0),
RATETAB_ENT(B43_OFDM_RATE_9MB, 0),
RATETAB_ENT(B43_OFDM_RATE_12MB, 0),
RATETAB_ENT(B43_OFDM_RATE_18MB, 0),
RATETAB_ENT(B43_OFDM_RATE_24MB, 0),
RATETAB_ENT(B43_OFDM_RATE_36MB, 0),
RATETAB_ENT(B43_OFDM_RATE_48MB, 0),
RATETAB_ENT(B43_OFDM_RATE_54MB, 0),
};
#define b43_a_ratetable (__b43_ratetable + 4)
@ -124,53 +128,144 @@ static struct ieee80211_rate __b43_ratetable[] = {
#define b43_g_ratetable (__b43_ratetable + 0)
#define b43_g_ratetable_size 12
#define CHANTAB_ENT(_chanid, _freq) \
{ \
.chan = (_chanid), \
.freq = (_freq), \
.val = (_chanid), \
.flag = IEEE80211_CHAN_W_SCAN | \
IEEE80211_CHAN_W_ACTIVE_SCAN | \
IEEE80211_CHAN_W_IBSS, \
.power_level = 0xFF, \
.antenna_max = 0xFF, \
}
#define CHAN4G(_channel, _freq, _flags) { \
.band = IEEE80211_BAND_2GHZ, \
.center_freq = (_freq), \
.hw_value = (_channel), \
.flags = (_flags), \
.max_antenna_gain = 0, \
.max_power = 30, \
}
static struct ieee80211_channel b43_2ghz_chantable[] = {
CHANTAB_ENT(1, 2412),
CHANTAB_ENT(2, 2417),
CHANTAB_ENT(3, 2422),
CHANTAB_ENT(4, 2427),
CHANTAB_ENT(5, 2432),
CHANTAB_ENT(6, 2437),
CHANTAB_ENT(7, 2442),
CHANTAB_ENT(8, 2447),
CHANTAB_ENT(9, 2452),
CHANTAB_ENT(10, 2457),
CHANTAB_ENT(11, 2462),
CHANTAB_ENT(12, 2467),
CHANTAB_ENT(13, 2472),
CHANTAB_ENT(14, 2484),
CHAN4G(1, 2412, 0),
CHAN4G(2, 2417, 0),
CHAN4G(3, 2422, 0),
CHAN4G(4, 2427, 0),
CHAN4G(5, 2432, 0),
CHAN4G(6, 2437, 0),
CHAN4G(7, 2442, 0),
CHAN4G(8, 2447, 0),
CHAN4G(9, 2452, 0),
CHAN4G(10, 2457, 0),
CHAN4G(11, 2462, 0),
CHAN4G(12, 2467, 0),
CHAN4G(13, 2472, 0),
CHAN4G(14, 2484, 0),
};
#define b43_2ghz_chantable_size ARRAY_SIZE(b43_2ghz_chantable)
#undef CHAN4G
#if 0
static struct ieee80211_channel b43_5ghz_chantable[] = {
CHANTAB_ENT(36, 5180),
CHANTAB_ENT(40, 5200),
CHANTAB_ENT(44, 5220),
CHANTAB_ENT(48, 5240),
CHANTAB_ENT(52, 5260),
CHANTAB_ENT(56, 5280),
CHANTAB_ENT(60, 5300),
CHANTAB_ENT(64, 5320),
CHANTAB_ENT(149, 5745),
CHANTAB_ENT(153, 5765),
CHANTAB_ENT(157, 5785),
CHANTAB_ENT(161, 5805),
CHANTAB_ENT(165, 5825),
#define CHAN5G(_channel, _flags) { \
.band = IEEE80211_BAND_5GHZ, \
.center_freq = 5000 + (5 * (_channel)), \
.hw_value = (_channel), \
.flags = (_flags), \
.max_antenna_gain = 0, \
.max_power = 30, \
}
static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
CHAN5G(32, 0), CHAN5G(34, 0),
CHAN5G(36, 0), CHAN5G(38, 0),
CHAN5G(40, 0), CHAN5G(42, 0),
CHAN5G(44, 0), CHAN5G(46, 0),
CHAN5G(48, 0), CHAN5G(50, 0),
CHAN5G(52, 0), CHAN5G(54, 0),
CHAN5G(56, 0), CHAN5G(58, 0),
CHAN5G(60, 0), CHAN5G(62, 0),
CHAN5G(64, 0), CHAN5G(66, 0),
CHAN5G(68, 0), CHAN5G(70, 0),
CHAN5G(72, 0), CHAN5G(74, 0),
CHAN5G(76, 0), CHAN5G(78, 0),
CHAN5G(80, 0), CHAN5G(82, 0),
CHAN5G(84, 0), CHAN5G(86, 0),
CHAN5G(88, 0), CHAN5G(90, 0),
CHAN5G(92, 0), CHAN5G(94, 0),
CHAN5G(96, 0), CHAN5G(98, 0),
CHAN5G(100, 0), CHAN5G(102, 0),
CHAN5G(104, 0), CHAN5G(106, 0),
CHAN5G(108, 0), CHAN5G(110, 0),
CHAN5G(112, 0), CHAN5G(114, 0),
CHAN5G(116, 0), CHAN5G(118, 0),
CHAN5G(120, 0), CHAN5G(122, 0),
CHAN5G(124, 0), CHAN5G(126, 0),
CHAN5G(128, 0), CHAN5G(130, 0),
CHAN5G(132, 0), CHAN5G(134, 0),
CHAN5G(136, 0), CHAN5G(138, 0),
CHAN5G(140, 0), CHAN5G(142, 0),
CHAN5G(144, 0), CHAN5G(145, 0),
CHAN5G(146, 0), CHAN5G(147, 0),
CHAN5G(148, 0), CHAN5G(149, 0),
CHAN5G(150, 0), CHAN5G(151, 0),
CHAN5G(152, 0), CHAN5G(153, 0),
CHAN5G(154, 0), CHAN5G(155, 0),
CHAN5G(156, 0), CHAN5G(157, 0),
CHAN5G(158, 0), CHAN5G(159, 0),
CHAN5G(160, 0), CHAN5G(161, 0),
CHAN5G(162, 0), CHAN5G(163, 0),
CHAN5G(164, 0), CHAN5G(165, 0),
CHAN5G(166, 0), CHAN5G(168, 0),
CHAN5G(170, 0), CHAN5G(172, 0),
CHAN5G(174, 0), CHAN5G(176, 0),
CHAN5G(178, 0), CHAN5G(180, 0),
CHAN5G(182, 0), CHAN5G(184, 0),
CHAN5G(186, 0), CHAN5G(188, 0),
CHAN5G(190, 0), CHAN5G(192, 0),
CHAN5G(194, 0), CHAN5G(196, 0),
CHAN5G(198, 0), CHAN5G(200, 0),
CHAN5G(202, 0), CHAN5G(204, 0),
CHAN5G(206, 0), CHAN5G(208, 0),
CHAN5G(210, 0), CHAN5G(212, 0),
CHAN5G(214, 0), CHAN5G(216, 0),
CHAN5G(218, 0), CHAN5G(220, 0),
CHAN5G(222, 0), CHAN5G(224, 0),
CHAN5G(226, 0), CHAN5G(228, 0),
};
static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
CHAN5G(34, 0), CHAN5G(36, 0),
CHAN5G(38, 0), CHAN5G(40, 0),
CHAN5G(42, 0), CHAN5G(44, 0),
CHAN5G(46, 0), CHAN5G(48, 0),
CHAN5G(52, 0), CHAN5G(56, 0),
CHAN5G(60, 0), CHAN5G(64, 0),
CHAN5G(100, 0), CHAN5G(104, 0),
CHAN5G(108, 0), CHAN5G(112, 0),
CHAN5G(116, 0), CHAN5G(120, 0),
CHAN5G(124, 0), CHAN5G(128, 0),
CHAN5G(132, 0), CHAN5G(136, 0),
CHAN5G(140, 0), CHAN5G(149, 0),
CHAN5G(153, 0), CHAN5G(157, 0),
CHAN5G(161, 0), CHAN5G(165, 0),
CHAN5G(184, 0), CHAN5G(188, 0),
CHAN5G(192, 0), CHAN5G(196, 0),
CHAN5G(200, 0), CHAN5G(204, 0),
CHAN5G(208, 0), CHAN5G(212, 0),
CHAN5G(216, 0),
};
#undef CHAN5G
static struct ieee80211_supported_band b43_band_5GHz_nphy = {
.band = IEEE80211_BAND_5GHZ,
.channels = b43_5ghz_nphy_chantable,
.n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable),
.bitrates = b43_a_ratetable,
.n_bitrates = b43_a_ratetable_size,
};
static struct ieee80211_supported_band b43_band_5GHz_aphy = {
.band = IEEE80211_BAND_5GHZ,
.channels = b43_5ghz_aphy_chantable,
.n_channels = ARRAY_SIZE(b43_5ghz_aphy_chantable),
.bitrates = b43_a_ratetable,
.n_bitrates = b43_a_ratetable_size,
};
static struct ieee80211_supported_band b43_band_2GHz = {
.band = IEEE80211_BAND_2GHZ,
.channels = b43_2ghz_chantable,
.n_channels = ARRAY_SIZE(b43_2ghz_chantable),
.bitrates = b43_g_ratetable,
.n_bitrates = b43_g_ratetable_size,
};
#define b43_5ghz_chantable_size ARRAY_SIZE(b43_5ghz_chantable)
#endif
static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
@ -370,24 +465,30 @@ out:
}
/* Read HostFlags */
u32 b43_hf_read(struct b43_wldev * dev)
u64 b43_hf_read(struct b43_wldev * dev)
{
u32 ret;
u64 ret;
ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);
ret <<= 16;
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI);
ret <<= 16;
ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO);
return ret;
}
/* Write HostFlags */
void b43_hf_write(struct b43_wldev *dev, u32 value)
void b43_hf_write(struct b43_wldev *dev, u64 value)
{
b43_shm_write16(dev, B43_SHM_SHARED,
B43_SHM_SH_HOSTFLO, (value & 0x0000FFFF));
b43_shm_write16(dev, B43_SHM_SHARED,
B43_SHM_SH_HOSTFHI, ((value & 0xFFFF0000) >> 16));
u16 lo, mi, hi;
lo = (value & 0x00000000FFFFULL);
mi = (value & 0x0000FFFF0000ULL) >> 16;
hi = (value & 0xFFFF00000000ULL) >> 32;
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
}
void b43_tsf_read(struct b43_wldev *dev, u64 * tsf)
@ -1222,17 +1323,18 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
}
static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
u16 shm_offset, u16 size, u8 rate)
u16 shm_offset, u16 size,
struct ieee80211_rate *rate)
{
struct b43_plcp_hdr4 plcp;
u32 tmp;
__le16 dur;
plcp.data = 0;
b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
dev->wl->vif, size,
B43_RATE_TO_BASE100KBPS(rate));
rate);
/* Write PLCP in two parts and timing for packet transfer */
tmp = le32_to_cpu(plcp.data);
b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
@ -1247,7 +1349,8 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
* 3) Stripping TIM
*/
static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
u16 *dest_size, u8 rate)
u16 *dest_size,
struct ieee80211_rate *rate)
{
const u8 *src_data;
u8 *dest_data;
@ -1292,7 +1395,7 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
IEEE80211_STYPE_PROBE_RESP);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
dev->wl->vif, *dest_size,
B43_RATE_TO_BASE100KBPS(rate));
rate);
hdr->duration_id = dur;
return dest_data;
@ -1300,7 +1403,8 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
static void b43_write_probe_resp_template(struct b43_wldev *dev,
u16 ram_offset,
u16 shm_size_offset, u8 rate)
u16 shm_size_offset,
struct ieee80211_rate *rate)
{
const u8 *probe_resp_data;
u16 size;
@ -1313,14 +1417,15 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
/* Looks like PLCP headers plus packet timings are stored for
* all possible basic rates
*/
b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB);
b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB);
b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB);
b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB);
b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]);
b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]);
b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]);
b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]);
size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
b43_write_template_common(dev, probe_resp_data,
size, ram_offset, shm_size_offset, rate);
size, ram_offset, shm_size_offset,
rate->hw_value);
kfree(probe_resp_data);
}
@ -1388,7 +1493,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
b43_write_beacon_template(dev, 0x68, 0x18,
B43_CCK_RATE_1MB);
b43_write_probe_resp_template(dev, 0x268, 0x4A,
B43_CCK_RATE_11MB);
&__b43_ratetable[3]);
wl->beacon0_uploaded = 1;
}
cmd |= B43_MACCMD_BEACON0_VALID;
@ -2643,45 +2748,6 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
return 0;
}
static const char *phymode_to_string(unsigned int phymode)
{
switch (phymode) {
case B43_PHYMODE_A:
return "A";
case B43_PHYMODE_B:
return "B";
case B43_PHYMODE_G:
return "G";
default:
B43_WARN_ON(1);
}
return "";
}
static int find_wldev_for_phymode(struct b43_wl *wl,
unsigned int phymode,
struct b43_wldev **dev, bool * gmode)
{
struct b43_wldev *d;
list_for_each_entry(d, &wl->devlist, list) {
if (d->phy.possible_phymodes & phymode) {
/* Ok, this device supports the PHY-mode.
* Now figure out how the gmode bit has to be
* set to support it. */
if (phymode == B43_PHYMODE_A)
*gmode = 0;
else
*gmode = 1;
*dev = d;
return 0;
}
}
return -ESRCH;
}
static void b43_put_phy_into_reset(struct b43_wldev *dev)
{
struct ssb_device *sdev = dev->dev;
@ -2701,28 +2767,64 @@ static void b43_put_phy_into_reset(struct b43_wldev *dev)
msleep(1);
}
/* Expects wl->mutex locked */
static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
static const char * band_to_string(enum ieee80211_band band)
{
struct b43_wldev *up_dev;
switch (band) {
case IEEE80211_BAND_5GHZ:
return "5";
case IEEE80211_BAND_2GHZ:
return "2.4";
default:
break;
}
B43_WARN_ON(1);
return "";
}
/* Expects wl->mutex locked */
static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
{
struct b43_wldev *up_dev = NULL;
struct b43_wldev *down_dev;
struct b43_wldev *d;
int err;
bool gmode = 0;
bool gmode;
int prev_status;
err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode);
if (err) {
b43err(wl, "Could not find a device for %s-PHY mode\n",
phymode_to_string(new_mode));
return err;
/* Find a device and PHY which supports the band. */
list_for_each_entry(d, &wl->devlist, list) {
switch (chan->band) {
case IEEE80211_BAND_5GHZ:
if (d->phy.supports_5ghz) {
up_dev = d;
gmode = 0;
}
break;
case IEEE80211_BAND_2GHZ:
if (d->phy.supports_2ghz) {
up_dev = d;
gmode = 1;
}
break;
default:
B43_WARN_ON(1);
return -EINVAL;
}
if (up_dev)
break;
}
if (!up_dev) {
b43err(wl, "Could not find a device for %s-GHz band operation\n",
band_to_string(chan->band));
return -ENODEV;
}
if ((up_dev == wl->current_dev) &&
(!!wl->current_dev->phy.gmode == !!gmode)) {
/* This device is already running. */
return 0;
}
b43dbg(wl, "Reconfiguring PHYmode to %s-PHY\n",
phymode_to_string(new_mode));
b43dbg(wl, "Switching to %s-GHz band\n",
band_to_string(chan->band));
down_dev = wl->current_dev;
prev_status = b43_status(down_dev);
@ -2744,8 +2846,8 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
err = b43_wireless_core_init(up_dev);
if (err) {
b43err(wl, "Fatal: Could not initialize device for "
"newly selected %s-PHY mode\n",
phymode_to_string(new_mode));
"selected %s-GHz band\n",
band_to_string(chan->band));
goto init_failure;
}
}
@ -2753,8 +2855,8 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
err = b43_wireless_core_start(up_dev);
if (err) {
b43err(wl, "Fatal: Coult not start device for "
"newly selected %s-PHY mode\n",
phymode_to_string(new_mode));
"selected %s-GHz band\n",
band_to_string(chan->band));
b43_wireless_core_exit(up_dev);
goto init_failure;
}
@ -2764,7 +2866,7 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
wl->current_dev = up_dev;
return 0;
init_failure:
init_failure:
/* Whoops, failed to init the new core. No core is operating now. */
wl->current_dev = NULL;
return err;
@ -2822,28 +2924,14 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
struct b43_wldev *dev;
struct b43_phy *phy;
unsigned long flags;
unsigned int new_phymode = 0xFFFF;
int antenna;
int err = 0;
u32 savedirqs;
mutex_lock(&wl->mutex);
/* Switch the PHY mode (if necessary). */
switch (conf->phymode) {
case MODE_IEEE80211A:
new_phymode = B43_PHYMODE_A;
break;
case MODE_IEEE80211B:
new_phymode = B43_PHYMODE_B;
break;
case MODE_IEEE80211G:
new_phymode = B43_PHYMODE_G;
break;
default:
B43_WARN_ON(1);
}
err = b43_switch_phymode(wl, new_phymode);
/* Switch the band (if necessary). This might change the active core. */
err = b43_switch_band(wl, conf->channel);
if (err)
goto out_unlock_mutex;
dev = wl->current_dev;
@ -2863,8 +2951,8 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
if (conf->channel_val != phy->channel)
b43_radio_selectchannel(dev, conf->channel_val, 0);
if (conf->channel->hw_value != phy->channel)
b43_radio_selectchannel(dev, conf->channel->hw_value, 0);
/* Enable/Disable ShortSlot timing. */
if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
@ -3806,31 +3894,23 @@ static void b43_chip_reset(struct work_struct *work)
b43info(wl, "Controller restarted\n");
}
static int b43_setup_modes(struct b43_wldev *dev,
static int b43_setup_bands(struct b43_wldev *dev,
bool have_2ghz_phy, bool have_5ghz_phy)
{
struct ieee80211_hw *hw = dev->wl->hw;
struct ieee80211_hw_mode *mode;
struct b43_phy *phy = &dev->phy;
int err;
/* XXX: This function will go away soon, when mac80211
* band stuff is rewritten. So this is just a hack.
* For now we always claim GPHY mode, as there is no
* support for NPHY and APHY in the device, yet.
* This assumption is OK, as any B, N or A PHY will already
* have died a horrible sanity check death earlier. */
if (have_2ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz;
if (dev->phy.type == B43_PHYTYPE_N) {
if (have_5ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy;
} else {
if (have_5ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
}
mode = &phy->hwmodes[0];
mode->mode = MODE_IEEE80211G;
mode->num_channels = b43_2ghz_chantable_size;
mode->channels = b43_2ghz_chantable;
mode->num_rates = b43_g_ratetable_size;
mode->rates = b43_g_ratetable;
err = ieee80211_register_hwmode(hw, mode);
if (err)
return err;
phy->possible_phymodes |= B43_PHYMODE_G;
dev->phy.supports_2ghz = have_2ghz_phy;
dev->phy.supports_5ghz = have_5ghz_phy;
return 0;
}
@ -3912,7 +3992,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
err = b43_validate_chipaccess(dev);
if (err)
goto err_powerdown;
err = b43_setup_modes(dev, have_2ghz_phy, have_5ghz_phy);
err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
if (err)
goto err_powerdown;

Просмотреть файл

@ -95,8 +95,8 @@ u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
u32 b43_hf_read(struct b43_wldev *dev);
void b43_hf_write(struct b43_wldev *dev, u32 value);
u64 b43_hf_read(struct b43_wldev *dev);
void b43_hf_write(struct b43_wldev *dev, u64 value);
void b43_dummy_transmission(struct b43_wldev *dev);

Просмотреть файл

@ -47,29 +47,6 @@ static int get_integer(const char *buf, size_t count)
return ret;
}
static int get_boolean(const char *buf, size_t count)
{
if (count != 0) {
if (buf[0] == '1')
return 1;
if (buf[0] == '0')
return 0;
if (count >= 4 && memcmp(buf, "true", 4) == 0)
return 1;
if (count >= 5 && memcmp(buf, "false", 5) == 0)
return 0;
if (count >= 3 && memcmp(buf, "yes", 3) == 0)
return 1;
if (count >= 2 && memcmp(buf, "no", 2) == 0)
return 0;
if (count >= 2 && memcmp(buf, "on", 2) == 0)
return 1;
if (count >= 3 && memcmp(buf, "off", 3) == 0)
return 0;
}
return -EINVAL;
}
static ssize_t b43_attr_interfmode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@ -155,82 +132,18 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
static DEVICE_ATTR(interference, 0644,
b43_attr_interfmode_show, b43_attr_interfmode_store);
static ssize_t b43_attr_preamble_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct b43_wldev *wldev = dev_to_b43_wldev(dev);
ssize_t count;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mutex_lock(&wldev->wl->mutex);
if (wldev->short_preamble)
count =
snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
else
count =
snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
mutex_unlock(&wldev->wl->mutex);
return count;
}
static ssize_t b43_attr_preamble_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct b43_wldev *wldev = dev_to_b43_wldev(dev);
unsigned long flags;
int value;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
value = get_boolean(buf, count);
if (value < 0)
return value;
mutex_lock(&wldev->wl->mutex);
spin_lock_irqsave(&wldev->wl->irq_lock, flags);
wldev->short_preamble = !!value;
spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
mutex_unlock(&wldev->wl->mutex);
return count;
}
static DEVICE_ATTR(shortpreamble, 0644,
b43_attr_preamble_show, b43_attr_preamble_store);
int b43_sysfs_register(struct b43_wldev *wldev)
{
struct device *dev = wldev->dev->dev;
int err;
B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
err = device_create_file(dev, &dev_attr_interference);
if (err)
goto out;
err = device_create_file(dev, &dev_attr_shortpreamble);
if (err)
goto err_remove_interfmode;
out:
return err;
err_remove_interfmode:
device_remove_file(dev, &dev_attr_interference);
goto out;
return device_create_file(dev, &dev_attr_interference);
}
void b43_sysfs_unregister(struct b43_wldev *wldev)
{
struct device *dev = wldev->dev->dev;
device_remove_file(dev, &dev_attr_shortpreamble);
device_remove_file(dev, &dev_attr_interference);
}

Просмотреть файл

@ -32,46 +32,48 @@
#include "dma.h"
/* Extract the bitrate out of a CCK PLCP header. */
static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp)
/* Extract the bitrate index out of a CCK PLCP header. */
static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
{
switch (plcp->raw[0]) {
case 0x0A:
return B43_CCK_RATE_1MB;
return 0;
case 0x14:
return B43_CCK_RATE_2MB;
return 1;
case 0x37:
return B43_CCK_RATE_5MB;
return 2;
case 0x6E:
return B43_CCK_RATE_11MB;
return 3;
}
B43_WARN_ON(1);
return 0;
return -1;
}
/* Extract the bitrate out of an OFDM PLCP header. */
static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp)
/* Extract the bitrate index out of an OFDM PLCP header. */
static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
{
int base = aphy ? 0 : 4;
switch (plcp->raw[0] & 0xF) {
case 0xB:
return B43_OFDM_RATE_6MB;
return base + 0;
case 0xF:
return B43_OFDM_RATE_9MB;
return base + 1;
case 0xA:
return B43_OFDM_RATE_12MB;
return base + 2;
case 0xE:
return B43_OFDM_RATE_18MB;
return base + 3;
case 0x9:
return B43_OFDM_RATE_24MB;
return base + 4;
case 0xD:
return B43_OFDM_RATE_36MB;
return base + 5;
case 0x8:
return B43_OFDM_RATE_48MB;
return base + 6;
case 0xC:
return B43_OFDM_RATE_54MB;
return base + 7;
}
B43_WARN_ON(1);
return 0;
return -1;
}
u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
@ -191,6 +193,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
(const struct ieee80211_hdr *)fragment_data;
int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
u16 fctl = le16_to_cpu(wlhdr->frame_control);
struct ieee80211_rate *fbrate;
u8 rate, rate_fb;
int rate_ofdm, rate_fb_ofdm;
unsigned int plcp_fragment_len;
@ -200,9 +203,11 @@ int b43_generate_txhdr(struct b43_wldev *dev,
memset(txhdr, 0, sizeof(*txhdr));
rate = txctl->tx_rate;
WARN_ON(!txctl->tx_rate);
rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB;
rate_ofdm = b43_is_ofdm_rate(rate);
rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
fbrate = txctl->alt_retry_rate ? : txctl->tx_rate;
rate_fb = fbrate->hw_value;
rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
if (rate_ofdm)
@ -221,11 +226,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
* use the original dur_id field. */
txhdr->dur_fb = wlhdr->duration_id;
} else {
int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
txctl->vif,
fragment_len,
fbrate_base100kbps);
fbrate);
}
plcp_fragment_len = fragment_len + FCS_LEN;
@ -287,7 +291,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
phy_ctl |= B43_TXH_PHY_ENC_OFDM;
else
phy_ctl |= B43_TXH_PHY_ENC_CCK;
if (dev->short_preamble)
if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) {
@ -332,7 +336,8 @@ int b43_generate_txhdr(struct b43_wldev *dev,
int rts_rate_ofdm, rts_rate_fb_ofdm;
struct b43_plcp_hdr6 *plcp;
rts_rate = txctl->rts_cts_rate;
WARN_ON(!txctl->rts_cts_rate);
rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
rts_rate_fb = b43_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
@ -506,6 +511,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
u16 phystat0, phystat3, chanstat, mactime;
u32 macstat;
u16 chanid;
u16 phytype;
u8 jssi;
int padding;
@ -518,6 +524,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
macstat = le32_to_cpu(rxhdr->mac_status);
mactime = le16_to_cpu(rxhdr->mac_time);
chanstat = le16_to_cpu(rxhdr->channel);
phytype = chanstat & B43_RX_CHAN_PHYTYPE;
if (macstat & B43_RX_MAC_FCSERR)
dev->wl->ieee_stats.dot11FCSErrorCount++;
@ -575,18 +582,23 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
/* the next line looks wrong, but is what mac80211 wants */
status.signal = (jssi * 100) / B43_RX_MAX_SSI;
if (phystat0 & B43_RX_PHYST0_OFDM)
status.rate = b43_plcp_get_bitrate_ofdm(plcp);
status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
phytype == B43_PHYTYPE_A);
else
status.rate = b43_plcp_get_bitrate_cck(plcp);
status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
/*
* If monitors are present get full 64-bit timestamp. This
* code assumes we get to process the packet within 16 bits
* of timestamp, i.e. about 65 milliseconds after the PHY
* received the first symbol.
* All frames on monitor interfaces and beacons always need a full
* 64-bit timestamp. Monitor interfaces need it for diagnostic
* purposes and beacons for IBSS merging.
* This code assumes we get to process the packet within 16 bits
* of timestamp, i.e. about 65 milliseconds after the PHY received
* the first symbol.
*/
if (dev->wl->radiotap_enabled) {
if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
== (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
dev->wl->radiotap_enabled) {
u16 low_mactime_now;
b43_tsf_read(dev, &status.mactime);
@ -601,29 +613,28 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
switch (chanstat & B43_RX_CHAN_PHYTYPE) {
case B43_PHYTYPE_A:
status.phymode = MODE_IEEE80211A;
status.band = IEEE80211_BAND_5GHZ;
B43_WARN_ON(1);
/* FIXME: We don't really know which value the "chanid" contains.
* So the following assignment might be wrong. */
status.channel = chanid;
status.freq = b43_channel_to_freq_5ghz(status.channel);
status.freq = b43_channel_to_freq_5ghz(chanid);
break;
case B43_PHYTYPE_G:
status.phymode = MODE_IEEE80211G;
status.band = IEEE80211_BAND_2GHZ;
/* chanid is the radio channel cookie value as used
* to tune the radio. */
status.freq = chanid + 2400;
status.channel = b43_freq_to_channel_2ghz(status.freq);
break;
case B43_PHYTYPE_N:
status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/;
/* chanid is the SHM channel cookie. Which is the plain
* channel number in b43. */
status.channel = chanid;
if (chanstat & B43_RX_CHAN_5GHZ)
status.freq = b43_freq_to_channel_5ghz(status.freq);
else
status.freq = b43_freq_to_channel_2ghz(status.freq);
if (chanstat & B43_RX_CHAN_5GHZ) {
status.band = IEEE80211_BAND_5GHZ;
status.freq = b43_freq_to_channel_5ghz(chanid);
} else {
status.band = IEEE80211_BAND_2GHZ;
status.freq = b43_freq_to_channel_2ghz(chanid);
}
break;
default:
B43_WARN_ON(1);

Просмотреть файл

@ -130,13 +130,19 @@
#define B43legacy_SHM_SH_HOSTFHI 0x0060 /* Hostflags ucode opts (high) */
/* SHM_SHARED crypto engine */
#define B43legacy_SHM_SH_KEYIDXBLOCK 0x05D4 /* Key index/algorithm block */
/* SHM_SHARED beacon variables */
/* SHM_SHARED beacon/AP variables */
#define B43legacy_SHM_SH_DTIMP 0x0012 /* DTIM period */
#define B43legacy_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */
#define B43legacy_SHM_SH_BTL1 0x001A /* Beacon template length 1 */
#define B43legacy_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
#define B43legacy_SHM_SH_TIMPOS 0x001E /* TIM position in beacon */
#define B43legacy_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word */
/* SHM_SHARED ACK/CTS control */
#define B43legacy_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word */
/* SHM_SHARED probe response variables */
#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
#define B43legacy_SHM_SH_PRTLEN 0x004A /* Probe Response template length */
#define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */
#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
/* SHM_SHARED rate tables */
/* SHM_SHARED microcode soft registers */
#define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */
@ -199,6 +205,13 @@
#define B43legacy_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */
#define B43legacy_MACCTL_GMODE 0x80000000 /* G Mode */
/* MAC Command bitfield */
#define B43legacy_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */
#define B43legacy_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */
#define B43legacy_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */
#define B43legacy_MACCMD_CCA 0x00000008 /* Clear channel assessment */
#define B43legacy_MACCMD_BGNOISE 0x00000010 /* Background noise */
/* 802.11 core specific TM State Low flags */
#define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
#define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */
@ -317,15 +330,7 @@ enum {
# undef assert
#endif
#ifdef CONFIG_B43LEGACY_DEBUG
# define B43legacy_WARN_ON(expr) \
do { \
if (unlikely((expr))) { \
printk(KERN_INFO PFX "Test (%s) failed at:" \
" %s:%d:%s()\n", \
#expr, __FILE__, \
__LINE__, __FUNCTION__); \
} \
} while (0)
# define B43legacy_WARN_ON(x) WARN_ON(x)
# define B43legacy_BUG_ON(expr) \
do { \
if (unlikely((expr))) { \
@ -336,7 +341,9 @@ enum {
} while (0)
# define B43legacy_DEBUG 1
#else
# define B43legacy_WARN_ON(x) do { /* nothing */ } while (0)
/* This will evaluate the argument even if debugging is disabled. */
static inline bool __b43legacy_warn_on_dummy(bool x) { return x; }
# define B43legacy_WARN_ON(x) __b43legacy_warn_on_dummy(unlikely(!!(x)))
# define B43legacy_BUG_ON(x) do { /* nothing */ } while (0)
# define B43legacy_DEBUG 0
#endif
@ -392,10 +399,6 @@ struct b43legacy_phy {
u8 possible_phymodes;
/* GMODE bit enabled in MACCTL? */
bool gmode;
/* Possible ieee80211 subsystem hwmodes for this PHY.
* Which mode is selected, depends on thr GMODE enabled bit */
#define B43legacy_MAX_PHYHWMODES 2
struct ieee80211_hw_mode hwmodes[B43legacy_MAX_PHYHWMODES];
/* Analog Type */
u8 analog;
@ -598,6 +601,12 @@ struct b43legacy_wl {
u8 nr_devs;
bool radiotap_enabled;
/* The beacon we are currently using (AP or IBSS mode).
* This beacon stuff is protected by the irq_lock. */
struct sk_buff *current_beacon;
bool beacon0_uploaded;
bool beacon1_uploaded;
};
/* Pointers to the firmware data and meta information about it. */
@ -649,7 +658,7 @@ struct b43legacy_wldev {
bool __using_pio; /* Using pio rather than dma. */
bool bad_frames_preempt;/* Use "Bad Frames Preemption". */
bool reg124_set_0x4; /* Variable to keep track of IRQ. */
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */
bool short_preamble; /* TRUE if using short preamble. */
bool short_slot; /* TRUE if using short slot timing. */
bool radio_hw_enable; /* State of radio hardware enable bit. */
@ -696,9 +705,6 @@ struct b43legacy_wldev {
u8 max_nr_keys;
struct b43legacy_key key[58];
/* Cached beacon template while uploading the template. */
struct sk_buff *cached_beacon;
/* Firmware data */
struct b43legacy_firmware fw;

Просмотреть файл

@ -96,27 +96,28 @@ MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl);
* get concurrency issues */
#define RATETAB_ENT(_rateid, _flags) \
{ \
.rate = B43legacy_RATE_TO_100KBPS(_rateid), \
.val = (_rateid), \
.val2 = (_rateid), \
.bitrate = B43legacy_RATE_TO_100KBPS(_rateid), \
.hw_value = (_rateid), \
.flags = (_flags), \
}
/*
* NOTE: When changing this, sync with xmit.c's
* b43legacy_plcp_get_bitrate_idx_* functions!
*/
static struct ieee80211_rate __b43legacy_ratetable[] = {
RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK),
RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0),
RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0),
RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0),
RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0),
RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0),
RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0),
RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0),
RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0),
RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0),
};
#define b43legacy_a_ratetable (__b43legacy_ratetable + 4)
#define b43legacy_a_ratetable_size 8
#define b43legacy_b_ratetable (__b43legacy_ratetable + 0)
#define b43legacy_b_ratetable_size 4
#define b43legacy_g_ratetable (__b43legacy_ratetable + 0)
@ -124,14 +125,8 @@ static struct ieee80211_rate __b43legacy_ratetable[] = {
#define CHANTAB_ENT(_chanid, _freq) \
{ \
.chan = (_chanid), \
.freq = (_freq), \
.val = (_chanid), \
.flag = IEEE80211_CHAN_W_SCAN | \
IEEE80211_CHAN_W_ACTIVE_SCAN | \
IEEE80211_CHAN_W_IBSS, \
.power_level = 0x0A, \
.antenna_max = 0xFF, \
.center_freq = (_freq), \
.hw_value = (_chanid), \
}
static struct ieee80211_channel b43legacy_bg_chantable[] = {
CHANTAB_ENT(1, 2412),
@ -149,7 +144,20 @@ static struct ieee80211_channel b43legacy_bg_chantable[] = {
CHANTAB_ENT(13, 2472),
CHANTAB_ENT(14, 2484),
};
#define b43legacy_bg_chantable_size ARRAY_SIZE(b43legacy_bg_chantable)
static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = {
.channels = b43legacy_bg_chantable,
.n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
.bitrates = b43legacy_b_ratetable,
.n_bitrates = b43legacy_b_ratetable_size,
};
static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = {
.channels = b43legacy_bg_chantable,
.n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
.bitrates = b43legacy_g_ratetable,
.n_bitrates = b43legacy_g_ratetable_size,
};
static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev);
static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev);
@ -797,9 +805,8 @@ static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
{
b43legacy_jssi_write(dev, 0x7F7F7F7F);
b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
b43legacy_read32(dev,
B43legacy_MMIO_MACCMD)
| (1 << 4));
b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
| B43legacy_MACCMD_BGNOISE);
B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
dev->phy.channel);
}
@ -888,18 +895,18 @@ static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev)
if (1/*FIXME: the last PSpoll frame was sent successfully */)
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
dev->reg124_set_0x4 = 0;
if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
dev->reg124_set_0x4 = 1;
dev->dfq_valid = 1;
}
static void handle_irq_atim_end(struct b43legacy_wldev *dev)
{
if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
return;
if (dev->dfq_valid) {
b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
| 0x4);
| B43legacy_MACCMD_DFQ_VALID);
dev->dfq_valid = 0;
}
}
static void handle_irq_pmq(struct b43legacy_wldev *dev)
@ -955,32 +962,77 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
u16 ram_offset,
u16 shm_size_offset, u8 rate)
{
int len;
const u8 *data;
B43legacy_WARN_ON(!dev->cached_beacon);
len = min((size_t)dev->cached_beacon->len,
unsigned int i, len, variable_len;
const struct ieee80211_mgmt *bcn;
const u8 *ie;
bool tim_found = 0;
bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
len = min((size_t)dev->wl->current_beacon->len,
0x200 - sizeof(struct b43legacy_plcp_hdr6));
data = (const u8 *)(dev->cached_beacon->data);
b43legacy_write_template_common(dev, data,
len, ram_offset,
b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
shm_size_offset, rate);
/* Find the position of the TIM and the DTIM_period value
* and write them to SHM. */
ie = bcn->u.beacon.variable;
variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
for (i = 0; i < variable_len - 2; ) {
uint8_t ie_id, ie_len;
ie_id = ie[i];
ie_len = ie[i + 1];
if (ie_id == 5) {
u16 tim_position;
u16 dtim_period;
/* This is the TIM Information Element */
/* Check whether the ie_len is in the beacon data range. */
if (variable_len < ie_len + 2 + i)
break;
/* A valid TIM is at least 4 bytes long. */
if (ie_len < 4)
break;
tim_found = 1;
tim_position = sizeof(struct b43legacy_plcp_hdr6);
tim_position += offsetof(struct ieee80211_mgmt,
u.beacon.variable);
tim_position += i;
dtim_period = ie[i + 3];
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
B43legacy_SHM_SH_TIMPOS, tim_position);
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
B43legacy_SHM_SH_DTIMP, dtim_period);
break;
}
i += ie_len + 2;
}
if (!tim_found) {
b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
"beacon template packet. AP or IBSS operation "
"may be broken.\n");
}
}
static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
u16 shm_offset, u16 size,
u8 rate)
struct ieee80211_rate *rate)
{
struct b43legacy_plcp_hdr4 plcp;
u32 tmp;
__le16 dur;
plcp.data = 0;
b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
dev->wl->vif,
size,
B43legacy_RATE_TO_100KBPS(rate));
rate);
/* Write PLCP in two parts and timing for packet transfer */
tmp = le32_to_cpu(plcp.data);
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,
@ -997,45 +1049,44 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
* 2) Patching duration field
* 3) Stripping TIM
*/
static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
u16 *dest_size, u8 rate)
static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
u16 *dest_size,
struct ieee80211_rate *rate)
{
const u8 *src_data;
u8 *dest_data;
u16 src_size;
u16 elem_size;
u16 src_pos;
u16 dest_pos;
u16 src_size, elem_size, src_pos, dest_pos;
__le16 dur;
struct ieee80211_hdr *hdr;
size_t ie_start;
B43legacy_WARN_ON(!dev->cached_beacon);
src_size = dev->cached_beacon->len;
src_data = (const u8 *)dev->cached_beacon->data;
src_size = dev->wl->current_beacon->len;
src_data = (const u8 *)dev->wl->current_beacon->data;
if (unlikely(src_size < 0x24)) {
b43legacydbg(dev->wl, "b43legacy_generate_probe_resp: "
"invalid beacon\n");
/* Get the start offset of the variable IEs in the packet. */
ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt,
u.beacon.variable));
if (B43legacy_WARN_ON(src_size < ie_start))
return NULL;
}
dest_data = kmalloc(src_size, GFP_ATOMIC);
if (unlikely(!dest_data))
return NULL;
/* 0x24 is offset of first variable-len Information-Element
* in beacon frame.
*/
memcpy(dest_data, src_data, 0x24);
src_pos = 0x24;
dest_pos = 0x24;
for (; src_pos < src_size - 2; src_pos += elem_size) {
/* Copy the static data and all Information Elements, except the TIM. */
memcpy(dest_data, src_data, ie_start);
src_pos = ie_start;
dest_pos = ie_start;
for ( ; src_pos < src_size - 2; src_pos += elem_size) {
elem_size = src_data[src_pos + 1] + 2;
if (src_data[src_pos] != 0x05) { /* TIM */
memcpy(dest_data + dest_pos, src_data + src_pos,
elem_size);
dest_pos += elem_size;
if (src_data[src_pos] == 5) {
/* This is the TIM. */
continue;
}
memcpy(dest_data + dest_pos, src_data + src_pos, elem_size);
dest_pos += elem_size;
}
*dest_size = dest_pos;
hdr = (struct ieee80211_hdr *)dest_data;
@ -1046,7 +1097,7 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
dur = ieee80211_generic_frame_duration(dev->wl->hw,
dev->wl->vif,
*dest_size,
B43legacy_RATE_TO_100KBPS(rate));
rate);
hdr->duration_id = dur;
return dest_data;
@ -1054,13 +1105,13 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
u16 ram_offset,
u16 shm_size_offset, u8 rate)
u16 shm_size_offset,
struct ieee80211_rate *rate)
{
u8 *probe_resp_data;
const u8 *probe_resp_data;
u16 size;
B43legacy_WARN_ON(!dev->cached_beacon);
size = dev->cached_beacon->len;
size = dev->wl->current_beacon->len;
probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate);
if (unlikely(!probe_resp_data))
return;
@ -1069,59 +1120,37 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
* all possible basic rates
*/
b43legacy_write_probe_resp_plcp(dev, 0x31A, size,
B43legacy_CCK_RATE_1MB);
&b43legacy_b_ratetable[0]);
b43legacy_write_probe_resp_plcp(dev, 0x32C, size,
B43legacy_CCK_RATE_2MB);
&b43legacy_b_ratetable[1]);
b43legacy_write_probe_resp_plcp(dev, 0x33E, size,
B43legacy_CCK_RATE_5MB);
&b43legacy_b_ratetable[2]);
b43legacy_write_probe_resp_plcp(dev, 0x350, size,
B43legacy_CCK_RATE_11MB);
&b43legacy_b_ratetable[3]);
size = min((size_t)size,
0x200 - sizeof(struct b43legacy_plcp_hdr6));
b43legacy_write_template_common(dev, probe_resp_data,
size, ram_offset,
shm_size_offset, rate);
shm_size_offset, rate->bitrate);
kfree(probe_resp_data);
}
static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev,
/* Asynchronously update the packet templates in template RAM.
* Locking: Requires wl->irq_lock to be locked. */
static void b43legacy_update_templates(struct b43legacy_wl *wl,
struct sk_buff *beacon)
{
if (dev->cached_beacon)
kfree_skb(dev->cached_beacon);
dev->cached_beacon = beacon;
/* This is the top half of the ansynchronous beacon update. The bottom
* half is the beacon IRQ. Beacon update must be asynchronous to avoid
* sending an invalid beacon. This can happen for example, if the
* firmware transmits a beacon while we are updating it. */
return 0;
}
static void b43legacy_update_templates(struct b43legacy_wldev *dev)
{
u32 status;
B43legacy_WARN_ON(!dev->cached_beacon);
b43legacy_write_beacon_template(dev, 0x68, 0x18,
B43legacy_CCK_RATE_1MB);
b43legacy_write_beacon_template(dev, 0x468, 0x1A,
B43legacy_CCK_RATE_1MB);
b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
B43legacy_CCK_RATE_11MB);
status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
status |= 0x03;
b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
}
static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
struct sk_buff *beacon)
{
int err;
err = b43legacy_refresh_cached_beacon(dev, beacon);
if (unlikely(err))
return;
b43legacy_update_templates(dev);
if (wl->current_beacon)
dev_kfree_skb_any(wl->current_beacon);
wl->current_beacon = beacon;
wl->beacon0_uploaded = 0;
wl->beacon1_uploaded = 0;
}
static void b43legacy_set_ssid(struct b43legacy_wldev *dev,
@ -1162,38 +1191,37 @@ static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
static void handle_irq_beacon(struct b43legacy_wldev *dev)
{
u32 status;
struct b43legacy_wl *wl = dev->wl;
u32 cmd;
if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
return;
dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
/* This is the bottom half of the asynchronous beacon update. */
if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
/* ACK beacon IRQ. */
b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
B43legacy_IRQ_BEACON);
dev->irq_savedstate |= B43legacy_IRQ_BEACON;
if (dev->cached_beacon)
kfree_skb(dev->cached_beacon);
dev->cached_beacon = NULL;
return;
}
if (!(status & 0x1)) {
b43legacy_write_beacon_template(dev, 0x68, 0x18,
cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) {
if (!wl->beacon0_uploaded) {
b43legacy_write_beacon_template(dev, 0x68,
B43legacy_SHM_SH_BTL0,
B43legacy_CCK_RATE_1MB);
status |= 0x1;
b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
status);
b43legacy_write_probe_resp_template(dev, 0x268,
B43legacy_SHM_SH_PRTLEN,
&__b43legacy_ratetable[3]);
wl->beacon0_uploaded = 1;
}
if (!(status & 0x2)) {
b43legacy_write_beacon_template(dev, 0x468, 0x1A,
cmd |= B43legacy_MACCMD_BEACON0_VALID;
}
if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) {
if (!wl->beacon1_uploaded) {
b43legacy_write_beacon_template(dev, 0x468,
B43legacy_SHM_SH_BTL1,
B43legacy_CCK_RATE_1MB);
status |= 0x2;
b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
status);
wl->beacon1_uploaded = 1;
}
cmd |= B43legacy_MACCMD_BEACON1_VALID;
}
b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
}
static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
@ -2550,13 +2578,15 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
mutex_lock(&wl->mutex);
dev = wl->current_dev;
phy = &dev->phy;
/* Switch the PHY mode (if necessary). */
switch (conf->phymode) {
case MODE_IEEE80211B:
switch (conf->channel->band) {
case IEEE80211_BAND_2GHZ:
if (phy->type == B43legacy_PHYTYPE_B)
new_phymode = B43legacy_PHYMODE_B;
break;
case MODE_IEEE80211G:
else
new_phymode = B43legacy_PHYMODE_G;
break;
default:
@ -2565,8 +2595,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
err = b43legacy_switch_phymode(wl, new_phymode);
if (err)
goto out_unlock_mutex;
dev = wl->current_dev;
phy = &dev->phy;
/* Disable IRQs while reconfiguring the device.
* This makes it possible to drop the spinlock throughout
@ -2582,8 +2610,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
if (conf->channel_val != phy->channel)
b43legacy_radio_selectchannel(dev, conf->channel_val, 0);
if (conf->channel->hw_value != phy->channel)
b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
/* Enable/Disable ShortSlot timing. */
if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
@ -2700,7 +2728,7 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->beacon)
b43legacy_refresh_templates(dev, conf->beacon);
b43legacy_update_templates(wl, conf->beacon);
}
b43legacy_write_mac_bssid_templates(dev);
}
@ -2918,7 +2946,7 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
{
/* Flags */
dev->reg124_set_0x4 = 0;
dev->dfq_valid = 0;
/* Stats */
memset(&dev->stats, 0, sizeof(dev->stats));
@ -3013,6 +3041,11 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
kfree(phy->tssi2dbm);
kfree(phy->lo_control);
phy->lo_control = NULL;
if (dev->wl->current_beacon) {
dev_kfree_skb_any(dev->wl->current_beacon);
dev->wl->current_beacon = NULL;
}
ssb_device_disable(dev->dev, 0);
ssb_bus_may_powerdown(dev->dev->bus);
}
@ -3337,6 +3370,41 @@ out_unlock:
return err;
}
static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
int aid, int set)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct sk_buff *beacon;
unsigned long flags;
/* We could modify the existing beacon and set the aid bit in the TIM
* field, but that would probably require resizing and moving of data
* within the beacon template. Simply request a new beacon and let
* mac80211 do the hard work. */
beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
if (unlikely(!beacon))
return -ENOMEM;
spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_update_templates(wl, beacon);
spin_unlock_irqrestore(&wl->irq_lock, flags);
return 0;
}
static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
struct sk_buff *beacon,
struct ieee80211_tx_control *ctl)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;
spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_update_templates(wl, beacon);
spin_unlock_irqrestore(&wl->irq_lock, flags);
return 0;
}
static const struct ieee80211_ops b43legacy_hw_ops = {
.tx = b43legacy_op_tx,
.conf_tx = b43legacy_op_conf_tx,
@ -3350,6 +3418,8 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
.start = b43legacy_op_start,
.stop = b43legacy_op_stop,
.set_retry_limit = b43legacy_op_set_retry_limit,
.set_tim = b43legacy_op_beacon_set_tim,
.beacon_update = b43legacy_op_ibss_beacon_update,
};
/* Hard-reset the chip. Do not call this directly.
@ -3398,48 +3468,19 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev,
int have_gphy)
{
struct ieee80211_hw *hw = dev->wl->hw;
struct ieee80211_hw_mode *mode;
struct b43legacy_phy *phy = &dev->phy;
int cnt = 0;
int err;
phy->possible_phymodes = 0;
for (; 1; cnt++) {
if (have_bphy) {
B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
mode = &phy->hwmodes[cnt];
mode->mode = MODE_IEEE80211B;
mode->num_channels = b43legacy_bg_chantable_size;
mode->channels = b43legacy_bg_chantable;
mode->num_rates = b43legacy_b_ratetable_size;
mode->rates = b43legacy_b_ratetable;
err = ieee80211_register_hwmode(hw, mode);
if (err)
return err;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&b43legacy_band_2GHz_BPHY;
phy->possible_phymodes |= B43legacy_PHYMODE_B;
have_bphy = 0;
continue;
}
if (have_gphy) {
B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
mode = &phy->hwmodes[cnt];
mode->mode = MODE_IEEE80211G;
mode->num_channels = b43legacy_bg_chantable_size;
mode->channels = b43legacy_bg_chantable;
mode->num_rates = b43legacy_g_ratetable_size;
mode->rates = b43legacy_g_ratetable;
err = ieee80211_register_hwmode(hw, mode);
if (err)
return err;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&b43legacy_band_2GHz_GPHY;
phy->possible_phymodes |= B43legacy_PHYMODE_G;
have_gphy = 0;
continue;
}
break;
}
return 0;

Просмотреть файл

@ -37,45 +37,48 @@
/* Extract the bitrate out of a CCK PLCP header. */
static u8 b43legacy_plcp_get_bitrate_cck(struct b43legacy_plcp_hdr6 *plcp)
static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
{
switch (plcp->raw[0]) {
case 0x0A:
return B43legacy_CCK_RATE_1MB;
return 0;
case 0x14:
return B43legacy_CCK_RATE_2MB;
return 1;
case 0x37:
return B43legacy_CCK_RATE_5MB;
return 2;
case 0x6E:
return B43legacy_CCK_RATE_11MB;
return 3;
}
B43legacy_BUG_ON(1);
return 0;
return -1;
}
/* Extract the bitrate out of an OFDM PLCP header. */
static u8 b43legacy_plcp_get_bitrate_ofdm(struct b43legacy_plcp_hdr6 *plcp)
static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
bool aphy)
{
int base = aphy ? 0 : 4;
switch (plcp->raw[0] & 0xF) {
case 0xB:
return B43legacy_OFDM_RATE_6MB;
return base + 0;
case 0xF:
return B43legacy_OFDM_RATE_9MB;
return base + 1;
case 0xA:
return B43legacy_OFDM_RATE_12MB;
return base + 2;
case 0xE:
return B43legacy_OFDM_RATE_18MB;
return base + 3;
case 0x9:
return B43legacy_OFDM_RATE_24MB;
return base + 4;
case 0xD:
return B43legacy_OFDM_RATE_36MB;
return base + 5;
case 0x8:
return B43legacy_OFDM_RATE_48MB;
return base + 6;
case 0xC:
return B43legacy_OFDM_RATE_54MB;
return base + 7;
}
B43legacy_BUG_ON(1);
return 0;
return -1;
}
u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
@ -192,7 +195,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
u16 fctl;
u8 rate;
u8 rate_fb;
struct ieee80211_rate *rate_fb;
int rate_ofdm;
int rate_fb_ofdm;
unsigned int plcp_fragment_len;
@ -204,16 +207,16 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
memset(txhdr, 0, sizeof(*txhdr));
rate = txctl->tx_rate;
rate = txctl->tx_rate->hw_value;
rate_ofdm = b43legacy_is_ofdm_rate(rate);
rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb);
rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate;
rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
txhdr->mac_frame_ctl = wlhdr->frame_control;
memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
/* Calculate duration for fallback rate */
if ((rate_fb == rate) ||
if ((rate_fb->hw_value == rate) ||
(wlhdr->duration_id & cpu_to_le16(0x8000)) ||
(wlhdr->duration_id == cpu_to_le16(0))) {
/* If the fallback rate equals the normal rate or the
@ -221,11 +224,10 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
* use the original dur_id field. */
txhdr->dur_fb = wlhdr->duration_id;
} else {
int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb);
txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
txctl->vif,
fragment_len,
fbrate_base100kbps);
rate_fb);
}
plcp_fragment_len = fragment_len + FCS_LEN;
@ -266,7 +268,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
rate);
b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
(&txhdr->plcp_fb), plcp_fragment_len,
rate_fb);
rate_fb->hw_value);
/* PHY TX Control word */
if (rate_ofdm)
@ -310,7 +312,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
int rts_rate_ofdm;
int rts_rate_fb_ofdm;
rts_rate = txctl->rts_cts_rate;
rts_rate = txctl->rts_cts_rate->hw_value;
rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
@ -536,19 +538,24 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
(phystat3 & B43legacy_RX_PHYST3_TRSTATE));
status.noise = dev->stats.link_noise;
status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI;
/* change to support A PHY */
if (phystat0 & B43legacy_RX_PHYST0_OFDM)
status.rate = b43legacy_plcp_get_bitrate_ofdm(plcp);
status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
else
status.rate = b43legacy_plcp_get_bitrate_cck(plcp);
status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
/*
* If monitors are present get full 64-bit timestamp. This
* code assumes we get to process the packet within 16 bits
* of timestamp, i.e. about 65 milliseconds after the PHY
* received the first symbol.
* All frames on monitor interfaces and beacons always need a full
* 64-bit timestamp. Monitor interfaces need it for diagnostic
* purposes and beacons for IBSS merging.
* This code assumes we get to process the packet within 16 bits
* of timestamp, i.e. about 65 milliseconds after the PHY received
* the first symbol.
*/
if (dev->wl->radiotap_enabled) {
if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
== (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
dev->wl->radiotap_enabled) {
u16 low_mactime_now;
b43legacy_tsf_read(dev, &status.mactime);
@ -564,14 +571,9 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
B43legacy_RX_CHAN_ID_SHIFT;
switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
case B43legacy_PHYTYPE_B:
status.phymode = MODE_IEEE80211B;
status.freq = chanid + 2400;
status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
break;
case B43legacy_PHYTYPE_G:
status.phymode = MODE_IEEE80211G;
status.band = IEEE80211_BAND_2GHZ;
status.freq = chanid + 2400;
status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
break;
default:
b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",

Просмотреть файл

@ -10349,9 +10349,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
remaining_bytes,
PCI_DMA_TODEVICE));
tfd->u.data.num_chunks =
cpu_to_le32(le32_to_cpu(tfd->u.data.num_chunks) +
1);
le32_add_cpu(&tfd->u.data.num_chunks, 1);
}
}

Просмотреть файл

@ -24,18 +24,10 @@ config IWL4965
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwl4965.ko.
config IWL4965_QOS
bool "Enable Wireless QoS in iwl4965 driver"
depends on IWL4965
---help---
This option will enable wireless quality of service (QoS) for the
iwl4965 driver.
config IWL4965_HT
bool "Enable 802.11n HT features in iwl4965 driver"
depends on EXPERIMENTAL
depends on IWL4965 && IWL4965_QOS
depends on n
depends on IWL4965
---help---
This option enables IEEE 802.11n High Throughput features
for the iwl4965 driver.
@ -105,13 +97,6 @@ config IWL3945
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwl3945.ko.
config IWL3945_QOS
bool "Enable Wireless QoS in iwl3945 driver"
depends on IWL3945
---help---
This option will enable wireless quality of service (QoS) for the
iwl3945 driver.
config IWL3945_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwl3945 drivers"
depends on IWL3945

Просмотреть файл

@ -515,14 +515,20 @@ struct iwl3945_qosparam_cmd {
#define STA_CONTROL_MODIFY_MSK 0x01
/* key flags __le16*/
#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7)
#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0)
#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1)
#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2)
#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3)
#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007)
#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000)
#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001)
#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002)
#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003)
#define STA_KEY_FLG_KEYID_POS 8
#define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
/* wep key is either from global key (0) or from station info array (1) */
#define STA_KEY_FLG_WEP_KEY_MAP_MSK __constant_cpu_to_le16(0x0008)
/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
/* Flags indicate whether to modify vs. don't change various station params */
#define STA_MODIFY_KEY_MASK 0x01
@ -546,7 +552,8 @@ struct iwl3945_keyinfo {
u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
u8 reserved1;
__le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
__le16 reserved2;
u8 key_offset;
u8 reserved2;
u8 key[16]; /* 16-byte unicast decryption key */
} __attribute__ ((packed));

Просмотреть файл

@ -324,7 +324,6 @@ struct iwl3945_eeprom {
/*=== CSR (control and status registers) ===*/
#define CSR_BASE (0x000)
#define CSR_SW_VER (CSR_BASE+0x000)
#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */

Просмотреть файл

@ -59,28 +59,28 @@
*
*/
#define _iwl3945_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
#define _iwl3945_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
#ifdef CONFIG_IWL3945_DEBUG
static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *iwl,
static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv,
u32 ofs, u32 val)
{
IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
_iwl3945_write32(iwl, ofs, val);
_iwl3945_write32(priv, ofs, val);
}
#define iwl3945_write32(iwl, ofs, val) \
__iwl3945_write32(__FILE__, __LINE__, iwl, ofs, val)
#define iwl3945_write32(priv, ofs, val) \
__iwl3945_write32(__FILE__, __LINE__, priv, ofs, val)
#else
#define iwl3945_write32(iwl, ofs, val) _iwl3945_write32(iwl, ofs, val)
#define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val)
#endif
#define _iwl3945_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
#define _iwl3945_read32(priv, ofs) readl((priv)->hw_base + (ofs))
#ifdef CONFIG_IWL3945_DEBUG
static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *iwl, u32 ofs)
static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs)
{
IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
return _iwl3945_read32(iwl, ofs);
return _iwl3945_read32(priv, ofs);
}
#define iwl3945_read32(iwl, ofs) __iwl3945_read32(__FILE__, __LINE__, iwl, ofs)
#define iwl3945_read32(priv, ofs) __iwl3945_read32(__FILE__, __LINE__, priv, ofs)
#else
#define iwl3945_read32(p, o) _iwl3945_read32(p, o)
#endif
@ -105,18 +105,13 @@ static inline int __iwl3945_poll_bit(const char *f, u32 l,
u32 bits, u32 mask, int timeout)
{
int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout);
if (unlikely(ret == -ETIMEDOUT))
IWL_DEBUG_IO
("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
addr, bits, mask, f, l);
else
IWL_DEBUG_IO
("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
addr, bits, mask, ret, f, l);
IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
addr, bits, mask,
unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
return ret;
}
#define iwl3945_poll_bit(iwl, addr, bits, mask, timeout) \
__iwl3945_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \
__iwl3945_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
#else
#define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t)
#endif
@ -321,8 +316,8 @@ static inline int __iwl3945_poll_direct_bit(const char *f, u32 l,
"- %s %d\n", addr, mask, ret, f, l);
return ret;
}
#define iwl3945_poll_direct_bit(iwl, addr, mask, timeout) \
__iwl3945_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
#define iwl3945_poll_direct_bit(priv, addr, mask, timeout) \
__iwl3945_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
#else
#define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit
#endif

Просмотреть файл

@ -100,14 +100,6 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
{-89, IWL_RATE_6M_INDEX}
};
static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = {
{-86, IWL_RATE_11M_INDEX},
{-88, IWL_RATE_5M_INDEX},
{-90, IWL_RATE_2M_INDEX},
{-92, IWL_RATE_1M_INDEX}
};
static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
{-60, IWL_RATE_54M_INDEX},
{-64, IWL_RATE_48M_INDEX},
@ -129,7 +121,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
#define IWL_RATE_MIN_SUCCESS_TH 8
#define IWL_RATE_DECREASE_TH 1920
static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
{
u32 index = 0;
u32 table_size = 0;
@ -138,21 +130,19 @@ static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
rssi = IWL_MIN_RSSI_VAL;
switch (mode) {
case MODE_IEEE80211G:
switch (band) {
case IEEE80211_BAND_2GHZ:
tpt_table = iwl3945_tpt_table_g;
table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
break;
case MODE_IEEE80211A:
case IEEE80211_BAND_5GHZ:
tpt_table = iwl3945_tpt_table_a;
table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
break;
default:
case MODE_IEEE80211B:
tpt_table = iwl3945_tpt_table_b;
table_size = ARRAY_SIZE(iwl3945_tpt_table_b);
BUG();
break;
}
@ -340,17 +330,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
* after assoc.. */
for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
if (sta->supp_rates & (1 << i)) {
sta->txrate = i;
if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) {
sta->txrate_idx = i;
break;
}
}
sta->last_txrate = sta->txrate;
sta->last_txrate_idx = sta->txrate_idx;
/* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */
if (local->hw.conf.phymode == MODE_IEEE80211A)
sta->last_txrate += IWL_FIRST_OFDM_RATE;
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
IWL_DEBUG_RATE("leave\n");
}
@ -429,17 +419,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
{
int next_rate = iwl3945_get_prev_ieee_rate(rate);
switch (priv->phymode) {
case MODE_IEEE80211A:
switch (priv->band) {
case IEEE80211_BAND_5GHZ:
if (rate == IWL_RATE_12M_INDEX)
next_rate = IWL_RATE_9M_INDEX;
else if (rate == IWL_RATE_6M_INDEX)
next_rate = IWL_RATE_6M_INDEX;
break;
/* XXX cannot be invoked in current mac80211 so not a regression
case MODE_IEEE80211B:
if (rate == IWL_RATE_11M_INDEX_TABLE)
next_rate = IWL_RATE_5M_INDEX_TABLE;
break;
*/
default:
break;
}
@ -465,15 +457,17 @@ static void rs_tx_status(void *priv_rate,
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct iwl3945_rs_sta *rs_sta;
struct ieee80211_supported_band *sband;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
IWL_DEBUG_RATE("enter\n");
retries = tx_resp->retry_count;
first_index = tx_resp->control.tx_rate;
/* FIXME : this is wrong */
first_index = &sband->bitrates[0] - tx_resp->control.tx_rate;
if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
IWL_DEBUG_RATE("leave: Rate out of bounds: %0x for %d\n",
tx_resp->control.tx_rate, first_index);
IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
return;
}
@ -561,14 +555,14 @@ static void rs_tx_status(void *priv_rate,
}
static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
u8 index, u16 rate_mask, int phymode)
u8 index, u16 rate_mask, enum ieee80211_band band)
{
u8 high = IWL_RATE_INVALID;
u8 low = IWL_RATE_INVALID;
/* 802.11A walks to the next literal adjacent rate in
* the rate table */
if (unlikely(phymode == MODE_IEEE80211A)) {
if (unlikely(band == IEEE80211_BAND_5GHZ)) {
int i;
u32 mask;
@ -639,7 +633,8 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
*
*/
static void rs_get_rate(void *priv_rate, struct net_device *dev,
struct ieee80211_hw_mode *mode, struct sk_buff *skb,
struct ieee80211_supported_band *band,
struct sk_buff *skb,
struct rate_selection *sel)
{
u8 low = IWL_RATE_INVALID;
@ -672,16 +667,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
is_multicast_ether_addr(hdr->addr1) ||
!sta || !sta->rate_ctrl_priv) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
sel->rate = rate_lowest(local, band, sta);
if (sta)
sta_info_put(sta);
return;
}
rate_mask = sta->supp_rates;
index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1);
rate_mask = sta->supp_rates[band->band];
index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
if (priv->phymode == (u8) MODE_IEEE80211A)
if (priv->band == IEEE80211_BAND_5GHZ)
rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
rs_sta = (void *)sta->rate_ctrl_priv;
@ -732,7 +727,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
current_tpt = window->average_tpt;
high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
local->hw.conf.phymode);
band->band);
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;
@ -810,11 +805,11 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
out:
sta->last_txrate = index;
if (priv->phymode == (u8) MODE_IEEE80211A)
sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE;
sta->last_txrate_idx = index;
if (priv->band == IEEE80211_BAND_5GHZ)
sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
else
sta->txrate = sta->last_txrate;
sta->txrate_idx = sta->last_txrate_idx;
sta_info_put(sta);
@ -945,8 +940,9 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
spin_lock_irqsave(&rs_sta->lock, flags);
rs_sta->tgg = 0;
switch (priv->phymode) {
case MODE_IEEE80211G:
switch (priv->band) {
case IEEE80211_BAND_2GHZ:
/* TODO: this always does G, not a regression */
if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
rs_sta->tgg = 1;
rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
@ -954,14 +950,11 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
rs_sta->expected_tpt = iwl3945_expected_tpt_g;
break;
case MODE_IEEE80211A:
case IEEE80211_BAND_5GHZ:
rs_sta->expected_tpt = iwl3945_expected_tpt_a;
break;
default:
IWL_WARNING("Invalid phymode. Defaulting to 802.11b\n");
case MODE_IEEE80211B:
rs_sta->expected_tpt = iwl3945_expected_tpt_b;
case IEEE80211_NUM_BANDS:
BUG();
break;
}
@ -974,8 +967,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi);
rs_sta->start_rate =
iwl3945_get_rate_index_by_rssi(rssi, priv->phymode);
rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
"%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,

Просмотреть файл

@ -247,7 +247,7 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
* the information provided in the skb from the hardware */
s8 signal = stats->ssi;
s8 noise = 0;
int rate = stats->rate;
int rate = stats->rate_idx;
u64 tsf = stats->mactime;
__le16 phy_flags_hw = rx_hdr->phy_flags;
@ -315,7 +315,6 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
IEEE80211_CHAN_2GHZ),
&iwl3945_rt->rt_chbitmask);
rate = iwl3945_rate_index_from_plcp(rate);
if (rate == -1)
iwl3945_rt->rt_rate = 0;
else
@ -387,11 +386,10 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
struct ieee80211_rx_status stats = {
.mactime = le64_to_cpu(rx_end->timestamp),
.freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)),
.channel = le16_to_cpu(rx_hdr->channel),
.phymode = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
MODE_IEEE80211G : MODE_IEEE80211A,
.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ,
.antenna = 0,
.rate = rx_hdr->rate,
.rate_idx = iwl3945_rate_index_from_plcp(rx_hdr->rate),
.flag = 0,
};
u8 network_packet;
@ -450,8 +448,6 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
stats.ssi, stats.noise, stats.signal,
rx_stats_sig_avg, rx_stats_noise_diff);
stats.freq = ieee80211chan2mhz(stats.channel);
/* can be covered by iwl3945_report_frame() in most cases */
/* IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */
@ -464,8 +460,9 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
IWL_DEBUG_STATS
("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n",
network_packet ? '*' : ' ',
stats.channel, stats.ssi, stats.ssi,
stats.ssi, stats.rate);
le16_to_cpu(rx_hdr->channel),
stats.ssi, stats.ssi,
stats.ssi, stats.rate_idx);
if (iwl3945_debug_level & (IWL_DL_RX))
/* Set "1" to report good data frames in groups of 100 */
@ -689,7 +686,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
struct ieee80211_hdr *hdr, int sta_id, int tx_id)
{
unsigned long flags;
u16 rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
u16 rate_index = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
u16 rate_mask;
int rate;
u8 rts_retry_limit;
@ -1552,14 +1549,14 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
.channel = priv->active_rxon.channel,
};
txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1;
txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
ch_info = iwl3945_get_channel_info(priv,
priv->phymode,
priv->band,
le16_to_cpu(priv->active_rxon.channel));
if (!ch_info) {
IWL_ERROR
("Failed to get channel info for channel %d [%d]\n",
le16_to_cpu(priv->active_rxon.channel), priv->phymode);
le16_to_cpu(priv->active_rxon.channel), priv->band);
return -EINVAL;
}
@ -2241,8 +2238,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
}
switch (priv->phymode) {
case MODE_IEEE80211A:
switch (priv->band) {
case IEEE80211_BAND_5GHZ:
IWL_DEBUG_RATE("Select A mode rate scale\n");
/* If one of the following CCK rates is used,
* have it fall back to the 6M OFDM rate */
@ -2257,8 +2254,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
break;
case MODE_IEEE80211B:
IWL_DEBUG_RATE("Select B mode rate scale\n");
case IEEE80211_BAND_2GHZ:
IWL_DEBUG_RATE("Select B/G mode rate scale\n");
/* If an OFDM rate is used, have it fall back to the
* 1M CCK rates */
for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
@ -2269,7 +2266,7 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
break;
default:
IWL_DEBUG_RATE("Select G mode rate scale\n");
WARN_ON(1);
break;
}
@ -2303,7 +2300,6 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
return -ENOMEM;
}
priv->hw_setting.ac_queue_count = AC_NUM;
priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE;
priv->hw_setting.max_pkt_size = 2342;
priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd);
@ -2311,6 +2307,8 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
priv->hw_setting.max_stations = IWL3945_STATION_COUNT;
priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID;
priv->hw_setting.tx_ant_num = 2;
return 0;
}

Просмотреть файл

@ -195,7 +195,7 @@ struct iwl3945_channel_info {
u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
u8 phymode; /* MODE_IEEE80211{A,B,G} */
enum ieee80211_band band;
/* Radio/DSP gain settings for each "normal" data Tx rate.
* These include, in addition to RF and DSP gain, a few fields for
@ -431,8 +431,6 @@ union iwl3945_ht_rate_supp {
};
};
#ifdef CONFIG_IWL3945_QOS
union iwl3945_qos_capabity {
struct {
u8 edca_count:4; /* bit 0-3 */
@ -460,7 +458,6 @@ struct iwl3945_qos_info {
union iwl3945_qos_capabity qos_cap;
struct iwl3945_qosparam_cmd def_qos_parm;
};
#endif /*CONFIG_IWL3945_QOS */
#define STA_PS_STATUS_WAKE 0
#define STA_PS_STATUS_SLEEP 1
@ -511,8 +508,8 @@ struct iwl3945_ibss_seq {
/**
* struct iwl3945_driver_hw_info
* @max_txq_num: Max # Tx queues supported
* @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
* @tx_cmd_len: Size of Tx command (but not including frame itself)
* @tx_ant_num: Number of TX antennas
* @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
* @rx_buf_size:
* @max_pkt_size:
@ -524,8 +521,8 @@ struct iwl3945_ibss_seq {
*/
struct iwl3945_driver_hw_info {
u16 max_txq_num;
u16 ac_queue_count;
u16 tx_cmd_len;
u16 tx_ant_num;
u16 max_rxq_size;
u32 rx_buf_size;
u32 max_pkt_size;
@ -699,14 +696,14 @@ struct iwl3945_priv {
struct list_head free_frames;
int frames_count;
u8 phymode;
enum ieee80211_band band;
int alloc_rxb_skb;
bool add_radiotap;
void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
struct iwl3945_rx_mem_buffer *rxb);
const struct ieee80211_hw_mode *modes;
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
/* spectrum measurement report caching */
@ -869,9 +866,7 @@ struct iwl3945_priv {
u16 assoc_capability;
u8 ps_mode;
#ifdef CONFIG_IWL3945_QOS
struct iwl3945_qos_info qos_data;
#endif /*CONFIG_IWL3945_QOS */
struct workqueue_struct *workqueue;
@ -937,13 +932,12 @@ static inline int is_channel_radar(const struct iwl3945_channel_info *ch_info)
static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info)
{
return ch_info->phymode == MODE_IEEE80211A;
return ch_info->band == IEEE80211_BAND_5GHZ;
}
static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info)
{
return ((ch_info->phymode == MODE_IEEE80211B) ||
(ch_info->phymode == MODE_IEEE80211G));
return ch_info->band == IEEE80211_BAND_2GHZ;
}
static inline int is_channel_passive(const struct iwl3945_channel_info *ch)
@ -967,7 +961,7 @@ static inline int iwl3945_rate_index_from_plcp(int plcp)
}
extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
const struct iwl3945_priv *priv, int phymode, u16 channel);
const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel);
/* Requires full declaration of iwl3945_priv before including */
#include "iwl-3945-io.h"

Просмотреть файл

@ -727,14 +727,20 @@ struct iwl4965_qosparam_cmd {
#define STA_CONTROL_MODIFY_MSK 0x01
/* key flags __le16*/
#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7)
#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0)
#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1)
#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2)
#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3)
#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007)
#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000)
#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001)
#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002)
#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003)
#define STA_KEY_FLG_KEYID_POS 8
#define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
/* wep key is either from global key (0) or from station info array (1) */
#define STA_KEY_FLG_MAP_KEY_MSK __constant_cpu_to_le16(0x0008)
/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
/* Flags indicate whether to modify vs. don't change various station params */
#define STA_MODIFY_KEY_MASK 0x01
@ -752,7 +758,8 @@ struct iwl4965_keyinfo {
u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
u8 reserved1;
__le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
__le16 reserved2;
u8 key_offset;
u8 reserved2;
u8 key[16]; /* 16-byte unicast decryption key */
} __attribute__ ((packed));
@ -1300,6 +1307,25 @@ struct iwl4965_tx_resp {
__le32 status; /* TX status (for aggregation status of 1st frame) */
} __attribute__ ((packed));
struct agg_tx_status {
__le16 status;
__le16 sequence;
} __attribute__ ((packed));
struct iwl4965_tx_resp_agg {
u8 frame_count; /* 1 no aggregation, >1 aggregation */
u8 reserved1;
u8 failure_rts;
u8 failure_frame;
__le32 rate_n_flags;
__le16 wireless_media_time;
__le16 reserved3;
__le32 pa_power1;
__le32 pa_power2;
struct agg_tx_status status; /* TX status (for aggregation status */
/* of 1st frame) */
} __attribute__ ((packed));
/*
* REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
*
@ -1313,9 +1339,8 @@ struct iwl4965_compressed_ba_resp {
/* Index of recipient (BA-sending) station in uCode's station table */
u8 sta_id;
u8 tid;
__le16 ba_seq_ctl;
__le32 ba_bitmap0;
__le32 ba_bitmap1;
__le16 seq_ctl;
__le64 bitmap;
__le16 scd_flow;
__le16 scd_ssn;
} __attribute__ ((packed));

Просмотреть файл

@ -413,7 +413,6 @@ struct iwl4965_eeprom {
/*=== CSR (control and status registers) ===*/
#define CSR_BASE (0x000)
#define CSR_SW_VER (CSR_BASE+0x000)
#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */

Просмотреть файл

@ -59,28 +59,28 @@
*
*/
#define _iwl4965_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
#define _iwl4965_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
#ifdef CONFIG_IWL4965_DEBUG
static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *iwl,
static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *priv,
u32 ofs, u32 val)
{
IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
_iwl4965_write32(iwl, ofs, val);
_iwl4965_write32(priv, ofs, val);
}
#define iwl4965_write32(iwl, ofs, val) \
__iwl4965_write32(__FILE__, __LINE__, iwl, ofs, val)
#define iwl4965_write32(priv, ofs, val) \
__iwl4965_write32(__FILE__, __LINE__, priv, ofs, val)
#else
#define iwl4965_write32(iwl, ofs, val) _iwl4965_write32(iwl, ofs, val)
#define iwl4965_write32(priv, ofs, val) _iwl4965_write32(priv, ofs, val)
#endif
#define _iwl4965_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
#define _iwl4965_read32(priv, ofs) readl((priv)->hw_base + (ofs))
#ifdef CONFIG_IWL4965_DEBUG
static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *iwl, u32 ofs)
static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *priv, u32 ofs)
{
IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
return _iwl4965_read32(iwl, ofs);
return _iwl4965_read32(priv, ofs);
}
#define iwl4965_read32(iwl, ofs) __iwl4965_read32(__FILE__, __LINE__, iwl, ofs)
#define iwl4965_read32(priv, ofs) __iwl4965_read32(__FILE__, __LINE__, priv, ofs)
#else
#define iwl4965_read32(p, o) _iwl4965_read32(p, o)
#endif
@ -105,18 +105,13 @@ static inline int __iwl4965_poll_bit(const char *f, u32 l,
u32 bits, u32 mask, int timeout)
{
int ret = _iwl4965_poll_bit(priv, addr, bits, mask, timeout);
if (unlikely(ret == -ETIMEDOUT))
IWL_DEBUG_IO
("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
addr, bits, mask, f, l);
else
IWL_DEBUG_IO
("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
addr, bits, mask, ret, f, l);
IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
addr, bits, mask,
unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
return ret;
}
#define iwl4965_poll_bit(iwl, addr, bits, mask, timeout) \
__iwl4965_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
#define iwl4965_poll_bit(priv, addr, bits, mask, timeout) \
__iwl4965_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
#else
#define iwl4965_poll_bit(p, a, b, m, t) _iwl4965_poll_bit(p, a, b, m, t)
#endif
@ -321,8 +316,8 @@ static inline int __iwl4965_poll_direct_bit(const char *f, u32 l,
"- %s %d\n", addr, mask, ret, f, l);
return ret;
}
#define iwl4965_poll_direct_bit(iwl, addr, mask, timeout) \
__iwl4965_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
#define iwl4965_poll_direct_bit(priv, addr, mask, timeout) \
__iwl4965_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
#else
#define iwl4965_poll_direct_bit _iwl4965_poll_direct_bit
#endif

Просмотреть файл

@ -83,7 +83,7 @@ struct iwl4965_rate_scale_data {
/**
* struct iwl4965_scale_tbl_info -- tx params and success history for all rates
*
* There are two of these in struct iwl_rate_scale_priv,
* There are two of these in struct iwl4965_lq_sta,
* one for "active", and one for "search".
*/
struct iwl4965_scale_tbl_info {
@ -98,8 +98,23 @@ struct iwl4965_scale_tbl_info {
struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
};
#ifdef CONFIG_IWL4965_HT
struct iwl4965_traffic_load {
unsigned long time_stamp; /* age of the oldest statistics */
u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time
* slice */
u32 total; /* total num of packets during the
* last TID_MAX_TIME_DIFF */
u8 queue_count; /* number of queues that has
* been used since the last cleanup */
u8 head; /* start of the circular buffer */
};
#endif /* CONFIG_IWL4965_HT */
/**
* struct iwl_rate_scale_priv -- driver's rate scaling private structure
* struct iwl4965_lq_sta -- driver's rate scaling private structure
*
* Pointer to this gets passed back and forth between driver and mac80211.
*/
@ -124,7 +139,7 @@ struct iwl4965_lq_sta {
u8 valid_antenna;
u8 is_green;
u8 is_dup;
u8 phymode;
enum ieee80211_band band;
u8 ibss_sta_added;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
@ -136,9 +151,16 @@ struct iwl4965_lq_sta {
struct iwl4965_link_quality_cmd lq;
struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
#ifdef CONFIG_IWL4965_HT
struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT];
u8 tx_agg_tid_en;
#endif
#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *rs_sta_dbgfs_scale_table_file;
struct dentry *rs_sta_dbgfs_stats_table_file;
#ifdef CONFIG_IWL4965_HT
struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
#endif
struct iwl4965_rate dbg_fixed;
struct iwl4965_priv *drv;
#endif
@ -269,6 +291,135 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
window->stamp = 0;
}
#ifdef CONFIG_IWL4965_HT
/*
* removes the old data from the statistics. All data that is older than
* TID_MAX_TIME_DIFF, will be deleted.
*/
static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time)
{
/* The oldest age we want to keep */
u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
while (tl->queue_count &&
(tl->time_stamp < oldest_time)) {
tl->total -= tl->packet_count[tl->head];
tl->packet_count[tl->head] = 0;
tl->time_stamp += TID_QUEUE_CELL_SPACING;
tl->queue_count--;
tl->head++;
if (tl->head >= TID_QUEUE_MAX_SIZE)
tl->head = 0;
}
}
/*
* increment traffic load value for tid and also remove
* any old values if passed the certain time period
*/
static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, u8 tid)
{
u32 curr_time = jiffies_to_msecs(jiffies);
u32 time_diff;
s32 index;
struct iwl4965_traffic_load *tl = NULL;
if (tid >= TID_MAX_LOAD_COUNT)
return;
tl = &lq_data->load[tid];
curr_time -= curr_time % TID_ROUND_VALUE;
/* Happens only for the first packet. Initialize the data */
if (!(tl->queue_count)) {
tl->total = 1;
tl->time_stamp = curr_time;
tl->queue_count = 1;
tl->head = 0;
tl->packet_count[0] = 1;
return;
}
time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
index = time_diff / TID_QUEUE_CELL_SPACING;
/* The history is too long: remove data that is older than */
/* TID_MAX_TIME_DIFF */
if (index >= TID_QUEUE_MAX_SIZE)
rs_tl_rm_old_stats(tl, curr_time);
index = (tl->head + index) % TID_QUEUE_MAX_SIZE;
tl->packet_count[index] = tl->packet_count[index] + 1;
tl->total = tl->total + 1;
if ((index + 1) > tl->queue_count)
tl->queue_count = index + 1;
}
/*
get the traffic load value for tid
*/
static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid)
{
u32 curr_time = jiffies_to_msecs(jiffies);
u32 time_diff;
s32 index;
struct iwl4965_traffic_load *tl = NULL;
if (tid >= TID_MAX_LOAD_COUNT)
return 0;
tl = &(lq_data->load[tid]);
curr_time -= curr_time % TID_ROUND_VALUE;
if (!(tl->queue_count))
return 0;
time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
index = time_diff / TID_QUEUE_CELL_SPACING;
/* The history is too long: remove data that is older than */
/* TID_MAX_TIME_DIFF */
if (index >= TID_QUEUE_MAX_SIZE)
rs_tl_rm_old_stats(tl, curr_time);
return tl->total;
}
static void rs_tl_turn_on_agg_for_tid(struct iwl4965_priv *priv,
struct iwl4965_lq_sta *lq_data, u8 tid,
struct sta_info *sta)
{
unsigned long state;
DECLARE_MAC_BUF(mac);
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
state = sta->ampdu_mlme.tid_tx[tid].state;
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
if (state == HT_AGG_STATE_IDLE &&
rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
print_mac(mac, sta->addr), tid);
ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
}
}
static void rs_tl_turn_on_agg(struct iwl4965_priv *priv, u8 tid,
struct iwl4965_lq_sta *lq_data,
struct sta_info *sta)
{
if ((tid < TID_MAX_LOAD_COUNT))
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
else if (tid == IWL_AGG_ALL_TID)
for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
}
#endif /* CONFIG_IWLWIFI_HT */
/**
* rs_collect_tx_data - Update the success/failure sliding window
*
@ -277,7 +428,8 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
* packets.
*/
static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
int scale_index, s32 tpt, u32 status)
int scale_index, s32 tpt, int retries,
int successes)
{
struct iwl4965_rate_scale_data *window = NULL;
u64 mask;
@ -298,26 +450,33 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
* subtract "1" from the success counter (this is the main reason
* we keep these bitmaps!).
*/
while (retries > 0) {
if (window->counter >= win_size) {
window->counter = win_size - 1;
mask = 1;
mask = (mask << (win_size - 1));
if ((window->data & mask)) {
if (window->data & mask) {
window->data &= ~mask;
window->success_counter = window->success_counter - 1;
window->success_counter =
window->success_counter - 1;
}
}
/* Increment frames-attempted counter */
window->counter = window->counter + 1;
window->counter++;
/* Shift bitmap by one frame (throw away oldest history),
* OR in "1", and increment "success" if this frame was successful. */
* OR in "1", and increment "success" if this
* frame was successful. */
mask = window->data;
window->data = (mask << 1);
if (status != 0) {
if (successes > 0) {
window->success_counter = window->success_counter + 1;
window->data |= 0x1;
successes--;
}
retries--;
}
/* Calculate current success ratio, avoid divide-by-0! */
@ -404,7 +563,8 @@ static void rs_mcs_from_tbl(struct iwl4965_rate *mcs_rate,
* fill "search" or "active" tx mode table.
*/
static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
int phymode, struct iwl4965_scale_tbl_info *tbl,
enum ieee80211_band band,
struct iwl4965_scale_tbl_info *tbl,
int *rate_idx)
{
int index;
@ -429,7 +589,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
tbl->lq_type = LQ_NONE;
else {
if (phymode == MODE_IEEE80211A)
if (band == IEEE80211_BAND_5GHZ)
tbl->lq_type = LQ_A;
else
tbl->lq_type = LQ_G;
@ -607,7 +767,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta,
if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
switch_to_legacy = 1;
scale_index = rs_ht_to_legacy[scale_index];
if (lq_sta->phymode == MODE_IEEE80211A)
if (lq_sta->band == IEEE80211_BAND_5GHZ)
tbl->lq_type = LQ_A;
else
tbl->lq_type = LQ_G;
@ -625,7 +785,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta,
/* Mask with station rate restriction */
if (is_legacy(tbl->lq_type)) {
/* supp_rates has no CCK bits in A mode */
if (lq_sta->phymode == (u8) MODE_IEEE80211A)
if (lq_sta->band == IEEE80211_BAND_5GHZ)
rate_mask = (u16)(rate_mask &
(lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
else
@ -677,6 +837,11 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
return;
/* This packet was aggregated but doesn't carry rate scale info */
if ((tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) &&
!(tx_resp->flags & IEEE80211_TX_STATUS_AMPDU))
return;
retries = tx_resp->retry_count;
if (retries > 15)
@ -719,9 +884,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
search_win = (struct iwl4965_rate_scale_data *)
&(search_tbl->win[0]);
tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value;
rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
&tbl_type, &rs_index);
if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) {
IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n",
@ -754,7 +919,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
* Each tx attempt steps one entry deeper in the rate table. */
tx_mcs.rate_n_flags =
le32_to_cpu(table->rs_table[index].rate_n_flags);
rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
&tbl_type, &rs_index);
/* If type matches "search" table,
@ -766,7 +931,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
tpt = search_tbl->expected_tpt[rs_index];
else
tpt = 0;
rs_collect_tx_data(search_win, rs_index, tpt, 0);
rs_collect_tx_data(search_win, rs_index, tpt, 1, 0);
/* Else if type matches "current/active" table,
* add failure to "current/active" history */
@ -777,7 +942,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
tpt = curr_tbl->expected_tpt[rs_index];
else
tpt = 0;
rs_collect_tx_data(window, rs_index, tpt, 0);
rs_collect_tx_data(window, rs_index, tpt, 1, 0);
}
/* If not searching for a new mode, increment failed counter
@ -795,12 +960,12 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
* else look up the rate that was, finally, successful.
*/
if (!tx_resp->retry_count)
tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value;
else
tx_mcs.rate_n_flags =
le32_to_cpu(table->rs_table[index].rate_n_flags);
rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
&tbl_type, &rs_index);
/* Update frame history window with "success" if Tx got ACKed ... */
@ -818,9 +983,13 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
tpt = search_tbl->expected_tpt[rs_index];
else
tpt = 0;
rs_collect_tx_data(search_win,
rs_index, tpt, status);
if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
rs_collect_tx_data(search_win, rs_index, tpt,
tx_resp->ampdu_ack_len,
tx_resp->ampdu_ack_map);
else
rs_collect_tx_data(search_win, rs_index, tpt,
1, status);
/* Else if type matches "current/active" table,
* add final tx status to "current/active" history */
} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
@ -830,17 +999,29 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
tpt = curr_tbl->expected_tpt[rs_index];
else
tpt = 0;
rs_collect_tx_data(window, rs_index, tpt, status);
if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
rs_collect_tx_data(window, rs_index, tpt,
tx_resp->ampdu_ack_len,
tx_resp->ampdu_ack_map);
else
rs_collect_tx_data(window, rs_index, tpt,
1, status);
}
/* If not searching for new mode, increment success/failed counter
* ... these help determine when to start searching again */
if (lq_sta->stay_in_tbl) {
if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) {
lq_sta->total_success += tx_resp->ampdu_ack_map;
lq_sta->total_failed +=
(tx_resp->ampdu_ack_len - tx_resp->ampdu_ack_map);
} else {
if (status)
lq_sta->total_success++;
else
lq_sta->total_failed++;
}
}
/* See if there's a better rate or modulation mode to try. */
rs_rate_scale_perform(priv, dev, hdr, sta);
@ -1325,6 +1506,7 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv,
break;
case IWL_SISO_SWITCH_GI:
IWL_DEBUG_HT("LQ: SISO SWITCH TO GI\n");
memcpy(search_tbl, tbl, sz);
search_tbl->action = 0;
if (search_tbl->is_SGI)
@ -1390,6 +1572,7 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
case IWL_MIMO_SWITCH_ANTENNA_B:
IWL_DEBUG_HT("LQ: MIMO SWITCH TO SISO\n");
/* Set up new search table for SISO */
memcpy(search_tbl, tbl, sz);
search_tbl->lq_type = LQ_SISO;
@ -1574,6 +1757,10 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
u8 active_tbl = 0;
u8 done_search = 0;
u16 high_low;
#ifdef CONFIG_IWL4965_HT
u8 tid = MAX_TID_COUNT;
__le16 *qc;
#endif
IWL_DEBUG_RATE("rate scale calculate new rate for skb\n");
@ -1594,6 +1781,13 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
}
lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
#ifdef CONFIG_IWL4965_HT
qc = ieee80211_get_qos_ctrl(hdr);
if (qc) {
tid = (u8)(le16_to_cpu(*qc) & 0xf);
rs_tl_add_packet(lq_sta, tid);
}
#endif
/*
* Select rate-scale / modulation-mode table to work with in
* the rest of this function: "search" if searching for better
@ -1608,7 +1802,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
is_green = lq_sta->is_green;
/* current tx rate */
index = sta->last_txrate;
index = sta->last_txrate_idx;
IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index,
tbl->lq_type);
@ -1621,7 +1815,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
/* mask with station rate restriction */
if (is_legacy(tbl->lq_type)) {
if (lq_sta->phymode == (u8) MODE_IEEE80211A)
if (lq_sta->band == IEEE80211_BAND_5GHZ)
/* supp_rates has no CCK bits in A mode */
rate_scale_index_msk = (u16) (rate_mask &
(lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
@ -1914,15 +2108,14 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
* mode for a while before next round of mode comparisons. */
if (lq_sta->enable_counter &&
(lq_sta->action_counter >= IWL_ACTION_LIMIT)) {
#ifdef CONFIG_IWL4965_HT_AGG
/* If appropriate, set up aggregation! */
if ((lq_sta->last_tpt > TID_AGG_TPT_THREHOLD) &&
(priv->lq_mngr.agg_ctrl.auto_agg)) {
priv->lq_mngr.agg_ctrl.tid_retry =
TID_ALL_SPECIFIED;
schedule_work(&priv->agg_work);
#ifdef CONFIG_IWL4965_HT
if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
(lq_sta->tx_agg_tid_en & (1 << tid)) &&
(tid != MAX_TID_COUNT)) {
IWL_DEBUG_HT("try to aggregate tid %d\n", tid);
rs_tl_turn_on_agg(priv, tid, lq_sta, sta);
}
#endif /*CONFIG_IWL4965_HT_AGG */
#endif /*CONFIG_IWL4965_HT */
lq_sta->action_counter = 0;
rs_set_stay_in_table(0, lq_sta);
}
@ -1942,15 +2135,15 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
out:
rs_mcs_from_tbl(&tbl->current_rate, tbl, index, is_green);
i = index;
sta->last_txrate = i;
sta->last_txrate_idx = i;
/* sta->txrate is an index to A mode rates which start
/* sta->txrate_idx is an index to A mode rates which start
* at IWL_FIRST_OFDM_RATE
*/
if (lq_sta->phymode == (u8) MODE_IEEE80211A)
sta->txrate = i - IWL_FIRST_OFDM_RATE;
if (lq_sta->band == IEEE80211_BAND_5GHZ)
sta->txrate_idx = i - IWL_FIRST_OFDM_RATE;
else
sta->txrate = i;
sta->txrate_idx = i;
return;
}
@ -1972,7 +2165,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
goto out;
lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
i = sta->last_txrate;
i = sta->last_txrate_idx;
if ((lq_sta->lq.sta_id == 0xff) &&
(priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
@ -1996,7 +2189,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
mcs_rate.rate_n_flags |= RATE_MCS_CCK_MSK;
tbl->antenna_type = ANT_AUX;
rs_get_tbl_info_from_mcs(&mcs_rate, priv->phymode, tbl, &rate_idx);
rs_get_tbl_info_from_mcs(&mcs_rate, priv->band, tbl, &rate_idx);
if (!rs_is_ant_connected(priv->valid_antenna, tbl->antenna_type))
rs_toggle_antenna(&mcs_rate, tbl);
@ -2010,7 +2203,8 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
}
static void rs_get_rate(void *priv_rate, struct net_device *dev,
struct ieee80211_hw_mode *mode, struct sk_buff *skb,
struct ieee80211_supported_band *sband,
struct sk_buff *skb,
struct rate_selection *sel)
{
@ -2032,14 +2226,14 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
fc = le16_to_cpu(hdr->frame_control);
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
!sta || !sta->rate_ctrl_priv) {
sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
sel->rate = rate_lowest(local, sband, sta);
if (sta)
sta_info_put(sta);
return;
}
lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
i = sta->last_txrate;
i = sta->last_txrate_idx;
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
!lq_sta->ibss_sta_added) {
@ -2064,7 +2258,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
done:
if ((i < 0) || (i > IWL_RATE_COUNT)) {
sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
sel->rate = rate_lowest(local, sband, sta);
return;
}
sta_info_put(sta);
@ -2099,13 +2293,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
{
int i, j;
struct ieee80211_conf *conf = &local->hw.conf;
struct ieee80211_hw_mode *mode = local->oper_hw_mode;
struct ieee80211_supported_band *sband;
struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
struct iwl4965_lq_sta *lq_sta = priv_sta;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
lq_sta->flush_timer = 0;
lq_sta->supp_rates = sta->supp_rates;
sta->txrate = 3;
lq_sta->supp_rates = sta->supp_rates[sband->band];
sta->txrate_idx = 3;
for (j = 0; j < LQ_SIZE; j++)
for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i]));
@ -2140,15 +2336,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
}
/* Find highest tx rate supported by hardware and destination station */
for (i = 0; i < mode->num_rates; i++) {
if ((sta->supp_rates & BIT(i)) &&
(mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
sta->txrate = i;
}
sta->last_txrate = sta->txrate;
for (i = 0; i < sband->n_bitrates; i++)
if (sta->supp_rates[sband->band] & BIT(i))
sta->txrate_idx = i;
sta->last_txrate_idx = sta->txrate_idx;
/* WTF is with this bogus comment? A doesn't have cck rates */
/* For MODE_IEEE80211A, cck rates are at end of rate table */
if (local->hw.conf.phymode == MODE_IEEE80211A)
sta->last_txrate += IWL_FIRST_OFDM_RATE;
if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_dup = 0;
lq_sta->valid_antenna = priv->valid_antenna;
@ -2157,7 +2353,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
lq_sta->active_rate = priv->active_rate;
lq_sta->active_rate &= ~(0x1000);
lq_sta->active_rate_basic = priv->active_rate_basic;
lq_sta->phymode = priv->phymode;
lq_sta->band = priv->band;
#ifdef CONFIG_IWL4965_HT
/*
* active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
@ -2180,6 +2376,8 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
IWL_DEBUG_HT("SISO RATE 0x%X MIMO RATE 0x%X\n",
lq_sta->active_siso_rate,
lq_sta->active_mimo_rate);
/* as default allow aggregation for all tids */
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
#endif /*CONFIG_IWL4965_HT*/
#ifdef CONFIG_MAC80211_DEBUGFS
lq_sta->drv = priv;
@ -2207,7 +2405,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
rs_dbgfs_set_mcs(lq_sta, tx_mcs, index);
/* Interpret rate_n_flags */
rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->phymode,
rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->band,
&tbl_type, &rate_idx);
/* How many times should we repeat the initial rate? */
@ -2261,7 +2459,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
index++;
}
rs_get_tbl_info_from_mcs(&new_rate, lq_sta->phymode, &tbl_type,
rs_get_tbl_info_from_mcs(&new_rate, lq_sta->band, &tbl_type,
&rate_idx);
/* Indicate to uCode which entries might be MIMO.
@ -2323,12 +2521,6 @@ static void rs_clear(void *priv_rate)
IWL_DEBUG_RATE("enter\n");
priv->lq_mngr.lq_ready = 0;
#ifdef CONFIG_IWL4965_HT
#ifdef CONFIG_IWL4965_HT_AGG
if (priv->lq_mngr.agg_ctrl.granted_ba)
iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);
#endif /*CONFIG_IWL4965_HT_AGG */
#endif /* CONFIG_IWL4965_HT */
IWL_DEBUG_RATE("leave\n");
}
@ -2354,7 +2546,7 @@ static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta,
{
u32 base_rate;
if (lq_sta->phymode == (u8) MODE_IEEE80211A)
if (lq_sta->band == IEEE80211_BAND_5GHZ)
base_rate = 0x800D;
else
base_rate = 0x820A;
@ -2495,6 +2687,12 @@ static void rs_add_debugfs(void *priv, void *priv_sta,
lq_sta->rs_sta_dbgfs_stats_table_file =
debugfs_create_file("rate_stats_table", 0600, dir,
lq_sta, &rs_sta_dbgfs_stats_table_ops);
#ifdef CONFIG_IWL4965_HT
lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
debugfs_create_u8("tx_agg_tid_enable", 0600, dir,
&lq_sta->tx_agg_tid_en);
#endif
}
static void rs_remove_debugfs(void *priv, void *priv_sta)
@ -2502,6 +2700,9 @@ static void rs_remove_debugfs(void *priv, void *priv_sta)
struct iwl4965_lq_sta *lq_sta = priv_sta;
debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
#ifdef CONFIG_IWL4965_HT
debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
#endif
}
#endif
@ -2605,7 +2806,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d "
"active_search %d rate index %d\n", lq_type, antenna,
lq_sta->search_better_tbl, sta->last_txrate);
lq_sta->search_better_tbl, sta->last_txrate_idx);
sta_info_put(sta);
return cnt;

Просмотреть файл

@ -212,6 +212,18 @@ enum {
#define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */
/* load per tid defines for A-MPDU activation */
#define IWL_AGG_TPT_THREHOLD 0
#define IWL_AGG_LOAD_THRESHOLD 10
#define IWL_AGG_ALL_TID 0xff
#define TID_QUEUE_CELL_SPACING 50 /*mS */
#define TID_QUEUE_MAX_SIZE 20
#define TID_ROUND_VALUE 5 /* mS */
#define TID_MAX_LOAD_COUNT 8
#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
extern const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT];
enum iwl4965_table_type {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -206,7 +206,7 @@ struct iwl4965_channel_info {
u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
u8 phymode; /* MODE_IEEE80211{A,B,G} */
enum ieee80211_band band;
/* Radio/DSP gain settings for each "normal" data Tx rate.
* These include, in addition to RF and DSP gain, a few fields for
@ -433,7 +433,6 @@ struct iwl4965_rx_queue {
#define IWL_INVALID_VALUE -1
#ifdef CONFIG_IWL4965_HT
#ifdef CONFIG_IWL4965_HT_AGG
/**
* struct iwl4965_ht_agg -- aggregation status while waiting for block-ack
* @txq_id: Tx queue used for Tx attempt
@ -453,19 +452,22 @@ struct iwl4965_ht_agg {
u16 frame_count;
u16 wait_for_ba;
u16 start_idx;
u32 bitmap0;
u32 bitmap1;
u64 bitmap;
u32 rate_n_flags;
#define IWL_AGG_OFF 0
#define IWL_AGG_ON 1
#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
#define IWL_EMPTYING_HW_QUEUE_DELBA 3
u8 state;
};
#endif /* CONFIG_IWL4965_HT_AGG */
#endif /* CONFIG_IWL4965_HT */
struct iwl4965_tid_data {
u16 seq_number;
u16 tfds_in_queue;
#ifdef CONFIG_IWL4965_HT
#ifdef CONFIG_IWL4965_HT_AGG
struct iwl4965_ht_agg agg;
#endif /* CONFIG_IWL4965_HT_AGG */
#endif /* CONFIG_IWL4965_HT */
};
@ -508,8 +510,6 @@ struct iwl_ht_info {
};
#endif /*CONFIG_IWL4965_HT */
#ifdef CONFIG_IWL4965_QOS
union iwl4965_qos_capabity {
struct {
u8 edca_count:4; /* bit 0-3 */
@ -537,7 +537,6 @@ struct iwl4965_qos_info {
union iwl4965_qos_capabity qos_cap;
struct iwl4965_qosparam_cmd def_qos_parm;
};
#endif /*CONFIG_IWL4965_QOS */
#define STA_PS_STATUS_WAKE 0
#define STA_PS_STATUS_SLEEP 1
@ -581,8 +580,8 @@ struct iwl4965_ibss_seq {
/**
* struct iwl4965_driver_hw_info
* @max_txq_num: Max # Tx queues supported
* @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
* @tx_cmd_len: Size of Tx command (but not including frame itself)
* @tx_ant_num: Number of TX antennas
* @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
* @rx_buffer_size:
* @max_rxq_log: Log-base-2 of max_rxq_size
@ -593,8 +592,8 @@ struct iwl4965_ibss_seq {
*/
struct iwl4965_driver_hw_info {
u16 max_txq_num;
u16 ac_queue_count;
u16 tx_cmd_len;
u16 tx_ant_num;
u16 max_rxq_size;
u32 rx_buf_size;
u32 max_pkt_size;
@ -743,7 +742,7 @@ extern u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *bssid);
extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel);
extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index);
extern int iwl4965_queue_space(const struct iwl4965_queue *q);
struct iwl4965_priv;
/*
@ -762,31 +761,29 @@ extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode);
extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv);
extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags,
u8 force);
extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode,
extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv,
enum ieee80211_band band,
u16 channel,
const struct iwl4965_eeprom_channel *eeprom_ch,
u8 fat_extension_channel);
extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv);
#ifdef CONFIG_IWL4965_HT
extern void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info,
int mode);
extern void iwl4965_set_rxon_ht(struct iwl4965_priv *priv,
void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info,
enum ieee80211_band band);
void iwl4965_set_rxon_ht(struct iwl4965_priv *priv,
struct iwl_ht_info *ht_info);
extern void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
struct ieee80211_ht_info *sta_ht_inf);
extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 ssn);
#ifdef CONFIG_IWL4965_HT_AGG
extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da,
u16 tid, u16 *start_seq_num);
extern int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da,
u16 tid, int generator);
extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid);
extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
struct ieee80211_hdr *hdr);
#endif /* CONFIG_IWL4965_HT_AGG */
const u8 *addr, u16 tid, u16 *ssn);
int iwl4965_check_empty_hw_queue(struct iwl4965_priv *priv, int sta_id,
u8 tid, int txq_id);
#else
static inline void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info,
enum ieee80211_band band) {}
#endif /*CONFIG_IWL4965_HT */
/* Structures, enum, and defines specific to the 4965 */
@ -798,18 +795,6 @@ struct iwl4965_kw {
size_t size;
};
#define TID_QUEUE_CELL_SPACING 50 /*mS */
#define TID_QUEUE_MAX_SIZE 20
#define TID_ROUND_VALUE 5 /* mS */
#define TID_MAX_LOAD_COUNT 8
#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
#define TID_ALL_ENABLED 0x7f
#define TID_ALL_SPECIFIED 0xff
#define TID_AGG_TPT_THREHOLD 0x0
#define IWL_CHANNEL_WIDTH_20MHZ 0
#define IWL_CHANNEL_WIDTH_40MHZ 1
@ -834,37 +819,7 @@ struct iwl4965_kw {
#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
struct iwl4965_traffic_load {
unsigned long time_stamp;
u32 packet_count[TID_QUEUE_MAX_SIZE];
u8 queue_count;
u8 head;
u32 total;
};
#ifdef CONFIG_IWL4965_HT_AGG
/**
* struct iwl4965_agg_control
* @requested_ba: bit map of tids requesting aggregation/block-ack
* @granted_ba: bit map of tids granted aggregation/block-ack
*/
struct iwl4965_agg_control {
unsigned long next_retry;
u32 wait_for_agg_status;
u32 tid_retry;
u32 requested_ba;
u32 granted_ba;
u8 auto_agg;
u32 tid_traffic_load_threshold;
u32 ba_timeout;
struct iwl4965_traffic_load traffic_load[TID_MAX_LOAD_COUNT];
};
#endif /*CONFIG_IWL4965_HT_AGG */
struct iwl4965_lq_mngr {
#ifdef CONFIG_IWL4965_HT_AGG
struct iwl4965_agg_control agg_ctrl;
#endif
spinlock_t lock;
s32 max_window_size;
s32 *expected_tpt;
@ -877,7 +832,6 @@ struct iwl4965_lq_mngr {
u8 lq_ready;
};
/* Sensitivity and chain noise calibration */
#define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1)
#define INITIALIZATION_VALUE 0xFFFF
@ -1025,14 +979,14 @@ struct iwl4965_priv {
struct list_head free_frames;
int frames_count;
u8 phymode;
enum ieee80211_band band;
int alloc_rxb_skb;
bool add_radiotap;
void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv,
struct iwl4965_rx_mem_buffer *rxb);
const struct ieee80211_hw_mode *modes;
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
/* spectrum measurement report caching */
@ -1216,9 +1170,7 @@ struct iwl4965_priv {
u16 assoc_capability;
u8 ps_mode;
#ifdef CONFIG_IWL4965_QOS
struct iwl4965_qos_info qos_data;
#endif /*CONFIG_IWL4965_QOS */
struct workqueue_struct *workqueue;
@ -1265,10 +1217,6 @@ struct iwl4965_priv {
#endif
struct work_struct statistics_work;
struct timer_list statistics_periodic;
#ifdef CONFIG_IWL4965_HT_AGG
struct work_struct agg_work;
#endif
}; /*iwl4965_priv */
static inline int iwl4965_is_associated(struct iwl4965_priv *priv)
@ -1295,13 +1243,12 @@ static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info)
static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info)
{
return ch_info->phymode == MODE_IEEE80211A;
return ch_info->band == IEEE80211_BAND_5GHZ;
}
static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info)
{
return ((ch_info->phymode == MODE_IEEE80211B) ||
(ch_info->phymode == MODE_IEEE80211G));
return ch_info->band == IEEE80211_BAND_2GHZ;
}
static inline int is_channel_passive(const struct iwl4965_channel_info *ch)
@ -1315,7 +1262,7 @@ static inline int is_channel_ibss(const struct iwl4965_channel_info *ch)
}
extern const struct iwl4965_channel_info *iwl4965_get_channel_info(
const struct iwl4965_priv *priv, int phymode, u16 channel);
const struct iwl4965_priv *priv, enum ieee80211_band band, u16 channel);
/* Requires full declaration of iwl4965_priv before including */
#include "iwl-4965-io.h"

Просмотреть файл

@ -91,7 +91,7 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
#define VS
#endif
#define IWLWIFI_VERSION "1.2.23k" VD VS
#define IWLWIFI_VERSION "1.2.26k" VD VS
#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation"
#define DRV_VERSION IWLWIFI_VERSION
@ -116,16 +116,10 @@ static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
return NULL;
}
static const struct ieee80211_hw_mode *iwl3945_get_hw_mode(
struct iwl3945_priv *priv, int mode)
static const struct ieee80211_supported_band *iwl3945_get_band(
struct iwl3945_priv *priv, enum ieee80211_band band)
{
int i;
for (i = 0; i < 3; i++)
if (priv->modes[i].mode == mode)
return &priv->modes[i];
return NULL;
return priv->hw->wiphy->bands[band];
}
static int iwl3945_is_empty_essid(const char *essid, int essid_len)
@ -547,7 +541,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
station->sta.sta.sta_id = index;
station->sta.station_flags = 0;
if (priv->phymode == MODE_IEEE80211A)
if (priv->band == IEEE80211_BAND_5GHZ)
rate = IWL_RATE_6M_PLCP;
else
rate = IWL_RATE_1M_PLCP;
@ -894,35 +888,37 @@ int iwl3945_send_statistics_request(struct iwl3945_priv *priv)
/**
* iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON
* @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
* @channel: Any channel valid for the requested phymode
* @band: 2.4 or 5 GHz band
* @channel: Any channel valid for the requested band
* In addition to setting the staging RXON, priv->phymode is also set.
* In addition to setting the staging RXON, priv->band is also set.
*
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
* in the staging RXON flag structure based on the phymode
* in the staging RXON flag structure based on the band
*/
static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel)
static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv,
enum ieee80211_band band,
u16 channel)
{
if (!iwl3945_get_channel_info(priv, phymode, channel)) {
if (!iwl3945_get_channel_info(priv, band, channel)) {
IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
channel, phymode);
channel, band);
return -EINVAL;
}
if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
(priv->phymode == phymode))
(priv->band == band))
return 0;
priv->staging_rxon.channel = cpu_to_le16(channel);
if (phymode == MODE_IEEE80211A)
if (band == IEEE80211_BAND_5GHZ)
priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
else
priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
priv->phymode = phymode;
priv->band = band;
IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
return 0;
}
@ -1210,8 +1206,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
return -EIO;
}
/* Init the hardware's rate fallback order based on the
* phymode */
/* Init the hardware's rate fallback order based on the band */
rc = iwl3945_init_hw_rate_table(priv);
if (rc) {
IWL_ERROR("Error setting HW rate table: %02X\n", rc);
@ -1915,7 +1910,6 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
/*
* QoS support
*/
#ifdef CONFIG_IWL3945_QOS
static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv,
struct iwl3945_qosparam_cmd *qos)
{
@ -2044,7 +2038,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
}
}
#endif /* CONFIG_IWL3945_QOS */
/*
* Power management (not Tx power!) functions
*/
@ -2461,9 +2454,10 @@ static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt)
return 0;
}
static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode)
static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
enum ieee80211_band band)
{
if (phymode == MODE_IEEE80211A) {
if (band == IEEE80211_BAND_5GHZ) {
priv->staging_rxon.flags &=
~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
| RXON_FLG_CCK_MSK);
@ -2526,7 +2520,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif
ch_info = iwl3945_get_channel_info(priv, priv->phymode,
ch_info = iwl3945_get_channel_info(priv, priv->band,
le16_to_cpu(priv->staging_rxon.channel));
if (!ch_info)
@ -2542,11 +2536,11 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
if (is_channel_a_band(ch_info))
priv->phymode = MODE_IEEE80211A;
priv->band = IEEE80211_BAND_5GHZ;
else
priv->phymode = MODE_IEEE80211G;
priv->band = IEEE80211_BAND_2GHZ;
iwl3945_set_flags_for_phymode(priv, priv->phymode);
iwl3945_set_flags_for_phymode(priv, priv->band);
priv->staging_rxon.ofdm_basic_rates =
(IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
@ -2560,7 +2554,7 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
const struct iwl3945_channel_info *ch_info;
ch_info = iwl3945_get_channel_info(priv,
priv->phymode,
priv->band,
le16_to_cpu(priv->staging_rxon.channel));
if (!ch_info || !is_channel_ibss(ch_info)) {
@ -2792,7 +2786,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
goto drop_unlock;
}
if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
IWL_ERROR("ERROR: No TX rate available.\n");
goto drop_unlock;
}
@ -2992,12 +2986,12 @@ drop:
static void iwl3945_set_rate(struct iwl3945_priv *priv)
{
const struct ieee80211_hw_mode *hw = NULL;
const struct ieee80211_supported_band *sband = NULL;
struct ieee80211_rate *rate;
int i;
hw = iwl3945_get_hw_mode(priv, priv->phymode);
if (!hw) {
sband = iwl3945_get_band(priv, priv->band);
if (!sband) {
IWL_ERROR("Failed to set rate: unable to get hw mode\n");
return;
}
@ -3005,24 +2999,17 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv)
priv->active_rate = 0;
priv->active_rate_basic = 0;
IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
hw->mode == MODE_IEEE80211A ?
'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
IWL_DEBUG_RATE("Setting rates for %s GHz\n",
sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5");
for (i = 0; i < hw->num_rates; i++) {
rate = &(hw->rates[i]);
if ((rate->val < IWL_RATE_COUNT) &&
(rate->flags & IEEE80211_RATE_SUPPORTED)) {
IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
rate->val, iwl3945_rates[rate->val].plcp,
(rate->flags & IEEE80211_RATE_BASIC) ?
"*" : "");
priv->active_rate |= (1 << rate->val);
if (rate->flags & IEEE80211_RATE_BASIC)
priv->active_rate_basic |= (1 << rate->val);
} else
IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
rate->val, iwl3945_rates[rate->val].plcp);
for (i = 0; i < sband->n_bitrates; i++) {
rate = &sband->bitrates[i];
if ((rate->hw_value < IWL_RATE_COUNT) &&
!(rate->flags & IEEE80211_CHAN_DISABLED)) {
IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n",
rate->hw_value, iwl3945_rates[rate->hw_value].plcp);
priv->active_rate |= (1 << rate->hw_value);
}
}
IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
@ -3436,8 +3423,6 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
tx_status->flags =
iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate);
IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
txq_id, iwl3945_get_tx_fail_reason(status), status,
tx_resp->rate, tx_resp->failure_frame);
@ -4792,7 +4777,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
/* Queue restart only if RF_KILL switch was set to "kill"
* when we loaded driver, and is now set to "enable".
* After we're Alive, RF_KILL gets handled by
* iwl_rx_card_state_notif() */
* iwl3945_rx_card_state_notif() */
if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
clear_bit(STATUS_RF_KILL_HW, &priv->status);
queue_work(priv->workqueue, &priv->restart);
@ -5026,24 +5011,24 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban
* Based on band and channel number.
*/
const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv,
int phymode, u16 channel)
enum ieee80211_band band, u16 channel)
{
int i;
switch (phymode) {
case MODE_IEEE80211A:
switch (band) {
case IEEE80211_BAND_5GHZ:
for (i = 14; i < priv->channel_count; i++) {
if (priv->channel_info[i].channel == channel)
return &priv->channel_info[i];
}
break;
case MODE_IEEE80211B:
case MODE_IEEE80211G:
case IEEE80211_BAND_2GHZ:
if (channel >= 1 && channel <= 14)
return &priv->channel_info[channel - 1];
break;
case IEEE80211_NUM_BANDS:
WARN_ON(1);
}
return NULL;
@ -5106,8 +5091,8 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
/* Loop through each band adding each of the channels */
for (ch = 0; ch < eeprom_ch_count; ch++) {
ch_info->channel = eeprom_ch_index[ch];
ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
MODE_IEEE80211A;
ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
IEEE80211_BAND_5GHZ;
/* permanently store EEPROM's channel regulatory flags
* and max power in channel info database. */
@ -5203,18 +5188,20 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
#define IWL_PASSIVE_DWELL_BASE (100)
#define IWL_CHANNEL_TUNE_TIME 5
static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode)
static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
enum ieee80211_band band)
{
if (phymode == MODE_IEEE80211A)
if (band == IEEE80211_BAND_5GHZ)
return IWL_ACTIVE_DWELL_TIME_52;
else
return IWL_ACTIVE_DWELL_TIME_24;
}
static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode)
static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
enum ieee80211_band band)
{
u16 active = iwl3945_get_active_dwell_time(priv, phymode);
u16 passive = (phymode != MODE_IEEE80211A) ?
u16 active = iwl3945_get_active_dwell_time(priv, band);
u16 passive = (band == IEEE80211_BAND_2GHZ) ?
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
@ -5234,28 +5221,29 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode
return passive;
}
static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 direct_mask,
struct iwl3945_scan_channel *scan_ch)
{
const struct ieee80211_channel *channels = NULL;
const struct ieee80211_hw_mode *hw_mode;
const struct ieee80211_supported_band *sband;
const struct iwl3945_channel_info *ch_info;
u16 passive_dwell = 0;
u16 active_dwell = 0;
int added, i;
hw_mode = iwl3945_get_hw_mode(priv, phymode);
if (!hw_mode)
sband = iwl3945_get_band(priv, band);
if (!sband)
return 0;
channels = hw_mode->channels;
channels = sband->channels;
active_dwell = iwl3945_get_active_dwell_time(priv, phymode);
passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode);
active_dwell = iwl3945_get_active_dwell_time(priv, band);
passive_dwell = iwl3945_get_passive_dwell_time(priv, band);
for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
if (channels[i].chan ==
for (i = 0, added = 0; i < sband->n_channels; i++) {
if (channels[i].hw_value ==
le16_to_cpu(priv->active_rxon.channel)) {
if (iwl3945_is_associated(priv)) {
IWL_DEBUG_SCAN
@ -5266,9 +5254,9 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
} else if (priv->only_active_channel)
continue;
scan_ch->channel = channels[i].chan;
scan_ch->channel = channels[i].hw_value;
ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel);
ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
scan_ch->channel);
@ -5276,7 +5264,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
}
if (!is_active || is_channel_passive(ch_info) ||
!(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
(channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
scan_ch->type = 0; /* passive */
else
scan_ch->type = 1; /* active */
@ -5295,7 +5283,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
/* scan_pwr_info->tpc.dsp_atten; */
/*scan_pwr_info->tpc.tx_gain; */
if (phymode == MODE_IEEE80211A)
if (band == IEEE80211_BAND_5GHZ)
scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
else {
scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
@ -5319,41 +5307,23 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
return added;
}
static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv)
{
int i, j;
for (i = 0; i < 3; i++) {
struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
for (j = 0; j < hw_mode->num_channels; j++)
hw_mode->channels[j].flag = hw_mode->channels[j].val;
}
}
static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
struct ieee80211_rate *rates)
{
int i;
for (i = 0; i < IWL_RATE_COUNT; i++) {
rates[i].rate = iwl3945_rates[i].ieee * 5;
rates[i].val = i; /* Rate scaling will work on indexes */
rates[i].val2 = i;
rates[i].flags = IEEE80211_RATE_SUPPORTED;
/* Only OFDM have the bits-per-symbol set */
if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
rates[i].flags |= IEEE80211_RATE_OFDM;
else {
rates[i].bitrate = iwl3945_rates[i].ieee * 5;
rates[i].hw_value = i; /* Rate scaling will work on indexes */
rates[i].hw_value_short = i;
rates[i].flags = 0;
if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
/*
* If CCK 1M then set rate flag to CCK else CCK_2
* which is CCK | PREAMBLE2
* If CCK != 1M then set short preamble rate flag.
*/
rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
0 : IEEE80211_RATE_SHORT_PREAMBLE;
}
/* Set up which ones are basic rates... */
if (IWL_BASIC_RATES_MASK & (1 << i))
rates[i].flags |= IEEE80211_RATE_BASIC;
}
}
@ -5363,67 +5333,41 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
static int iwl3945_init_geos(struct iwl3945_priv *priv)
{
struct iwl3945_channel_info *ch;
struct ieee80211_hw_mode *modes;
struct ieee80211_supported_band *band;
struct ieee80211_channel *channels;
struct ieee80211_channel *geo_ch;
struct ieee80211_rate *rates;
int i = 0;
enum {
A = 0,
B = 1,
G = 2,
};
int mode_count = 3;
if (priv->modes) {
if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
IWL_DEBUG_INFO("Geography modes already initialized.\n");
set_bit(STATUS_GEO_CONFIGURED, &priv->status);
return 0;
}
modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
GFP_KERNEL);
if (!modes)
return -ENOMEM;
channels = kzalloc(sizeof(struct ieee80211_channel) *
priv->channel_count, GFP_KERNEL);
if (!channels) {
kfree(modes);
if (!channels)
return -ENOMEM;
}
rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
GFP_KERNEL);
if (!rates) {
kfree(modes);
kfree(channels);
return -ENOMEM;
}
/* 0 = 802.11a
* 1 = 802.11b
* 2 = 802.11g
*/
/* 5.2GHz channels start after the 2.4GHz channels */
modes[A].mode = MODE_IEEE80211A;
modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
modes[A].rates = &rates[4];
modes[A].num_rates = 8; /* just OFDM */
modes[A].num_channels = 0;
band = &priv->bands[IEEE80211_BAND_5GHZ];
band->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
band->bitrates = &rates[4];
band->n_bitrates = 8; /* just OFDM */
modes[B].mode = MODE_IEEE80211B;
modes[B].channels = channels;
modes[B].rates = rates;
modes[B].num_rates = 4; /* just CCK */
modes[B].num_channels = 0;
modes[G].mode = MODE_IEEE80211G;
modes[G].channels = channels;
modes[G].rates = rates;
modes[G].num_rates = 12; /* OFDM & CCK */
modes[G].num_channels = 0;
band = &priv->bands[IEEE80211_BAND_2GHZ];
band->channels = channels;
band->bitrates = rates;
band->n_bitrates = 12; /* OFDM & CCK */
priv->ieee_channels = channels;
priv->ieee_rates = rates;
@ -5442,37 +5386,33 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
}
if (is_channel_a_band(ch))
geo_ch = &modes[A].channels[modes[A].num_channels++];
else {
geo_ch = &modes[B].channels[modes[B].num_channels++];
modes[G].num_channels++;
}
geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++];
else
geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++];
geo_ch->freq = ieee80211chan2mhz(ch->channel);
geo_ch->chan = ch->channel;
geo_ch->power_level = ch->max_power_avg;
geo_ch->antenna_max = 0xff;
geo_ch->center_freq = ieee80211chan2mhz(ch->channel);
geo_ch->max_power = ch->max_power_avg;
geo_ch->max_antenna_gain = 0xff;
geo_ch->hw_value = ch->channel;
if (is_channel_valid(ch)) {
geo_ch->flag = IEEE80211_CHAN_W_SCAN;
if (ch->flags & EEPROM_CHANNEL_IBSS)
geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
if (!(ch->flags & EEPROM_CHANNEL_IBSS))
geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
if (ch->flags & EEPROM_CHANNEL_ACTIVE)
geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
if (ch->flags & EEPROM_CHANNEL_RADAR)
geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
geo_ch->flags |= IEEE80211_CHAN_RADAR;
if (ch->max_power_avg > priv->max_channel_txpower_limit)
priv->max_channel_txpower_limit =
ch->max_power_avg;
} else
geo_ch->flags |= IEEE80211_CHAN_DISABLED;
}
geo_ch->val = geo_ch->flag;
}
if ((modes[A].num_channels == 0) && priv->is_abg) {
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) {
printk(KERN_INFO DRV_NAME
": Incorrectly detected BG card as ABG. Please send "
"your PCI ID 0x%04X:0x%04X to maintainer.\n",
@ -5482,24 +5422,12 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
printk(KERN_INFO DRV_NAME
": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
modes[G].num_channels, modes[A].num_channels);
priv->bands[IEEE80211_BAND_2GHZ].n_channels,
priv->bands[IEEE80211_BAND_5GHZ].n_channels);
/*
* NOTE: We register these in preference of order -- the
* stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
* a phymode based on rates or AP capabilities but seems to
* configure it purely on if the channel being configured
* is supported by a mode -- and the first match is taken
*/
priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ];
priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ];
if (modes[G].num_channels)
ieee80211_register_hwmode(priv->hw, &modes[G]);
if (modes[B].num_channels)
ieee80211_register_hwmode(priv->hw, &modes[B]);
if (modes[A].num_channels)
ieee80211_register_hwmode(priv->hw, &modes[A]);
priv->modes = modes;
set_bit(STATUS_GEO_CONFIGURED, &priv->status);
return 0;
@ -5510,7 +5438,6 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
*/
static void iwl3945_free_geos(struct iwl3945_priv *priv)
{
kfree(priv->modes);
kfree(priv->ieee_channels);
kfree(priv->ieee_rates);
clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
@ -6519,7 +6446,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
struct iwl3945_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
u8 direct_mask;
int phymode;
enum ieee80211_band band;
conf = ieee80211_get_hw_conf(priv->hw);
@ -6651,13 +6578,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
scan->good_CRC_th = 0;
phymode = MODE_IEEE80211G;
band = IEEE80211_BAND_2GHZ;
break;
case 1:
scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
scan->good_CRC_th = IWL_GOOD_CRC_TH;
phymode = MODE_IEEE80211A;
band = IEEE80211_BAND_5GHZ;
break;
default:
@ -6680,7 +6607,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
scan->channel_count =
iwl3945_get_channels_for_scan(
priv, phymode, 1, /* active */
priv, band, 1, /* active */
direct_mask,
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
@ -6825,7 +6752,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
iwl3945_add_station(priv, priv->bssid, 0, 0);
iwl3945_sync_sta(priv, IWL_STA_ID,
(priv->phymode == MODE_IEEE80211A)?
(priv->band == IEEE80211_BAND_5GHZ) ?
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
CMD_ASYNC);
iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
@ -6841,9 +6768,8 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
iwl3945_sequence_reset(priv);
#ifdef CONFIG_IWL3945_QOS
iwl3945_activate_qos(priv, 0);
#endif /* CONFIG_IWL3945_QOS */
/* we have just associated, don't start scan too early */
priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
mutex_unlock(&priv->mutex);
@ -7020,7 +6946,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
}
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ctl->tx_rate);
ctl->tx_rate->bitrate);
if (iwl3945_tx_skb(priv, skb, ctl))
dev_kfree_skb_any(skb);
@ -7079,7 +7005,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
int ret = 0;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
@ -7099,19 +7025,20 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
spin_lock_irqsave(&priv->lock, flags);
ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel);
ch_info = iwl3945_get_channel_info(priv, conf->channel->band,
conf->channel->hw_value);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
conf->channel, conf->phymode);
conf->channel->hw_value, conf->channel->band);
IWL_DEBUG_MAC80211("leave - invalid channel\n");
spin_unlock_irqrestore(&priv->lock, flags);
ret = -EINVAL;
goto out;
}
iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel);
iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value);
iwl3945_set_flags_for_phymode(priv, conf->phymode);
iwl3945_set_flags_for_phymode(priv, conf->channel->band);
/* The list of supported rates and rate mask can be different
* for each phymode; since the phymode may have changed, reset
@ -7487,10 +7414,8 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params)
{
struct iwl3945_priv *priv = hw->priv;
#ifdef CONFIG_IWL3945_QOS
unsigned long flags;
int q;
#endif /* CONFIG_IWL3945_QOS */
IWL_DEBUG_MAC80211("enter\n");
@ -7504,7 +7429,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
return 0;
}
#ifdef CONFIG_IWL3945_QOS
if (!priv->qos_data.qos_enable) {
priv->qos_data.qos_active = 0;
IWL_DEBUG_MAC80211("leave - qos not enabled\n");
@ -7518,7 +7442,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
priv->qos_data.def_qos_parm.ac[q].edca_txop =
cpu_to_le16((params->burst_time * 100));
cpu_to_le16((params->txop * 32));
priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
priv->qos_data.qos_active = 1;
@ -7533,8 +7457,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
mutex_unlock(&priv->mutex);
#endif /*CONFIG_IWL3945_QOS */
IWL_DEBUG_MAC80211("leave\n");
return 0;
}
@ -7599,9 +7521,8 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
#ifdef CONFIG_IWL3945_QOS
iwl3945_reset_qos(priv);
#endif
cancel_delayed_work(&priv->post_associate);
spin_lock_irqsave(&priv->lock, flags);
@ -7689,9 +7610,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
IWL_DEBUG_MAC80211("leave\n");
spin_unlock_irqrestore(&priv->lock, flags);
#ifdef CONFIG_IWL3945_QOS
iwl3945_reset_qos(priv);
#endif
queue_work(priv->workqueue, &priv->post_associate.work);
@ -7892,65 +7811,6 @@ static ssize_t store_filter_flags(struct device *d,
static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
store_filter_flags);
static ssize_t show_tune(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
return sprintf(buf, "0x%04X\n",
(priv->phymode << 8) |
le16_to_cpu(priv->active_rxon.channel));
}
static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode);
static ssize_t store_tune(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
char *p = (char *)buf;
u16 tune = simple_strtoul(p, &p, 0);
u8 phymode = (tune >> 8) & 0xff;
u16 channel = tune & 0xff;
IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
mutex_lock(&priv->mutex);
if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
(priv->phymode != phymode)) {
const struct iwl3945_channel_info *ch_info;
ch_info = iwl3945_get_channel_info(priv, phymode, channel);
if (!ch_info) {
IWL_WARNING("Requested invalid phymode/channel "
"combination: %d %d\n", phymode, channel);
mutex_unlock(&priv->mutex);
return -EINVAL;
}
/* Cancel any currently running scans... */
if (iwl3945_scan_cancel_timeout(priv, 100))
IWL_WARNING("Could not cancel scan.\n");
else {
IWL_DEBUG_INFO("Committing phymode and "
"rxon.channel = %d %d\n",
phymode, channel);
iwl3945_set_rxon_channel(priv, phymode, channel);
iwl3945_set_flags_for_phymode(priv, phymode);
iwl3945_set_rate(priv);
iwl3945_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
return count;
}
static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
static ssize_t show_measurement(struct device *d,
@ -8165,73 +8025,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
static ssize_t show_channels(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl3945_priv *priv = dev_get_drvdata(d);
int len = 0, i;
struct ieee80211_channel *channels = NULL;
const struct ieee80211_hw_mode *hw_mode = NULL;
int count = 0;
if (!iwl3945_is_ready(priv))
return -EAGAIN;
hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G);
if (!hw_mode)
hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B);
if (hw_mode) {
channels = hw_mode->channels;
count = hw_mode->num_channels;
}
len +=
sprintf(&buf[len],
"Displaying %d channels in 2.4GHz band "
"(802.11bg):\n", count);
for (i = 0; i < count; i++)
len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
channels[i].chan,
channels[i].power_level,
channels[i].
flag & IEEE80211_CHAN_W_RADAR_DETECT ?
" (IEEE 802.11h required)" : "",
(!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
|| (channels[i].
flag &
IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
", IBSS",
channels[i].
flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
"active/passive" : "passive only");
hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A);
if (hw_mode) {
channels = hw_mode->channels;
count = hw_mode->num_channels;
} else {
channels = NULL;
count = 0;
}
len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
"(802.11a):\n", count);
for (i = 0; i < count; i++)
len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
channels[i].chan,
channels[i].power_level,
channels[i].
flag & IEEE80211_CHAN_W_RADAR_DETECT ?
" (IEEE 802.11h required)" : "",
(!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
|| (channels[i].
flag &
IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
", IBSS",
channels[i].
flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
"active/passive" : "passive only");
return len;
/* all this shit doesn't belong into sysfs anyway */
return 0;
}
static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
@ -8411,7 +8206,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
&dev_attr_statistics.attr,
&dev_attr_status.attr,
&dev_attr_temperature.attr,
&dev_attr_tune.attr,
&dev_attr_tx_power.attr,
NULL
@ -8532,7 +8326,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->data_retry_limit = -1;
priv->ieee_channels = NULL;
priv->ieee_rates = NULL;
priv->phymode = -1;
priv->band = IEEE80211_BAND_2GHZ;
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (!err)
@ -8604,7 +8398,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
goto out_iounmap;
}
#ifdef CONFIG_IWL3945_QOS
if (iwl3945_param_qos_enable)
priv->qos_data.qos_enable = 1;
@ -8612,9 +8405,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
#endif /* CONFIG_IWL3945_QOS */
iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6);
iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
iwl3945_setup_deferred_work(priv);
iwl3945_setup_rx_handlers(priv);
@ -8665,7 +8457,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
IWL_ERROR("initializing geos failed: %d\n", err);
goto out_free_channel_map;
}
iwl3945_reset_channel_flag(priv);
iwl3945_rate_control_register(priv->hw);
err = ieee80211_register_hw(priv->hw);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -181,17 +181,6 @@ int lbs_update_channel(struct lbs_private *priv)
return ret;
}
void lbs_sync_channel(struct work_struct *work)
{
struct lbs_private *priv = container_of(work, struct lbs_private,
sync_channel);
lbs_deb_enter(LBS_DEB_ASSOC);
if (lbs_update_channel(priv))
lbs_pr_info("Channel synchronization failed.");
lbs_deb_leave(LBS_DEB_ASSOC);
}
static int assoc_helper_channel(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
@ -413,11 +402,10 @@ static int should_deauth_infrastructure(struct lbs_private *priv,
{
int ret = 0;
lbs_deb_enter(LBS_DEB_ASSOC);
if (priv->connect_status != LBS_CONNECTED)
return 0;
lbs_deb_enter(LBS_DEB_ASSOC);
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
lbs_deb_assoc("Deauthenticating due to new SSID\n");
ret = 1;
@ -456,7 +444,7 @@ static int should_deauth_infrastructure(struct lbs_private *priv,
out:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return 0;
return ret;
}
@ -643,9 +631,7 @@ void lbs_association_worker(struct work_struct *work)
}
if (success) {
lbs_deb_assoc("ASSOC: associated to '%s', %s\n",
escape_essid(priv->curbssparams.ssid,
priv->curbssparams.ssid_len),
lbs_deb_assoc("associated to %s\n",
print_mac(mac, priv->curbssparams.bssid));
lbs_prepare_and_send_command(priv,
CMD_802_11_RSSI,

Просмотреть файл

@ -7,6 +7,5 @@
void lbs_association_worker(struct work_struct *work);
struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
void lbs_sync_channel(struct work_struct *work);
#endif /* _LBS_ASSOC_H */

Просмотреть файл

@ -1153,9 +1153,9 @@ static void lbs_submit_command(struct lbs_private *priv,
command == CMD_802_11_AUTHENTICATE)
timeo = 10 * HZ;
lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n",
lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n",
command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies);
lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
@ -1164,9 +1164,7 @@ static void lbs_submit_command(struct lbs_private *priv,
/* Let the timer kick in and retry, and potentially reset
the whole thing if the condition persists */
timeo = HZ;
} else
lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n",
command, jiffies);
}
/* Setup the timer after transmit command */
mod_timer(&priv->command_timer, jiffies + timeo);
@ -1185,7 +1183,7 @@ static int lbs_cmd_mac_control(struct lbs_private *priv,
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
mac->action = cpu_to_le16(priv->currentpacketfilter);
lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
lbs_deb_cmd("MAC_CONTROL: action 0x%04x, size %d\n",
le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
lbs_deb_leave(LBS_DEB_CMD);
@ -1741,9 +1739,9 @@ int lbs_execute_next_command(struct lbs_private *priv)
unsigned long flags;
int ret = 0;
// Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
// only caller to us is lbs_thread() and we get even when a
// data packet is received
/* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
* only caller to us is lbs_thread() and we get even when a
* data packet is received */
lbs_deb_enter(LBS_DEB_THREAD);
spin_lock_irqsave(&priv->driver_lock, flags);
@ -2043,15 +2041,8 @@ int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
struct cmd_header *buf = (void *)extra;
uint16_t copy_len;
lbs_deb_enter(LBS_DEB_CMD);
copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
lbs_deb_cmd("Copying back %u bytes; command response was %u bytes, "
"copy back buffer was %u bytes\n", copy_len,
le16_to_cpu(resp->size), le16_to_cpu(buf->size));
memcpy(buf, resp, copy_len);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
EXPORT_SYMBOL_GPL(lbs_cmd_copyback);

Просмотреть файл

@ -74,7 +74,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
lbs_deb_cmd("disconnected, so exit PS mode\n");
lbs_ps_wakeup(priv, 0);
}
lbs_deb_leave(LBS_DEB_CMD);
lbs_deb_leave(LBS_DEB_ASSOC);
}
/**
@ -568,9 +568,9 @@ int lbs_process_rx_command(struct lbs_private *priv)
respcmd = le16_to_cpu(resp->command);
result = le16_to_cpu(resp->result);
lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len);
if (resp->seqnum != resp->seqnum) {
lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",

Просмотреть файл

@ -315,7 +315,7 @@ static ssize_t lbs_setuserscan(struct file *file,
lbs_scan_networks(priv, scan_cfg, 1);
wait_event_interruptible(priv->cmd_pending,
priv->surpriseremoved || !priv->last_scanned_channel);
priv->surpriseremoved || !priv->scan_channel);
if (priv->surpriseremoved)
goto out_scan_cfg;

Просмотреть файл

@ -143,9 +143,12 @@ struct lbs_private {
wait_queue_head_t waitq;
struct workqueue_struct *work_thread;
/** Scanning */
struct delayed_work scan_work;
struct delayed_work assoc_work;
struct work_struct sync_channel;
/* remember which channel was scanned last, != 0 if currently scanning */
int scan_channel;
/** Hardware access */
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
@ -321,7 +324,6 @@ struct lbs_private {
struct cmd_ds_802_11_get_log logmsg;
u32 monitormode;
int last_scanned_channel;
u8 fw_ready;
};

Просмотреть файл

@ -98,23 +98,6 @@ static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
}
}
/**
* @brief Unsets the MSB on basic rates
*
* Scan through an array and unset the MSB for basic data rates.
*
* @param rates buffer of data rates
* @param len size of buffer
*/
void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
{
int i;
for (i = 0; i < len; i++)
rates[i] &= 0x7f;
}
/**
* @brief Associate to a specific BSS discovered in a scan
*
@ -769,9 +752,6 @@ int lbs_ret_80211_associate(struct lbs_private *priv,
priv->curbssparams.ssid_len = bss->ssid_len;
memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
lbs_deb_assoc("ASSOC_RESP: currentpacketfilter is 0x%x\n",
priv->currentpacketfilter);
priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
priv->NF[TYPE_RXPD][TYPE_AVG] = 0;

Просмотреть файл

@ -48,6 +48,4 @@ int lbs_send_deauthentication(struct lbs_private *priv);
int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req);
void lbs_unset_basic_rate_flags(u8 *rates, size_t len);
#endif

Просмотреть файл

@ -985,6 +985,18 @@ out:
lbs_deb_leave(LBS_DEB_CMD);
}
static void lbs_sync_channel_worker(struct work_struct *work)
{
struct lbs_private *priv = container_of(work, struct lbs_private,
sync_channel);
lbs_deb_enter(LBS_DEB_MAIN);
if (lbs_update_channel(priv))
lbs_pr_info("Channel synchronization failed.");
lbs_deb_leave(LBS_DEB_MAIN);
}
static int lbs_init_adapter(struct lbs_private *priv)
{
size_t bufsize;
@ -1128,7 +1140,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
priv->work_thread = create_singlethread_workqueue("lbs_worker");
INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
INIT_WORK(&priv->sync_channel, lbs_sync_channel);
INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
sprintf(priv->mesh_ssid, "mesh");
priv->mesh_ssid_len = 4;

Просмотреть файл

@ -73,6 +73,23 @@ static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/* */
/*********************************************************************/
/**
* @brief Unsets the MSB on basic rates
*
* Scan through an array and unset the MSB for basic data rates.
*
* @param rates buffer of data rates
* @param len size of buffer
*/
static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
{
int i;
for (i = 0; i < len; i++)
rates[i] &= 0x7f;
}
static inline void clear_bss_descriptor (struct bss_descriptor * bss)
{
/* Don't blow away ->list, just BSS data */
@ -595,13 +612,13 @@ int lbs_scan_networks(struct lbs_private *priv,
}
/* Prepare to continue an interrupted scan */
lbs_deb_scan("chan_count %d, last_scanned_channel %d\n",
chan_count, priv->last_scanned_channel);
lbs_deb_scan("chan_count %d, scan_channel %d\n",
chan_count, priv->scan_channel);
curr_chans = chan_list;
/* advance channel list by already-scanned-channels */
if (priv->last_scanned_channel > 0) {
curr_chans += priv->last_scanned_channel;
chan_count -= priv->last_scanned_channel;
if (priv->scan_channel > 0) {
curr_chans += priv->scan_channel;
chan_count -= priv->scan_channel;
}
/* Send scan command(s)
@ -627,10 +644,10 @@ int lbs_scan_networks(struct lbs_private *priv,
!full_scan &&
!priv->surpriseremoved) {
/* -1 marks just that we're currently scanning */
if (priv->last_scanned_channel < 0)
priv->last_scanned_channel = to_scan;
if (priv->scan_channel < 0)
priv->scan_channel = to_scan;
else
priv->last_scanned_channel += to_scan;
priv->scan_channel += to_scan;
cancel_delayed_work(&priv->scan_work);
queue_delayed_work(priv->work_thread, &priv->scan_work,
msecs_to_jiffies(300));
@ -654,7 +671,7 @@ int lbs_scan_networks(struct lbs_private *priv,
#endif
out2:
priv->last_scanned_channel = 0;
priv->scan_channel = 0;
out:
if (priv->connect_status == LBS_CONNECTED) {
@ -1376,7 +1393,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
queue_delayed_work(priv->work_thread, &priv->scan_work,
msecs_to_jiffies(50));
/* set marker that currently a scan is taking place */
priv->last_scanned_channel = -1;
priv->scan_channel = -1;
if (priv->surpriseremoved)
return -EIO;
@ -1410,7 +1427,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_SCAN);
/* iwlist should wait until the current scan is finished */
if (priv->last_scanned_channel)
if (priv->scan_channel)
return -EAGAIN;
/* Update RSSI if current BSS is a locally created ad-hoc BSS */

Просмотреть файл

@ -64,10 +64,6 @@ struct p54_common {
unsigned int tx_hdr_len;
void *cached_vdcf;
unsigned int fw_var;
/* FIXME: this channels/modes/rates stuff sucks */
struct ieee80211_channel channels[14];
struct ieee80211_rate rates[12];
struct ieee80211_hw_mode modes[2];
struct ieee80211_tx_queue_stats tx_stats;
};

Просмотреть файл

@ -27,6 +27,46 @@ MODULE_DESCRIPTION("Softmac Prism54 common code");
MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54common");
static struct ieee80211_rate p54_rates[] = {
{ .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 60, .hw_value = 4, },
{ .bitrate = 90, .hw_value = 5, },
{ .bitrate = 120, .hw_value = 6, },
{ .bitrate = 180, .hw_value = 7, },
{ .bitrate = 240, .hw_value = 8, },
{ .bitrate = 360, .hw_value = 9, },
{ .bitrate = 480, .hw_value = 10, },
{ .bitrate = 540, .hw_value = 11, },
};
static struct ieee80211_channel p54_channels[] = {
{ .center_freq = 2412, .hw_value = 1, },
{ .center_freq = 2417, .hw_value = 2, },
{ .center_freq = 2422, .hw_value = 3, },
{ .center_freq = 2427, .hw_value = 4, },
{ .center_freq = 2432, .hw_value = 5, },
{ .center_freq = 2437, .hw_value = 6, },
{ .center_freq = 2442, .hw_value = 7, },
{ .center_freq = 2447, .hw_value = 8, },
{ .center_freq = 2452, .hw_value = 9, },
{ .center_freq = 2457, .hw_value = 10, },
{ .center_freq = 2462, .hw_value = 11, },
{ .center_freq = 2467, .hw_value = 12, },
{ .center_freq = 2472, .hw_value = 13, },
{ .center_freq = 2484, .hw_value = 14, },
};
static struct ieee80211_supported_band band_2GHz = {
.channels = p54_channels,
.n_channels = ARRAY_SIZE(p54_channels),
.bitrates = p54_rates,
.n_bitrates = ARRAY_SIZE(p54_rates),
};
void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
{
struct p54_common *priv = dev->priv;
@ -251,6 +291,10 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
case PDR_END:
i = len;
break;
default:
printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n",
le16_to_cpu(entry->code));
break;
}
entry = (void *)entry + (entry_len + 1)*2;
@ -308,10 +352,10 @@ static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
u16 freq = le16_to_cpu(hdr->freq);
rx_status.ssi = hdr->rssi;
rx_status.rate = hdr->rate & 0x1f; /* report short preambles & CCK too */
rx_status.channel = freq == 2484 ? 14 : (freq - 2407)/5;
/* XX correct? */
rx_status.rate_idx = hdr->rate & 0xf;
rx_status.freq = freq;
rx_status.phymode = MODE_IEEE80211G;
rx_status.band = IEEE80211_BAND_2GHZ;
rx_status.antenna = hdr->antenna;
rx_status.mactime = le64_to_cpu(hdr->timestamp);
rx_status.flag |= RX_FLAG_TSFT;
@ -349,7 +393,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
while (entry != (struct sk_buff *)&priv->tx_queue) {
range = (struct memrecord *)&entry->cb;
if (range->start_addr == addr) {
struct ieee80211_tx_status status = {{0}};
struct ieee80211_tx_status status;
struct p54_control_hdr *entry_hdr;
struct p54_tx_control_allocdata *entry_data;
int pad = 0;
@ -365,6 +409,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
kfree_skb(entry);
break;
}
memset(&status, 0, sizeof(status));
memcpy(&status.control, range->control,
sizeof(status.control));
kfree(range->control);
@ -547,7 +592,9 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
txhdr->padding2 = 0;
/* TODO: add support for alternate retry TX rates */
rate = control->tx_rate;
rate = control->tx_rate->hw_value;
if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
rate |= 0x10;
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
rate |= 0x40;
else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
@ -717,13 +764,12 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
return 0;
}
#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, burst) \
#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \
do { \
queue.aifs = cpu_to_le16(ai_fs); \
queue.cwmin = cpu_to_le16(cw_min); \
queue.cwmax = cpu_to_le16(cw_max); \
queue.txop = (burst == 0) ? \
0 : cpu_to_le16((burst * 100) / 32 + 1); \
queue.txop = cpu_to_le16(_txop); \
} while(0)
static void p54_init_vdcf(struct ieee80211_hw *dev)
@ -741,10 +787,10 @@ static void p54_init_vdcf(struct ieee80211_hw *dev)
vdcf = (struct p54_tx_control_vdcf *) hdr->data;
P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 0x000f);
P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 0x001e);
P54_SET_QUEUE(vdcf->queue[2], 0x0002, 0x000f, 0x03ff, 0x0014);
P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0x0000);
P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47);
P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94);
P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0);
P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0);
}
static void p54_set_vdcf(struct ieee80211_hw *dev)
@ -849,7 +895,7 @@ static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
int ret;
ret = p54_set_freq(dev, cpu_to_le16(conf->freq));
ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
p54_set_vdcf(dev);
return ret;
}
@ -897,7 +943,7 @@ static int p54_conf_tx(struct ieee80211_hw *dev, int queue,
if ((params) && !((queue < 0) || (queue > 4))) {
P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
params->cw_min, params->cw_max, params->burst_time);
params->cw_min, params->cw_max, params->txop);
} else
return -EINVAL;
@ -944,7 +990,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
{
struct ieee80211_hw *dev;
struct p54_common *priv;
int i;
dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
if (!dev)
@ -953,18 +998,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
priv = dev->priv;
priv->mode = IEEE80211_IF_TYPE_INVALID;
skb_queue_head_init(&priv->tx_queue);
memcpy(priv->channels, p54_channels, sizeof(p54_channels));
memcpy(priv->rates, p54_rates, sizeof(p54_rates));
priv->modes[1].mode = MODE_IEEE80211B;
priv->modes[1].num_rates = 4;
priv->modes[1].rates = priv->rates;
priv->modes[1].num_channels = ARRAY_SIZE(p54_channels);
priv->modes[1].channels = priv->channels;
priv->modes[0].mode = MODE_IEEE80211G;
priv->modes[0].num_rates = ARRAY_SIZE(p54_rates);
priv->modes[0].rates = priv->rates;
priv->modes[0].num_channels = ARRAY_SIZE(p54_channels);
priv->modes[0].channels = priv->channels;
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
IEEE80211_HW_RX_INCLUDES_FCS;
dev->channel_change_time = 1000; /* TODO: find actual value */
@ -986,14 +1020,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
p54_init_vdcf(dev);
for (i = 0; i < 2; i++) {
if (ieee80211_register_hwmode(dev, &priv->modes[i])) {
kfree(priv->cached_vdcf);
ieee80211_free_hw(dev);
return NULL;
}
}
return dev;
}
EXPORT_SYMBOL_GPL(p54_init_common);

Просмотреть файл

@ -251,79 +251,4 @@ struct p54_tx_control_vdcf {
__le16 frameburst;
} __attribute__ ((packed));
static const struct ieee80211_rate p54_rates[] = {
{ .rate = 10,
.val = 0,
.val2 = 0x10,
.flags = IEEE80211_RATE_CCK_2 },
{ .rate = 20,
.val = 1,
.val2 = 0x11,
.flags = IEEE80211_RATE_CCK_2 },
{ .rate = 55,
.val = 2,
.val2 = 0x12,
.flags = IEEE80211_RATE_CCK_2 },
{ .rate = 110,
.val = 3,
.val2 = 0x13,
.flags = IEEE80211_RATE_CCK_2 },
{ .rate = 60,
.val = 4,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 90,
.val = 5,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 120,
.val = 6,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 180,
.val = 7,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 240,
.val = 8,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 360,
.val = 9,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 480,
.val = 10,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 540,
.val = 11,
.flags = IEEE80211_RATE_OFDM },
};
// TODO: just generate this..
static const struct ieee80211_channel p54_channels[] = {
{ .chan = 1,
.freq = 2412},
{ .chan = 2,
.freq = 2417},
{ .chan = 3,
.freq = 2422},
{ .chan = 4,
.freq = 2427},
{ .chan = 5,
.freq = 2432},
{ .chan = 6,
.freq = 2437},
{ .chan = 7,
.freq = 2442},
{ .chan = 8,
.freq = 2447},
{ .chan = 9,
.freq = 2452},
{ .chan = 10,
.freq = 2457},
{ .chan = 11,
.freq = 2462},
{ .chan = 12,
.freq = 2467},
{ .chan = 13,
.freq = 2472},
{ .chan = 14,
.freq = 2484}
};
#endif /* PRISM54COMMON_H */

Просмотреть файл

@ -165,7 +165,7 @@ prism54_update_stats(struct work_struct *work)
struct obj_bss bss, *bss2;
union oid_res_t r;
down(&priv->stats_sem);
mutex_lock(&priv->stats_lock);
/* Noise floor.
* I'm not sure if the unit is dBm.
@ -207,7 +207,7 @@ prism54_update_stats(struct work_struct *work)
mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r);
priv->local_iwstatistics.discard.retries = r.u;
up(&priv->stats_sem);
mutex_unlock(&priv->stats_lock);
return;
}
@ -218,12 +218,12 @@ prism54_get_wireless_stats(struct net_device *ndev)
islpci_private *priv = netdev_priv(ndev);
/* If the stats are being updated return old data */
if (down_trylock(&priv->stats_sem) == 0) {
if (mutex_trylock(&priv->stats_lock) == 0) {
memcpy(&priv->iwstatistics, &priv->local_iwstatistics,
sizeof (struct iw_statistics));
/* They won't be marked updated for the next time */
priv->local_iwstatistics.qual.updated = 0;
up(&priv->stats_sem);
mutex_unlock(&priv->stats_lock);
} else
priv->iwstatistics.qual.updated = 0;
@ -1780,7 +1780,7 @@ prism54_set_raw(struct net_device *ndev, struct iw_request_info *info,
void
prism54_acl_init(struct islpci_acl *acl)
{
sema_init(&acl->sem, 1);
mutex_init(&acl->lock);
INIT_LIST_HEAD(&acl->mac_list);
acl->size = 0;
acl->policy = MAC_POLICY_OPEN;
@ -1792,10 +1792,10 @@ prism54_clear_mac(struct islpci_acl *acl)
struct list_head *ptr, *next;
struct mac_entry *entry;
down(&acl->sem);
mutex_lock(&acl->lock);
if (acl->size == 0) {
up(&acl->sem);
mutex_unlock(&acl->lock);
return;
}
@ -1806,7 +1806,7 @@ prism54_clear_mac(struct islpci_acl *acl)
kfree(entry);
}
acl->size = 0;
up(&acl->sem);
mutex_unlock(&acl->lock);
}
void
@ -1833,13 +1833,13 @@ prism54_add_mac(struct net_device *ndev, struct iw_request_info *info,
memcpy(entry->addr, addr->sa_data, ETH_ALEN);
if (down_interruptible(&acl->sem)) {
if (mutex_lock_interruptible(&acl->lock)) {
kfree(entry);
return -ERESTARTSYS;
}
list_add_tail(&entry->_list, &acl->mac_list);
acl->size++;
up(&acl->sem);
mutex_unlock(&acl->lock);
return 0;
}
@ -1856,18 +1856,18 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
if (addr->sa_family != ARPHRD_ETHER)
return -EOPNOTSUPP;
if (down_interruptible(&acl->sem))
if (mutex_lock_interruptible(&acl->lock))
return -ERESTARTSYS;
list_for_each_entry(entry, &acl->mac_list, _list) {
if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
list_del(&entry->_list);
acl->size--;
kfree(entry);
up(&acl->sem);
mutex_unlock(&acl->lock);
return 0;
}
}
up(&acl->sem);
mutex_unlock(&acl->lock);
return -EINVAL;
}
@ -1882,7 +1882,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
dwrq->length = 0;
if (down_interruptible(&acl->sem))
if (mutex_lock_interruptible(&acl->lock))
return -ERESTARTSYS;
list_for_each_entry(entry, &acl->mac_list, _list) {
@ -1891,7 +1891,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
dwrq->length++;
dst++;
}
up(&acl->sem);
mutex_unlock(&acl->lock);
return 0;
}
@ -1955,11 +1955,11 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac)
struct mac_entry *entry;
int res = 0;
if (down_interruptible(&acl->sem))
if (mutex_lock_interruptible(&acl->lock))
return -ERESTARTSYS;
if (acl->policy == MAC_POLICY_OPEN) {
up(&acl->sem);
mutex_unlock(&acl->lock);
return 1;
}
@ -1970,7 +1970,7 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac)
}
}
res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res;
up(&acl->sem);
mutex_unlock(&acl->lock);
return res;
}
@ -2114,7 +2114,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
if (wpa_ie_len > MAX_WPA_IE_LEN)
wpa_ie_len = MAX_WPA_IE_LEN;
down(&priv->wpa_sem);
mutex_lock(&priv->wpa_lock);
/* try to use existing entry */
list_for_each(ptr, &priv->bss_wpa_list) {
@ -2165,7 +2165,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
kfree(bss);
}
up(&priv->wpa_sem);
mutex_unlock(&priv->wpa_lock);
}
static size_t
@ -2175,7 +2175,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
struct islpci_bss_wpa_ie *bss = NULL;
size_t len = 0;
down(&priv->wpa_sem);
mutex_lock(&priv->wpa_lock);
list_for_each(ptr, &priv->bss_wpa_list) {
bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
@ -2187,7 +2187,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
len = bss->wpa_ie_len;
memcpy(wpa_ie, bss->wpa_ie, len);
}
up(&priv->wpa_sem);
mutex_unlock(&priv->wpa_lock);
return len;
}
@ -2196,7 +2196,7 @@ void
prism54_wpa_bss_ie_init(islpci_private *priv)
{
INIT_LIST_HEAD(&priv->bss_wpa_list);
sema_init(&priv->wpa_sem, 1);
mutex_init(&priv->wpa_lock);
}
void

Просмотреть файл

@ -864,7 +864,7 @@ islpci_setup(struct pci_dev *pdev)
mutex_init(&priv->mgmt_lock);
priv->mgmt_received = NULL;
init_waitqueue_head(&priv->mgmt_wqueue);
sema_init(&priv->stats_sem, 1);
mutex_init(&priv->stats_lock);
spin_lock_init(&priv->slock);
/* init state machine with off#1 state */

Просмотреть файл

@ -55,7 +55,7 @@ struct islpci_acl {
enum { MAC_POLICY_OPEN=0, MAC_POLICY_ACCEPT=1, MAC_POLICY_REJECT=2 } policy;
struct list_head mac_list; /* a list of mac_entry */
int size; /* size of queue */
struct semaphore sem; /* accessed in ioctls and trap_work */
struct mutex lock; /* accessed in ioctls and trap_work */
};
struct islpci_membuf {
@ -88,7 +88,7 @@ typedef struct {
/* Take care of the wireless stats */
struct work_struct stats_work;
struct semaphore stats_sem;
struct mutex stats_lock;
/* remember when we last updated the stats */
unsigned long stats_timestamp;
/* The first is accessed under semaphore locking.
@ -178,7 +178,7 @@ typedef struct {
int wpa; /* WPA mode enabled */
struct list_head bss_wpa_list;
int num_bss_wpa;
struct semaphore wpa_sem;
struct mutex wpa_lock;
u8 wpa_ie[MAX_WPA_IE_LEN];
size_t wpa_ie_len;

Просмотреть файл

@ -5,29 +5,29 @@ config RT2X00
This will enable the experimental support for the Ralink drivers,
developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
These drivers will make use of the Devicescape ieee80211 stack.
These drivers will make use of the mac80211 stack.
When building one of the individual drivers, the rt2x00 library
will also be created. That library (when the driver is built as
a module) will be called "rt2x00lib.ko".
if RT2X00
config RT2X00_LIB
tristate
depends on RT2X00
config RT2X00_LIB_PCI
tristate
depends on RT2X00
select RT2X00_LIB
config RT2X00_LIB_USB
tristate
depends on RT2X00
select RT2X00_LIB
config RT2X00_LIB_FIRMWARE
boolean
depends on RT2X00_LIB
select CRC_CCITT
select CRC_ITU_T
select FW_LOADER
@ -37,9 +37,17 @@ config RT2X00_LIB_RFKILL
select RFKILL
select INPUT_POLLDEV
config RT2X00_LIB_LEDS
boolean
depends on RT2X00_LIB
select NEW_LEDS
select LEDS_CLASS
select LEDS_TRIGGERS
select MAC80211_LEDS
config RT2400PCI
tristate "Ralink rt2400 pci/pcmcia support"
depends on RT2X00 && PCI
depends on PCI
select RT2X00_LIB_PCI
select EEPROM_93CX6
---help---
@ -56,9 +64,16 @@ config RT2400PCI_RFKILL
hardware button to control the radio state.
This feature depends on the RF switch subsystem rfkill.
config RT2400PCI_LEDS
bool "RT2400 leds support"
depends on RT2400PCI
select RT2X00_LIB_LEDS
---help---
This adds support for led triggers provided my mac80211.
config RT2500PCI
tristate "Ralink rt2500 pci/pcmcia support"
depends on RT2X00 && PCI
depends on PCI
select RT2X00_LIB_PCI
select EEPROM_93CX6
---help---
@ -75,9 +90,16 @@ config RT2500PCI_RFKILL
hardware button to control the radio state.
This feature depends on the RF switch subsystem rfkill.
config RT2500PCI_LEDS
bool "RT2500 leds support"
depends on RT2500PCI
select RT2X00_LIB_LEDS
---help---
This adds support for led triggers provided my mac80211.
config RT61PCI
tristate "Ralink rt61 pci/pcmcia support"
depends on RT2X00 && PCI
depends on PCI
select RT2X00_LIB_PCI
select RT2X00_LIB_FIRMWARE
select EEPROM_93CX6
@ -95,18 +117,32 @@ config RT61PCI_RFKILL
hardware button to control the radio state.
This feature depends on the RF switch subsystem rfkill.
config RT61PCI_LEDS
bool "RT61 leds support"
depends on RT61PCI
select RT2X00_LIB_LEDS
---help---
This adds support for led triggers provided my mac80211.
config RT2500USB
tristate "Ralink rt2500 usb support"
depends on RT2X00 && USB
depends on USB
select RT2X00_LIB_USB
---help---
This is an experimental driver for the Ralink rt2500 wireless chip.
When compiled as a module, this driver will be called "rt2500usb.ko".
config RT2500USB_LEDS
bool "RT2500 leds support"
depends on RT2500USB
select RT2X00_LIB_LEDS
---help---
This adds support for led triggers provided my mac80211.
config RT73USB
tristate "Ralink rt73 usb support"
depends on RT2X00 && USB
depends on USB
select RT2X00_LIB_USB
select RT2X00_LIB_FIRMWARE
---help---
@ -114,6 +150,13 @@ config RT73USB
When compiled as a module, this driver will be called "rt73usb.ko".
config RT73USB_LEDS
bool "RT73 leds support"
depends on RT73USB
select RT2X00_LIB_LEDS
---help---
This adds support for led triggers provided my mac80211.
config RT2X00_LIB_DEBUGFS
bool "Ralink debugfs support"
depends on RT2X00_LIB && MAC80211_DEBUGFS
@ -128,3 +171,4 @@ config RT2X00_DEBUG
---help---
Enable debugging output for all rt2x00 modules
endif

Просмотреть файл

@ -1,16 +1,11 @@
rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o
ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y)
rt2x00lib-objs += rt2x00debug.o
endif
ifeq ($(CONFIG_RT2X00_LIB_RFKILL),y)
rt2x00lib-objs += rt2x00rfkill.o
endif
ifeq ($(CONFIG_RT2X00_LIB_FIRMWARE),y)
rt2x00lib-objs += rt2x00firmware.o
endif
rt2x00lib-y += rt2x00dev.o
rt2x00lib-y += rt2x00mac.o
rt2x00lib-y += rt2x00config.o
rt2x00lib-y += rt2x00queue.o
rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o
rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -243,36 +243,50 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
#define rt2400pci_rfkill_poll NULL
#endif /* CONFIG_RT2400PCI_RFKILL */
#ifdef CONFIG_RT2400PCI_LEDS
static void rt2400pci_led_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct rt2x00_led *led =
container_of(led_cdev, struct rt2x00_led, led_dev);
unsigned int enabled = brightness != LED_OFF;
unsigned int activity =
led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY;
u32 reg;
rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) {
rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled && activity);
}
rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
}
#else
#define rt2400pci_led_brightness NULL
#endif /* CONFIG_RT2400PCI_LEDS */
/*
* Configuration handlers.
*/
static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev,
__le32 *mac)
{
rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac,
(2 * sizeof(__le32)));
}
static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev,
__le32 *bssid)
{
rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid,
(2 * sizeof(__le32)));
}
static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
const int tsf_sync)
static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf,
const unsigned int flags)
{
unsigned int bcn_preload;
u32 reg;
if (flags & CONFIG_UPDATE_TYPE) {
rt2x00pci_register_write(rt2x00dev, CSR14, 0);
/*
* Enable beacon config
*/
bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD,
PREAMBLE + get_duration(IEEE80211_HEADER, 20));
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
/*
@ -280,13 +294,23 @@ static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, CSR14_TBCN,
(conf->sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
if (flags & CONFIG_UPDATE_MAC)
rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
conf->mac, sizeof(conf->mac));
if (flags & CONFIG_UPDATE_BSSID)
rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
conf->bssid, sizeof(conf->bssid));
}
static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
static int rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
const int short_preamble,
const int ack_timeout,
const int ack_consume_time)
@ -327,6 +351,8 @@ static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
return 0;
}
static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev,
@ -481,8 +507,8 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
}
static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
struct rt2x00lib_conf *libconf)
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
if (flags & CONFIG_UPDATE_PHYMODE)
rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates);
@ -498,44 +524,16 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
}
static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
struct ieee80211_tx_queue_params *params)
const int cw_min, const int cw_max)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_CWMIN, params->cw_min);
rt2x00_set_field32(&reg, CSR11_CWMAX, params->cw_max);
rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
}
/*
* LED functions.
*/
static void rt2400pci_enable_led(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
rt2x00_set_field32(&reg, LEDCSR_LINK,
(rt2x00dev->led_mode != LED_MODE_ASUS));
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY,
(rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
}
static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
}
/*
* Link tuning
*/
@ -593,90 +591,94 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
* Initialization functions.
*/
static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry)
struct queue_entry *entry)
{
__le32 *rxd = entry->priv;
struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
u32 word;
rt2x00_desc_read(rxd, 2, &word);
rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size);
rt2x00_desc_write(rxd, 2, word);
rt2x00_desc_read(priv_rx->desc, 2, &word);
rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
entry->queue->data_size);
rt2x00_desc_write(priv_rx->desc, 2, word);
rt2x00_desc_read(rxd, 1, &word);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
rt2x00_desc_write(rxd, 1, word);
rt2x00_desc_read(priv_rx->desc, 1, &word);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
rt2x00_desc_write(priv_rx->desc, 1, word);
rt2x00_desc_read(rxd, 0, &word);
rt2x00_desc_read(priv_rx->desc, 0, &word);
rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
rt2x00_desc_write(rxd, 0, word);
rt2x00_desc_write(priv_rx->desc, 0, word);
}
static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry)
struct queue_entry *entry)
{
__le32 *txd = entry->priv;
struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
u32 word;
rt2x00_desc_read(txd, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
rt2x00_desc_write(txd, 1, word);
rt2x00_desc_read(priv_tx->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
rt2x00_desc_write(priv_tx->desc, 1, word);
rt2x00_desc_read(txd, 2, &word);
rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size);
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(priv_tx->desc, 2, &word);
rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH,
entry->queue->data_size);
rt2x00_desc_write(priv_tx->desc, 2, word);
rt2x00_desc_read(txd, 0, &word);
rt2x00_desc_read(priv_tx->desc, 0, &word);
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
rt2x00_desc_write(txd, 0, word);
rt2x00_desc_write(priv_tx->desc, 0, word);
}
static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
struct queue_entry_priv_pci_rx *priv_rx;
struct queue_entry_priv_pci_tx *priv_tx;
u32 reg;
/*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
rt2x00_set_field32(&reg, TXCSR2_NUM_TXD,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM,
rt2x00dev->bcn[1].stats.limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
rt2x00dev->bcn[1].data_dma);
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
rt2x00dev->bcn[0].data_dma);
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
priv_rx = rt2x00dev->rx->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
rt2x00dev->rx->data_dma);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
return 0;
@ -702,6 +704,11 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
(rt2x00dev->rx->data_size / 128));
rt2x00pci_register_write(rt2x00dev, CSR9, reg);
rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
rt2x00pci_register_read(rt2x00dev, ARCSR0, &reg);
@ -795,19 +802,15 @@ continue_csr_init:
rt2400pci_bbp_write(rt2x00dev, 30, 0x21);
rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
reg_id, value);
rt2400pci_bbp_write(rt2x00dev, reg_id, value);
}
}
DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
return 0;
}
@ -859,7 +862,7 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all registers.
*/
if (rt2400pci_init_rings(rt2x00dev) ||
if (rt2400pci_init_queues(rt2x00dev) ||
rt2400pci_init_registers(rt2x00dev) ||
rt2400pci_init_bbp(rt2x00dev)) {
ERROR(rt2x00dev, "Register initialization failed.\n");
@ -871,11 +874,6 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
*/
rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
/*
* Enable LED
*/
rt2400pci_enable_led(rt2x00dev);
return 0;
}
@ -883,11 +881,6 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
/*
* Disable LED
*/
rt2400pci_disable_led(rt2x00dev);
rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
/*
@ -986,10 +979,10 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
*/
static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
struct txdata_entry_desc *desc,
struct txentry_desc *txdesc,
struct ieee80211_tx_control *control)
{
struct skb_desc *skbdesc = get_skb_desc(skb);
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txd = skbdesc->desc;
u32 word;
@ -1001,19 +994,19 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 3, &word);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
rt2x00_desc_write(txd, 3, word);
rt2x00_desc_read(txd, 4, &word);
rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, desc->length_low);
rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, desc->length_high);
rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
rt2x00_desc_write(txd, 4, word);
@ -1022,14 +1015,14 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
test_bit(ENTRY_TXD_ACK, &desc->flags));
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_RTS,
test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
@ -1040,11 +1033,11 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
* TX data initialization
*/
static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
unsigned int queue)
const unsigned int queue)
{
u32 reg;
if (queue == IEEE80211_TX_QUEUE_BEACON) {
if (queue == RT2X00_BCN_QUEUE_BEACON) {
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
@ -1059,56 +1052,56 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
(queue == IEEE80211_TX_QUEUE_DATA1));
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
(queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
(queue == RT2X00_BCN_QUEUE_ATIM));
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
/*
* RX control handlers
*/
static void rt2400pci_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
static void rt2400pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
__le32 *rxd = entry->priv;
struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
u32 word0;
u32 word2;
rt2x00_desc_read(rxd, 0, &word0);
rt2x00_desc_read(rxd, 2, &word2);
rt2x00_desc_read(priv_rx->desc, 0, &word0);
rt2x00_desc_read(priv_rx->desc, 2, &word2);
desc->flags = 0;
rxdesc->flags = 0;
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
desc->flags |= RX_FLAG_FAILED_FCS_CRC;
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
/*
* Obtain the status about this packet.
*/
desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = 0;
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
entry->queue->rt2x00dev->rssi_offset;
rxdesc->ofdm = 0;
rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}
/*
* Interrupt functions.
*/
static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
const enum ieee80211_tx_queue queue_idx)
{
struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
struct data_entry *entry;
__le32 *txd;
struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
struct queue_entry_priv_pci_tx *priv_tx;
struct queue_entry *entry;
struct txdone_entry_desc txdesc;
u32 word;
int tx_status;
int retry;
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->priv;
rt2x00_desc_read(txd, 0, &word);
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
priv_tx = entry->priv_data;
rt2x00_desc_read(priv_tx->desc, 0, &word);
if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
!rt2x00_get_field32(word, TXD_W0_VALID))
@ -1117,10 +1110,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
/*
* Obtain the status about this packet.
*/
tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
}
}
@ -1164,7 +1157,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
* 3 - Atim ring transmit done interrupt.
*/
if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
rt2400pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
rt2400pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
/*
* 4 - Priority ring transmit done interrupt.
@ -1272,8 +1265,24 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Store led mode, for correct led behaviour.
*/
rt2x00dev->led_mode =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
#ifdef CONFIG_RT2400PCI_LEDS
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
switch (value) {
case LED_MODE_ASUS:
case LED_MODE_ALPHA:
case LED_MODE_DEFAULT:
rt2x00dev->led_flags = LED_SUPPORT_RADIO;
break;
case LED_MODE_TXRX_ACTIVITY:
rt2x00dev->led_flags =
LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY;
break;
case LED_MODE_SIGNAL_STRENGTH:
rt2x00dev->led_flags = LED_SUPPORT_RADIO;
break;
}
#endif /* CONFIG_RT2400PCI_LEDS */
/*
* Detect if this device has an hardware controlled radio.
@ -1343,8 +1352,8 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw_mode information.
*/
spec->num_modes = 1;
spec->num_rates = 4;
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK;
spec->tx_power_a = NULL;
spec->tx_power_bg = txpower;
spec->tx_power_default = DEFAULT_TXPOWER;
@ -1374,9 +1383,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
rt2400pci_probe_hw_mode(rt2x00dev);
/*
* This device requires the beacon ring
* This device requires the atim queue
*/
__set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
/*
* Set the rssi offset.
@ -1481,7 +1490,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw,
/*
* Write configuration to register.
*/
rt2400pci_config_cw(rt2x00dev, &rt2x00dev->tx->tx_params);
rt2400pci_config_cw(rt2x00dev,
rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max);
return 0;
}
@ -1500,12 +1510,48 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
static void rt2400pci_reset_tsf(struct ieee80211_hw *hw)
static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct rt2x00_intf *intf = vif_to_intf(control->vif);
struct queue_entry_priv_pci_tx *priv_tx;
struct skb_frame_desc *skbdesc;
rt2x00pci_register_write(rt2x00dev, CSR16, 0);
rt2x00pci_register_write(rt2x00dev, CSR17, 0);
if (unlikely(!intf->beacon))
return -ENOBUFS;
priv_tx = intf->beacon->priv_data;
/*
* Fill in skb descriptor
*/
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
skbdesc->data = skb->data;
skbdesc->data_len = skb->len;
skbdesc->desc = priv_tx->desc;
skbdesc->desc_len = intf->beacon->queue->desc_size;
skbdesc->entry = intf->beacon;
/*
* mac80211 doesn't provide the control->queue variable
* for beacons. Set our own queue identification so
* it can be used during descriptor initialization.
*/
control->queue = RT2X00_BCN_QUEUE_BEACON;
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Enable beacon generation.
* Write entire beacon with descriptor to register,
* and kick the beacon generator.
*/
memcpy(priv_tx->data, skb->data, skb->len);
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
@ -1532,8 +1578,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.conf_tx = rt2400pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2400pci_get_tsf,
.reset_tsf = rt2400pci_reset_tsf,
.beacon_update = rt2x00pci_beacon_update,
.beacon_update = rt2400pci_beacon_update,
.tx_last_beacon = rt2400pci_tx_last_beacon,
};
@ -1549,23 +1594,54 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.link_stats = rt2400pci_link_stats,
.reset_tuner = rt2400pci_reset_tuner,
.link_tuner = rt2400pci_link_tuner,
.led_brightness = rt2400pci_led_brightness,
.write_tx_desc = rt2400pci_write_tx_desc,
.write_tx_data = rt2x00pci_write_tx_data,
.kick_tx_queue = rt2400pci_kick_tx_queue,
.fill_rxdone = rt2400pci_fill_rxdone,
.config_mac_addr = rt2400pci_config_mac_addr,
.config_bssid = rt2400pci_config_bssid,
.config_type = rt2400pci_config_type,
.config_intf = rt2400pci_config_intf,
.config_preamble = rt2400pci_config_preamble,
.config = rt2400pci_config,
};
static const struct data_queue_desc rt2400pci_queue_rx = {
.entry_num = RX_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_rx),
};
static const struct data_queue_desc rt2400pci_queue_tx = {
.entry_num = TX_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_tx),
};
static const struct data_queue_desc rt2400pci_queue_bcn = {
.entry_num = BEACON_ENTRIES,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_tx),
};
static const struct data_queue_desc rt2400pci_queue_atim = {
.entry_num = ATIM_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_tx),
};
static const struct rt2x00_ops rt2400pci_ops = {
.name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.max_sta_intf = 1,
.max_ap_intf = 1,
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
.rx = &rt2400pci_queue_rx,
.tx = &rt2400pci_queue_tx,
.bcn = &rt2400pci_queue_bcn,
.atim = &rt2400pci_queue_atim,
.lib = &rt2400pci_rt2x00_ops,
.hw = &rt2400pci_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -923,13 +923,13 @@
#define RXD_W7_RESERVED FIELD32(0xffffffff)
/*
* Macro's for converting txpower from EEPROM to dscape value
* and from dscape value to register value.
* Macro's for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
* NOTE: Logics in rt2400pci for txpower are reversed
* compared to the other rt2x00 drivers. A higher txpower
* value means that the txpower must be lowered. This is
* important when converting the value coming from the
* dscape stack to the rt2400 acceptable value.
* mac80211 stack to the rt2400 acceptable value.
*/
#define MIN_TXPOWER 31
#define MAX_TXPOWER 62

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -243,40 +243,53 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
#define rt2500pci_rfkill_poll NULL
#endif /* CONFIG_RT2500PCI_RFKILL */
#ifdef CONFIG_RT2500PCI_LEDS
static void rt2500pci_led_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct rt2x00_led *led =
container_of(led_cdev, struct rt2x00_led, led_dev);
unsigned int enabled = brightness != LED_OFF;
unsigned int activity =
led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY;
u32 reg;
rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) {
rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled && activity);
}
rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
}
#else
#define rt2500pci_led_brightness NULL
#endif /* CONFIG_RT2500PCI_LEDS */
/*
* Configuration handlers.
*/
static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev,
__le32 *mac)
{
rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac,
(2 * sizeof(__le32)));
}
static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev,
__le32 *bssid)
{
rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid,
(2 * sizeof(__le32)));
}
static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
const int tsf_sync)
static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf,
const unsigned int flags)
{
struct data_queue *queue =
rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
unsigned int bcn_preload;
u32 reg;
if (flags & CONFIG_UPDATE_TYPE) {
rt2x00pci_register_write(rt2x00dev, CSR14, 0);
/*
* Enable beacon config
*/
bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD,
PREAMBLE + get_duration(IEEE80211_HEADER, 20));
rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN,
rt2x00lib_get_ring(rt2x00dev,
IEEE80211_TX_QUEUE_BEACON)
->tx_params.cw_min);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
/*
@ -284,13 +297,23 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, CSR14_TBCN,
(conf->sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
if (flags & CONFIG_UPDATE_MAC)
rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
conf->mac, sizeof(conf->mac));
if (flags & CONFIG_UPDATE_BSSID)
rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
conf->bssid, sizeof(conf->bssid));
}
static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
static int rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
const int short_preamble,
const int ack_timeout,
const int ack_consume_time)
@ -331,6 +354,8 @@ static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
return 0;
}
static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev,
@ -530,8 +555,8 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
}
static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
struct rt2x00lib_conf *libconf)
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
if (flags & CONFIG_UPDATE_PHYMODE)
rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates);
@ -547,34 +572,6 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
rt2500pci_config_duration(rt2x00dev, libconf);
}
/*
* LED functions.
*/
static void rt2500pci_enable_led(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
rt2x00_set_field32(&reg, LEDCSR_LINK,
(rt2x00dev->led_mode != LED_MODE_ASUS));
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY,
(rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
}
static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
}
/*
* Link tuning
*/
@ -610,9 +607,10 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
/*
* To prevent collisions with MAC ASIC on chipsets
* up to version C the link tuning should halt after 20
* seconds.
* seconds while being associated.
*/
if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
rt2x00dev->intf_associated &&
rt2x00dev->link.count > 20)
return;
@ -620,9 +618,12 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
/*
* Chipset versions C and lower should directly continue
* to the dynamic CCA tuning.
* to the dynamic CCA tuning. Chipset version D and higher
* should go straight to dynamic CCA tuning when they
* are not associated.
*/
if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D)
if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D ||
!rt2x00dev->intf_associated)
goto dynamic_cca_tune;
/*
@ -684,82 +685,84 @@ dynamic_cca_tune:
* Initialization functions.
*/
static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry)
struct queue_entry *entry)
{
__le32 *rxd = entry->priv;
struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
u32 word;
rt2x00_desc_read(rxd, 1, &word);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
rt2x00_desc_write(rxd, 1, word);
rt2x00_desc_read(priv_rx->desc, 1, &word);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
rt2x00_desc_write(priv_rx->desc, 1, word);
rt2x00_desc_read(rxd, 0, &word);
rt2x00_desc_read(priv_rx->desc, 0, &word);
rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
rt2x00_desc_write(rxd, 0, word);
rt2x00_desc_write(priv_rx->desc, 0, word);
}
static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry)
struct queue_entry *entry)
{
__le32 *txd = entry->priv;
struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
u32 word;
rt2x00_desc_read(txd, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
rt2x00_desc_write(txd, 1, word);
rt2x00_desc_read(priv_tx->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
rt2x00_desc_write(priv_tx->desc, 1, word);
rt2x00_desc_read(txd, 0, &word);
rt2x00_desc_read(priv_tx->desc, 0, &word);
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
rt2x00_desc_write(txd, 0, word);
rt2x00_desc_write(priv_tx->desc, 0, word);
}
static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
struct queue_entry_priv_pci_rx *priv_rx;
struct queue_entry_priv_pci_tx *priv_tx;
u32 reg;
/*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
rt2x00_set_field32(&reg, TXCSR2_NUM_TXD,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM,
rt2x00dev->bcn[1].stats.limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
rt2x00dev->bcn[1].data_dma);
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
rt2x00dev->bcn[0].data_dma);
priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
priv_rx = rt2x00dev->rx->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
rt2x00dev->rx->data_dma);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_tx->desc_dma);
rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
return 0;
@ -792,6 +795,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
rt2x00pci_register_write(rt2x00dev, CNT3, 0);
rt2x00pci_register_read(rt2x00dev, TXCSR8, &reg);
@ -947,19 +955,15 @@ continue_csr_init:
rt2500pci_bbp_write(rt2x00dev, 61, 0x6d);
rt2500pci_bbp_write(rt2x00dev, 62, 0x10);
DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
reg_id, value);
rt2500pci_bbp_write(rt2x00dev, reg_id, value);
}
}
DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
return 0;
}
@ -1011,7 +1015,7 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all registers.
*/
if (rt2500pci_init_rings(rt2x00dev) ||
if (rt2500pci_init_queues(rt2x00dev) ||
rt2500pci_init_registers(rt2x00dev) ||
rt2500pci_init_bbp(rt2x00dev)) {
ERROR(rt2x00dev, "Register initialization failed.\n");
@ -1023,11 +1027,6 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
*/
rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
/*
* Enable LED
*/
rt2500pci_enable_led(rt2x00dev);
return 0;
}
@ -1035,11 +1034,6 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
/*
* Disable LED
*/
rt2500pci_disable_led(rt2x00dev);
rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
/*
@ -1138,10 +1132,10 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
*/
static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
struct txdata_entry_desc *desc,
struct txentry_desc *txdesc,
struct ieee80211_tx_control *control)
{
struct skb_desc *skbdesc = get_skb_desc(skb);
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txd = skbdesc->desc;
u32 word;
@ -1150,36 +1144,36 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
*/
rt2x00_desc_read(txd, 2, &word);
rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&word, TXD_W2_AIFS, desc->aifs);
rt2x00_set_field32(&word, TXD_W2_CWMIN, desc->cw_min);
rt2x00_set_field32(&word, TXD_W2_CWMAX, desc->cw_max);
rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min);
rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max);
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 3, &word);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, desc->length_low);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, desc->length_high);
rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low);
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_desc_write(txd, 3, word);
rt2x00_desc_read(txd, 10, &word);
rt2x00_set_field32(&word, TXD_W10_RTS,
test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));
test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
rt2x00_desc_write(txd, 10, word);
rt2x00_desc_read(txd, 0, &word);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
test_bit(ENTRY_TXD_ACK, &desc->flags));
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
@ -1192,11 +1186,11 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
* TX data initialization
*/
static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
unsigned int queue)
const unsigned int queue)
{
u32 reg;
if (queue == IEEE80211_TX_QUEUE_BEACON) {
if (queue == RT2X00_BCN_QUEUE_BEACON) {
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
@ -1211,53 +1205,53 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
(queue == IEEE80211_TX_QUEUE_DATA1));
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
(queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
(queue == RT2X00_BCN_QUEUE_ATIM));
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
/*
* RX control handlers
*/
static void rt2500pci_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
static void rt2500pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
__le32 *rxd = entry->priv;
struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
u32 word0;
u32 word2;
rt2x00_desc_read(rxd, 0, &word0);
rt2x00_desc_read(rxd, 2, &word2);
rt2x00_desc_read(priv_rx->desc, 0, &word0);
rt2x00_desc_read(priv_rx->desc, 2, &word2);
desc->flags = 0;
rxdesc->flags = 0;
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
desc->flags |= RX_FLAG_FAILED_FCS_CRC;
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
entry->queue->rt2x00dev->rssi_offset;
rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}
/*
* Interrupt functions.
*/
static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
const enum ieee80211_tx_queue queue_idx)
{
struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
struct data_entry *entry;
__le32 *txd;
struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
struct queue_entry_priv_pci_tx *priv_tx;
struct queue_entry *entry;
struct txdone_entry_desc txdesc;
u32 word;
int tx_status;
int retry;
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
txd = entry->priv;
rt2x00_desc_read(txd, 0, &word);
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
priv_tx = entry->priv_data;
rt2x00_desc_read(priv_tx->desc, 0, &word);
if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
!rt2x00_get_field32(word, TXD_W0_VALID))
@ -1266,10 +1260,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
/*
* Obtain the status about this packet.
*/
tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
}
}
@ -1313,7 +1307,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
* 3 - Atim ring transmit done interrupt.
*/
if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
rt2500pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
/*
* 4 - Priority ring transmit done interrupt.
@ -1442,8 +1436,24 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Store led mode, for correct led behaviour.
*/
rt2x00dev->led_mode =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
#ifdef CONFIG_RT2500PCI_LEDS
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
switch (value) {
case LED_MODE_ASUS:
case LED_MODE_ALPHA:
case LED_MODE_DEFAULT:
rt2x00dev->led_flags = LED_SUPPORT_RADIO;
break;
case LED_MODE_TXRX_ACTIVITY:
rt2x00dev->led_flags =
LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY;
break;
case LED_MODE_SIGNAL_STRENGTH:
rt2x00dev->led_flags = LED_SUPPORT_RADIO;
break;
}
#endif /* CONFIG_RT2500PCI_LEDS */
/*
* Detect if this device has an hardware controlled radio.
@ -1656,8 +1666,8 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw_mode information.
*/
spec->num_modes = 2;
spec->num_rates = 12;
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
spec->tx_power_a = NULL;
spec->tx_power_bg = txpower;
spec->tx_power_default = DEFAULT_TXPOWER;
@ -1678,9 +1688,9 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
spec->channels = rf_vals_bg_2525e;
} else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
spec->channels = rf_vals_5222;
spec->num_modes = 3;
}
}
@ -1705,9 +1715,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
rt2500pci_probe_hw_mode(rt2x00dev);
/*
* This device requires the beacon ring
* This device requires the atim queue
*/
__set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
/*
* Set the rssi offset.
@ -1811,12 +1821,48 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
static void rt2500pci_reset_tsf(struct ieee80211_hw *hw)
static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct rt2x00_intf *intf = vif_to_intf(control->vif);
struct queue_entry_priv_pci_tx *priv_tx;
struct skb_frame_desc *skbdesc;
rt2x00pci_register_write(rt2x00dev, CSR16, 0);
rt2x00pci_register_write(rt2x00dev, CSR17, 0);
if (unlikely(!intf->beacon))
return -ENOBUFS;
priv_tx = intf->beacon->priv_data;
/*
* Fill in skb descriptor
*/
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
skbdesc->data = skb->data;
skbdesc->data_len = skb->len;
skbdesc->desc = priv_tx->desc;
skbdesc->desc_len = intf->beacon->queue->desc_size;
skbdesc->entry = intf->beacon;
/*
* mac80211 doesn't provide the control->queue variable
* for beacons. Set our own queue identification so
* it can be used during descriptor initialization.
*/
control->queue = RT2X00_BCN_QUEUE_BEACON;
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Enable beacon generation.
* Write entire beacon with descriptor to register,
* and kick the beacon generator.
*/
memcpy(priv_tx->data, skb->data, skb->len);
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
@ -1843,8 +1889,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2500pci_get_tsf,
.reset_tsf = rt2500pci_reset_tsf,
.beacon_update = rt2x00pci_beacon_update,
.beacon_update = rt2500pci_beacon_update,
.tx_last_beacon = rt2500pci_tx_last_beacon,
};
@ -1860,23 +1905,54 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.link_stats = rt2500pci_link_stats,
.reset_tuner = rt2500pci_reset_tuner,
.link_tuner = rt2500pci_link_tuner,
.led_brightness = rt2500pci_led_brightness,
.write_tx_desc = rt2500pci_write_tx_desc,
.write_tx_data = rt2x00pci_write_tx_data,
.kick_tx_queue = rt2500pci_kick_tx_queue,
.fill_rxdone = rt2500pci_fill_rxdone,
.config_mac_addr = rt2500pci_config_mac_addr,
.config_bssid = rt2500pci_config_bssid,
.config_type = rt2500pci_config_type,
.config_intf = rt2500pci_config_intf,
.config_preamble = rt2500pci_config_preamble,
.config = rt2500pci_config,
};
static const struct data_queue_desc rt2500pci_queue_rx = {
.entry_num = RX_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_rx),
};
static const struct data_queue_desc rt2500pci_queue_tx = {
.entry_num = TX_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_tx),
};
static const struct data_queue_desc rt2500pci_queue_bcn = {
.entry_num = BEACON_ENTRIES,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_tx),
};
static const struct data_queue_desc rt2500pci_queue_atim = {
.entry_num = ATIM_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_tx),
};
static const struct rt2x00_ops rt2500pci_ops = {
.name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.max_sta_intf = 1,
.max_ap_intf = 1,
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
.rx = &rt2500pci_queue_rx,
.tx = &rt2500pci_queue_tx,
.bcn = &rt2500pci_queue_bcn,
.atim = &rt2500pci_queue_atim,
.lib = &rt2500pci_rt2x00_ops,
.hw = &rt2500pci_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -1213,8 +1213,8 @@
#define RXD_W10_DROP FIELD32(0x00000001)
/*
* Macro's for converting txpower from EEPROM to dscape value
* and from dscape value to register value.
* Macro's for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_TXPOWER 0
#define MAX_TXPOWER 31

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -282,40 +282,58 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
#ifdef CONFIG_RT2500USB_LEDS
static void rt2500usb_led_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct rt2x00_led *led =
container_of(led_cdev, struct rt2x00_led, led_dev);
unsigned int enabled = brightness != LED_OFF;
unsigned int activity =
led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY;
if (in_atomic()) {
NOTICE(led->rt2x00dev,
"Ignoring LED brightness command for led %d", led->type);
return;
}
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) {
rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
MAC_CSR20_LINK, enabled);
rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
MAC_CSR20_ACTIVITY, enabled && activity);
}
rt2500usb_register_write(led->rt2x00dev, MAC_CSR20,
led->rt2x00dev->led_mcu_reg);
}
#else
#define rt2500usb_led_brightness NULL
#endif /* CONFIG_RT2500USB_LEDS */
/*
* Configuration handlers.
*/
static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev,
__le32 *mac)
{
rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
(3 * sizeof(__le16)));
}
static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev,
__le32 *bssid)
{
rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid,
(3 * sizeof(__le16)));
}
static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
const int tsf_sync)
static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf,
const unsigned int flags)
{
unsigned int bcn_preload;
u16 reg;
if (flags & CONFIG_UPDATE_TYPE) {
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
/*
* Enable beacon config
*/
bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET,
(PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6);
if (type == IEEE80211_IF_TYPE_STA)
rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
else
rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 2);
rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
2 * (conf->type != IEEE80211_IF_TYPE_STA));
rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
/*
@ -328,13 +346,22 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
rt2x00_set_field16(&reg, TXRX_CSR19_TBCN,
(tsf_sync == TSF_SYNC_BEACON));
(conf->sync == TSF_SYNC_BEACON));
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, tsf_sync);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
}
if (flags & CONFIG_UPDATE_MAC)
rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac,
(3 * sizeof(__le16)));
if (flags & CONFIG_UPDATE_BSSID)
rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid,
(3 * sizeof(__le16)));
}
static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
const int short_preamble,
const int ack_timeout,
const int ack_consume_time)
@ -342,13 +369,11 @@ static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
u16 reg;
/*
* When in atomic context, reschedule and let rt2x00lib
* call this function again.
* When in atomic context, we should let rt2x00lib
* try this configuration again later.
*/
if (in_atomic()) {
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
return;
}
if (in_atomic())
return -EAGAIN;
rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, ack_timeout);
@ -358,21 +383,14 @@ static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
!!short_preamble);
rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
return 0;
}
static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
const int phymode,
const int basic_rate_mask)
{
rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
if (phymode == HWMODE_B) {
rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b);
rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040);
} else {
rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0005);
rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x016c);
}
}
static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
@ -510,6 +528,8 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
u16 reg;
rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time);
rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs);
rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs);
rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
@ -518,12 +538,11 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
}
static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
struct rt2x00lib_conf *libconf)
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
if (flags & CONFIG_UPDATE_PHYMODE)
rt2500usb_config_phymode(rt2x00dev, libconf->phymode,
libconf->basic_rates);
rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
rt2500usb_config_channel(rt2x00dev, &libconf->rf,
libconf->conf->power_level);
@ -536,36 +555,6 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
rt2500usb_config_duration(rt2x00dev, libconf);
}
/*
* LED functions.
*/
static void rt2500usb_enable_led(struct rt2x00_dev *rt2x00dev)
{
u16 reg;
rt2500usb_register_read(rt2x00dev, MAC_CSR21, &reg);
rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, 70);
rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, 30);
rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
rt2500usb_register_read(rt2x00dev, MAC_CSR20, &reg);
rt2x00_set_field16(&reg, MAC_CSR20_LINK,
(rt2x00dev->led_mode != LED_MODE_ASUS));
rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY,
(rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
}
static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev)
{
u16 reg;
rt2500usb_register_read(rt2x00dev, MAC_CSR20, &reg);
rt2x00_set_field16(&reg, MAC_CSR20_LINK, 0);
rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 0);
rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
}
/*
* Link tuning
*/
@ -625,6 +614,24 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
u8 up_bound;
u8 low_bound;
/*
* Read current r17 value, as well as the sensitivity values
* for the r17 register.
*/
rt2500usb_bbp_read(rt2x00dev, 17, &r17);
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER);
/*
* If we are not associated, we should go straight to the
* dynamic CCA tuning.
*/
if (!rt2x00dev->intf_associated)
goto dynamic_cca_tune;
/*
* Determine the BBP tuning threshold and correctly
* set BBP 24, 25 and 61.
@ -650,13 +657,6 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
rt2500usb_bbp_write(rt2x00dev, 25, r25);
rt2500usb_bbp_write(rt2x00dev, 61, r61);
/*
* Read current r17 value, as well as the sensitivity values
* for the r17 register.
*/
rt2500usb_bbp_read(rt2x00dev, 17, &r17);
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
/*
* A too low RSSI will cause too much false CCA which will
* then corrupt the R17 tuning. To remidy this the tuning should
@ -692,14 +692,9 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
* Leave short or middle distance condition, restore r17
* to the dynamic tuning range.
*/
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
vgc_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
low_bound = 0x32;
if (rssi >= -77)
up_bound = vgc_bound;
else
up_bound = vgc_bound - (-77 - rssi);
if (rssi < -77)
up_bound -= (-77 - rssi);
if (up_bound < low_bound)
up_bound = low_bound;
@ -707,7 +702,16 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
if (r17 > up_bound) {
rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
rt2x00dev->link.vgc_level = up_bound;
} else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
return;
}
dynamic_cca_tune:
/*
* R17 is inside the dynamic tuning range,
* start tuning the link based on the false cca counter.
*/
if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
rt2x00dev->link.vgc_level = r17;
} else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
@ -747,6 +751,11 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
rt2500usb_register_read(rt2x00dev, MAC_CSR21, &reg);
rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, 70);
rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, 30);
rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
rt2500usb_register_read(rt2x00dev, TXRX_CSR5, &reg);
rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0, 13);
rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0_VALID, 1);
@ -878,19 +887,15 @@ continue_csr_init:
rt2500usb_bbp_write(rt2x00dev, 62, 0x10);
rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
reg_id, value);
rt2500usb_bbp_write(rt2x00dev, reg_id, value);
}
}
DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
return 0;
}
@ -920,21 +925,11 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
return -EIO;
}
/*
* Enable LED
*/
rt2500usb_enable_led(rt2x00dev);
return 0;
}
static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
/*
* Disable LED
*/
rt2500usb_disable_led(rt2x00dev);
rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121);
rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121);
@ -1027,10 +1022,10 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
*/
static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
struct txdata_entry_desc *desc,
struct txentry_desc *txdesc,
struct ieee80211_tx_control *control)
{
struct skb_desc *skbdesc = get_skb_desc(skb);
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txd = skbdesc->desc;
u32 word;
@ -1039,31 +1034,31 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
*/
rt2x00_desc_read(txd, 1, &word);
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&word, TXD_W1_AIFS, desc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
rt2x00_desc_write(txd, 1, word);
rt2x00_desc_read(txd, 2, &word);
rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 0, &word);
rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, control->retry_limit);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
test_bit(ENTRY_TXD_ACK, &desc->flags));
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
!!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT));
rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
@ -1088,11 +1083,11 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
* TX data initialization
*/
static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
unsigned int queue)
const unsigned int queue)
{
u16 reg;
if (queue != IEEE80211_TX_QUEUE_BEACON)
if (queue != RT2X00_BCN_QUEUE_BEACON)
return;
rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
@ -1114,42 +1109,61 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
/*
* RX control handlers
*/
static void rt2500usb_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
static void rt2500usb_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct skb_desc *skbdesc = get_skb_desc(entry->skb);
struct urb *urb = entry->priv;
__le32 *rxd = (__le32 *)(entry->skb->data +
(urb->actual_length - entry->ring->desc_size));
struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *rxd =
(__le32 *)(entry->skb->data +
(priv_rx->urb->actual_length - entry->queue->desc_size));
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
u32 word0;
u32 word1;
rt2x00_desc_read(rxd, 0, &word0);
rt2x00_desc_read(rxd, 1, &word1);
desc->flags = 0;
rxdesc->flags = 0;
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
desc->flags |= RX_FLAG_FAILED_FCS_CRC;
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
/*
* Obtain the status about this packet.
*/
desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
entry->queue->rt2x00dev->rssi_offset;
rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
/*
* Set descriptor and data pointer.
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
if (header_size % 4 == 0) {
skb_push(entry->skb, 2);
memmove(entry->skb->data, entry->skb->data + 2,
entry->skb->len - 2);
}
/*
* Set descriptor pointer.
*/
skbdesc->desc = entry->skb->data + desc->size;
skbdesc->desc_len = entry->ring->desc_size;
skbdesc->data = entry->skb->data;
skbdesc->data_len = desc->size;
skbdesc->data_len = rxdesc->size;
skbdesc->desc = entry->skb->data + rxdesc->size;
skbdesc->desc_len = entry->queue->desc_size;
/*
* Remove descriptor from skb buffer and trim the whole thing
* down to only contain data.
*/
skb_trim(entry->skb, rxdesc->size);
}
/*
@ -1157,10 +1171,10 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry,
*/
static void rt2500usb_beacondone(struct urb *urb)
{
struct data_entry *entry = (struct data_entry *)urb->context;
struct data_ring *ring = entry->ring;
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct queue_entry_priv_usb_bcn *priv_bcn = entry->priv_data;
if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags))
if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
return;
/*
@ -1169,19 +1183,12 @@ static void rt2500usb_beacondone(struct urb *urb)
* 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) {
if (priv_bcn->guardian_urb == urb) {
usb_submit_urb(priv_bcn->urb, GFP_ATOMIC);
} else if (priv_bcn->urb == urb) {
dev_kfree_skb(entry->skb);
entry->skb = NULL;
}
rt2x00_ring_index_done_inc(ring);
}
}
/*
@ -1191,6 +1198,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
{
u16 word;
u8 *mac;
u8 bbp;
rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
@ -1245,9 +1253,17 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word);
}
/*
* Switch lower vgc bound to current BBP R17 value,
* lower the value a bit for better quality.
*/
rt2500usb_bbp_read(rt2x00dev, 17, &bbp);
bbp -= 6;
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
}
@ -1258,6 +1274,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
} else {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
@ -1342,8 +1361,31 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Store led mode, for correct led behaviour.
*/
rt2x00dev->led_mode =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
#ifdef CONFIG_RT2500USB_LEDS
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
switch (value) {
case LED_MODE_ASUS:
case LED_MODE_ALPHA:
case LED_MODE_DEFAULT:
rt2x00dev->led_flags = LED_SUPPORT_RADIO;
break;
case LED_MODE_TXRX_ACTIVITY:
rt2x00dev->led_flags =
LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY;
break;
case LED_MODE_SIGNAL_STRENGTH:
rt2x00dev->led_flags = LED_SUPPORT_RADIO;
break;
}
/*
* Store the current led register value, we need it later
* in set_brightness but that is called in irq context which
* means we can't use rt2500usb_register_read() at that time.
*/
rt2500usb_register_read(rt2x00dev, MAC_CSR20, &rt2x00dev->led_mcu_reg);
#endif /* CONFIG_RT2500USB_LEDS */
/*
* Check if the BBP tuning should be disabled.
@ -1550,8 +1592,8 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw_mode information.
*/
spec->num_modes = 2;
spec->num_rates = 12;
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
spec->tx_power_a = NULL;
spec->tx_power_bg = txpower;
spec->tx_power_default = DEFAULT_TXPOWER;
@ -1572,9 +1614,9 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
spec->channels = rf_vals_bg_2525e;
} else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5222);
spec->channels = rf_vals_5222;
spec->num_modes = 3;
}
}
@ -1599,9 +1641,10 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
rt2500usb_probe_hw_mode(rt2x00dev);
/*
* This device requires the beacon ring
* This device requires the atim queue
*/
__set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
/*
* Set the rssi offset.
@ -1691,48 +1734,42 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct skb_desc *desc;
struct data_ring *ring;
struct data_entry *beacon;
struct data_entry *guardian;
struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
struct rt2x00_intf *intf = vif_to_intf(control->vif);
struct queue_entry_priv_usb_bcn *priv_bcn;
struct skb_frame_desc *skbdesc;
int pipe = usb_sndbulkpipe(usb_dev, 1);
int length;
/*
* Just in case the ieee80211 doesn't set this,
* but we need this queue set for the descriptor
* initialization.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
if (unlikely(!intf->beacon))
return -ENOBUFS;
/*
* 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);
priv_bcn = intf->beacon->priv_data;
/*
* Add the descriptor in front of the skb.
*/
skb_push(skb, ring->desc_size);
memset(skb->data, 0, ring->desc_size);
skb_push(skb, intf->beacon->queue->desc_size);
memset(skb->data, 0, intf->beacon->queue->desc_size);
/*
* Fill in skb descriptor
*/
desc = get_skb_desc(skb);
desc->desc_len = ring->desc_size;
desc->data_len = skb->len - ring->desc_size;
desc->desc = skb->data;
desc->data = skb->data + ring->desc_size;
desc->ring = ring;
desc->entry = beacon;
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
skbdesc->data = skb->data + intf->beacon->queue->desc_size;
skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
skbdesc->desc = skb->data;
skbdesc->desc_len = intf->beacon->queue->desc_size;
skbdesc->entry = intf->beacon;
/*
* mac80211 doesn't provide the control->queue variable
* for beacons. Set our own queue identification so
* it can be used during descriptor initialization.
*/
control->queue = RT2X00_BCN_QUEUE_BEACON;
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
@ -1742,27 +1779,29 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
*/
length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
skb->data, length, rt2500usb_beacondone, beacon);
usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe,
skb->data, length, rt2500usb_beacondone,
intf->beacon);
/*
* 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, pipe,
&guardian->flags, 1, rt2500usb_beacondone, guardian);
priv_bcn->guardian_data = 0;
usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe,
&priv_bcn->guardian_data, 1, rt2500usb_beacondone,
intf->beacon);
/*
* Send out the guardian byte.
*/
usb_submit_urb(guardian->priv, GFP_ATOMIC);
usb_submit_urb(priv_bcn->guardian_urb, GFP_ATOMIC);
/*
* Enable beacon generation.
*/
rt2500usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
rt2500usb_kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
@ -1793,24 +1832,55 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.link_stats = rt2500usb_link_stats,
.reset_tuner = rt2500usb_reset_tuner,
.link_tuner = rt2500usb_link_tuner,
.led_brightness = rt2500usb_led_brightness,
.write_tx_desc = rt2500usb_write_tx_desc,
.write_tx_data = rt2x00usb_write_tx_data,
.get_tx_data_len = rt2500usb_get_tx_data_len,
.kick_tx_queue = rt2500usb_kick_tx_queue,
.fill_rxdone = rt2500usb_fill_rxdone,
.config_mac_addr = rt2500usb_config_mac_addr,
.config_bssid = rt2500usb_config_bssid,
.config_type = rt2500usb_config_type,
.config_intf = rt2500usb_config_intf,
.config_preamble = rt2500usb_config_preamble,
.config = rt2500usb_config,
};
static const struct data_queue_desc rt2500usb_queue_rx = {
.entry_num = RX_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb_rx),
};
static const struct data_queue_desc rt2500usb_queue_tx = {
.entry_num = TX_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb_tx),
};
static const struct data_queue_desc rt2500usb_queue_bcn = {
.entry_num = BEACON_ENTRIES,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb_bcn),
};
static const struct data_queue_desc rt2500usb_queue_atim = {
.entry_num = ATIM_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb_tx),
};
static const struct rt2x00_ops rt2500usb_ops = {
.name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.max_sta_intf = 1,
.max_ap_intf = 1,
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
.rx = &rt2500usb_queue_rx,
.tx = &rt2500usb_queue_tx,
.bcn = &rt2500usb_queue_bcn,
.atim = &rt2500usb_queue_atim,
.lib = &rt2500usb_rt2x00_ops,
.hw = &rt2500usb_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -135,7 +135,7 @@
* Misc MAC_CSR registers.
* MAC_CSR9: Timer control.
* MAC_CSR10: Slot time.
* MAC_CSR11: IFS.
* MAC_CSR11: SIFS.
* MAC_CSR12: EIFS.
* MAC_CSR13: Power mode0.
* MAC_CSR14: Power mode1.
@ -686,6 +686,7 @@
*/
#define EEPROM_BBPTUNE_VGC 0x0034
#define EEPROM_BBPTUNE_VGCUPPER FIELD16(0x00ff)
#define EEPROM_BBPTUNE_VGCLOWER FIELD16(0xff00)
/*
* EEPROM BBP R17 Tuning.
@ -786,8 +787,8 @@
#define RXD_W3_EIV FIELD32(0xffffffff)
/*
* Macro's for converting txpower from EEPROM to dscape value
* and from dscape value to register value.
* Macro's for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_TXPOWER 0
#define MAX_TXPOWER 31

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -27,23 +27,24 @@
#define RT2X00_H
#include <linux/bitops.h>
#include <linux/prefetch.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/leds.h>
#include <linux/mutex.h>
#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "rt2x00debug.h"
#include "rt2x00leds.h"
#include "rt2x00reg.h"
#include "rt2x00ring.h"
#include "rt2x00queue.h"
/*
* Module information.
*/
#define DRV_VERSION "2.0.14"
#define DRV_VERSION "2.1.3"
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
/*
@ -90,26 +91,6 @@
#define EEPROM(__dev, __msg, __args...) \
DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
/*
* Ring sizes.
* Ralink PCI devices demand the Frame size to be a multiple of 128 bytes.
* DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings.
* MGMT_FRAME_SIZE is used for the BEACON ring.
*/
#define DATA_FRAME_SIZE 2432
#define MGMT_FRAME_SIZE 256
/*
* Number of entries in a packet ring.
* PCI devices only need 1 Beacon entry,
* but USB devices require a second because they
* have to send a Guardian byte first.
*/
#define RX_ENTRIES 12
#define TX_ENTRIES 12
#define ATIM_ENTRIES 1
#define BEACON_ENTRIES 2
/*
* Standard timing and size defines.
* These values should follow the ieee80211 specifications.
@ -364,20 +345,22 @@ static inline int rt2x00_update_ant_rssi(struct link *link, int rssi)
/*
* Interface structure
* Configuration details about the current interface.
* Per interface configuration details, this structure
* is allocated as the private data for ieee80211_vif.
*/
struct interface {
struct rt2x00_intf {
/*
* Interface identification. The value is assigned
* to us by the 80211 stack, and is used to request
* new beacons.
* All fields within the rt2x00_intf structure
* must be protected with a spinlock.
*/
struct ieee80211_vif *id;
spinlock_t lock;
/*
* Current working type (IEEE80211_IF_TYPE_*).
* BSS configuration. Copied from the structure
* passed to us through the bss_info_changed()
* callback funtion.
*/
int type;
struct ieee80211_bss_conf conf;
/*
* MAC of the device.
@ -388,42 +371,59 @@ struct interface {
* BBSID of the AP to associate with.
*/
u8 bssid[ETH_ALEN];
/*
* Entry in the beacon queue which belongs to
* this interface. Each interface has its own
* dedicated beacon entry.
*/
struct queue_entry *beacon;
/*
* Actions that needed rescheduling.
*/
unsigned int delayed_flags;
#define DELAYED_UPDATE_BEACON 0x00000001
#define DELAYED_CONFIG_PREAMBLE 0x00000002
};
static inline int is_interface_present(struct interface *intf)
static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
{
return !!intf->id;
return (struct rt2x00_intf *)vif->drv_priv;
}
static inline int is_interface_type(struct interface *intf, int type)
{
return intf->type == type;
}
/*
/**
* struct hw_mode_spec: Hardware specifications structure
*
* Details about the supported modes, rates and channels
* of a particular chipset. This is used by rt2x00lib
* to build the ieee80211_hw_mode array for mac80211.
*
* @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
* @supported_rates: Rate types which are supported (CCK, OFDM).
* @num_channels: Number of supported channels. This is used as array size
* for @tx_power_a, @tx_power_bg and @channels.
* channels: Device/chipset specific channel values (See &struct rf_channel).
* @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
* @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
* @tx_power_default: Default TX power value to use when either
* @tx_power_a or @tx_power_bg is missing.
*/
struct hw_mode_spec {
/*
* Number of modes, rates and channels.
*/
int num_modes;
int num_rates;
int num_channels;
unsigned int supported_bands;
#define SUPPORT_BAND_2GHZ 0x00000001
#define SUPPORT_BAND_5GHZ 0x00000002
unsigned int supported_rates;
#define SUPPORT_RATE_CCK 0x00000001
#define SUPPORT_RATE_OFDM 0x00000002
unsigned int num_channels;
const struct rf_channel *channels;
/*
* txpower values.
*/
const u8 *tx_power_a;
const u8 *tx_power_bg;
u8 tx_power_default;
/*
* Device/chipset specific value.
*/
const struct rf_channel *channels;
};
/*
@ -439,7 +439,7 @@ struct rt2x00lib_conf {
struct antenna_setup ant;
int phymode;
enum ieee80211_band band;
int basic_rates;
int slot_time;
@ -450,6 +450,37 @@ struct rt2x00lib_conf {
short eifs;
};
/*
* Configuration structure wrapper around the
* rt2x00 interface configuration handler.
*/
struct rt2x00intf_conf {
/*
* Interface type
*/
enum ieee80211_if_types type;
/*
* TSF sync value, this is dependant on the operation type.
*/
enum tsf_sync sync;
/*
* The MAC and BSSID addressess are simple array of bytes,
* these arrays are little endian, so when sending the addressess
* to the drivers, copy the it into a endian-signed variable.
*
* Note that all devices (except rt2500usb) have 32 bits
* register word sizes. This means that whatever variable we
* pass _must_ be a multiple of 32 bits. Otherwise the device
* might not accept what we are sending to it.
* This will also make it easier for the driver to write
* the data to the device.
*/
__le32 mac[2];
__le32 bssid[2];
};
/*
* rt2x00lib callback functions.
*/
@ -474,12 +505,12 @@ struct rt2x00lib_ops {
void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
/*
* Ring initialization handlers
* queue initialization handlers
*/
void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
struct data_entry *entry);
struct queue_entry *entry);
void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
struct data_entry *entry);
struct queue_entry *entry);
/*
* Radio control handlers.
@ -491,41 +522,48 @@ struct rt2x00lib_ops {
struct link_qual *qual);
void (*reset_tuner) (struct rt2x00_dev *rt2x00dev);
void (*link_tuner) (struct rt2x00_dev *rt2x00dev);
void (*led_brightness) (struct led_classdev *led_cdev,
enum led_brightness brightness);
/*
* TX control handlers
*/
void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
struct txdata_entry_desc *desc,
struct txentry_desc *txdesc,
struct ieee80211_tx_control *control);
int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct data_queue *queue, struct sk_buff *skb,
struct ieee80211_tx_control *control);
int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb);
void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
unsigned int queue);
const unsigned int queue);
/*
* RX control handlers
*/
void (*fill_rxdone) (struct data_entry *entry,
struct rxdata_entry_desc *desc);
void (*fill_rxdone) (struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc);
/*
* Configuration handlers.
*/
void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac);
void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid);
void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type,
const int tsf_sync);
void (*config_preamble) (struct rt2x00_dev *rt2x00dev,
void (*config_intf) (struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf,
const unsigned int flags);
#define CONFIG_UPDATE_TYPE ( 1 << 1 )
#define CONFIG_UPDATE_MAC ( 1 << 2 )
#define CONFIG_UPDATE_BSSID ( 1 << 3 )
int (*config_preamble) (struct rt2x00_dev *rt2x00dev,
const int short_preamble,
const int ack_timeout,
const int ack_consume_time);
void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags,
struct rt2x00lib_conf *libconf);
void (*config) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags);
#define CONFIG_UPDATE_PHYMODE ( 1 << 1 )
#define CONFIG_UPDATE_CHANNEL ( 1 << 2 )
#define CONFIG_UPDATE_TXPOWER ( 1 << 3 )
@ -540,10 +578,14 @@ struct rt2x00lib_ops {
*/
struct rt2x00_ops {
const char *name;
const unsigned int rxd_size;
const unsigned int txd_size;
const unsigned int max_sta_intf;
const unsigned int max_ap_intf;
const unsigned int eeprom_size;
const unsigned int rf_size;
const struct data_queue_desc *rx;
const struct data_queue_desc *tx;
const struct data_queue_desc *bcn;
const struct data_queue_desc *atim;
const struct rt2x00lib_ops *lib;
const struct ieee80211_ops *hw;
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
@ -569,8 +611,12 @@ enum rt2x00_flags {
/*
* Driver features
*/
DRIVER_SUPPORT_MIXED_INTERFACES,
DRIVER_REQUIRE_FIRMWARE,
DRIVER_REQUIRE_BEACON_RING,
DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T,
DRIVER_REQUIRE_FIRMWARE_CCITT,
DRIVER_REQUIRE_BEACON_GUARD,
DRIVER_REQUIRE_ATIM_QUEUE,
/*
* Driver configuration
@ -582,7 +628,6 @@ enum rt2x00_flags {
CONFIG_EXTERNAL_LNA_BG,
CONFIG_DOUBLE_ANTENNA,
CONFIG_DISABLE_LINK_TUNING,
CONFIG_SHORT_PREAMBLE,
};
/*
@ -597,8 +642,10 @@ struct rt2x00_dev {
* macro's should be used for correct typecasting.
*/
void *dev;
#define rt2x00dev_pci(__dev) ( (struct pci_dev*)(__dev)->dev )
#define rt2x00dev_usb(__dev) ( (struct usb_interface*)(__dev)->dev )
#define rt2x00dev_pci(__dev) ( (struct pci_dev *)(__dev)->dev )
#define rt2x00dev_usb(__dev) ( (struct usb_interface *)(__dev)->dev )
#define rt2x00dev_usb_dev(__dev)\
( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) )
/*
* Callback functions.
@ -609,11 +656,8 @@ struct rt2x00_dev {
* IEEE80211 control structure.
*/
struct ieee80211_hw *hw;
struct ieee80211_hw_mode *hwmodes;
unsigned int curr_hwmode;
#define HWMODE_B 0
#define HWMODE_G 1
#define HWMODE_A 2
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
enum ieee80211_band curr_band;
/*
* rfkill structure for RF state switching support.
@ -632,6 +676,19 @@ struct rt2x00_dev {
struct rt2x00debug_intf *debugfs_intf;
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
* LED structure for changing the LED status
* by mac8011 or the kernel.
*/
#ifdef CONFIG_RT2X00_LIB_LEDS
unsigned int led_flags;
struct rt2x00_trigger trigger_qual;
struct rt2x00_led led_radio;
struct rt2x00_led led_assoc;
struct rt2x00_led led_qual;
u16 led_mcu_reg;
#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Device flags.
* In these flags the current status and some
@ -658,11 +715,13 @@ struct rt2x00_dev {
/*
* Register pointers
* csr_addr: Base register address. (PCI)
* csr_cache: CSR cache for usb_control_msg. (USB)
* csr.base: CSR base register address. (PCI)
* csr.cache: CSR cache for usb_control_msg. (USB)
*/
void __iomem *csr_addr;
void *csr_cache;
union csr {
void __iomem *base;
void *cache;
} csr;
/*
* Mutex to protect register accesses on USB devices.
@ -684,9 +743,14 @@ struct rt2x00_dev {
unsigned int packet_filter;
/*
* Interface configuration.
* Interface details:
* - Open ap interface count.
* - Open sta interface count.
* - Association count.
*/
struct interface interface;
unsigned int intf_ap_count;
unsigned int intf_sta_count;
unsigned int intf_associated;
/*
* Link quality
@ -718,16 +782,6 @@ struct rt2x00_dev {
*/
u16 tx_power;
/*
* LED register (for rt61pci & rt73usb).
*/
u16 led_reg;
/*
* Led mode (LED_MODE_*)
*/
u8 led_mode;
/*
* Rssi <-> Dbm offset
*/
@ -752,19 +806,18 @@ struct rt2x00_dev {
/*
* Scheduled work.
*/
struct work_struct beacon_work;
struct work_struct intf_work;
struct work_struct filter_work;
struct work_struct config_work;
/*
* Data ring arrays for RX, TX and Beacon.
* The Beacon array also contains the Atim ring
* Data queue arrays for RX, TX and Beacon.
* The Beacon array also contains the Atim queue
* if that is supported by the device.
*/
int data_rings;
struct data_ring *rx;
struct data_ring *tx;
struct data_ring *bcn;
int data_queues;
struct data_queue *rx;
struct data_queue *tx;
struct data_queue *bcn;
/*
* Firmware image.
@ -772,37 +825,6 @@ struct rt2x00_dev {
const struct firmware *fw;
};
/*
* For-each loop for the ring array.
* All rings have been allocated as a single array,
* this means we can create a very simply loop macro
* that is capable of looping through all rings.
* ring_end(), txring_end() and ring_loop() are helper macro's which
* should not be used directly. Instead the following should be used:
* ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim)
* txring_for_each() - Loops through TX data rings (TX only)
* txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim)
*/
#define ring_end(__dev) \
&(__dev)->rx[(__dev)->data_rings]
#define txring_end(__dev) \
&(__dev)->tx[(__dev)->hw->queues]
#define ring_loop(__entry, __start, __end) \
for ((__entry) = (__start); \
prefetch(&(__entry)[1]), (__entry) != (__end); \
(__entry) = &(__entry)[1])
#define ring_for_each(__dev, __entry) \
ring_loop(__entry, (__dev)->rx, ring_end(__dev))
#define txring_for_each(__dev, __entry) \
ring_loop(__entry, (__dev)->tx, txring_end(__dev))
#define txringall_for_each(__dev, __entry) \
ring_loop(__entry, (__dev)->tx, ring_end(__dev))
/*
* Generic RF access.
* The RF is being accessed by word index.
@ -895,20 +917,43 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate)
return ((size * 8 * 10) % rate);
}
/*
* Library functions.
/**
* rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue
* @rt2x00dev: Pointer to &struct rt2x00_dev.
* @queue: mac80211/rt2x00 queue index
* (see &enum ieee80211_tx_queue and &enum rt2x00_bcn_queue).
*/
struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
const unsigned int queue);
/**
* rt2x00queue_get_entry - Get queue entry where the given index points to.
* @rt2x00dev: Pointer to &struct rt2x00_dev.
* @index: Index identifier for obtaining the correct index.
*/
struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
enum queue_index index);
/**
* rt2x00queue_index_inc - Index incrementation function
* @queue: Queue (&struct data_queue) to perform the action on.
* @action: Index type (&enum queue_index) to perform the action on.
*
* This function will increase the requested index on the queue,
* it will grab the appropriate locks and handle queue overflow events by
* resetting the index to the start of the queue.
*/
void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
/*
* Interrupt context handlers.
*/
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_txdone(struct data_entry *entry,
const int status, const int retry);
void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
struct rxdata_entry_desc *desc);
void rt2x00lib_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc);
void rt2x00lib_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc);
/*
* TX descriptor initializer

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -29,64 +29,89 @@
#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)
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
enum ieee80211_if_types type,
u8 *mac, u8 *bssid)
{
__le32 reg[2];
struct rt2x00intf_conf conf;
unsigned int flags = 0;
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;
conf.type = type;
switch (type) {
case IEEE80211_IF_TYPE_IBSS:
case IEEE80211_IF_TYPE_AP:
tsf_sync = TSF_SYNC_BEACON;
conf.sync = TSF_SYNC_BEACON;
break;
case IEEE80211_IF_TYPE_STA:
tsf_sync = TSF_SYNC_INFRA;
conf.sync = TSF_SYNC_INFRA;
break;
default:
tsf_sync = TSF_SYNC_NONE;
conf.sync = TSF_SYNC_NONE;
break;
}
rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync);
/*
* Note that when NULL is passed as address 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.
*/
memset(&conf.mac, 0, sizeof(conf.mac));
if (mac)
memcpy(&conf.mac, mac, ETH_ALEN);
memset(&conf.bssid, 0, sizeof(conf.bssid));
if (bssid)
memcpy(&conf.bssid, bssid, ETH_ALEN);
flags |= CONFIG_UPDATE_TYPE;
if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
flags |= CONFIG_UPDATE_MAC;
if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
flags |= CONFIG_UPDATE_BSSID;
rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
}
void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
const unsigned int short_preamble)
{
int retval;
int ack_timeout;
int ack_consume_time;
ack_timeout = PLCP + get_duration(ACK_SIZE, 10);
ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10);
if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME)
ack_timeout += SHORT_DIFS;
else
ack_timeout += DIFS;
if (short_preamble) {
ack_timeout += SHORT_PREAMBLE;
ack_consume_time += SHORT_PREAMBLE;
} else {
ack_timeout += PREAMBLE;
ack_consume_time += PREAMBLE;
}
retval = rt2x00dev->ops->lib->config_preamble(rt2x00dev,
short_preamble,
ack_timeout,
ack_consume_time);
spin_lock(&intf->lock);
if (retval) {
intf->delayed_flags |= DELAYED_CONFIG_PREAMBLE;
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
}
spin_unlock(&intf->lock);
}
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
@ -113,7 +138,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
* The latter is required since we need to recalibrate the
* noise-sensitivity ratio for the new setup.
*/
rt2x00dev->ops->lib->config(rt2x00dev, CONFIG_UPDATE_ANTENNA, &libconf);
rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
rt2x00lib_reset_link_tuner(rt2x00dev);
rt2x00dev->link.ant.active.rx = libconf.ant.rx;
@ -127,7 +152,7 @@ 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_supported_band *band;
struct ieee80211_rate *rate;
struct antenna_setup *default_ant = &rt2x00dev->default_ant;
struct antenna_setup *active_ant = &rt2x00dev->link.ant.active;
@ -147,9 +172,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
* Check which configuration options have been
* updated and should be send to the device.
*/
if (rt2x00dev->rx_status.phymode != conf->phymode)
if (rt2x00dev->rx_status.band != conf->channel->band)
flags |= CONFIG_UPDATE_PHYMODE;
if (rt2x00dev->rx_status.channel != conf->channel)
if (rt2x00dev->rx_status.freq != conf->channel->center_freq)
flags |= CONFIG_UPDATE_CHANNEL;
if (rt2x00dev->tx_power != conf->power_level)
flags |= CONFIG_UPDATE_TXPOWER;
@ -204,33 +229,16 @@ 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;
}
band = &rt2x00dev->bands[conf->channel->band];
rate = &band->bitrates[band->n_bitrates - 1];
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;
libconf.band = conf->channel->band;
libconf.basic_rates = rt2x00_get_rate(rate->hw_value)->ratemask;
}
if (flags & CONFIG_UPDATE_CHANNEL) {
memcpy(&libconf.rf,
&rt2x00dev->spec.channels[conf->channel_val],
&rt2x00dev->spec.channels[conf->channel->hw_value],
sizeof(libconf.rf));
}
@ -266,7 +274,7 @@ config:
/*
* Start configuration.
*/
rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf);
rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags);
/*
* Some configuration changes affect the link quality
@ -276,12 +284,11 @@ config:
rt2x00lib_reset_link_tuner(rt2x00dev);
if (flags & CONFIG_UPDATE_PHYMODE) {
rt2x00dev->curr_hwmode = libconf.phymode;
rt2x00dev->rx_status.phymode = conf->phymode;
rt2x00dev->curr_band = conf->channel->band;
rt2x00dev->rx_status.band = conf->channel->band;
}
rt2x00dev->rx_status.freq = conf->freq;
rt2x00dev->rx_status.channel = conf->channel;
rt2x00dev->rx_status.freq = conf->channel->center_freq;
rt2x00dev->tx_power = conf->power_level;
if (flags & CONFIG_UPDATE_ANTENNA) {

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -33,7 +33,7 @@
#include "rt2x00lib.h"
#include "rt2x00dump.h"
#define PRINT_LINE_LEN_MAX 32
#define MAX_LINE_LENGTH 64
struct rt2x00debug_intf {
/*
@ -60,8 +60,9 @@ struct rt2x00debug_intf {
* - eeprom offset/value files
* - bbp offset/value files
* - rf offset/value files
* - frame dump folder
* - queue folder
* - frame dump file
* - queue stats file
*/
struct dentry *driver_folder;
struct dentry *driver_entry;
@ -76,8 +77,9 @@ struct rt2x00debug_intf {
struct dentry *bbp_val_entry;
struct dentry *rf_off_entry;
struct dentry *rf_val_entry;
struct dentry *frame_folder;
struct dentry *frame_dump_entry;
struct dentry *queue_folder;
struct dentry *queue_frame_dump_entry;
struct dentry *queue_stats_entry;
/*
* The frame dump file only allows a single reader,
@ -116,7 +118,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb)
{
struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
struct skb_desc *desc = get_skb_desc(skb);
struct skb_frame_desc *desc = get_skb_frame_desc(skb);
struct sk_buff *skbcopy;
struct rt2x00dump_hdr *dump_hdr;
struct timeval timestamp;
@ -147,7 +149,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
dump_hdr->type = cpu_to_le16(desc->frame_type);
dump_hdr->ring_index = desc->ring->queue_idx;
dump_hdr->queue_index = desc->entry->queue->qid;
dump_hdr->entry_index = desc->entry->entry_idx;
dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
@ -186,7 +188,7 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
return 0;
}
static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
{
struct rt2x00debug_intf *intf = inode->i_private;
int retval;
@ -203,7 +205,7 @@ static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
return 0;
}
static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
{
struct rt2x00debug_intf *intf = inode->i_private;
@ -214,7 +216,7 @@ static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
return rt2x00debug_file_release(inode, file);
}
static ssize_t rt2x00debug_read_ring_dump(struct file *file,
static ssize_t rt2x00debug_read_queue_dump(struct file *file,
char __user *buf,
size_t length,
loff_t *offset)
@ -248,7 +250,7 @@ exit:
return status;
}
static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
poll_table *wait)
{
struct rt2x00debug_intf *intf = file->private_data;
@ -261,12 +263,67 @@ static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
return 0;
}
static const struct file_operations rt2x00debug_fop_ring_dump = {
static const struct file_operations rt2x00debug_fop_queue_dump = {
.owner = THIS_MODULE,
.read = rt2x00debug_read_ring_dump,
.poll = rt2x00debug_poll_ring_dump,
.open = rt2x00debug_open_ring_dump,
.release = rt2x00debug_release_ring_dump,
.read = rt2x00debug_read_queue_dump,
.poll = rt2x00debug_poll_queue_dump,
.open = rt2x00debug_open_queue_dump,
.release = rt2x00debug_release_queue_dump,
};
static ssize_t rt2x00debug_read_queue_stats(struct file *file,
char __user *buf,
size_t length,
loff_t *offset)
{
struct rt2x00debug_intf *intf = file->private_data;
struct data_queue *queue;
unsigned int lines = 1 + intf->rt2x00dev->data_queues;
size_t size;
char *data;
char *temp;
if (*offset)
return 0;
data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL);
if (!data)
return -ENOMEM;
temp = data +
sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n");
queue_for_each(intf->rt2x00dev, queue) {
spin_lock(&queue->lock);
temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
queue->count, queue->limit, queue->length,
queue->index[Q_INDEX],
queue->index[Q_INDEX_DONE],
queue->index[Q_INDEX_CRYPTO]);
spin_unlock(&queue->lock);
}
size = strlen(data);
size = min(size, length);
if (copy_to_user(buf, data, size)) {
kfree(data);
return -EFAULT;
}
kfree(data);
*offset += size;
return size;
}
static const struct file_operations rt2x00debug_fop_queue_stats = {
.owner = THIS_MODULE,
.read = rt2x00debug_read_queue_stats,
.open = rt2x00debug_file_open,
.release = rt2x00debug_file_release,
};
#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
@ -386,7 +443,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
{
char *data;
data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
if (!data)
return NULL;
@ -409,7 +466,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
const struct rt2x00debug *debug = intf->debug;
char *data;
data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL);
if (!data)
return NULL;
@ -496,20 +553,24 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
intf->frame_folder =
debugfs_create_dir("frame", intf->driver_folder);
if (IS_ERR(intf->frame_folder))
intf->queue_folder =
debugfs_create_dir("queue", intf->driver_folder);
if (IS_ERR(intf->queue_folder))
goto exit;
intf->frame_dump_entry =
debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
intf, &rt2x00debug_fop_ring_dump);
if (IS_ERR(intf->frame_dump_entry))
intf->queue_frame_dump_entry =
debugfs_create_file("dump", S_IRUGO, intf->queue_folder,
intf, &rt2x00debug_fop_queue_dump);
if (IS_ERR(intf->queue_frame_dump_entry))
goto exit;
skb_queue_head_init(&intf->frame_dump_skbqueue);
init_waitqueue_head(&intf->frame_dump_waitqueue);
intf->queue_stats_entry =
debugfs_create_file("queue", S_IRUGO, intf->queue_folder,
intf, &rt2x00debug_fop_queue_stats);
return;
exit:
@ -528,8 +589,9 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
skb_queue_purge(&intf->frame_dump_skbqueue);
debugfs_remove(intf->frame_dump_entry);
debugfs_remove(intf->frame_folder);
debugfs_remove(intf->queue_stats_entry);
debugfs_remove(intf->queue_frame_dump_entry);
debugfs_remove(intf->queue_folder);
debugfs_remove(intf->rf_val_entry);
debugfs_remove(intf->rf_off_entry);
debugfs_remove(intf->bbp_val_entry);

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -93,8 +93,8 @@ enum rt2x00_dump_type {
* @chip_rf: RF chipset
* @chip_rev: Chipset revision
* @type: The frame type (&rt2x00_dump_type)
* @ring_index: The index number of the data ring.
* @entry_index: The index number of the entry inside the data ring.
* @queue_index: The index number of the data queue.
* @entry_index: The index number of the entry inside the data queue.
* @timestamp_sec: Timestamp - seconds
* @timestamp_usec: Timestamp - microseconds
*/
@ -111,7 +111,7 @@ struct rt2x00dump_hdr {
__le32 chip_rev;
__le16 type;
__u8 ring_index;
__u8 queue_index;
__u8 entry_index;
__le32 timestamp_sec;

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -23,6 +23,7 @@
Abstract: rt2x00 firmware loading routines.
*/
#include <linux/crc-ccitt.h>
#include <linux/crc-itu-t.h>
#include <linux/kernel.h>
#include <linux/module.h>
@ -37,7 +38,6 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
char *fw_name;
int retval;
u16 crc;
u16 tmp;
/*
* Read correct firmware from harddisk.
@ -64,17 +64,37 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
}
/*
* Validate the firmware using 16 bit CRC.
* The last 2 bytes of the firmware are the CRC
* so substract those 2 bytes from the CRC checksum,
* and set those 2 bytes to 0 when calculating CRC.
* Perform crc validation on the firmware.
* The last 2 bytes in the firmware array are the crc checksum itself,
* this means that we should never pass those 2 bytes to the crc
* algorithm.
*/
if (test_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags)) {
/*
* Use the crc itu-t algorithm.
* Use 0 for the last 2 bytes to complete the checksum.
*/
tmp = 0;
crc = crc_itu_t(0, fw->data, fw->size - 2);
crc = crc_itu_t(crc, (u8 *)&tmp, 2);
crc = crc_itu_t_byte(crc, 0);
crc = crc_itu_t_byte(crc, 0);
} else if (test_bit(DRIVER_REQUIRE_FIRMWARE_CCITT, &rt2x00dev->flags)) {
/*
* Use the crc ccitt algorithm.
* This will return the same value as the legacy driver which
* used bit ordering reversion on the both the firmware bytes
* before input input as well as on the final output.
* Obviously using crc ccitt directly is much more efficient.
*/
crc = crc_ccitt(~0, fw->data, fw->size - 2);
} else {
ERROR(rt2x00dev, "No checksum algorithm selected "
"for firmware validation.\n");
retval = -ENOENT;
goto exit;
}
if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
ERROR(rt2x00dev, "Firmware CRC error.\n");
ERROR(rt2x00dev, "Firmware checksum error.\n");
retval = -ENOENT;
goto exit;
}
@ -96,6 +116,9 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
{
int retval;
if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
return 0;
if (!rt2x00dev->fw) {
retval = rt2x00lib_request_firmware(rt2x00dev);
if (retval)

Просмотреть файл

@ -0,0 +1,217 @@
/*
Copyright (C) 2004 - 2008 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 led specific routines.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
{
if (!rt2x00dev->trigger_qual.registered)
return;
/*
* Led handling requires a positive value for the rssi,
* to do that correctly we need to add the correction.
*/
rssi += rt2x00dev->rssi_offset;
/*
* Get the rssi level, this is used to convert the rssi
* to a LED value inside the range LED_OFF - LED_FULL.
*/
if (rssi <= 30)
rssi = 0;
else if (rssi <= 39)
rssi = 1;
else if (rssi <= 49)
rssi = 2;
else if (rssi <= 53)
rssi = 3;
else if (rssi <= 63)
rssi = 4;
else
rssi = 5;
/*
* Note that we must _not_ send LED_OFF since the driver
* is going to calculate the value and might use it in a
* division.
*/
led_trigger_event(&rt2x00dev->trigger_qual.trigger,
((LED_FULL / 6) * rssi) + 1);
}
static int rt2x00leds_register_trigger(struct rt2x00_dev *rt2x00dev,
struct rt2x00_trigger *trigger,
const char *name)
{
int retval;
trigger->trigger.name = name;
retval = led_trigger_register(&trigger->trigger);
if (retval) {
ERROR(rt2x00dev, "Failed to register led trigger.\n");
return retval;
}
trigger->registered = 1;
return 0;
}
static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
struct rt2x00_led *led,
enum led_type type,
const char *name, char *trigger)
{
struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
int retval;
led->led_dev.name = name;
led->led_dev.brightness_set = rt2x00dev->ops->lib->led_brightness;
led->led_dev.default_trigger = trigger;
retval = led_classdev_register(device, &led->led_dev);
if (retval) {
ERROR(rt2x00dev, "Failed to register led handler.\n");
return retval;
}
led->rt2x00dev = rt2x00dev;
led->type = type;
led->registered = 1;
return 0;
}
int rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
{
char *trigger;
char dev_name[16];
char name[32];
int retval;
if (!rt2x00dev->ops->lib->led_brightness)
return 0;
snprintf(dev_name, sizeof(dev_name), "%s-%s",
rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy));
if (rt2x00dev->led_flags & LED_SUPPORT_RADIO) {
trigger = ieee80211_get_radio_led_name(rt2x00dev->hw);
snprintf(name, sizeof(name), "%s:radio", dev_name);
retval = rt2x00leds_register_led(rt2x00dev,
&rt2x00dev->led_radio,
LED_TYPE_RADIO,
name, trigger);
if (retval)
goto exit_fail;
}
if (rt2x00dev->led_flags & LED_SUPPORT_ASSOC) {
trigger = ieee80211_get_assoc_led_name(rt2x00dev->hw);
snprintf(name, sizeof(name), "%s:assoc", dev_name);
retval = rt2x00leds_register_led(rt2x00dev,
&rt2x00dev->led_assoc,
LED_TYPE_ASSOC,
name, trigger);
if (retval)
goto exit_fail;
}
if (rt2x00dev->led_flags & LED_SUPPORT_QUALITY) {
snprintf(name, sizeof(name), "%s:quality", dev_name);
retval = rt2x00leds_register_trigger(rt2x00dev,
&rt2x00dev->trigger_qual,
name);
retval = rt2x00leds_register_led(rt2x00dev,
&rt2x00dev->led_qual,
LED_TYPE_QUALITY,
name, name);
if (retval)
goto exit_fail;
}
return 0;
exit_fail:
rt2x00leds_unregister(rt2x00dev);
return retval;
}
static void rt2x00leds_unregister_trigger(struct rt2x00_trigger *trigger)
{
if (!trigger->registered)
return;
led_trigger_unregister(&trigger->trigger);
trigger->registered = 0;
}
static void rt2x00leds_unregister_led(struct rt2x00_led *led)
{
if (!led->registered)
return;
led_classdev_unregister(&led->led_dev);
led->led_dev.brightness_set(&led->led_dev, LED_OFF);
led->registered = 0;
}
void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
{
rt2x00leds_unregister_trigger(&rt2x00dev->trigger_qual);
rt2x00leds_unregister_led(&rt2x00dev->led_qual);
rt2x00leds_unregister_led(&rt2x00dev->led_assoc);
rt2x00leds_unregister_led(&rt2x00dev->led_radio);
}
void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00dev->led_qual.registered)
led_classdev_suspend(&rt2x00dev->led_qual.led_dev);
if (rt2x00dev->led_assoc.registered)
led_classdev_suspend(&rt2x00dev->led_assoc.led_dev);
if (rt2x00dev->led_radio.registered)
led_classdev_suspend(&rt2x00dev->led_radio.led_dev);
}
void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00dev->led_radio.registered)
led_classdev_resume(&rt2x00dev->led_radio.led_dev);
if (rt2x00dev->led_assoc.registered)
led_classdev_resume(&rt2x00dev->led_assoc.led_dev);
if (rt2x00dev->led_qual.registered)
led_classdev_resume(&rt2x00dev->led_qual.led_dev);
}

Просмотреть файл

@ -0,0 +1,63 @@
/*
Copyright (C) 2004 - 2008 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 led datastructures and routines
*/
#ifndef RT2X00LEDS_H
#define RT2X00LEDS_H
/*
* Flags used by driver to indicate which
* which led types are supported.
*/
#define LED_SUPPORT_RADIO 0x000001
#define LED_SUPPORT_ASSOC 0x000002
#define LED_SUPPORT_ACTIVITY 0x000004
#define LED_SUPPORT_QUALITY 0x000008
enum led_type {
LED_TYPE_RADIO,
LED_TYPE_ASSOC,
LED_TYPE_QUALITY,
};
#ifdef CONFIG_RT2X00_LIB_LEDS
struct rt2x00_led {
struct rt2x00_dev *rt2x00dev;
struct led_classdev led_dev;
enum led_type type;
unsigned int registered;
};
struct rt2x00_trigger {
struct led_trigger trigger;
enum led_type type;
unsigned int registered;
};
#endif /* CONFIG_RT2X00_LIB_LEDS */
#endif /* RT2X00LEDS_H */

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -33,6 +33,52 @@
#define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) )
#define RFKILL_POLL_INTERVAL ( 1000 )
/*
* rt2x00_rate: Per rate device information
*/
struct rt2x00_rate {
unsigned short flags;
#define DEV_RATE_CCK 0x0001
#define DEV_RATE_OFDM 0x0002
#define DEV_RATE_SHORT_PREAMBLE 0x0004
unsigned short bitrate; /* In 100kbit/s */
unsigned short ratemask;
#define DEV_RATEMASK_1MB ( (1 << 1) - 1 )
#define DEV_RATEMASK_2MB ( (1 << 2) - 1 )
#define DEV_RATEMASK_5_5MB ( (1 << 3) - 1 )
#define DEV_RATEMASK_11MB ( (1 << 4) - 1 )
#define DEV_RATEMASK_6MB ( (1 << 5) - 1 )
#define DEV_RATEMASK_9MB ( (1 << 6) - 1 )
#define DEV_RATEMASK_12MB ( (1 << 7) - 1 )
#define DEV_RATEMASK_18MB ( (1 << 8) - 1 )
#define DEV_RATEMASK_24MB ( (1 << 9) - 1 )
#define DEV_RATEMASK_36MB ( (1 << 10) - 1 )
#define DEV_RATEMASK_48MB ( (1 << 11) - 1 )
#define DEV_RATEMASK_54MB ( (1 << 12) - 1 )
unsigned short plcp;
};
extern const struct rt2x00_rate rt2x00_supported_rates[12];
static inline u16 rt2x00_create_rate_hw_value(const u16 index,
const u16 short_preamble)
{
return (short_preamble << 8) | (index & 0xff);
}
static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
{
return &rt2x00_supported_rates[hw_value & 0xff];
}
static inline int rt2x00_get_rate_preamble(const u16 hw_value)
{
return (hw_value & 0xff00);
}
/*
* Radio control handlers.
*/
@ -50,14 +96,28 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
/*
* Configuration handlers.
*/
void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
enum ieee80211_if_types type,
u8 *mac, u8 *bssid);
void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
const unsigned int short_preamble);
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
enum antenna rx, enum antenna tx);
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config);
/*
* Queue handlers.
*/
void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev);
void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev);
int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
/*
* Firmware handlers.
*/
@ -124,4 +184,37 @@ static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
}
#endif /* CONFIG_RT2X00_LIB_RFKILL */
/*
* LED handlers
*/
#ifdef CONFIG_RT2X00_LIB_LEDS
void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
int rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev);
void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev);
void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev);
#else
static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
int rssi)
{
}
static inline int rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
{
return 0;
}
static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
{
}
static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
{
}
static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
{
}
#endif /* CONFIG_RT2X00_LIB_LEDS */
#endif /* RT2X00LIB_H */

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -30,10 +30,11 @@
#include "rt2x00lib.h"
static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring,
struct data_queue *queue,
struct sk_buff *frag_skb,
struct ieee80211_tx_control *control)
{
struct skb_frame_desc *skbdesc;
struct sk_buff *skb;
int size;
@ -52,15 +53,22 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
skb_put(skb, size);
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id,
ieee80211_ctstoself_get(rt2x00dev->hw, control->vif,
frag_skb->data, frag_skb->len, control,
(struct ieee80211_cts *)(skb->data));
else
ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id,
ieee80211_rts_get(rt2x00dev->hw, control->vif,
frag_skb->data, frag_skb->len, control,
(struct ieee80211_rts *)(skb->data));
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
/*
* Initialize skb descriptor
*/
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
return NETDEV_TX_BUSY;
}
@ -73,7 +81,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
struct data_ring *ring;
struct data_queue *queue;
struct skb_frame_desc *skbdesc;
u16 frame_control;
/*
@ -88,10 +97,10 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
}
/*
* Determine which ring to put packet on.
* Determine which queue to put packet on.
*/
ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
if (unlikely(!ring)) {
queue = rt2x00queue_get_queue(rt2x00dev, control->queue);
if (unlikely(!queue)) {
ERROR(rt2x00dev,
"Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
@ -110,23 +119,29 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
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) {
if (rt2x00queue_available(queue) <= 1) {
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
}
if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) {
if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb, control)) {
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
}
}
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
/*
* Initialize skb descriptor
*/
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
}
if (rt2x00_ring_full(ring))
if (rt2x00queue_full(queue))
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
if (rt2x00dev->ops->lib->kick_tx_queue)
@ -162,27 +177,67 @@ 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;
}
struct rt2x00_intf *intf = vif_to_intf(conf->vif);
struct data_queue *queue =
rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
struct queue_entry *entry = NULL;
unsigned int i;
/*
* Don't allow interfaces to be added while
* either the device has disappeared or when
* another interface is already present.
* Don't allow interfaces to be added
* the device has disappeared.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
is_interface_present(intf))
!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
return -ENODEV;
/*
* When we don't support mixed interfaces (a combination
* of sta and ap virtual interfaces) then we can only
* add this interface when the rival interface count is 0.
*/
if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) &&
((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
(conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count)))
return -ENOBUFS;
intf->id = conf->vif;
intf->type = conf->type;
/*
* Check if we exceeded the maximum amount of supported interfaces.
*/
if ((conf->type == IEEE80211_IF_TYPE_AP &&
rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) ||
(conf->type != IEEE80211_IF_TYPE_AP &&
rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf))
return -ENOBUFS;
/*
* Loop through all beacon queues to find a free
* entry. Since there are as much beacon entries
* as the maximum interfaces, this search shouldn't
* fail.
*/
for (i = 0; i < queue->limit; i++) {
entry = &queue->entries[i];
if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
break;
}
if (unlikely(i == queue->limit))
return -ENOBUFS;
/*
* We are now absolutely sure the interface can be created,
* increase interface count and start initialization.
*/
if (conf->type == IEEE80211_IF_TYPE_AP)
rt2x00dev->intf_ap_count++;
else
rt2x00dev->intf_sta_count++;
spin_lock_init(&intf->lock);
intf->beacon = entry;
if (conf->type == IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
@ -192,8 +247,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
* has been initialized. Otherwise the device can reset
* the MAC registers.
*/
rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
rt2x00lib_config_type(rt2x00dev, conf->type);
rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
return 0;
}
@ -203,7 +257,7 @@ 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;
struct rt2x00_intf *intf = vif_to_intf(conf->vif);
/*
* Don't allow interfaces to be remove while
@ -211,21 +265,27 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
* no interface is present.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
!is_interface_present(intf))
(conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) ||
(conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count))
return;
intf->id = 0;
intf->type = IEEE80211_IF_TYPE_INVALID;
memset(&intf->bssid, 0x00, ETH_ALEN);
memset(&intf->mac, 0x00, ETH_ALEN);
if (conf->type == IEEE80211_IF_TYPE_AP)
rt2x00dev->intf_ap_count--;
else
rt2x00dev->intf_sta_count--;
/*
* Release beacon entry so it is available for
* new interfaces again.
*/
__clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
/*
* Make sure the bssid and mac address registers
* are cleared to prevent false ACKing of frames.
*/
rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
rt2x00lib_config_type(rt2x00dev, intf->type);
rt2x00lib_config_intf(rt2x00dev, intf,
IEEE80211_IF_TYPE_INVALID, NULL, NULL);
}
EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
@ -270,7 +330,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_if_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
struct rt2x00_intf *intf = vif_to_intf(vif);
int status;
/*
@ -280,12 +340,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
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 != intf->type)
return -EINVAL;
spin_lock(&intf->lock);
/*
* If the interface does not work in master mode,
@ -294,7 +349,16 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
*/
if (conf->type != IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
spin_unlock(&intf->lock);
/*
* Call rt2x00_config_intf() outside of the spinlock context since
* the call will sleep for USB drivers. By using the ieee80211_if_conf
* values as arguments we make keep access to rt2x00_intf thread safe
* even without the lock.
*/
rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid);
/*
* We only need to initialize the beacon when master mode is enabled.
@ -334,9 +398,11 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
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));
for (i = 0; i < hw->queues; i++) {
stats->data[i].len = rt2x00dev->tx[i].length;
stats->data[i].limit = rt2x00dev->tx[i].limit;
stats->data[i].count = rt2x00dev->tx[i].count;
}
return 0;
}
@ -348,71 +414,70 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
u32 changes)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
int short_preamble;
int ack_timeout;
int ack_consume_time;
int difs;
int preamble;
struct rt2x00_intf *intf = vif_to_intf(vif);
/*
* We only support changing preamble mode.
* When the association status has changed we must reset the link
* tuner counter. This is because some drivers determine if they
* should perform link tuning based on the number of seconds
* while associated or not associated.
*/
if (!(changes & BSS_CHANGED_ERP_PREAMBLE))
return;
if (changes & BSS_CHANGED_ASSOC) {
rt2x00dev->link.count = 0;
short_preamble = bss_conf->use_short_preamble;
preamble = bss_conf->use_short_preamble ?
SHORT_PREAMBLE : 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);
if (bss_conf->assoc)
rt2x00dev->intf_associated++;
else
__clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
rt2x00dev->intf_associated--;
}
rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
ack_timeout, ack_consume_time);
/*
* When the preamble mode has changed, we should perform additional
* configuration steps. For all other changes we are already done.
*/
if (changes & BSS_CHANGED_ERP_PREAMBLE) {
rt2x00lib_config_preamble(rt2x00dev, intf,
bss_conf->use_short_preamble);
spin_lock(&intf->lock);
memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
spin_unlock(&intf->lock);
}
}
EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue_idx,
const struct ieee80211_tx_queue_params *params)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct data_ring *ring;
struct data_queue *queue;
ring = rt2x00lib_get_ring(rt2x00dev, queue);
if (unlikely(!ring))
queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
if (unlikely(!queue))
return -EINVAL;
/*
* The passed variables are stored as real value ((2^n)-1).
* Ralink registers require to know the bit number 'n'.
*/
if (params->cw_min)
ring->tx_params.cw_min = fls(params->cw_min);
if (params->cw_min > 0)
queue->cw_min = fls(params->cw_min);
else
ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
queue->cw_min = 5; /* cw_min: 2^5 = 32. */
if (params->cw_max)
ring->tx_params.cw_max = fls(params->cw_max);
if (params->cw_max > 0)
queue->cw_max = fls(params->cw_max);
else
ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
if (params->aifs)
ring->tx_params.aifs = params->aifs;
if (params->aifs >= 0)
queue->aifs = params->aifs;
else
ring->tx_params.aifs = 2;
queue->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 queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
queue_idx, queue->cw_min, queue->cw_max, queue->aifs);
return 0;
}

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -31,65 +31,22 @@
#include "rt2x00.h"
#include "rt2x00pci.h"
/*
* Beacon handlers.
*/
int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct skb_desc *desc;
struct data_ring *ring;
struct data_entry *entry;
/*
* Just in case mac80211 doesn't set this correctly,
* but we need this queue set for the descriptor
* initialization.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
entry = rt2x00_get_data_entry(ring);
/*
* Fill in skb descriptor
*/
desc = get_skb_desc(skb);
desc->desc_len = ring->desc_size;
desc->data_len = skb->len;
desc->desc = entry->priv;
desc->data = skb->data;
desc->ring = ring;
desc->entry = entry;
memcpy(entry->data_addr, skb->data, skb->len);
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Enable beacon generation.
*/
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update);
/*
* TX data handlers.
*/
int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct data_queue *queue, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct data_entry *entry = rt2x00_get_data_entry(ring);
__le32 *txd = entry->priv;
struct skb_desc *desc;
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
struct skb_frame_desc *skbdesc;
u32 word;
if (rt2x00_ring_full(ring))
if (rt2x00queue_full(queue))
return -EINVAL;
rt2x00_desc_read(txd, 0, &word);
rt2x00_desc_read(priv_tx->desc, 0, &word);
if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) ||
rt2x00_get_field32(word, TXD_ENTRY_VALID)) {
@ -103,18 +60,17 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
/*
* Fill in skb descriptor
*/
desc = get_skb_desc(skb);
desc->desc_len = ring->desc_size;
desc->data_len = skb->len;
desc->desc = entry->priv;
desc->data = skb->data;
desc->ring = ring;
desc->entry = entry;
skbdesc = get_skb_frame_desc(skb);
skbdesc->data = skb->data;
skbdesc->data_len = skb->len;
skbdesc->desc = priv_tx->desc;
skbdesc->desc_len = queue->desc_size;
skbdesc->entry = entry;
memcpy(entry->data_addr, skb->data, skb->len);
memcpy(priv_tx->data, skb->data, skb->len);
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
rt2x00_ring_index_inc(ring);
rt2x00queue_index_inc(queue, Q_INDEX);
return 0;
}
@ -125,29 +81,28 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
*/
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring = rt2x00dev->rx;
struct data_entry *entry;
struct sk_buff *skb;
struct data_queue *queue = rt2x00dev->rx;
struct queue_entry *entry;
struct queue_entry_priv_pci_rx *priv_rx;
struct ieee80211_hdr *hdr;
struct skb_desc *skbdesc;
struct rxdata_entry_desc desc;
struct skb_frame_desc *skbdesc;
struct rxdone_entry_desc rxdesc;
int header_size;
__le32 *rxd;
int align;
u32 word;
while (1) {
entry = rt2x00_get_data_entry(ring);
rxd = entry->priv;
rt2x00_desc_read(rxd, 0, &word);
entry = rt2x00queue_get_entry(queue, Q_INDEX);
priv_rx = entry->priv_data;
rt2x00_desc_read(priv_rx->desc, 0, &word);
if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
break;
memset(&desc, 0, sizeof(desc));
rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
memset(&rxdesc, 0, sizeof(rxdesc));
rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
hdr = (struct ieee80211_hdr *)entry->data_addr;
hdr = (struct ieee80211_hdr *)priv_rx->data;
header_size =
ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
@ -161,66 +116,68 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
* Allocate the sk_buffer, initialize it and copy
* all data into it.
*/
skb = dev_alloc_skb(desc.size + align);
if (!skb)
entry->skb = dev_alloc_skb(rxdesc.size + align);
if (!entry->skb)
return;
skb_reserve(skb, align);
memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
skb_reserve(entry->skb, align);
memcpy(skb_put(entry->skb, rxdesc.size),
priv_rx->data, rxdesc.size);
/*
* Fill in skb descriptor
*/
skbdesc = get_skb_desc(skb);
skbdesc->desc_len = entry->ring->desc_size;
skbdesc->data_len = skb->len;
skbdesc->desc = entry->priv;
skbdesc->data = skb->data;
skbdesc->ring = ring;
skbdesc = get_skb_frame_desc(entry->skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->data = entry->skb->data;
skbdesc->data_len = entry->skb->len;
skbdesc->desc = priv_rx->desc;
skbdesc->desc_len = queue->desc_size;
skbdesc->entry = entry;
/*
* Send the frame to rt2x00lib for further processing.
*/
rt2x00lib_rxdone(entry, skb, &desc);
rt2x00lib_rxdone(entry, &rxdesc);
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) {
rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1);
rt2x00_desc_write(rxd, 0, word);
rt2x00_desc_write(priv_rx->desc, 0, word);
}
rt2x00_ring_index_inc(ring);
rt2x00queue_index_inc(queue, Q_INDEX);
}
}
EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
const int tx_status, const int retry)
void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
struct txdone_entry_desc *txdesc)
{
struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
u32 word;
rt2x00lib_txdone(entry, tx_status, retry);
txdesc->control = &priv_tx->control;
rt2x00lib_txdone(entry, txdesc);
/*
* Make this entry available for reuse.
*/
entry->flags = 0;
rt2x00_desc_read(entry->priv, 0, &word);
rt2x00_desc_read(priv_tx->desc, 0, &word);
rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0);
rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0);
rt2x00_desc_write(entry->priv, 0, word);
rt2x00_desc_write(priv_tx->desc, 0, word);
rt2x00_ring_index_done_inc(entry->ring);
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
/*
* If the data ring was full before the txdone handler
* If the data queue was full before the txdone handler
* we must make sure the packet queue in the mac80211 stack
* is reenabled when the txdone handler has finished.
*/
if (!rt2x00_ring_full(entry->ring))
ieee80211_wake_queue(rt2x00dev->hw,
entry->tx_status.control.queue);
if (!rt2x00queue_full(entry->queue))
ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue);
}
EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
@ -228,73 +185,122 @@ EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
/*
* Device initialization handlers.
*/
#define priv_offset(__ring, __i) \
#define desc_size(__queue) \
({ \
ring->data_addr + (i * ring->desc_size); \
((__queue)->limit * (__queue)->desc_size);\
})
#define data_addr_offset(__ring, __i) \
#define data_size(__queue) \
({ \
(__ring)->data_addr + \
((__ring)->stats.limit * (__ring)->desc_size) + \
((__i) * (__ring)->data_size); \
((__queue)->limit * (__queue)->data_size);\
})
#define data_dma_offset(__ring, __i) \
#define dma_size(__queue) \
({ \
(__ring)->data_dma + \
((__ring)->stats.limit * (__ring)->desc_size) + \
((__i) * (__ring)->data_size); \
data_size(__queue) + desc_size(__queue);\
})
static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
#define desc_offset(__queue, __base, __i) \
({ \
(__base) + data_size(__queue) + \
((__i) * (__queue)->desc_size); \
})
#define data_offset(__queue, __base, __i) \
({ \
(__base) + \
((__i) * (__queue)->data_size); \
})
static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
struct data_queue *queue)
{
struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
struct queue_entry_priv_pci_rx *priv_rx;
struct queue_entry_priv_pci_tx *priv_tx;
void *addr;
dma_addr_t dma;
void *desc_addr;
dma_addr_t desc_dma;
void *data_addr;
dma_addr_t data_dma;
unsigned int i;
/*
* Allocate DMA memory for descriptor and buffer.
*/
ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev),
rt2x00_get_ring_size(ring),
&ring->data_dma);
if (!ring->data_addr)
addr = pci_alloc_consistent(pci_dev, dma_size(queue), &dma);
if (!addr)
return -ENOMEM;
memset(addr, 0, dma_size(queue));
/*
* Initialize all ring entries to contain valid
* addresses.
* Initialize all queue entries to contain valid addresses.
*/
for (i = 0; i < ring->stats.limit; i++) {
ring->entry[i].priv = priv_offset(ring, i);
ring->entry[i].data_addr = data_addr_offset(ring, i);
ring->entry[i].data_dma = data_dma_offset(ring, i);
for (i = 0; i < queue->limit; i++) {
desc_addr = desc_offset(queue, addr, i);
desc_dma = desc_offset(queue, dma, i);
data_addr = data_offset(queue, addr, i);
data_dma = data_offset(queue, dma, i);
if (queue->qid == QID_RX) {
priv_rx = queue->entries[i].priv_data;
priv_rx->desc = desc_addr;
priv_rx->desc_dma = desc_dma;
priv_rx->data = data_addr;
priv_rx->data_dma = data_dma;
} else {
priv_tx = queue->entries[i].priv_data;
priv_tx->desc = desc_addr;
priv_tx->desc_dma = desc_dma;
priv_tx->data = data_addr;
priv_tx->data_dma = data_dma;
}
}
return 0;
}
static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
struct data_queue *queue)
{
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;
struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
struct queue_entry_priv_pci_rx *priv_rx;
struct queue_entry_priv_pci_tx *priv_tx;
void *data_addr;
dma_addr_t data_dma;
if (queue->qid == QID_RX) {
priv_rx = queue->entries[0].priv_data;
data_addr = priv_rx->data;
data_dma = priv_rx->data_dma;
priv_rx->data = NULL;
} else {
priv_tx = queue->entries[0].priv_data;
data_addr = priv_tx->data;
data_dma = priv_tx->data_dma;
priv_tx->data = NULL;
}
if (data_addr)
pci_free_consistent(pci_dev, dma_size(queue),
data_addr, data_dma);
}
int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
{
struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
struct data_ring *ring;
struct data_queue *queue;
int status;
/*
* Allocate DMA
*/
ring_for_each(rt2x00dev, ring) {
status = rt2x00pci_alloc_dma(rt2x00dev, ring);
queue_for_each(rt2x00dev, queue) {
status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
if (status)
goto exit;
}
@ -321,7 +327,7 @@ EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
struct data_queue *queue;
/*
* Free irq line.
@ -331,8 +337,8 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
/*
* Free DMA
*/
ring_for_each(rt2x00dev, ring)
rt2x00pci_free_dma(rt2x00dev, ring);
queue_for_each(rt2x00dev, queue)
rt2x00pci_free_queue_dma(rt2x00dev, queue);
}
EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
@ -347,9 +353,9 @@ static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
kfree(rt2x00dev->eeprom);
rt2x00dev->eeprom = NULL;
if (rt2x00dev->csr_addr) {
iounmap(rt2x00dev->csr_addr);
rt2x00dev->csr_addr = NULL;
if (rt2x00dev->csr.base) {
iounmap(rt2x00dev->csr.base);
rt2x00dev->csr.base = NULL;
}
}
@ -357,9 +363,9 @@ 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),
rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0),
pci_resource_len(pci_dev, 0));
if (!rt2x00dev->csr_addr)
if (!rt2x00dev->csr.base)
goto exit;
rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
@ -530,5 +536,5 @@ EXPORT_SYMBOL_GPL(rt2x00pci_resume);
*/
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("rt2x00 library");
MODULE_DESCRIPTION("rt2x00 pci library");
MODULE_LICENSE("GPL");

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -61,7 +61,7 @@ static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
u32 *value)
{
*value = readl(rt2x00dev->csr_addr + offset);
*value = readl(rt2x00dev->csr.base + offset);
}
static inline void
@ -69,14 +69,14 @@ rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
void *value, const u16 length)
{
memcpy_fromio(value, rt2x00dev->csr_addr + offset, length);
memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
}
static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
u32 value)
{
writel(value, rt2x00dev->csr_addr + offset);
writel(value, rt2x00dev->csr.base + offset);
}
static inline void
@ -84,28 +84,63 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
void *value, const u16 length)
{
memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
memcpy_toio(rt2x00dev->csr.base + offset, value, length);
}
/*
* Beacon handlers.
*/
int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
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 data_queue *queue, struct sk_buff *skb,
struct ieee80211_tx_control *control);
/*
* RX/TX data handlers.
/**
* struct queue_entry_priv_pci_rx: Per RX entry PCI specific information
*
* @desc: Pointer to device descriptor.
* @data: Pointer to device's entry memory.
* @dma: DMA pointer to &data.
*/
struct queue_entry_priv_pci_rx {
__le32 *desc;
dma_addr_t desc_dma;
void *data;
dma_addr_t data_dma;
};
/**
* struct queue_entry_priv_pci_tx: Per TX entry PCI specific information
*
* @desc: Pointer to device descriptor
* @data: Pointer to device's entry memory.
* @dma: DMA pointer to &data.
* @control: mac80211 control structure used to transmit data.
*/
struct queue_entry_priv_pci_tx {
__le32 *desc;
dma_addr_t desc_dma;
void *data;
dma_addr_t data_dma;
struct ieee80211_tx_control control;
};
/**
* rt2x00pci_rxdone - Handle RX done events
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
*/
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
const int tx_status, const int retry);
/**
* rt2x00pci_txdone - Handle TX done events
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @entry: Entry which has completed the transmission of a frame.
* @desc: TX done descriptor
*/
void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
struct txdone_entry_desc *desc);
/*
* Device initialization handlers.

Просмотреть файл

@ -0,0 +1,299 @@
/*
Copyright (C) 2004 - 2008 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 queue specific routines.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
const unsigned int queue)
{
int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
return &rt2x00dev->tx[queue];
if (!rt2x00dev->bcn)
return NULL;
if (queue == RT2X00_BCN_QUEUE_BEACON)
return &rt2x00dev->bcn[0];
else if (queue == RT2X00_BCN_QUEUE_ATIM && atim)
return &rt2x00dev->bcn[1];
return NULL;
}
EXPORT_SYMBOL_GPL(rt2x00queue_get_queue);
struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
enum queue_index index)
{
struct queue_entry *entry;
if (unlikely(index >= Q_INDEX_MAX)) {
ERROR(queue->rt2x00dev,
"Entry requested from invalid index type (%d)\n", index);
return NULL;
}
spin_lock(&queue->lock);
entry = &queue->entries[queue->index[index]];
spin_unlock(&queue->lock);
return entry;
}
EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
{
if (unlikely(index >= Q_INDEX_MAX)) {
ERROR(queue->rt2x00dev,
"Index change on invalid index type (%d)\n", index);
return;
}
spin_lock(&queue->lock);
queue->index[index]++;
if (queue->index[index] >= queue->limit)
queue->index[index] = 0;
if (index == Q_INDEX) {
queue->length++;
} else if (index == Q_INDEX_DONE) {
queue->length--;
queue->count ++;
}
spin_unlock(&queue->lock);
}
EXPORT_SYMBOL_GPL(rt2x00queue_index_inc);
static void rt2x00queue_reset(struct data_queue *queue)
{
spin_lock(&queue->lock);
queue->count = 0;
queue->length = 0;
memset(queue->index, 0, sizeof(queue->index));
spin_unlock(&queue->lock);
}
void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue = rt2x00dev->rx;
unsigned int i;
rt2x00queue_reset(queue);
if (!rt2x00dev->ops->lib->init_rxentry)
return;
for (i = 0; i < queue->limit; i++)
rt2x00dev->ops->lib->init_rxentry(rt2x00dev,
&queue->entries[i]);
}
void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
unsigned int i;
txall_queue_for_each(rt2x00dev, queue) {
rt2x00queue_reset(queue);
if (!rt2x00dev->ops->lib->init_txentry)
continue;
for (i = 0; i < queue->limit; i++)
rt2x00dev->ops->lib->init_txentry(rt2x00dev,
&queue->entries[i]);
}
}
static int rt2x00queue_alloc_entries(struct data_queue *queue,
const struct data_queue_desc *qdesc)
{
struct queue_entry *entries;
unsigned int entry_size;
unsigned int i;
rt2x00queue_reset(queue);
queue->limit = qdesc->entry_num;
queue->data_size = qdesc->data_size;
queue->desc_size = qdesc->desc_size;
/*
* Allocate all queue entries.
*/
entry_size = sizeof(*entries) + qdesc->priv_size;
entries = kzalloc(queue->limit * entry_size, GFP_KERNEL);
if (!entries)
return -ENOMEM;
#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \
( ((char *)(__base)) + ((__limit) * (__esize)) + \
((__index) * (__psize)) )
for (i = 0; i < queue->limit; i++) {
entries[i].flags = 0;
entries[i].queue = queue;
entries[i].skb = NULL;
entries[i].entry_idx = i;
entries[i].priv_data =
QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit,
sizeof(*entries), qdesc->priv_size);
}
#undef QUEUE_ENTRY_PRIV_OFFSET
queue->entries = entries;
return 0;
}
int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
int status;
status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx);
if (status)
goto exit;
tx_queue_for_each(rt2x00dev, queue) {
status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx);
if (status)
goto exit;
}
status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn);
if (status)
goto exit;
if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
return 0;
status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1],
rt2x00dev->ops->atim);
if (status)
goto exit;
return 0;
exit:
ERROR(rt2x00dev, "Queue entries allocation failed.\n");
rt2x00queue_uninitialize(rt2x00dev);
return status;
}
void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
queue_for_each(rt2x00dev, queue) {
kfree(queue->entries);
queue->entries = NULL;
}
}
static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
struct data_queue *queue, enum data_queue_qid qid)
{
spin_lock_init(&queue->lock);
queue->rt2x00dev = rt2x00dev;
queue->qid = qid;
queue->aifs = 2;
queue->cw_min = 5;
queue->cw_max = 10;
}
int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
enum data_queue_qid qid;
unsigned int req_atim =
!!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
/*
* We need the following queues:
* RX: 1
* TX: hw->queues
* Beacon: 1
* Atim: 1 (if required)
*/
rt2x00dev->data_queues = 2 + rt2x00dev->hw->queues + req_atim;
queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL);
if (!queue) {
ERROR(rt2x00dev, "Queue allocation failed.\n");
return -ENOMEM;
}
/*
* Initialize pointers
*/
rt2x00dev->rx = queue;
rt2x00dev->tx = &queue[1];
rt2x00dev->bcn = &queue[1 + rt2x00dev->hw->queues];
/*
* Initialize queue parameters.
* RX: qid = QID_RX
* TX: qid = QID_AC_BE + index
* TX: cw_min: 2^5 = 32.
* TX: cw_max: 2^10 = 1024.
* BCN & Atim: qid = QID_MGMT
*/
rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX);
qid = QID_AC_BE;
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_init(rt2x00dev, queue, qid++);
rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_MGMT);
if (req_atim)
rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_MGMT);
return 0;
}
void rt2x00queue_free(struct rt2x00_dev *rt2x00dev)
{
kfree(rt2x00dev->rx);
rt2x00dev->rx = NULL;
rt2x00dev->tx = NULL;
rt2x00dev->bcn = NULL;
}

Просмотреть файл

@ -0,0 +1,457 @@
/*
Copyright (C) 2004 - 2008 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 queue datastructures and routines
*/
#ifndef RT2X00QUEUE_H
#define RT2X00QUEUE_H
#include <linux/prefetch.h>
/**
* DOC: Entrie frame size
*
* Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
* for USB devices this restriction does not apply, but the value of
* 2432 makes sense since it is big enough to contain the maximum fragment
* size according to the ieee802.11 specs.
*/
#define DATA_FRAME_SIZE 2432
#define MGMT_FRAME_SIZE 256
/**
* DOC: Number of entries per queue
*
* After research it was concluded that 12 entries in a RX and TX
* queue would be sufficient. Although this is almost one third of
* the amount the legacy driver allocated, the queues aren't getting
* filled to the maximum even when working with the maximum rate.
*/
#define RX_ENTRIES 12
#define TX_ENTRIES 12
#define BEACON_ENTRIES 1
#define ATIM_ENTRIES 1
/**
* enum data_queue_qid: Queue identification
*/
enum data_queue_qid {
QID_AC_BE = 0,
QID_AC_BK = 1,
QID_AC_VI = 2,
QID_AC_VO = 3,
QID_HCCA = 4,
QID_MGMT = 13,
QID_RX = 14,
QID_OTHER = 15,
};
/**
* enum rt2x00_bcn_queue: Beacon queue index
*
* Start counting with a high offset, this because this enumeration
* supplements &enum ieee80211_tx_queue and we should prevent value
* conflicts.
*
* @RT2X00_BCN_QUEUE_BEACON: Beacon queue
* @RT2X00_BCN_QUEUE_ATIM: Atim queue (sends frame after beacon)
*/
enum rt2x00_bcn_queue {
RT2X00_BCN_QUEUE_BEACON = 100,
RT2X00_BCN_QUEUE_ATIM = 101,
};
/**
* enum skb_frame_desc_flags: Flags for &struct skb_frame_desc
*
* @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver
* and should not be reported back to mac80211 during txdone.
*/
enum skb_frame_desc_flags {
FRAME_DESC_DRIVER_GENERATED = 1 << 0,
};
/**
* struct skb_frame_desc: Descriptor information for the skb buffer
*
* This structure is placed over the skb->cb array, this means that
* this structure should not exceed the size of that array (48 bytes).
*
* @flags: Frame flags, see &enum skb_frame_desc_flags.
* @frame_type: Frame type, see &enum rt2x00_dump_type.
* @data: Pointer to data part of frame (Start of ieee80211 header).
* @desc: Pointer to descriptor part of the frame.
* Note that this pointer could point to something outside
* of the scope of the skb->data pointer.
* @data_len: Length of the frame data.
* @desc_len: Length of the frame descriptor.
* @entry: The entry to which this sk buffer belongs.
*/
struct skb_frame_desc {
unsigned int flags;
unsigned int frame_type;
void *data;
void *desc;
unsigned int data_len;
unsigned int desc_len;
struct queue_entry *entry;
};
static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct skb_frame_desc) > sizeof(skb->cb));
return (struct skb_frame_desc *)&skb->cb[0];
}
/**
* struct rxdone_entry_desc: RX Entry descriptor
*
* Summary of information that has been read from the RX frame descriptor.
*
* @signal: Signal of the received frame.
* @rssi: RSSI of the received frame.
* @ofdm: Was frame send with an OFDM rate.
* @size: Data size of the received frame.
* @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
* @my_bss: Does this frame originate from device's BSS.
*/
struct rxdone_entry_desc {
int signal;
int rssi;
int ofdm;
int size;
int flags;
int my_bss;
};
/**
* struct txdone_entry_desc: TX done entry descriptor
*
* Summary of information that has been read from the TX frame descriptor
* after the device is done with transmission.
*
* @control: Control structure which was used to transmit the frame.
* @status: TX status (See &enum tx_status).
* @retry: Retry count.
*/
struct txdone_entry_desc {
struct ieee80211_tx_control *control;
int status;
int retry;
};
/**
* enum txentry_desc_flags: Status flags for TX entry descriptor
*
* @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame.
* @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate.
* @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment.
* @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted.
* @ENTRY_TXD_BURST: This frame belongs to the same burst event.
* @ENTRY_TXD_ACK: An ACK is required for this frame.
*/
enum txentry_desc_flags {
ENTRY_TXD_RTS_FRAME,
ENTRY_TXD_OFDM_RATE,
ENTRY_TXD_MORE_FRAG,
ENTRY_TXD_REQ_TIMESTAMP,
ENTRY_TXD_BURST,
ENTRY_TXD_ACK,
};
/**
* struct txentry_desc: TX Entry descriptor
*
* Summary of information for the frame descriptor before sending a TX frame.
*
* @flags: Descriptor flags (See &enum queue_entry_flags).
* @queue: Queue identification (See &enum data_queue_qid).
* @length_high: PLCP length high word.
* @length_low: PLCP length low word.
* @signal: PLCP signal.
* @service: PLCP service.
* @aifs: AIFS value.
* @ifs: IFS value.
* @cw_min: cwmin value.
* @cw_max: cwmax value.
*/
struct txentry_desc {
unsigned long flags;
enum data_queue_qid queue;
u16 length_high;
u16 length_low;
u16 signal;
u16 service;
int aifs;
int ifs;
int cw_min;
int cw_max;
};
/**
* enum queue_entry_flags: Status flags for queue entry
*
* @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface.
* As long as this bit is set, this entry may only be touched
* through the interface structure.
* @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data
* transfer (either TX or RX depending on the queue). The entry should
* only be touched after the device has signaled it is done with it.
* @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data
* encryption or decryption. The entry should only be touched after
* the device has signaled it is done with it.
*/
enum queue_entry_flags {
ENTRY_BCN_ASSIGNED,
ENTRY_OWNER_DEVICE_DATA,
ENTRY_OWNER_DEVICE_CRYPTO,
};
/**
* struct queue_entry: Entry inside the &struct data_queue
*
* @flags: Entry flags, see &enum queue_entry_flags.
* @queue: The data queue (&struct data_queue) to which this entry belongs.
* @skb: The buffer which is currently being transmitted (for TX queue),
* or used to directly recieve data in (for RX queue).
* @entry_idx: The entry index number.
* @priv_data: Private data belonging to this queue entry. The pointer
* points to data specific to a particular driver and queue type.
*/
struct queue_entry {
unsigned long flags;
struct data_queue *queue;
struct sk_buff *skb;
unsigned int entry_idx;
void *priv_data;
};
/**
* enum queue_index: Queue index type
*
* @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
* owned by the hardware then the queue is considered to be full.
* @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
* the hardware and for which we need to run the txdone handler. If this
* entry is not owned by the hardware the queue is considered to be empty.
* @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription
* will be completed by the hardware next.
* @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size
* of the index array.
*/
enum queue_index {
Q_INDEX,
Q_INDEX_DONE,
Q_INDEX_CRYPTO,
Q_INDEX_MAX,
};
/**
* struct data_queue: Data queue
*
* @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to.
* @entries: Base address of the &struct queue_entry which are
* part of this queue.
* @qid: The queue identification, see &enum data_queue_qid.
* @lock: Spinlock to protect index handling. Whenever @index, @index_done or
* @index_crypt needs to be changed this lock should be grabbed to prevent
* index corruption due to concurrency.
* @count: Number of frames handled in the queue.
* @limit: Maximum number of entries in the queue.
* @length: Number of frames in queue.
* @index: Index pointers to entry positions in the queue,
* use &enum queue_index to get a specific index field.
* @aifs: The aifs value for outgoing frames (field ignored in RX queue).
* @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
* @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
* @data_size: Maximum data size for the frames in this queue.
* @desc_size: Hardware descriptor size for the data in this queue.
*/
struct data_queue {
struct rt2x00_dev *rt2x00dev;
struct queue_entry *entries;
enum data_queue_qid qid;
spinlock_t lock;
unsigned int count;
unsigned short limit;
unsigned short length;
unsigned short index[Q_INDEX_MAX];
unsigned short aifs;
unsigned short cw_min;
unsigned short cw_max;
unsigned short data_size;
unsigned short desc_size;
};
/**
* struct data_queue_desc: Data queue description
*
* The information in this structure is used by drivers
* to inform rt2x00lib about the creation of the data queue.
*
* @entry_num: Maximum number of entries for a queue.
* @data_size: Maximum data size for the frames in this queue.
* @desc_size: Hardware descriptor size for the data in this queue.
* @priv_size: Size of per-queue_entry private data.
*/
struct data_queue_desc {
unsigned short entry_num;
unsigned short data_size;
unsigned short desc_size;
unsigned short priv_size;
};
/**
* queue_end - Return pointer to the last queue (HELPER MACRO).
* @__dev: Pointer to &struct rt2x00_dev
*
* Using the base rx pointer and the maximum number of available queues,
* this macro will return the address of 1 position beyond the end of the
* queues array.
*/
#define queue_end(__dev) \
&(__dev)->rx[(__dev)->data_queues]
/**
* tx_queue_end - Return pointer to the last TX queue (HELPER MACRO).
* @__dev: Pointer to &struct rt2x00_dev
*
* Using the base tx pointer and the maximum number of available TX
* queues, this macro will return the address of 1 position beyond
* the end of the TX queue array.
*/
#define tx_queue_end(__dev) \
&(__dev)->tx[(__dev)->hw->queues]
/**
* queue_loop - Loop through the queues within a specific range (HELPER MACRO).
* @__entry: Pointer where the current queue entry will be stored in.
* @__start: Start queue pointer.
* @__end: End queue pointer.
*
* This macro will loop through all queues between &__start and &__end.
*/
#define queue_loop(__entry, __start, __end) \
for ((__entry) = (__start); \
prefetch(&(__entry)[1]), (__entry) != (__end); \
(__entry) = &(__entry)[1])
/**
* queue_for_each - Loop through all queues
* @__dev: Pointer to &struct rt2x00_dev
* @__entry: Pointer where the current queue entry will be stored in.
*
* This macro will loop through all available queues.
*/
#define queue_for_each(__dev, __entry) \
queue_loop(__entry, (__dev)->rx, queue_end(__dev))
/**
* tx_queue_for_each - Loop through the TX queues
* @__dev: Pointer to &struct rt2x00_dev
* @__entry: Pointer where the current queue entry will be stored in.
*
* This macro will loop through all TX related queues excluding
* the Beacon and Atim queues.
*/
#define tx_queue_for_each(__dev, __entry) \
queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev))
/**
* txall_queue_for_each - Loop through all TX related queues
* @__dev: Pointer to &struct rt2x00_dev
* @__entry: Pointer where the current queue entry will be stored in.
*
* This macro will loop through all TX related queues including
* the Beacon and Atim queues.
*/
#define txall_queue_for_each(__dev, __entry) \
queue_loop(__entry, (__dev)->tx, queue_end(__dev))
/**
* rt2x00queue_empty - Check if the queue is empty.
* @queue: Queue to check if empty.
*/
static inline int rt2x00queue_empty(struct data_queue *queue)
{
return queue->length == 0;
}
/**
* rt2x00queue_full - Check if the queue is full.
* @queue: Queue to check if full.
*/
static inline int rt2x00queue_full(struct data_queue *queue)
{
return queue->length == queue->limit;
}
/**
* rt2x00queue_free - Check the number of available entries in queue.
* @queue: Queue to check.
*/
static inline int rt2x00queue_available(struct data_queue *queue)
{
return queue->limit - queue->length;
}
/**
* rt2x00_desc_read - Read a word from the hardware descriptor.
* @desc: Base descriptor address
* @word: Word index from where the descriptor should be read.
* @value: Address where the descriptor value should be written into.
*/
static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
{
*value = le32_to_cpu(desc[word]);
}
/**
* rt2x00_desc_write - wrote a word to the hardware descriptor.
* @desc: Base descriptor address
* @word: Word index from where the descriptor should be written.
* @value: Value that should be written into the descriptor.
*/
static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value)
{
desc[word] = cpu_to_le32(value);
}
#endif /* RT2X00QUEUE_H */

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -29,7 +29,7 @@
/*
* TX result flags.
*/
enum TX_STATUS {
enum tx_status {
TX_SUCCESS = 0,
TX_SUCCESS_RETRY = 1,
TX_FAIL_RETRY = 2,
@ -220,75 +220,4 @@ static inline u8 rt2x00_get_field8(const u8 reg,
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 */

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify

Просмотреть файл

@ -1,290 +0,0 @@
/*
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
/*
* skb_desc
* Descriptor information for the skb buffer
*/
struct skb_desc {
unsigned int frame_type;
unsigned int desc_len;
unsigned int data_len;
void *desc;
void *data;
struct data_ring *ring;
struct data_entry *entry;
};
static inline struct skb_desc* get_skb_desc(struct sk_buff *skb)
{
return (struct skb_desc*)&skb->cb[0];
}
/*
* 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;
int my_bss;
};
/*
* 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
#define ENTRY_TXD_ACK 7
/*
* 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;
/*
* Entry identification number (index).
*/
unsigned int entry_idx;
};
/*
* 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;
/*
* Queue identification number:
* RX: 0
* TX: IEEE80211_TX_*
*/
unsigned int queue_idx;
/*
* 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(__le32 *desc,
const u8 word, u32 *value)
{
*value = le32_to_cpu(desc[word]);
}
static inline void rt2x00_desc_write(__le32 *desc,
const u8 word, const u32 value)
{
desc[word] = cpu_to_le32(value);
}
#endif /* RT2X00RING_H */

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -40,8 +40,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
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 = rt2x00dev_usb_dev(rt2x00dev);
int status;
unsigned int i;
unsigned int pipe =
@ -85,20 +84,20 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
/*
* Check for Cache availability.
*/
if (unlikely(!rt2x00dev->csr_cache || buffer_length > CSR_CACHE_SIZE)) {
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);
memcpy(rt2x00dev->csr.cache, buffer, buffer_length);
status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
offset, 0, rt2x00dev->csr_cache,
offset, 0, rt2x00dev->csr.cache,
buffer_length, timeout);
if (!status && requesttype == USB_VENDOR_REQUEST_IN)
memcpy(buffer, rt2x00dev->csr_cache, buffer_length);
memcpy(buffer, rt2x00dev->csr.cache, buffer_length);
return status;
}
@ -128,15 +127,15 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
*/
static void rt2x00usb_interrupt_txdone(struct urb *urb)
{
struct data_entry *entry = (struct data_entry *)urb->context;
struct data_ring *ring = entry->ring;
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
struct txdone_entry_desc txdesc;
__le32 *txd = (__le32 *)entry->skb->data;
u32 word;
int tx_status;
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
!__test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
rt2x00_desc_read(txd, 0, &word);
@ -144,45 +143,46 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
/*
* Remove the descriptor data from the buffer.
*/
skb_pull(entry->skb, ring->desc_size);
skb_pull(entry->skb, entry->queue->desc_size);
/*
* Obtain the status about this packet.
*/
tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
txdesc.retry = 0;
txdesc.control = &priv_tx->control;
rt2x00lib_txdone(entry, tx_status, 0);
rt2x00lib_txdone(entry, &txdesc);
/*
* Make this entry available for reuse.
*/
entry->flags = 0;
rt2x00_ring_index_done_inc(entry->ring);
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
/*
* If the data ring was full before the txdone handler
* If the data queue was full before the txdone handler
* we must make sure the packet queue in the mac80211 stack
* is reenabled when the txdone handler has finished.
*/
if (!rt2x00_ring_full(ring))
ieee80211_wake_queue(rt2x00dev->hw,
entry->tx_status.control.queue);
if (!rt2x00queue_full(entry->queue))
ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue);
}
int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct data_queue *queue, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_entry *entry = rt2x00_get_data_entry(ring);
struct skb_desc *desc;
struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
struct skb_frame_desc *skbdesc;
u32 length;
if (rt2x00_ring_full(ring))
if (rt2x00queue_full(queue))
return -EINVAL;
if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) {
if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
ERROR(rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
@ -193,19 +193,18 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
/*
* Add the descriptor in front of the skb.
*/
skb_push(skb, ring->desc_size);
memset(skb->data, 0, ring->desc_size);
skb_push(skb, queue->desc_size);
memset(skb->data, 0, queue->desc_size);
/*
* Fill in skb descriptor
*/
desc = get_skb_desc(skb);
desc->desc_len = ring->desc_size;
desc->data_len = skb->len - ring->desc_size;
desc->desc = skb->data;
desc->data = skb->data + ring->desc_size;
desc->ring = ring;
desc->entry = entry;
skbdesc = get_skb_frame_desc(skb);
skbdesc->data = skb->data + queue->desc_size;
skbdesc->data_len = skb->len - queue->desc_size;
skbdesc->desc = skb->data;
skbdesc->desc_len = queue->desc_size;
skbdesc->entry = entry;
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
@ -219,12 +218,12 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
/*
* 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),
__set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
usb_fill_bulk_urb(priv_tx->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1),
skb->data, length, rt2x00usb_interrupt_txdone, entry);
usb_submit_urb(entry->priv, GFP_ATOMIC);
usb_submit_urb(priv_tx->urb, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
rt2x00queue_index_inc(queue, Q_INDEX);
return 0;
}
@ -233,44 +232,12 @@ EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
/*
* RX data handlers.
*/
static void rt2x00usb_interrupt_rxdone(struct urb *urb)
static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue)
{
struct data_entry *entry = (struct data_entry *)urb->context;
struct data_ring *ring = entry->ring;
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
struct skb_desc *skbdesc;
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))
return;
unsigned int frame_size;
/*
* Check if the received data is simply too small
* to be actually valid, or if the urb is signaling
* a problem.
*/
if (urb->actual_length < entry->ring->desc_size || urb->status)
goto skip_entry;
/*
* Fill in skb descriptor
*/
skbdesc = get_skb_desc(entry->skb);
skbdesc->ring = ring;
skbdesc->entry = entry;
memset(&desc, 0, 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
@ -279,42 +246,60 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
* and thus optimize alignment by reserving the 2 bytes in
* advance.
*/
frame_size = entry->ring->data_size + entry->ring->desc_size;
frame_size = queue->data_size + queue->desc_size;
skb = dev_alloc_skb(frame_size + 2);
if (!skb)
goto skip_entry;
return NULL;
skb_reserve(skb, 2);
skb_put(skb, frame_size);
/*
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
hdr = (struct ieee80211_hdr *)entry->skb->data;
header_size =
ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
return skb;
}
if (header_size % 4 == 0) {
skb_push(entry->skb, 2);
memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
}
static void rt2x00usb_interrupt_rxdone(struct urb *urb)
{
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct sk_buff *skb;
struct skb_frame_desc *skbdesc;
struct rxdone_entry_desc rxdesc;
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
/*
* Trim the entire buffer down to only contain the valid frame data
* excluding the device descriptor. The position of the descriptor
* varies. This means that we should check where the descriptor is
* and decide if we need to pull the data pointer to exclude the
* device descriptor.
* Check if the received data is simply too small
* to be actually valid, or if the urb is signaling
* a problem.
*/
if (skbdesc->data > skbdesc->desc)
skb_pull(entry->skb, skbdesc->desc_len);
skb_trim(entry->skb, desc.size);
if (urb->actual_length < entry->queue->desc_size || urb->status)
goto skip_entry;
/*
* Fill in skb descriptor
*/
skbdesc = get_skb_frame_desc(entry->skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->entry = entry;
memset(&rxdesc, 0, sizeof(rxdesc));
rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
/*
* 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.
*/
skb = rt2x00usb_alloc_rxskb(entry->queue);
if (!skb)
goto skip_entry;
/*
* Send the frame to rt2x00lib for further processing.
*/
rt2x00lib_rxdone(entry, entry->skb, &desc);
rt2x00lib_rxdone(entry, &rxdesc);
/*
* Replace current entry's skb with the newly allocated one,
@ -325,12 +310,12 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
urb->transfer_buffer_length = entry->skb->len;
skip_entry:
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
__set_bit(ENTRY_OWNER_NIC, &entry->flags);
if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) {
__set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
usb_submit_urb(urb, GFP_ATOMIC);
}
rt2x00_ring_index_inc(ring);
rt2x00queue_index_inc(entry->queue, Q_INDEX);
}
/*
@ -338,18 +323,44 @@ skip_entry:
*/
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
struct queue_entry_priv_usb_rx *priv_rx;
struct queue_entry_priv_usb_tx *priv_tx;
struct queue_entry_priv_usb_bcn *priv_bcn;
struct data_queue *queue;
unsigned int i;
rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000,
REGISTER_TIMEOUT);
/*
* Cancel all rings.
* Cancel all queues.
*/
ring_for_each(rt2x00dev, ring) {
for (i = 0; i < ring->stats.limit; i++)
usb_kill_urb(ring->entry[i].priv);
for (i = 0; i < rt2x00dev->rx->limit; i++) {
priv_rx = rt2x00dev->rx->entries[i].priv_data;
usb_kill_urb(priv_rx->urb);
}
tx_queue_for_each(rt2x00dev, queue) {
for (i = 0; i < queue->limit; i++) {
priv_tx = queue->entries[i].priv_data;
usb_kill_urb(priv_tx->urb);
}
}
for (i = 0; i < rt2x00dev->bcn->limit; i++) {
priv_bcn = rt2x00dev->bcn->entries[i].priv_data;
usb_kill_urb(priv_bcn->urb);
if (priv_bcn->guardian_urb)
usb_kill_urb(priv_bcn->guardian_urb);
}
if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
return;
for (i = 0; i < rt2x00dev->bcn[1].limit; i++) {
priv_tx = rt2x00dev->bcn[1].entries[i].priv_data;
usb_kill_urb(priv_tx->urb);
}
}
EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
@ -358,64 +369,108 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
* Device initialization handlers.
*/
void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry)
struct queue_entry *entry)
{
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
usb_fill_bulk_urb(entry->priv, usb_dev,
usb_fill_bulk_urb(priv_rx->urb, 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);
__set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
usb_submit_urb(priv_rx->urb, GFP_ATOMIC);
}
EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry)
struct queue_entry *entry)
{
entry->flags = 0;
}
EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
struct data_queue *queue)
{
struct queue_entry_priv_usb_rx *priv_rx;
struct queue_entry_priv_usb_tx *priv_tx;
struct queue_entry_priv_usb_bcn *priv_bcn;
struct urb *urb;
unsigned int guardian =
test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
unsigned int i;
/*
* Allocate the URB's
*/
for (i = 0; i < ring->stats.limit; i++) {
ring->entry[i].priv = usb_alloc_urb(0, GFP_KERNEL);
if (!ring->entry[i].priv)
for (i = 0; i < queue->limit; i++) {
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return -ENOMEM;
if (queue->qid == QID_RX) {
priv_rx = queue->entries[i].priv_data;
priv_rx->urb = urb;
} else if (queue->qid == QID_MGMT && guardian) {
priv_bcn = queue->entries[i].priv_data;
priv_bcn->urb = urb;
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return -ENOMEM;
priv_bcn->guardian_urb = urb;
} else {
priv_tx = queue->entries[i].priv_data;
priv_tx->urb = urb;
}
}
return 0;
}
static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
struct data_queue *queue)
{
struct queue_entry_priv_usb_rx *priv_rx;
struct queue_entry_priv_usb_tx *priv_tx;
struct queue_entry_priv_usb_bcn *priv_bcn;
struct urb *urb;
unsigned int guardian =
test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
unsigned int i;
if (!ring->entry)
if (!queue->entries)
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);
for (i = 0; i < queue->limit; i++) {
if (queue->qid == QID_RX) {
priv_rx = queue->entries[i].priv_data;
urb = priv_rx->urb;
} else if (queue->qid == QID_MGMT && guardian) {
priv_bcn = queue->entries[i].priv_data;
usb_kill_urb(priv_bcn->guardian_urb);
usb_free_urb(priv_bcn->guardian_urb);
urb = priv_bcn->urb;
} else {
priv_tx = queue->entries[i].priv_data;
urb = priv_tx->urb;
}
usb_kill_urb(urb);
usb_free_urb(urb);
if (queue->entries[i].skb)
kfree_skb(queue->entries[i].skb);
}
}
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
struct data_queue *queue;
struct sk_buff *skb;
unsigned int entry_size;
unsigned int i;
@ -424,25 +479,22 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
/*
* Allocate DMA
*/
ring_for_each(rt2x00dev, ring) {
status = rt2x00usb_alloc_urb(rt2x00dev, ring);
queue_for_each(rt2x00dev, queue) {
status = rt2x00usb_alloc_urb(rt2x00dev, queue);
if (status)
goto exit;
}
/*
* For the RX ring, skb's should be allocated.
* For the RX queue, skb's should be allocated.
*/
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);
for (i = 0; i < rt2x00dev->rx->limit; i++) {
skb = rt2x00usb_alloc_rxskb(rt2x00dev->rx);
if (!skb)
goto exit;
skb_reserve(skb, NET_IP_ALIGN);
skb_put(skb, entry_size);
rt2x00dev->rx->entry[i].skb = skb;
rt2x00dev->rx->entries[i].skb = skb;
}
return 0;
@ -456,10 +508,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize);
void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
struct data_queue *queue;
ring_for_each(rt2x00dev, ring)
rt2x00usb_free_urb(rt2x00dev, ring);
queue_for_each(rt2x00dev, queue)
rt2x00usb_free_urb(rt2x00dev, queue);
}
EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
@ -474,14 +526,14 @@ static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)
kfree(rt2x00dev->eeprom);
rt2x00dev->eeprom = NULL;
kfree(rt2x00dev->csr_cache);
rt2x00dev->csr_cache = 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)
rt2x00dev->csr.cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
if (!rt2x00dev->csr.cache)
goto exit;
rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
@ -627,9 +679,9 @@ EXPORT_SYMBOL_GPL(rt2x00usb_resume);
#endif /* CONFIG_PM */
/*
* rt2x00pci module information.
* rt2x00usb module information.
*/
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("rt2x00 library");
MODULE_DESCRIPTION("rt2x00 usb library");
MODULE_LICENSE("GPL");

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -60,34 +60,47 @@
#define USB_VENDOR_REQUEST_IN ( USB_DIR_IN | USB_VENDOR_REQUEST )
#define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST )
/*
* USB vendor commands.
/**
* enum rt2x00usb_vendor_request: USB vendor commands.
*/
#define USB_DEVICE_MODE 0x01
#define USB_SINGLE_WRITE 0x02
#define USB_SINGLE_READ 0x03
#define USB_MULTI_WRITE 0x06
#define USB_MULTI_READ 0x07
#define USB_EEPROM_WRITE 0x08
#define USB_EEPROM_READ 0x09
#define USB_LED_CONTROL 0x0a /* RT73USB */
#define USB_RX_CONTROL 0x0c
enum rt2x00usb_vendor_request {
USB_DEVICE_MODE = 1,
USB_SINGLE_WRITE = 2,
USB_SINGLE_READ = 3,
USB_MULTI_WRITE = 6,
USB_MULTI_READ = 7,
USB_EEPROM_WRITE = 8,
USB_EEPROM_READ = 9,
USB_LED_CONTROL = 10, /* RT73USB */
USB_RX_CONTROL = 12,
};
/*
* Device modes offset
/**
* enum rt2x00usb_mode_offset: Device modes offset.
*/
#define USB_MODE_RESET 0x01
#define USB_MODE_UNPLUG 0x02
#define USB_MODE_FUNCTION 0x03
#define USB_MODE_TEST 0x04
#define USB_MODE_SLEEP 0x07 /* RT73USB */
#define USB_MODE_FIRMWARE 0x08 /* RT73USB */
#define USB_MODE_WAKEUP 0x09 /* RT73USB */
enum rt2x00usb_mode_offset {
USB_MODE_RESET = 1,
USB_MODE_UNPLUG = 2,
USB_MODE_FUNCTION = 3,
USB_MODE_TEST = 4,
USB_MODE_SLEEP = 7, /* RT73USB */
USB_MODE_FIRMWARE = 8, /* RT73USB */
USB_MODE_WAKEUP = 9, /* RT73USB */
};
/*
* Used to read/write from/to the device.
/**
* rt2x00usb_vendor_request - Send register command to device
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
* @requesttype: Request type &USB_VENDOR_REQUEST_*
* @offset: Register offset to perform action on
* @value: Value to write to device
* @buffer: Buffer where information will be read/written to by device
* @buffer_length: Size of &buffer
* @timeout: Operation timeout
*
* This is the main function to communicate with the device,
* the buffer argument _must_ either be NULL or point to
* 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.
*/
@ -97,13 +110,21 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
void *buffer, const u16 buffer_length,
const int timeout);
/*
* Used to read/write from/to the device.
/**
* rt2x00usb_vendor_request_buff - Send register command to device (buffered)
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
* @requesttype: Request type &USB_VENDOR_REQUEST_*
* @offset: Register offset to perform action on
* @buffer: Buffer where information will be read/written to by device
* @buffer_length: Size of &buffer
* @timeout: Operation timeout
*
* 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
* 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.
*/
@ -112,15 +133,32 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
const u16 offset, void *buffer,
const u16 buffer_length, const int timeout);
/*
* A version of rt2x00usb_vendor_request_buff which must be called
* if the usb_cache_mutex is already held. */
/**
* rt2x00usb_vendor_request_buff - Send register command to device (buffered)
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
* @requesttype: Request type &USB_VENDOR_REQUEST_*
* @offset: Register offset to perform action on
* @buffer: Buffer where information will be read/written to by device
* @buffer_length: Size of &buffer
* @timeout: Operation timeout
*
* A version of &rt2x00usb_vendor_request_buff which must be called
* if the usb_cache_mutex is already held.
*/
int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length, const int timeout);
/*
/**
* rt2x00usb_vendor_request_sw - Send single register command to device
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @request: USB vendor command (See &enum rt2x00usb_vendor_request)
* @offset: Register offset to perform action on
* @value: Value to write to device
* @timeout: Operation 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.
@ -136,7 +174,12 @@ static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
value, NULL, 0, timeout);
}
/*
/**
* rt2x00usb_eeprom_read - Read eeprom from device
* @rt2x00dev: Pointer to &struct rt2x00_dev
* @eeprom: Pointer to eeprom array to store the information in
* @length: Number of bytes to read from the eeprom
*
* 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.
@ -147,8 +190,8 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
USB_VENDOR_REQUEST_IN, 0x0000,
0x0000, eeprom, lenght, timeout);
USB_VENDOR_REQUEST_IN, 0, 0,
eeprom, lenght, timeout);
}
/*
@ -160,16 +203,58 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
* TX data handlers.
*/
int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct data_queue *queue, struct sk_buff *skb,
struct ieee80211_tx_control *control);
/**
* struct queue_entry_priv_usb_rx: Per RX entry USB specific information
*
* @urb: Urb structure used for device communication.
*/
struct queue_entry_priv_usb_rx {
struct urb *urb;
};
/**
* struct queue_entry_priv_usb_tx: Per TX entry USB specific information
*
* @urb: Urb structure used for device communication.
* @control: mac80211 control structure used to transmit data.
*/
struct queue_entry_priv_usb_tx {
struct urb *urb;
struct ieee80211_tx_control control;
};
/**
* struct queue_entry_priv_usb_tx: Per TX entry USB specific information
*
* The first section should match &struct queue_entry_priv_usb_tx exactly.
* rt2500usb can use this structure to send a guardian byte when working
* with beacons.
*
* @urb: Urb structure used for device communication.
* @control: mac80211 control structure used to transmit data.
* @guardian_data: Set to 0, used for sending the guardian data.
* @guardian_urb: Urb structure used to send the guardian data.
*/
struct queue_entry_priv_usb_bcn {
struct urb *urb;
struct ieee80211_tx_control control;
unsigned int guardian_data;
struct urb *guardian_urb;
};
/*
* Device initialization handlers.
*/
void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry);
struct queue_entry *entry);
void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
struct data_entry *entry);
struct queue_entry *entry);
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -161,7 +161,9 @@ struct hw_pairwise_ta_entry {
#define HW_BEACON_BASE1 0x2d00
#define HW_BEACON_BASE2 0x2e00
#define HW_BEACON_BASE3 0x2f00
#define HW_BEACON_OFFSET 0x0100
#define HW_BEACON_OFFSET(__index) \
( HW_BEACON_BASE0 + (__index * 0x0100) )
/*
* HOST-MCU shared memory.
@ -234,6 +236,11 @@ struct hw_pairwise_ta_entry {
/*
* MAC_CSR3: STA MAC register 1.
* UNICAST_TO_ME_MASK:
* Used to mask off bits from byte 5 of the MAC address
* to determine the UNICAST_TO_ME bit for RX frames.
* The full mask is complemented by BSS_ID_MASK:
* MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
*/
#define MAC_CSR3 0x300c
#define MAC_CSR3_BYTE4 FIELD32(0x000000ff)
@ -251,7 +258,14 @@ struct hw_pairwise_ta_entry {
/*
* MAC_CSR5: BSSID register 1.
* BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID.
* BSS_ID_MASK:
* This mask is used to mask off bits 0 and 1 of byte 5 of the
* BSSID. This will make sure that those bits will be ignored
* when determining the MY_BSS of RX frames.
* 0: 1-BSSID mode (BSS index = 0)
* 1: 2-BSSID mode (BSS index: Byte5, bit 0)
* 2: 2-BSSID mode (BSS index: byte5, bit 1)
* 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
*/
#define MAC_CSR5 0x3014
#define MAC_CSR5_BYTE4 FIELD32(0x000000ff)
@ -391,7 +405,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)
@ -866,7 +880,7 @@ struct hw_pairwise_ta_entry {
#define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000)
/*
* LOAD_TX_RING_CSR: Load RX de
* LOAD_TX_RING_CSR: Load RX desriptor
*/
#define LOAD_TX_RING_CSR 0x3434
#define LOAD_TX_RING_CSR_LOAD_TXD_AC0 FIELD32(0x00000001)
@ -1116,10 +1130,10 @@ struct hw_pairwise_ta_entry {
#define EEPROM_MAC_ADDR_0 0x0002
#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff)
#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00)
#define EEPROM_MAC_ADDR1 0x0004
#define EEPROM_MAC_ADDR1 0x0003
#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff)
#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00)
#define EEPROM_MAC_ADDR_2 0x0006
#define EEPROM_MAC_ADDR_2 0x0004
#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff)
#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00)
@ -1247,6 +1261,7 @@ struct hw_pairwise_ta_entry {
* DMA descriptor defines.
*/
#define TXD_DESC_SIZE ( 16 * sizeof(__le32) )
#define TXINFO_SIZE ( 6 * sizeof(__le32) )
#define RXD_DESC_SIZE ( 16 * sizeof(__le32) )
/*
@ -1440,8 +1455,8 @@ struct hw_pairwise_ta_entry {
#define RXD_W15_RESERVED FIELD32(0xffffffff)
/*
* Macro's for converting txpower from EEPROM to dscape value
* and from dscape value to register value.
* Macro's for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_TXPOWER 0
#define MAX_TXPOWER 31

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -278,49 +278,77 @@ static const struct rt2x00debug rt73usb_rt2x00debug = {
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
#ifdef CONFIG_RT73USB_LEDS
static void rt73usb_led_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct rt2x00_led *led =
container_of(led_cdev, struct rt2x00_led, led_dev);
unsigned int enabled = brightness != LED_OFF;
unsigned int a_mode =
(enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
unsigned int bg_mode =
(enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
if (in_atomic()) {
NOTICE(led->rt2x00dev,
"Ignoring LED brightness command for led %d", led->type);
return;
}
if (led->type == LED_TYPE_RADIO) {
rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
MCU_LEDCS_RADIO_STATUS, enabled);
rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
0, led->rt2x00dev->led_mcu_reg,
REGISTER_TIMEOUT);
} else if (led->type == LED_TYPE_ASSOC) {
rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
MCU_LEDCS_LINK_BG_STATUS, bg_mode);
rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
MCU_LEDCS_LINK_A_STATUS, a_mode);
rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
0, led->rt2x00dev->led_mcu_reg,
REGISTER_TIMEOUT);
} else if (led->type == LED_TYPE_QUALITY) {
/*
* The brightness is divided into 6 levels (0 - 5),
* this means we need to convert the brightness
* argument into the matching level within that range.
*/
rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
brightness / (LED_FULL / 6),
led->rt2x00dev->led_mcu_reg,
REGISTER_TIMEOUT);
}
}
#else
#define rt73usb_led_brightness NULL
#endif /* CONFIG_RT73USB_LEDS */
/*
* Configuration handlers.
*/
static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
{
u32 tmp;
tmp = le32_to_cpu(mac[1]);
rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
mac[1] = cpu_to_le32(tmp);
rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
(2 * sizeof(__le32)));
}
static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
{
u32 tmp;
tmp = le32_to_cpu(bssid[1]);
rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
bssid[1] = cpu_to_le32(tmp);
rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
(2 * sizeof(__le32)));
}
static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
const int tsf_sync)
static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf,
const unsigned int flags)
{
unsigned int beacon_base;
u32 reg;
if (flags & CONFIG_UPDATE_TYPE) {
/*
* Clear current synchronisation setup.
* For the Beacon base registers we only need to clear
* the first byte since that byte contains the VALID and OWNER
* bits which (when set to 0) will invalidate the entire beacon.
*/
beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
rt73usb_register_write(rt2x00dev, beacon_base, 0);
/*
* Enable synchronisation.
@ -328,13 +356,32 @@ static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
(tsf_sync == TSF_SYNC_BEACON));
(conf->sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
if (flags & CONFIG_UPDATE_MAC) {
reg = le32_to_cpu(conf->mac[1]);
rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
conf->mac[1] = cpu_to_le32(reg);
rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
conf->mac, sizeof(conf->mac));
}
if (flags & CONFIG_UPDATE_BSSID) {
reg = le32_to_cpu(conf->bssid[1]);
rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
conf->bssid[1] = cpu_to_le32(reg);
rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
conf->bssid, sizeof(conf->bssid));
}
}
static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
static int rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
const int short_preamble,
const int ack_timeout,
const int ack_consume_time)
@ -342,13 +389,11 @@ static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
u32 reg;
/*
* When in atomic context, reschedule and let rt2x00lib
* call this function again.
* When in atomic context, we should let rt2x00lib
* try this configuration again later.
*/
if (in_atomic()) {
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
return;
}
if (in_atomic())
return -EAGAIN;
rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
@ -358,6 +403,8 @@ static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
!!short_preamble);
rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
return 0;
}
static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev,
@ -442,13 +489,13 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
&& (rt2x00dev->curr_hwmode != HWMODE_A);
&& (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
break;
case ANTENNA_A:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
if (rt2x00dev->curr_hwmode == HWMODE_A)
if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
else
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
@ -463,7 +510,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
case ANTENNA_B:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
if (rt2x00dev->curr_hwmode == HWMODE_A)
if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
else
rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
@ -558,7 +605,7 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
unsigned int i;
u32 reg;
if (rt2x00dev->curr_hwmode == HWMODE_A) {
if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
sel = antenna_sel_a;
lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
} else {
@ -572,10 +619,9 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
(rt2x00dev->curr_hwmode == HWMODE_B ||
rt2x00dev->curr_hwmode == HWMODE_G));
(rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
(rt2x00dev->curr_hwmode == HWMODE_A));
(rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
@ -617,8 +663,8 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
}
static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
struct rt2x00lib_conf *libconf)
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
if (flags & CONFIG_UPDATE_PHYMODE)
rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
@ -633,68 +679,6 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
rt73usb_config_duration(rt2x00dev, libconf);
}
/*
* LED functions.
*/
static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt73usb_register_read(rt2x00dev, MAC_CSR14, &reg);
rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
(rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
(rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
rt2x00dev->led_reg, REGISTER_TIMEOUT);
}
static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
{
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0);
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
rt2x00dev->led_reg, REGISTER_TIMEOUT);
}
static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
{
u32 led;
if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
return;
/*
* Led handling requires a positive value for the rssi,
* to do that correctly we need to add the correction.
*/
rssi += rt2x00dev->rssi_offset;
if (rssi <= 30)
led = 0;
else if (rssi <= 39)
led = 1;
else if (rssi <= 49)
led = 2;
else if (rssi <= 53)
led = 3;
else if (rssi <= 63)
led = 4;
else
led = 5;
rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led,
rt2x00dev->led_reg, REGISTER_TIMEOUT);
}
/*
* Link tuning
*/
@ -729,17 +713,12 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
u8 up_bound;
u8 low_bound;
/*
* Update Led strength
*/
rt73usb_activity_led(rt2x00dev, rssi);
rt73usb_bbp_read(rt2x00dev, 17, &r17);
/*
* Determine r17 bounds.
*/
if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
low_bound = 0x28;
up_bound = 0x48;
@ -765,6 +744,13 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
}
}
/*
* If we are not associated, we should go straight to the
* dynamic CCA tuning.
*/
if (!rt2x00dev->intf_associated)
goto dynamic_cca_tune;
/*
* Special big-R17 for very short distance
*/
@ -815,6 +801,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
return;
}
dynamic_cca_tune:
/*
* r17 does not yet exceed upper limit, continue and base
* the r17 tuning on the false CCA count.
@ -889,7 +877,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT,
FIRMWARE_IMAGE_BASE + i, 0x0000,
FIRMWARE_IMAGE_BASE + i, 0,
cache, buflen, timeout);
ptr += buflen;
@ -902,15 +890,13 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
* we need to specify a long timeout time.
*/
status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
0x0000, USB_MODE_FIRMWARE,
0, USB_MODE_FIRMWARE,
REGISTER_TIMEOUT_FIRMWARE);
if (status < 0) {
ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
return status;
}
rt73usb_disable_led(rt2x00dev);
return 0;
}
@ -988,6 +974,11 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
rt73usb_register_read(rt2x00dev, MAC_CSR14, &reg);
rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
/*
* Invalidate all Shared Keys (SEC_CSR0),
* and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
@ -1020,6 +1011,17 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
/*
* Clear all beacons
* For the Beacon base registers we only need to clear
* the first byte since that byte contains the VALID and OWNER
* bits which (when set to 0) will invalidate the entire beacon.
*/
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
/*
* We must clear the error counters.
* These registers are cleared on read,
@ -1094,19 +1096,15 @@ continue_csr_init:
rt73usb_bbp_write(rt2x00dev, 102, 0x16);
rt73usb_bbp_write(rt2x00dev, 107, 0x04);
DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
reg_id, value);
rt73usb_bbp_write(rt2x00dev, reg_id, value);
}
}
DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
return 0;
}
@ -1136,21 +1134,11 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
return -EIO;
}
/*
* Enable LED
*/
rt73usb_enable_led(rt2x00dev);
return 0;
}
static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
/*
* Disable LED
*/
rt73usb_disable_led(rt2x00dev);
rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
/*
@ -1234,10 +1222,10 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
*/
static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
struct sk_buff *skb,
struct txdata_entry_desc *desc,
struct txentry_desc *txdesc,
struct ieee80211_tx_control *control)
{
struct skb_desc *skbdesc = get_skb_desc(skb);
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txd = skbdesc->desc;
u32 word;
@ -1245,47 +1233,47 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
* Start writing the descriptor words.
*/
rt2x00_desc_read(txd, 1, &word);
rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
rt2x00_desc_write(txd, 1, word);
rt2x00_desc_read(txd, 2, &word);
rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 5, &word);
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
TXPOWER_TO_DEV(control->power_level));
TXPOWER_TO_DEV(rt2x00dev->tx_power));
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
rt2x00_desc_write(txd, 5, word);
rt2x00_desc_read(txd, 0, &word);
rt2x00_set_field32(&word, TXD_W0_BURST,
test_bit(ENTRY_TXD_BURST, &desc->flags));
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
test_bit(ENTRY_TXD_ACK, &desc->flags));
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_BURST2,
test_bit(ENTRY_TXD_BURST, &desc->flags));
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
@ -1309,11 +1297,11 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
* TX data initialization
*/
static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
unsigned int queue)
const unsigned int queue)
{
u32 reg;
if (queue != IEEE80211_TX_QUEUE_BEACON)
if (queue != RT2X00_BCN_QUEUE_BEACON)
return;
/*
@ -1353,7 +1341,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
return 0;
}
if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
if (lna == 3 || lna == 2)
offset += 10;
@ -1377,37 +1365,57 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
}
static void rt73usb_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
static void rt73usb_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct skb_desc *skbdesc = get_skb_desc(entry->skb);
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *rxd = (__le32 *)entry->skb->data;
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *)entry->skb->data + entry->queue->desc_size;
int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
u32 word0;
u32 word1;
rt2x00_desc_read(rxd, 0, &word0);
rt2x00_desc_read(rxd, 1, &word1);
desc->flags = 0;
rxdesc->flags = 0;
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
desc->flags |= RX_FLAG_FAILED_FCS_CRC;
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
/*
* Obtain the status about this packet.
*/
desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
/*
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/
if (header_size % 4 == 0) {
skb_push(entry->skb, 2);
memmove(entry->skb->data, entry->skb->data + 2,
entry->skb->len - 2);
}
/*
* Set descriptor and data pointer.
*/
skbdesc->data = entry->skb->data + entry->queue->desc_size;
skbdesc->data_len = rxdesc->size;
skbdesc->desc = entry->skb->data;
skbdesc->desc_len = entry->ring->desc_size;
skbdesc->data = entry->skb->data + entry->ring->desc_size;
skbdesc->data_len = desc->size;
skbdesc->desc_len = entry->queue->desc_size;
/*
* Remove descriptor from skb buffer and trim the whole thing
* down to only contain data.
*/
skb_pull(entry->skb, skbdesc->desc_len);
skb_trim(entry->skb, rxdesc->size);
}
/*
@ -1499,7 +1507,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
if (value < -10 || value > 10)
@ -1577,33 +1585,49 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Store led settings, for correct led behaviour.
*/
#ifdef CONFIG_RT73USB_LEDS
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
rt2x00dev->led_mode);
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
switch (value) {
case LED_MODE_TXRX_ACTIVITY:
case LED_MODE_ASUS:
case LED_MODE_ALPHA:
case LED_MODE_DEFAULT:
rt2x00dev->led_flags =
LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC;
break;
case LED_MODE_SIGNAL_STRENGTH:
rt2x00dev->led_flags =
LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC |
LED_SUPPORT_QUALITY;
break;
}
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_0));
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_1));
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_2));
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_3));
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_GPIO_4));
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_RDY_G));
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
rt2x00_get_field16(eeprom,
EEPROM_LED_POLARITY_RDY_A));
#endif /* CONFIG_RT73USB_LEDS */
return 0;
}
@ -1759,7 +1783,7 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
rt2x00dev->hw->max_signal = MAX_SIGNAL;
rt2x00dev->hw->max_rssi = MAX_RX_SSI;
rt2x00dev->hw->queues = 5;
rt2x00dev->hw->queues = 4;
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@ -1776,8 +1800,8 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize hw_mode information.
*/
spec->num_modes = 2;
spec->num_rates = 12;
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
spec->tx_power_a = NULL;
spec->tx_power_bg = txpower;
spec->tx_power_default = DEFAULT_TXPOWER;
@ -1786,20 +1810,20 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
spec->channels = rf_vals_bg_2528;
} else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5226);
spec->channels = rf_vals_5226;
} else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) {
spec->num_channels = 14;
spec->channels = rf_vals_5225_2527;
} else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
spec->supported_bands |= SUPPORT_BAND_5GHZ;
spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
spec->channels = rf_vals_5225_2527;
}
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
rt2x00_rf(&rt2x00dev->chip, RF5226)) {
spec->num_modes = 3;
txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
for (i = 0; i < 14; i++)
txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
@ -1829,9 +1853,10 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
rt73usb_probe_hw_mode(rt2x00dev);
/*
* This device requires firmware
* This device requires firmware.
*/
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags);
/*
* Set the rssi offset.
@ -1913,7 +1938,8 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw,
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
!(*total_flags & FIF_ALLMULTI));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
!(*total_flags & FIF_CONTROL));
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
}
@ -1955,61 +1981,54 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
#define rt73usb_get_tsf NULL
#endif
static void rt73usb_reset_tsf(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
rt73usb_register_write(rt2x00dev, TXRX_CSR12, 0);
rt73usb_register_write(rt2x00dev, TXRX_CSR13, 0);
}
static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct skb_desc *desc;
struct data_ring *ring;
struct data_entry *entry;
int timeout;
struct rt2x00_intf *intf = vif_to_intf(control->vif);
struct skb_frame_desc *skbdesc;
unsigned int beacon_base;
unsigned int timeout;
/*
* Just in case the ieee80211 doesn't set this,
* but we need this queue set for the descriptor
* initialization.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
entry = rt2x00_get_data_entry(ring);
if (unlikely(!intf->beacon))
return -ENOBUFS;
/*
* Add the descriptor in front of the skb.
*/
skb_push(skb, ring->desc_size);
memset(skb->data, 0, ring->desc_size);
skb_push(skb, intf->beacon->queue->desc_size);
memset(skb->data, 0, intf->beacon->queue->desc_size);
/*
* Fill in skb descriptor
*/
desc = get_skb_desc(skb);
desc->desc_len = ring->desc_size;
desc->data_len = skb->len - ring->desc_size;
desc->desc = skb->data;
desc->data = skb->data + ring->desc_size;
desc->ring = ring;
desc->entry = entry;
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
skbdesc->data = skb->data + intf->beacon->queue->desc_size;
skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
skbdesc->desc = skb->data;
skbdesc->desc_len = intf->beacon->queue->desc_size;
skbdesc->entry = intf->beacon;
/*
* mac80211 doesn't provide the control->queue variable
* for beacons. Set our own queue identification so
* it can be used during descriptor initialization.
*/
control->queue = RT2X00_BCN_QUEUE_BEACON;
rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Write entire beacon with descriptor to register,
* and kick the beacon generator.
*/
beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32));
rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT,
HW_BEACON_BASE0, 0x0000,
USB_VENDOR_REQUEST_OUT, beacon_base, 0,
skb->data, skb->len, timeout);
rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
rt73usb_kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
@ -2029,7 +2048,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt73usb_get_tsf,
.reset_tsf = rt73usb_reset_tsf,
.beacon_update = rt73usb_beacon_update,
};
@ -2045,24 +2063,47 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.link_stats = rt73usb_link_stats,
.reset_tuner = rt73usb_reset_tuner,
.link_tuner = rt73usb_link_tuner,
.led_brightness = rt73usb_led_brightness,
.write_tx_desc = rt73usb_write_tx_desc,
.write_tx_data = rt2x00usb_write_tx_data,
.get_tx_data_len = rt73usb_get_tx_data_len,
.kick_tx_queue = rt73usb_kick_tx_queue,
.fill_rxdone = rt73usb_fill_rxdone,
.config_mac_addr = rt73usb_config_mac_addr,
.config_bssid = rt73usb_config_bssid,
.config_type = rt73usb_config_type,
.config_intf = rt73usb_config_intf,
.config_preamble = rt73usb_config_preamble,
.config = rt73usb_config,
};
static const struct data_queue_desc rt73usb_queue_rx = {
.entry_num = RX_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb_rx),
};
static const struct data_queue_desc rt73usb_queue_tx = {
.entry_num = TX_ENTRIES,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb_tx),
};
static const struct data_queue_desc rt73usb_queue_bcn = {
.entry_num = 4 * BEACON_ENTRIES,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXINFO_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb_tx),
};
static const struct rt2x00_ops rt73usb_ops = {
.name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.max_sta_intf = 1,
.max_ap_intf = 4,
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
.rx = &rt73usb_queue_rx,
.tx = &rt73usb_queue_tx,
.bcn = &rt73usb_queue_bcn,
.lib = &rt73usb_rt2x00_ops,
.hw = &rt73usb_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@ -114,6 +114,9 @@ struct hw_pairwise_ta_entry {
#define HW_BEACON_BASE2 0x2600
#define HW_BEACON_BASE3 0x2700
#define HW_BEACON_OFFSET(__index) \
( HW_BEACON_BASE0 + (__index * 0x0100) )
/*
* MAC Control/Status Registers(CSR).
* Some values are set in TU, whereas 1 TU == 1024 us.
@ -146,6 +149,11 @@ struct hw_pairwise_ta_entry {
/*
* MAC_CSR3: STA MAC register 1.
* UNICAST_TO_ME_MASK:
* Used to mask off bits from byte 5 of the MAC address
* to determine the UNICAST_TO_ME bit for RX frames.
* The full mask is complemented by BSS_ID_MASK:
* MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
*/
#define MAC_CSR3 0x300c
#define MAC_CSR3_BYTE4 FIELD32(0x000000ff)
@ -163,7 +171,14 @@ struct hw_pairwise_ta_entry {
/*
* MAC_CSR5: BSSID register 1.
* BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID.
* BSS_ID_MASK:
* This mask is used to mask off bits 0 and 1 of byte 5 of the
* BSSID. This will make sure that those bits will be ignored
* when determining the MY_BSS of RX frames.
* 0: 1-BSSID mode (BSS index = 0)
* 1: 2-BSSID mode (BSS index: Byte5, bit 0)
* 2: 2-BSSID mode (BSS index: byte5, bit 1)
* 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
*/
#define MAC_CSR5 0x3014
#define MAC_CSR5_BYTE4 FIELD32(0x000000ff)
@ -867,6 +882,7 @@ struct hw_pairwise_ta_entry {
* DMA descriptor defines.
*/
#define TXD_DESC_SIZE ( 6 * sizeof(__le32) )
#define TXINFO_SIZE ( 6 * sizeof(__le32) )
#define RXD_DESC_SIZE ( 6 * sizeof(__le32) )
/*
@ -1007,8 +1023,8 @@ struct hw_pairwise_ta_entry {
#define RXD_W5_RESERVED FIELD32(0xffffffff)
/*
* Macro's for converting txpower from EEPROM to dscape value
* and from dscape value to register value.
* Macro's for converting txpower from EEPROM to mac80211 value
* and from mac80211 value to register value.
*/
#define MIN_TXPOWER 0
#define MAX_TXPOWER 31

Просмотреть файл

@ -102,7 +102,7 @@ struct rtl8180_priv {
struct rtl8180_tx_ring tx_ring[4];
struct ieee80211_channel channels[14];
struct ieee80211_rate rates[12];
struct ieee80211_hw_mode modes[2];
struct ieee80211_supported_band band;
struct pci_dev *pdev;
u32 rx_conf;

Просмотреть файл

@ -49,6 +49,41 @@ static struct pci_device_id rtl8180_table[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, rtl8180_table);
static const struct ieee80211_rate rtl818x_rates[] = {
{ .bitrate = 10, .hw_value = 0, },
{ .bitrate = 20, .hw_value = 1, },
{ .bitrate = 55, .hw_value = 2, },
{ .bitrate = 110, .hw_value = 3, },
{ .bitrate = 60, .hw_value = 4, },
{ .bitrate = 90, .hw_value = 5, },
{ .bitrate = 120, .hw_value = 6, },
{ .bitrate = 180, .hw_value = 7, },
{ .bitrate = 240, .hw_value = 8, },
{ .bitrate = 360, .hw_value = 9, },
{ .bitrate = 480, .hw_value = 10, },
{ .bitrate = 540, .hw_value = 11, },
};
static const struct ieee80211_channel rtl818x_channels[] = {
{ .center_freq = 2412 },
{ .center_freq = 2417 },
{ .center_freq = 2422 },
{ .center_freq = 2427 },
{ .center_freq = 2432 },
{ .center_freq = 2437 },
{ .center_freq = 2442 },
{ .center_freq = 2447 },
{ .center_freq = 2452 },
{ .center_freq = 2457 },
{ .center_freq = 2462 },
{ .center_freq = 2467 },
{ .center_freq = 2472 },
{ .center_freq = 2484 },
};
void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
{
struct rtl8180_priv *priv = dev->priv;
@ -99,10 +134,10 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
/* TODO: improve signal/rssi reporting */
rx_status.signal = flags2 & 0xFF;
rx_status.ssi = (flags2 >> 8) & 0x7F;
rx_status.rate = (flags >> 20) & 0xF;
rx_status.freq = dev->conf.freq;
rx_status.channel = dev->conf.channel;
rx_status.phymode = dev->conf.phymode;
/* XXX: is this correct? */
rx_status.rate_idx = (flags >> 20) & 0xF;
rx_status.freq = dev->conf.channel->center_freq;
rx_status.band = dev->conf.channel->band;
rx_status.mactime = le64_to_cpu(entry->tsft);
rx_status.flag |= RX_FLAG_TSFT;
if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR)
@ -222,18 +257,25 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
mapping = pci_map_single(priv->pdev, skb->data,
skb->len, PCI_DMA_TODEVICE);
BUG_ON(!control->tx_rate);
tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
RTL8180_TX_DESC_FLAG_LS | (control->tx_rate << 24) |
(control->rts_cts_rate << 19) | skb->len;
RTL8180_TX_DESC_FLAG_LS |
(control->tx_rate->hw_value << 24) | skb->len;
if (priv->r8185)
tx_flags |= RTL8180_TX_DESC_FLAG_DMA |
RTL8180_TX_DESC_FLAG_NO_ENC;
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
BUG_ON(!control->rts_cts_rate);
tx_flags |= RTL8180_TX_DESC_FLAG_RTS;
else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
tx_flags |= control->rts_cts_rate->hw_value << 19;
} else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
BUG_ON(!control->rts_cts_rate);
tx_flags |= RTL8180_TX_DESC_FLAG_CTS;
tx_flags |= control->rts_cts_rate->hw_value << 19;
}
*((struct ieee80211_tx_control **) skb->cb) =
kmemdup(control, sizeof(*control), GFP_ATOMIC);
@ -246,9 +288,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
unsigned int remainder;
plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
(control->rate->rate * 2) / 10);
(control->tx_rate->bitrate * 2) / 10);
remainder = (16 * (skb->len + 4)) %
((control->rate->rate * 2) / 10);
((control->tx_rate->bitrate * 2) / 10);
if (remainder > 0 && remainder <= 6)
plcp_len |= 1 << 15;
}
@ -261,8 +303,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
entry->plcp_len = cpu_to_le16(plcp_len);
entry->tx_buf = cpu_to_le32(mapping);
entry->frame_len = cpu_to_le32(skb->len);
entry->flags2 = control->alt_retry_rate != -1 ?
control->alt_retry_rate << 4 : 0;
entry->flags2 = control->alt_retry_rate != NULL ?
control->alt_retry_rate->bitrate << 4 : 0;
entry->retry_limit = control->retry_limit;
entry->flags = cpu_to_le32(tx_flags);
__skb_queue_tail(&ring->queue, skb);
@ -838,19 +880,19 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
goto err_free_dev;
}
BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
priv->modes[0].mode = MODE_IEEE80211G;
priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
priv->modes[0].rates = priv->rates;
priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
priv->modes[0].channels = priv->channels;
priv->modes[1].mode = MODE_IEEE80211B;
priv->modes[1].num_rates = 4;
priv->modes[1].rates = priv->rates;
priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
priv->modes[1].channels = priv->channels;
priv->mode = IEEE80211_IF_TYPE_INVALID;
priv->band.band = IEEE80211_BAND_2GHZ;
priv->band.channels = priv->channels;
priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
priv->band.bitrates = priv->rates;
priv->band.n_bitrates = 4;
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_RX_INCLUDES_FCS;
dev->queues = 1;
@ -879,15 +921,10 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
if (priv->r8185) {
if ((err = ieee80211_register_hwmode(dev, &priv->modes[0])))
goto err_iounmap;
priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
pci_try_set_mwi(pdev);
}
if ((err = ieee80211_register_hwmode(dev, &priv->modes[1])))
goto err_iounmap;
eeprom.data = dev;
eeprom.register_read = rtl8180_eeprom_register_read;
eeprom.register_write = rtl8180_eeprom_register_write;
@ -950,8 +987,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
for (i = 0; i < 14; i += 2) {
u16 txpwr;
eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr);
priv->channels[i].val = txpwr & 0xFF;
priv->channels[i + 1].val = txpwr >> 8;
priv->channels[i].hw_value = txpwr & 0xFF;
priv->channels[i + 1].hw_value = txpwr >> 8;
}
/* OFDM TX power */
@ -959,8 +996,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
for (i = 0; i < 14; i += 2) {
u16 txpwr;
eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr);
priv->channels[i].val |= (txpwr & 0xFF) << 8;
priv->channels[i + 1].val |= txpwr & 0xFF00;
priv->channels[i].hw_value |= (txpwr & 0xFF) << 8;
priv->channels[i + 1].hw_value |= txpwr & 0xFF00;
}
}

Просмотреть файл

@ -73,8 +73,9 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
u32 chan = conf->channel - 1;
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
u32 chan = channel - 1;
/* set TX power */
write_grf5101(dev, 0x15, 0x0);

Просмотреть файл

@ -78,8 +78,9 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
unsigned int chan_idx = conf ? conf->channel - 1 : 0;
u32 txpw = priv->channels[chan_idx].val & 0xFF;
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
unsigned int chan_idx = channel - 1;
u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
u32 chan = max2820_chan[chan_idx];
/* While philips SA2400 drive the PA bias from

Просмотреть файл

@ -261,8 +261,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
u32 reg;
int i;
cck_power = priv->channels[channel - 1].val & 0xFF;
ofdm_power = priv->channels[channel - 1].val >> 8;
cck_power = priv->channels[channel - 1].hw_value & 0xFF;
ofdm_power = priv->channels[channel - 1].hw_value >> 8;
cck_power = min(cck_power, (u8)35);
ofdm_power = min(ofdm_power, (u8)35);
@ -476,8 +476,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
const u8 *tmp;
int i;
cck_power = priv->channels[channel - 1].val & 0xFF;
ofdm_power = priv->channels[channel - 1].val >> 8;
cck_power = priv->channels[channel - 1].hw_value & 0xFF;
ofdm_power = priv->channels[channel - 1].hw_value >> 8;
if (channel == 14)
tmp = rtl8225z2_tx_power_cck_ch14;
@ -716,13 +716,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
if (priv->rf->init == rtl8225_rf_init)
rtl8225_rf_set_tx_power(dev, conf->channel);
rtl8225_rf_set_tx_power(dev, chan);
else
rtl8225z2_rf_set_tx_power(dev, conf->channel);
rtl8225z2_rf_set_tx_power(dev, chan);
rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
msleep(10);
if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {

Просмотреть файл

@ -80,8 +80,9 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
u32 chan = sa2400_chan[conf->channel - 1];
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
u32 chan = sa2400_chan[channel - 1];
write_sa2400(dev, 7, txpw);

Просмотреть файл

@ -71,7 +71,7 @@ struct rtl8187_priv {
/* rtl8187 specific */
struct ieee80211_channel channels[14];
struct ieee80211_rate rates[12];
struct ieee80211_hw_mode modes[2];
struct ieee80211_supported_band band;
struct usb_device *udev;
u32 rx_conf;
u16 txpwr_base;

Просмотреть файл

@ -45,6 +45,38 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
MODULE_DEVICE_TABLE(usb, rtl8187_table);
static const struct ieee80211_rate rtl818x_rates[] = {
{ .bitrate = 10, .hw_value = 0, },
{ .bitrate = 20, .hw_value = 1, },
{ .bitrate = 55, .hw_value = 2, },
{ .bitrate = 110, .hw_value = 3, },
{ .bitrate = 60, .hw_value = 4, },
{ .bitrate = 90, .hw_value = 5, },
{ .bitrate = 120, .hw_value = 6, },
{ .bitrate = 180, .hw_value = 7, },
{ .bitrate = 240, .hw_value = 8, },
{ .bitrate = 360, .hw_value = 9, },
{ .bitrate = 480, .hw_value = 10, },
{ .bitrate = 540, .hw_value = 11, },
};
static const struct ieee80211_channel rtl818x_channels[] = {
{ .center_freq = 2412 },
{ .center_freq = 2417 },
{ .center_freq = 2422 },
{ .center_freq = 2427 },
{ .center_freq = 2432 },
{ .center_freq = 2437 },
{ .center_freq = 2442 },
{ .center_freq = 2447 },
{ .center_freq = 2452 },
{ .center_freq = 2457 },
{ .center_freq = 2462 },
{ .center_freq = 2467 },
{ .center_freq = 2472 },
{ .center_freq = 2484 },
};
static void rtl8187_iowrite_async_cb(struct urb *urb)
{
kfree(urb->context);
@ -146,17 +178,23 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
flags = skb->len;
flags |= RTL8187_TX_FLAG_NO_ENCRYPT;
flags |= control->rts_cts_rate << 19;
flags |= control->tx_rate << 24;
BUG_ON(!control->tx_rate);
flags |= control->tx_rate->hw_value << 24;
if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data))
flags |= RTL8187_TX_FLAG_MORE_FRAG;
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
BUG_ON(!control->rts_cts_rate);
flags |= RTL8187_TX_FLAG_RTS;
flags |= control->rts_cts_rate->hw_value << 19;
rts_dur = ieee80211_rts_duration(dev, priv->vif,
skb->len, control);
}
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
} else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
BUG_ON(!control->rts_cts_rate);
flags |= RTL8187_TX_FLAG_CTS;
flags |= control->rts_cts_rate->hw_value << 19;
}
hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
hdr->flags = cpu_to_le32(flags);
@ -225,10 +263,9 @@ static void rtl8187_rx_cb(struct urb *urb)
rx_status.antenna = (hdr->signal >> 7) & 1;
rx_status.signal = 64 - min(hdr->noise, (u8)64);
rx_status.ssi = signal;
rx_status.rate = rate;
rx_status.freq = dev->conf.freq;
rx_status.channel = dev->conf.channel;
rx_status.phymode = dev->conf.phymode;
rx_status.rate_idx = rate;
rx_status.freq = dev->conf.channel->center_freq;
rx_status.band = dev->conf.channel->band;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
rx_status.flag |= RX_FLAG_TSFT;
if (flags & (1 << 13))
@ -682,19 +719,22 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
usb_get_dev(udev);
skb_queue_head_init(&priv->rx_queue);
BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
priv->map = (struct rtl818x_csr *)0xFF00;
priv->modes[0].mode = MODE_IEEE80211G;
priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
priv->modes[0].rates = priv->rates;
priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
priv->modes[0].channels = priv->channels;
priv->modes[1].mode = MODE_IEEE80211B;
priv->modes[1].num_rates = 4;
priv->modes[1].rates = priv->rates;
priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
priv->modes[1].channels = priv->channels;
priv->band.band = IEEE80211_BAND_2GHZ;
priv->band.channels = priv->channels;
priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
priv->band.bitrates = priv->rates;
priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
priv->mode = IEEE80211_IF_TYPE_MNTR;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_RX_INCLUDES_FCS;
@ -703,10 +743,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
dev->max_rssi = 65;
dev->max_signal = 64;
for (i = 0; i < 2; i++)
if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
goto err_free_dev;
eeprom.data = dev;
eeprom.register_read = rtl8187_eeprom_register_read;
eeprom.register_write = rtl8187_eeprom_register_write;
@ -730,20 +766,20 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
for (i = 0; i < 3; i++) {
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
&txpwr);
(*channel++).val = txpwr & 0xFF;
(*channel++).val = txpwr >> 8;
(*channel++).hw_value = txpwr & 0xFF;
(*channel++).hw_value = txpwr >> 8;
}
for (i = 0; i < 2; i++) {
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
&txpwr);
(*channel++).val = txpwr & 0xFF;
(*channel++).val = txpwr >> 8;
(*channel++).hw_value = txpwr & 0xFF;
(*channel++).hw_value = txpwr >> 8;
}
for (i = 0; i < 2; i++) {
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
&txpwr);
(*channel++).val = txpwr & 0xFF;
(*channel++).val = txpwr >> 8;
(*channel++).hw_value = txpwr & 0xFF;
(*channel++).hw_value = txpwr >> 8;
}
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,

Просмотреть файл

@ -283,8 +283,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
u32 reg;
int i;
cck_power = priv->channels[channel - 1].val & 0xF;
ofdm_power = priv->channels[channel - 1].val >> 4;
cck_power = priv->channels[channel - 1].hw_value & 0xF;
ofdm_power = priv->channels[channel - 1].hw_value >> 4;
cck_power = min(cck_power, (u8)11);
ofdm_power = min(ofdm_power, (u8)35);
@ -500,8 +500,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
u32 reg;
int i;
cck_power = priv->channels[channel - 1].val & 0xF;
ofdm_power = priv->channels[channel - 1].val >> 4;
cck_power = priv->channels[channel - 1].hw_value & 0xF;
ofdm_power = priv->channels[channel - 1].hw_value >> 4;
cck_power = min(cck_power, (u8)15);
cck_power += priv->txpwr_base & 0xF;
@ -735,13 +735,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
if (priv->rf->init == rtl8225_rf_init)
rtl8225_rf_set_tx_power(dev, conf->channel);
rtl8225_rf_set_tx_power(dev, chan);
else
rtl8225z2_rf_set_tx_power(dev, conf->channel);
rtl8225z2_rf_set_tx_power(dev, chan);
rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
msleep(10);
}

Просмотреть файл

@ -175,74 +175,4 @@ struct rtl818x_rf_ops {
void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
};
static const struct ieee80211_rate rtl818x_rates[] = {
{ .rate = 10,
.val = 0,
.flags = IEEE80211_RATE_CCK },
{ .rate = 20,
.val = 1,
.flags = IEEE80211_RATE_CCK },
{ .rate = 55,
.val = 2,
.flags = IEEE80211_RATE_CCK },
{ .rate = 110,
.val = 3,
.flags = IEEE80211_RATE_CCK },
{ .rate = 60,
.val = 4,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 90,
.val = 5,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 120,
.val = 6,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 180,
.val = 7,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 240,
.val = 8,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 360,
.val = 9,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 480,
.val = 10,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 540,
.val = 11,
.flags = IEEE80211_RATE_OFDM },
};
static const struct ieee80211_channel rtl818x_channels[] = {
{ .chan = 1,
.freq = 2412},
{ .chan = 2,
.freq = 2417},
{ .chan = 3,
.freq = 2422},
{ .chan = 4,
.freq = 2427},
{ .chan = 5,
.freq = 2432},
{ .chan = 6,
.freq = 2437},
{ .chan = 7,
.freq = 2442},
{ .chan = 8,
.freq = 2447},
{ .chan = 9,
.freq = 2452},
{ .chan = 10,
.freq = 2457},
{ .chan = 11,
.freq = 2462},
{ .chan = 12,
.freq = 2467},
{ .chan = 13,
.freq = 2472},
{ .chan = 14,
.freq = 2484}
};
#endif /* RTL818X_H */

Просмотреть файл

@ -962,12 +962,12 @@ static char *time_delta(char buffer[], long time)
/* get Nth element of the linked list */
static struct strip *strip_get_idx(loff_t pos)
{
struct list_head *l;
struct strip *str;
int i = 0;
list_for_each_rcu(l, &strip_list) {
list_for_each_entry_rcu(str, &strip_list, list) {
if (pos == i)
return list_entry(l, struct strip, list);
return str;
++i;
}
return NULL;

Просмотреть файл

@ -771,10 +771,10 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip)
{
static const struct zd_ioreq32 ioreqs[] = {
{ CR_ZD1211B_RETRY_MAX, 0x02020202 },
{ CR_ZD1211B_TX_PWR_CTL4, 0x007f003f },
{ CR_ZD1211B_TX_PWR_CTL3, 0x007f003f },
{ CR_ZD1211B_TX_PWR_CTL2, 0x003f001f },
{ CR_ZD1211B_TX_PWR_CTL1, 0x001f000f },
{ CR_ZD1211B_CWIN_MAX_MIN_AC0, 0x007f003f },
{ CR_ZD1211B_CWIN_MAX_MIN_AC1, 0x007f003f },
{ CR_ZD1211B_CWIN_MAX_MIN_AC2, 0x003f001f },
{ CR_ZD1211B_CWIN_MAX_MIN_AC3, 0x001f000f },
{ CR_ZD1211B_AIFS_CTL1, 0x00280028 },
{ CR_ZD1211B_AIFS_CTL2, 0x008C003C },
{ CR_ZD1211B_TXOP, 0x01800824 },
@ -986,7 +986,7 @@ static int print_fw_version(struct zd_chip *chip)
return 0;
}
static int set_mandatory_rates(struct zd_chip *chip, int mode)
static int set_mandatory_rates(struct zd_chip *chip, int gmode)
{
u32 rates;
ZD_ASSERT(mutex_is_locked(&chip->mutex));
@ -994,17 +994,12 @@ static int set_mandatory_rates(struct zd_chip *chip, int mode)
* that the device is supporting. Until further notice we should try
* to support 802.11g also for full speed USB.
*/
switch (mode) {
case MODE_IEEE80211B:
if (!gmode)
rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
break;
case MODE_IEEE80211G:
else
rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
break;
default:
return -EINVAL;
}
return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
}
@ -1108,7 +1103,7 @@ int zd_chip_init_hw(struct zd_chip *chip)
* It might be discussed, whether we should suppport pure b mode for
* full speed USB.
*/
r = set_mandatory_rates(chip, MODE_IEEE80211G);
r = set_mandatory_rates(chip, 1);
if (r)
goto out;
/* Disabling interrupts is certainly a smart thing here.

Просмотреть файл

@ -625,11 +625,10 @@ enum {
#define CR_S_MD CTL_REG(0x0830)
#define CR_USB_DEBUG_PORT CTL_REG(0x0888)
#define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00)
#define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04)
#define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08)
#define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c)
#define CR_ZD1211B_CWIN_MAX_MIN_AC0 CTL_REG(0x0b00)
#define CR_ZD1211B_CWIN_MAX_MIN_AC1 CTL_REG(0x0b04)
#define CR_ZD1211B_CWIN_MAX_MIN_AC2 CTL_REG(0x0b08)
#define CR_ZD1211B_CWIN_MAX_MIN_AC3 CTL_REG(0x0b0c)
#define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10)
#define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14)
#define CR_ZD1211B_TXOP CTL_REG(0x0b20)

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше