Commit d8ee398d authored by Luis R. Rodriguez's avatar Luis R. Rodriguez Committed by John W. Linville
Browse files

ath5k: Port to new bitrate/channel API



Author: Nick Kossifidis <mickflemm@gmail.com>

Tested on 5211, 5213+5112, 5213A+2112A and it wors fine.

Also i figured out a way to process rate vallue found
on status descriptors, it's still buggy but we are getting
closer (i think it improved stability a little).

Changes to hw.c, initvals.c, phy.c
Changes-licensed-under: ISC

Changes to ath5k.h, base.c, base.h
Changes-licensed-under: 3-Clause-BSD
Acked-by: default avatarJiri Slaby <jirislaby@gmail.com>
Signed-off-by: default avatarNick Kossifidis <mickflemm@gmail.com>
Signed-off-by: default avatarLuis R. Rodriguez <mcgrof@winlab.rutgers.edu>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 406f2388
......@@ -735,7 +735,6 @@ config P54_PCI
config ATH5K
tristate "Atheros 5xxx wireless cards support"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
depends on BROKEN
---help---
This module adds support for wireless adapters based on
Atheros 5xxx chipset.
......
ath5k-objs = base.o hw.o regdom.o initvals.o phy.o debug.o
ath5k-objs = base.o hw.o initvals.o phy.o 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,18 +250,20 @@ 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 HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE)
#define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
/****************\
......@@ -560,8 +561,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 +585,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 +644,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 +710,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 } } \
}
/*
......@@ -895,7 +897,7 @@ 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 +909,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 +1123,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);
......
......@@ -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);
......@@ -515,12 +517,12 @@ ath5k_pci_probe(struct pci_dev *pdev,
/* Single chip radio (!RF5111) */
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),
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)){
} 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),
sc->ah->ah_radio_5ghz_revision);
......@@ -693,11 +695,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 +842,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 +858,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 +882,26 @@ 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);
/* Check if channel is supported by the chipset */
if (!ath5k_channel_ok(ah, f, chfreq))
continue;
ch = i + 1 ;
freq = ath5k_ieee2mhz(ch);
/* Match regulation domain */
if (!all && !(IEEE80211_DMN(chans[i].domain) &
IEEE80211_DMN(dmn)))
/* Check if channel is supported by the chipset */
if (!ath5k_channel_ok(ah, freq, chfreq))
continue;
if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode)
continue;
/* Write channel info and increment counter */
channels[count].center_freq = freq;
if((mode == AR5K_MODE_11A) ||
(mode == AR5K_MODE_11G)){
channels[count].hw_value = chfreq|CHANNEL_OFDM;
} else if((mode == AR5K_MODE_11A_TURBO) ||
(mode == AR5K_MODE_11G_TURBO)){
channels[count].hw_value = chfreq|CHANNEL_OFDM|CHANNEL_TURBO;
}if(mode == AR5K_MODE_11B) {
channels[count].hw_value = CHANNEL_B;
}
/* Write channel and increment counter */
channels->chan = ch;
channels->freq = f;
channels->val = map[mode].chan;
channels++;
count++;
max--;
}
......@@ -927,95 +909,76 @@ 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)
static int
ath5k_getchannels(struct ieee80211_hw *hw)
{
struct ath5k_softc *sc = hw->priv;
struct ieee80211_hw_mode *modes = sc->modes;
unsigned int i;
int ret;
struct ath5k_hw *ah = sc->ah;
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;
if (!test_bit(m, sc->ah->ah_capabilities.cap_mode))
return 0;
BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
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;
max_r = ARRAY_SIZE(sc->rates);
max_c = ARRAY_SIZE(sc->channels);
count_r = count_c = 0;
/* 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;
}
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;
if(mode2g > 0){
struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_2GHZ];
BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
sband->bitrates = sc->rates;
sband->channels = sc->channels;
/* The order here does not matter */
modes[0].mode = MODE_IEEE80211G;
modes[1].mode = MODE_IEEE80211B;
modes[2].mode = MODE_IEEE80211A;
sband->band = IEEE80211_BAND_2GHZ;
sband->n_channels = ath5k_copy_channels(ah, sband->channels,
mode2g, max_c);
max_r = ARRAY_SIZE(sc->rates);
max_c = ARRAY_SIZE(sc->channels);
hw_rates = ath5k_hw_get_rate_table(ah, mode2g);
sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
hw_rates,max_r);
for (i = 0; i < NUM_DRIVER_MODES; i++) {
struct ieee80211_hw_mode *mode = &modes[i];
const struct ath5k_rate_table *hw_rates;
count_c = sband->n_channels;
count_r = sband->n_bitrates;
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];
}
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
max_r -= count_r;
max_c -= count_c;
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;
}
/* 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;
}
/* FIXME: ath5k_debug_dump_modes(sc, modes); */
return 0;
}
/*
......@@ -1030,11 +993,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 +1011,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 +1048,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 +1091,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 +1108,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 +1136,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){