Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.26
This commit is contained in:
Коммит
4a80f27889
|
@ -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);
|
||||
|
@ -513,32 +515,43 @@ ath5k_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
/* 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, ®);
|
||||
|
||||
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) {
|
||||
rt2x00_set_field32(®, LEDCSR_LINK, enabled);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, BCNCSR1_PRELOAD,
|
||||
PREAMBLE + get_duration(IEEE80211_HEADER, 20));
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
|
||||
rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
|
||||
rt2x00_set_field32(®, CSR14_TBCN,
|
||||
(conf->sync == TSF_SYNC_BEACON));
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
|
||||
rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync);
|
||||
rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
|
||||
}
|
||||
|
||||
static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
|
||||
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 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(®, ARCSR5_SERVICE, 0x84);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, CSR11_CWMIN, params->cw_min);
|
||||
rt2x00_set_field32(®, CSR11_CWMAX, params->cw_max);
|
||||
rt2x00_set_field32(®, CSR11_CWMIN, cw_min);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
|
||||
rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70);
|
||||
rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30);
|
||||
rt2x00_set_field32(®, LEDCSR_LINK,
|
||||
(rt2x00dev->led_mode != LED_MODE_ASUS));
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, LEDCSR_LINK, 0);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, TXCSR2_TXD_SIZE,
|
||||
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_TXD,
|
||||
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_ATIM,
|
||||
rt2x00dev->bcn[1].stats.limit);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_PRIO,
|
||||
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
|
||||
rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER,
|
||||
rt2x00dev->bcn[0].data_dma);
|
||||
priv_tx->desc_dma);
|
||||
rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, RXCSR1, ®);
|
||||
rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
|
||||
rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER,
|
||||
rt2x00dev->rx->data_dma);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70);
|
||||
rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30);
|
||||
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, ARCSR0, ®);
|
||||
|
@ -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, ®);
|
||||
if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
|
||||
|
@ -1059,56 +1052,56 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(®, TXCSR0_KICK_TX,
|
||||
(queue == IEEE80211_TX_QUEUE_DATA1));
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
|
||||
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) {
|
||||
rt2x00_set_field32(®, LEDCSR_LINK, enabled);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, BCNCSR1_PRELOAD,
|
||||
PREAMBLE + get_duration(IEEE80211_HEADER, 20));
|
||||
rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN,
|
||||
rt2x00lib_get_ring(rt2x00dev,
|
||||
IEEE80211_TX_QUEUE_BEACON)
|
||||
->tx_params.cw_min);
|
||||
rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
|
||||
rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
|
||||
rt2x00_set_field32(®, CSR14_TBCN,
|
||||
(conf->sync == TSF_SYNC_BEACON));
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
|
||||
rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync);
|
||||
rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
|
||||
}
|
||||
|
||||
static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
|
||||
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 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(®, ARCSR5_SERVICE, 0x84);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
|
||||
rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70);
|
||||
rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30);
|
||||
rt2x00_set_field32(®, LEDCSR_LINK,
|
||||
(rt2x00dev->led_mode != LED_MODE_ASUS));
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, LEDCSR_LINK, 0);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, TXCSR2_TXD_SIZE,
|
||||
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_TXD,
|
||||
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_ATIM,
|
||||
rt2x00dev->bcn[1].stats.limit);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_PRIO,
|
||||
rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
|
||||
rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
|
||||
rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER,
|
||||
rt2x00dev->bcn[0].data_dma);
|
||||
priv_tx->desc_dma);
|
||||
rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, RXCSR1, ®);
|
||||
rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
|
||||
rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER,
|
||||
rt2x00dev->rx->data_dma);
|
||||
rt2x00_set_field32(®, 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(®, CSR11_CW_SELECT, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, LEDCSR, ®);
|
||||
rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70);
|
||||
rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30);
|
||||
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, CNT3, 0);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, TXCSR8, ®);
|
||||
|
@ -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, ®);
|
||||
if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
|
||||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
|
||||
|
@ -1211,53 +1205,53 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(®, TXCSR0_KICK_TX,
|
||||
(queue == IEEE80211_TX_QUEUE_DATA1));
|
||||
rt2x00_set_field32(®, 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, ®);
|
||||
rt2x00_set_field16(®, TXRX_CSR20_OFFSET,
|
||||
(PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6);
|
||||
if (type == IEEE80211_IF_TYPE_STA)
|
||||
rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
|
||||
else
|
||||
rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 2);
|
||||
rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6);
|
||||
rt2x00_set_field16(®, 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, ®);
|
||||
rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1);
|
||||
rt2x00_set_field16(®, TXRX_CSR19_TBCN,
|
||||
(tsf_sync == TSF_SYNC_BEACON));
|
||||
(conf->sync == TSF_SYNC_BEACON));
|
||||
rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0);
|
||||
rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, tsf_sync);
|
||||
rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync);
|
||||
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
|
||||
}
|
||||
|
||||
static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
|
||||
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 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, ®);
|
||||
rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout);
|
||||
|
@ -358,21 +383,14 @@ static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field16(®, 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, ®);
|
||||
rt2x00_set_field16(®, 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, ®);
|
||||
rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, 70);
|
||||
rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, 30);
|
||||
rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
|
||||
|
||||
rt2500usb_register_read(rt2x00dev, MAC_CSR20, ®);
|
||||
rt2x00_set_field16(®, MAC_CSR20_LINK,
|
||||
(rt2x00dev->led_mode != LED_MODE_ASUS));
|
||||
rt2x00_set_field16(®, 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, ®);
|
||||
rt2x00_set_field16(®, MAC_CSR20_LINK, 0);
|
||||
rt2x00_set_field16(®, 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(®, MAC_CSR1_HOST_READY, 0);
|
||||
rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
|
||||
|
||||
rt2500usb_register_read(rt2x00dev, MAC_CSR21, ®);
|
||||
rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, 70);
|
||||
rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, 30);
|
||||
rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
|
||||
|
||||
rt2500usb_register_read(rt2x00dev, TXRX_CSR5, ®);
|
||||
rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0, 13);
|
||||
rt2x00_set_field16(®, 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, ®);
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
static inline int is_interface_present(struct interface *intf)
|
||||
{
|
||||
return !!intf->id;
|
||||
}
|
||||
|
||||
static inline int is_interface_type(struct interface *intf, int type)
|
||||
{
|
||||
return intf->type == type;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
|
||||
{
|
||||
return (struct rt2x00_intf *)vif->drv_priv;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct hw_mode_spec: Hardware specifications structure
|
||||
*
|
||||
* Details about the supported modes, rates and channels
|
||||
* of a particular chipset. This is used by rt2x00lib
|
||||
* to build the ieee80211_hw_mode array for mac80211.
|
||||
*
|
||||
* @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
|
||||
* @supported_rates: Rate types which are supported (CCK, OFDM).
|
||||
* @num_channels: Number of supported channels. This is used as array size
|
||||
* for @tx_power_a, @tx_power_bg and @channels.
|
||||
* channels: Device/chipset specific channel values (See &struct rf_channel).
|
||||
* @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
|
||||
* @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
|
||||
* @tx_power_default: Default TX power value to use when either
|
||||
* @tx_power_a or @tx_power_bg is missing.
|
||||
*/
|
||||
struct hw_mode_spec {
|
||||
/*
|
||||
* Number of modes, rates and channels.
|
||||
*/
|
||||
int num_modes;
|
||||
int num_rates;
|
||||
int num_channels;
|
||||
unsigned int supported_bands;
|
||||
#define SUPPORT_BAND_2GHZ 0x00000001
|
||||
#define SUPPORT_BAND_5GHZ 0x00000002
|
||||
|
||||
unsigned int supported_rates;
|
||||
#define SUPPORT_RATE_CCK 0x00000001
|
||||
#define SUPPORT_RATE_OFDM 0x00000002
|
||||
|
||||
unsigned int num_channels;
|
||||
const struct rf_channel *channels;
|
||||
|
||||
/*
|
||||
* txpower values.
|
||||
*/
|
||||
const u8 *tx_power_a;
|
||||
const u8 *tx_power_bg;
|
||||
u8 tx_power_default;
|
||||
|
||||
/*
|
||||
* Device/chipset specific value.
|
||||
*/
|
||||
const struct rf_channel *channels;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -599,6 +644,8 @@ struct rt2x00_dev {
|
|||
void *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(®, 0, sizeof(reg));
|
||||
if (mac)
|
||||
memcpy(®, mac, ETH_ALEN);
|
||||
|
||||
rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, ®[0]);
|
||||
}
|
||||
|
||||
void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
|
||||
{
|
||||
__le32 reg[2];
|
||||
|
||||
memset(®, 0, sizeof(reg));
|
||||
if (bssid)
|
||||
memcpy(®, bssid, ETH_ALEN);
|
||||
|
||||
rt2x00dev->ops->lib->config_bssid(rt2x00dev, ®[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));
|
||||
|
||||
if (header_size % 4 == 0) {
|
||||
skb_push(entry->skb, 2);
|
||||
memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
|
||||
return skb;
|
||||
}
|
||||
|
||||
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, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE,
|
||||
(tsf_sync == TSF_SYNC_BEACON));
|
||||
(conf->sync == TSF_SYNC_BEACON));
|
||||
rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync);
|
||||
rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync);
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
}
|
||||
|
||||
static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
|
||||
if (flags & CONFIG_UPDATE_MAC) {
|
||||
reg = le32_to_cpu(conf->mac[1]);
|
||||
rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
|
||||
conf->mac[1] = cpu_to_le32(reg);
|
||||
|
||||
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(®, 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 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, ®);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
|
||||
|
@ -358,6 +403,8 @@ static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(®, 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, ®);
|
||||
|
||||
rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG,
|
||||
(rt2x00dev->curr_hwmode == HWMODE_B ||
|
||||
rt2x00dev->curr_hwmode == HWMODE_G));
|
||||
(rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
|
||||
rt2x00_set_field32(®, PHY_CSR0_PA_PE_A,
|
||||
(rt2x00dev->curr_hwmode == HWMODE_A));
|
||||
(rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
|
||||
|
||||
rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
|
||||
|
||||
|
@ -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, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70);
|
||||
rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
|
||||
|
||||
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
|
||||
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
|
||||
(rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
|
||||
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
|
||||
(rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
|
||||
|
||||
rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
|
||||
rt2x00dev->led_reg, REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0);
|
||||
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
|
||||
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
|
||||
|
||||
rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
|
||||
rt2x00dev->led_reg, REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
|
||||
{
|
||||
u32 led;
|
||||
|
||||
if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Led handling requires a positive value for the rssi,
|
||||
* to do that correctly we need to add the correction.
|
||||
*/
|
||||
rssi += rt2x00dev->rssi_offset;
|
||||
|
||||
if (rssi <= 30)
|
||||
led = 0;
|
||||
else if (rssi <= 39)
|
||||
led = 1;
|
||||
else if (rssi <= 49)
|
||||
led = 2;
|
||||
else if (rssi <= 53)
|
||||
led = 3;
|
||||
else if (rssi <= 63)
|
||||
led = 4;
|
||||
else
|
||||
led = 5;
|
||||
|
||||
rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led,
|
||||
rt2x00dev->led_reg, REGISTER_TIMEOUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Link tuning
|
||||
*/
|
||||
|
@ -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, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70);
|
||||
rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
|
||||
|
||||
/*
|
||||
* Invalidate all Shared Keys (SEC_CSR0),
|
||||
* and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
|
||||
|
@ -1020,6 +1011,17 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
|||
rt2x00_set_field32(®, 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(®, TXRX_CSR0_DROP_MULTICAST,
|
||||
!(*total_flags & FIF_ALLMULTI));
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1);
|
||||
rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS,
|
||||
!(*total_flags & FIF_CONTROL));
|
||||
rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче