Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -735,7 +735,6 @@ config P54_PCI
config ATH5K
config ATH5K
	tristate "Atheros 5xxx wireless cards support"
	tristate "Atheros 5xxx wireless cards support"
	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
	depends on BROKEN
	---help---
	---help---
	  This module adds support for wireless adapters based on
	  This module adds support for wireless adapters based on
	  Atheros 5xxx chipset.
	  Atheros 5xxx chipset.
+1 −1
Original line number Original line Diff line number Diff line
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
obj-$(CONFIG_ATH5K)	+= ath5k.o
+46 −54
Original line number Original line Diff line number Diff line
@@ -30,7 +30,6 @@
#include <net/mac80211.h>
#include <net/mac80211.h>


#include "hw.h"
#include "hw.h"
#include "regdom.h"


/* PCI IDs */
/* PCI IDs */
#define PCI_DEVICE_ID_ATHEROS_AR5210 		0x0007 /* AR5210 */
#define PCI_DEVICE_ID_ATHEROS_AR5210 		0x0007 /* AR5210 */
@@ -251,18 +250,20 @@ struct ath5k_srev_name {
 */
 */
#define MODULATION_TURBO	0x00000080
#define MODULATION_TURBO	0x00000080


enum ath5k_vendor_mode {
enum ath5k_driver_mode {
	MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1,
	AR5K_MODE_11A		=	0,
	MODE_ATHEROS_TURBOG
	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 */
/* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
#define AR5K_SET_SHORT_PREAMBLE 0x04
#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)
#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
 * Used internaly in OpenHAL (ar5211.c/ar5212.c
 * for reset_tx_queue). Also see struct struct ieee80211_channel.
 * for reset_tx_queue). Also see struct struct ieee80211_channel.
 */
 */
#define IS_CHAN_XR(_c)	((_c.val & CHANNEL_XR) != 0)
#define IS_CHAN_XR(_c)	((_c.hw_value & CHANNEL_XR) != 0)
#define IS_CHAN_B(_c)	((_c.val & CHANNEL_B) != 0)
#define IS_CHAN_B(_c)	((_c.hw_value & CHANNEL_B) != 0)


/*
/*
 * The following structure will be used to map 2GHz channels to
 * The following structure will be used to map 2GHz channels to
@@ -584,7 +585,7 @@ struct ath5k_athchan_2ghz {


/**
/**
 * struct ath5k_rate - rate structure
 * 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
 * @modulation: respective mac80211 modulation
 * @rate_kbps: rate in kbit/s
 * @rate_kbps: rate in kbit/s
 * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
 * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
@@ -643,47 +644,48 @@ struct ath5k_rate_table {


/*
/*
 * Rate tables...
 * Rate tables...
 * TODO: CLEAN THIS !!!
 */
 */
#define AR5K_RATES_11A { 8, {					\
#define AR5K_RATES_11A { 8, {					\
	255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0,	\
	255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0,	\
	7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255,	\
	7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255,	\
	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, 0, 6000, 11, 140, 0 },		\
	{ 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 },		\
	{ 1, 0, 9000, 15, 18, 0 },		\
	{ 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 },		\
	{ 1, 0, 12000, 10, 152, 2 },		\
	{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 },		\
	{ 1, 0, 18000, 14, 36, 2 },		\
	{ 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 },		\
	{ 1, 0, 24000, 9, 176, 4 },		\
	{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 },		\
	{ 1, 0, 36000, 13, 72, 4 },		\
	{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 },		\
	{ 1, 0, 48000, 8, 96, 4 },		\
	{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } }		\
	{ 1, 0, 54000, 12, 108, 4 } }		\
}
}


#define AR5K_RATES_11B { 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,	\
	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 }, {				\
	3, 2, 1, 0, 255, 255, 255, 255 }, {				\
	{ 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 },	\
	{ 1, 0, 1000, 27, 130, 0 },	\
	{ 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 },	\
	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 132, 1 },	\
	{ 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 },	\
	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 139, 1 },	\
	{ 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } }	\
	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 150, 1 } }	\
}
}


#define AR5K_RATES_11G { 12, {					\
#define AR5K_RATES_11G { 12, {					\
	255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4,	\
	255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4,	\
	11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255,	\
	11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255,	\
	3, 2, 1, 0, 255, 255, 255, 255 }, {			\
	3, 2, 1, 0, 255, 255, 255, 255 }, {			\
	{ 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 },		\
	{ 1, 0, 1000, 27, 2, 0 },		\
	{ 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 },		\
	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 4, 1 },		\
	{ 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 },		\
	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 11, 1 },		\
	{ 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 },	\
	{ 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 22, 1 },	\
	{ 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 },	\
	{ 0, 0, 6000, 11, 12, 4 },	\
	{ 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 },	\
	{ 0, 0, 9000, 15, 18, 4 },	\
	{ 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 },	\
	{ 1, 0, 12000, 10, 24, 6 },	\
	{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 },	\
	{ 1, 0, 18000, 14, 36, 6 },	\
	{ 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 },	\
	{ 1, 0, 24000, 9, 48, 8 },	\
	{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 },	\
	{ 1, 0, 36000, 13, 72, 8 },	\
	{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 },	\
	{ 1, 0, 48000, 8, 96, 8 },	\
	{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } }	\
	{ 1, 0, 54000, 12, 108, 8 } }	\
}
}


#define AR5K_RATES_TURBO { 8, {					\
#define AR5K_RATES_TURBO { 8, {					\
@@ -708,14 +710,14 @@ struct ath5k_rate_table {
	{ 1, MODULATION_XR, 1000, 2, 139, 1 },		\
	{ 1, MODULATION_XR, 1000, 2, 139, 1 },		\
	{ 1, MODULATION_XR, 2000, 6, 150, 2 },		\
	{ 1, MODULATION_XR, 2000, 6, 150, 2 },		\
	{ 1, MODULATION_XR, 3000, 1, 150, 3 },		\
	{ 1, MODULATION_XR, 3000, 1, 150, 3 },		\
	{ 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 },	\
	{ 1, 0, 6000, 11, 140, 4 },	\
	{ 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 },	\
	{ 1, 0, 9000, 15, 18, 4 },	\
	{ 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 },	\
	{ 1, 0, 12000, 10, 152, 6 },	\
	{ 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 },	\
	{ 1, 0, 18000, 14, 36, 6 },	\
	{ 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 },	\
	{ 1, 0, 24000, 9, 176, 8 },	\
	{ 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 },	\
	{ 1, 0, 36000, 13, 72, 8 },	\
	{ 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 },	\
	{ 1, 0, 48000, 8, 96, 8 },	\
	{ 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } }	\
	{ 1, 0, 54000, 12, 108, 8 } }	\
}
}


/*
/*
@@ -895,7 +897,7 @@ struct ath5k_capabilities {
	 * Supported PHY modes
	 * Supported PHY modes
	 * (ie. CHANNEL_A, CHANNEL_B, ...)
	 * (ie. CHANNEL_A, CHANNEL_B, ...)
	 */
	 */
	DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES);
	DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);


	/*
	/*
	 * Frequency range (without regulation restrictions)
	 * Frequency range (without regulation restrictions)
@@ -907,14 +909,6 @@ struct ath5k_capabilities {
		u16	range_5ghz_max;
		u16	range_5ghz_max;
	} cap_range;
	} 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...)
	 * 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 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 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);
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 */
/* Misc functions */
extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);


+191 −155
Original line number Original line Diff line number Diff line
@@ -240,6 +240,8 @@ static int ath5k_chan_set(struct ath5k_softc *sc,
static void	ath5k_setcurmode(struct ath5k_softc *sc,
static void	ath5k_setcurmode(struct ath5k_softc *sc,
				unsigned int mode);
				unsigned int mode);
static void	ath5k_mode_setup(struct ath5k_softc *sc);
static void	ath5k_mode_setup(struct ath5k_softc *sc);
static void	ath5k_set_total_hw_rates(struct ath5k_softc *sc);

/* Descriptor setup */
/* Descriptor setup */
static int	ath5k_desc_alloc(struct ath5k_softc *sc,
static int	ath5k_desc_alloc(struct ath5k_softc *sc,
				struct pci_dev *pdev);
				struct pci_dev *pdev);
@@ -515,12 +517,12 @@ ath5k_pci_probe(struct pci_dev *pdev,
		/* Single chip radio (!RF5111) */
		/* 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 */
			/* 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_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);
							sc->ah->ah_radio_5ghz_revision);
			/* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */
			/* 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_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);
							sc->ah->ah_radio_5ghz_revision);
@@ -693,11 +695,14 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
		goto err;
		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 */
	/* NB: setup here so ath5k_rate_update is happy */
	if (test_bit(MODE_IEEE80211A, ah->ah_modes))
	if (test_bit(AR5K_MODE_11A, ah->ah_modes))
		ath5k_setcurmode(sc, MODE_IEEE80211A);
		ath5k_setcurmode(sc, AR5K_MODE_11A);
	else
	else
		ath5k_setcurmode(sc, MODE_IEEE80211B);
		ath5k_setcurmode(sc, AR5K_MODE_11B);


	/*
	/*
	 * Allocate tx+rx descriptors and populate the lists.
	 * Allocate tx+rx descriptors and populate the lists.
@@ -837,12 +842,9 @@ ath5k_copy_rates(struct ieee80211_rate *rates,
		return 0;
		return 0;


	for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
	for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
		if (!rt->rates[i].valid)
		rates[count].bitrate = rt->rates[i].rate_kbps / 100;
			continue;
		rates[count].hw_value = rt->rates[i].rate_code;
		rates->rate = rt->rates[i].rate_kbps / 100;
		rates[count].flags = rt->rates[i].modulation;
		rates->val = rt->rates[i].rate_code;
		rates->flags = rt->rates[i].modulation;
		rates++;
		count++;
		count++;
		max--;
		max--;
	}
	}
@@ -856,43 +858,22 @@ ath5k_copy_channels(struct ath5k_hw *ah,
		unsigned int mode,
		unsigned int mode,
		unsigned int max)
		unsigned int max)
{
{
	static const struct { unsigned int mode, mask, chan; } map[] = {
	unsigned int i, count, size, chfreq, freq, ch;
		[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;


	if (!test_bit(mode, ah->ah_modes))
	if (!test_bit(mode, ah->ah_modes))
		return 0;
		return 0;


	all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1;

	switch (mode) {
	switch (mode) {
	case MODE_IEEE80211A:
	case AR5K_MODE_11A:
	case MODE_ATHEROS_TURBO:
	case AR5K_MODE_11A_TURBO:
		/* 1..220, but 2GHz frequencies are filtered by check_channel */
		/* 1..220, but 2GHz frequencies are filtered by check_channel */
		size = all ? 220 : ARRAY_SIZE(chans_5ghz);
		size = 220 ;
		chans = chans_5ghz;
		dmn = ath5k_regdom2flag(ah->ah_regdomain,
				IEEE80211_CHANNELS_5GHZ_MIN);
		chfreq = CHANNEL_5GHZ;
		chfreq = CHANNEL_5GHZ;
		break;
		break;
	case MODE_IEEE80211B:
	case AR5K_MODE_11B:
	case MODE_IEEE80211G:
	case AR5K_MODE_11G:
	case MODE_ATHEROS_TURBOG:
	case AR5K_MODE_11G_TURBO:
		size = all ? 26 : ARRAY_SIZE(chans_2ghz);
		size = 26;
		chans = chans_2ghz;
		dmn = ath5k_regdom2flag(ah->ah_regdomain,
				IEEE80211_CHANNELS_2GHZ_MIN);
		chfreq = CHANNEL_2GHZ;
		chfreq = CHANNEL_2GHZ;
		break;
		break;
	default:
	default:
@@ -901,25 +882,26 @@ ath5k_copy_channels(struct ath5k_hw *ah,
	}
	}


	for (i = 0, count = 0; i < size && max > 0; i++) {
	for (i = 0, count = 0; i < size && max > 0; i++) {
		ch = all ? i + 1 : chans[i].chan;
		ch = i + 1 ;
		f = ath5k_ieee2mhz(ch);
		freq = ath5k_ieee2mhz(ch);

		/* Check if channel is supported by the chipset */
		/* Check if channel is supported by the chipset */
		if (!ath5k_channel_ok(ah, f, chfreq))
		if (!ath5k_channel_ok(ah, freq, chfreq))
			continue;
			continue;


		/* Match regulation domain */
		/* Write channel info and increment counter */
		if (!all && !(IEEE80211_DMN(chans[i].domain) &
		channels[count].center_freq = freq;
							IEEE80211_DMN(dmn)))
			continue;


		if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode)
		if((mode == AR5K_MODE_11A) ||
			continue;
		(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++;
		count++;
		max--;
		max--;
	}
	}
@@ -927,95 +909,76 @@ ath5k_copy_channels(struct ath5k_hw *ah,
	return count;
	return count;
}
}


/* Only tries to register modes our EEPROM says it can support */
static int
#define REGISTER_MODE(m) do { \
ath5k_getchannels(struct ieee80211_hw *hw)
	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 ath5k_softc *sc = hw->priv;
	struct ieee80211_hw_mode *modes = sc->modes;
	struct ath5k_hw *ah = sc->ah;
	unsigned int i;
	struct ieee80211_supported_band *sbands = sc->sbands;
	int ret;
	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))
	BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
		return 0;


	for (i = 0; i < NUM_DRIVER_MODES; i++) {
	max_r = ARRAY_SIZE(sc->rates);
		if (modes[i].mode != m || !modes[i].num_channels)
	max_c = ARRAY_SIZE(sc->channels);
			continue;
	count_r = count_c = 0;
		ret = ieee80211_register_hwmode(hw, &modes[i]);

		if (ret) {
	/* 2GHz band */
			ATH5K_ERR(sc, "can't register hwmode %u\n", m);
	if(!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)){
			return ret;
		mode2g = AR5K_MODE_11B;
		}
		if(!test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)){
		return 0;
			mode2g = -1;
		}
		}
	BUG();
	}
	}


static int
	if(mode2g > 0){
ath5k_getchannels(struct ieee80211_hw *hw)
		struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_2GHZ];
{
	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;


	BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
		sband->bitrates = sc->rates;
		sband->channels = sc->channels;


	/* The order here does not matter */
		sband->band = IEEE80211_BAND_2GHZ;
	modes[0].mode = MODE_IEEE80211G;
		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
	modes[1].mode = MODE_IEEE80211B;
					mode2g, max_c);
	modes[2].mode = MODE_IEEE80211A;


	max_r = ARRAY_SIZE(sc->rates);
		hw_rates = ath5k_hw_get_rate_table(ah, mode2g);
	max_c = ARRAY_SIZE(sc->channels);
		sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
					hw_rates,max_r);


	for (i = 0; i < NUM_DRIVER_MODES; i++) {
		count_c = sband->n_channels;
		struct ieee80211_hw_mode *mode = &modes[i];
		count_r = sband->n_bitrates;
		const struct ath5k_rate_table *hw_rates;


		if (i == 0) {
		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
			modes[0].rates	= sc->rates;

			modes->channels	= sc->channels;
		max_r -= count_r;
		} else {
		max_c -= count_c;
			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_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
	/* 5GHz band */
	 * 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. */


	REGISTER_MODE(MODE_IEEE80211G);
	if(test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)){
	if (ah->ah_version != AR5K_AR5212)
		struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_5GHZ];
		REGISTER_MODE(MODE_IEEE80211B);
	REGISTER_MODE(MODE_IEEE80211A);


	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;
	struct ath5k_hw *ah = sc->ah;
	int ret;
	int ret;


	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n",
	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
		sc->curchan->chan, sc->curchan->freq,
		sc->curchan->center_freq, chan->center_freq);
		chan->chan, chan->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;
		 * To switch channels clear any pending DMA operations;
		 * wait long enough for the RX fifo to drain, reset the
		 * 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_hw_set_intr(ah, 0);	/* disable interrupts */
		ath5k_txq_cleanup(sc);		/* clear pending tx frames */
		ath5k_txq_cleanup(sc);		/* clear pending tx frames */
		ath5k_rx_stop(sc);		/* turn off frame recv */
		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) {
		if (ret) {
			ATH5K_ERR(sc, "%s: unable to reset channel %u "
			ATH5K_ERR(sc, "%s: unable to reset channel "
				"(%u Mhz)\n", __func__, chan->chan, chan->freq);
				"(%u Mhz)\n", __func__, chan->center_freq);
			return ret;
			return ret;
		}
		}
		sc->curchan = chan;

		ath5k_hw_set_txpower_limit(sc->ah, 0);
		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;
	return 0;
}
}


/*
 * TODO: CLEAN THIS !!!
 */
static void
static void
ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
{
{
@@ -1121,10 +1091,6 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
				continue;
				continue;
			}
			}
			sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
			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 */
			/* receive frames include FCS */
			sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
			sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
					IEEE80211_RADIOTAP_F_FCS;
					IEEE80211_RADIOTAP_F_FCS;
@@ -1142,6 +1108,12 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
	}
	}


	sc->curmode = 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
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);
	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 +1306,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,


	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
		ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
		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)
	if (ret)
		goto err_unmap;
		goto err_unmap;


@@ -1791,9 +1829,8 @@ ath5k_tasklet_rx(unsigned long data)
		rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
		rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
		rxs.flag |= RX_FLAG_TSFT;
		rxs.flag |= RX_FLAG_TSFT;


		rxs.freq = sc->curchan->freq;
		rxs.freq = sc->curchan->center_freq;
		rxs.channel = sc->curchan->chan;
		rxs.band = sc->curband->band;
		rxs.phymode = sc->curmode;


		/*
		/*
		 * signal quality:
		 * signal quality:
@@ -1811,7 +1848,7 @@ ath5k_tasklet_rx(unsigned long data)
		rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
		rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;


		rxs.antenna = ds->ds_rxstat.rs_antenna;
		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);
		rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);


		ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
		ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
@@ -1958,7 +1995,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
	ds->ds_data = bf->skbaddr;
	ds->ds_data = bf->skbaddr;
	ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
	ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
			ieee80211_get_hdrlen_from_skb(skb),
			ieee80211_get_hdrlen_from_skb(skb),
			AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1,
			AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), ctl->tx_rate->hw_value, 1,
			AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
			AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
	if (ret)
	if (ret)
		goto err_unmap;
		goto err_unmap;
@@ -2211,7 +2248,8 @@ ath5k_init(struct ath5k_softc *sc)
	 * be followed by initialization of the appropriate bits
	 * be followed by initialization of the appropriate bits
	 * and then setup of the interrupt mask.
	 * 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);
	ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false);
	if (ret) {
	if (ret) {
		ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
		ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
@@ -2448,7 +2486,7 @@ ath5k_calibrate(unsigned long data)
	struct ath5k_hw *ah = sc->ah;
	struct ath5k_hw *ah = sc->ah;


	ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
	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) {
	if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) {
		/*
		/*
@@ -2460,7 +2498,7 @@ ath5k_calibrate(unsigned long data)
	}
	}
	if (ath5k_hw_phy_calibrate(ah, sc->curchan))
	if (ath5k_hw_phy_calibrate(ah, sc->curchan))
		ATH5K_ERR(sc, "calibration of channel %u failed\n",
		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 +
	mod_timer(&sc->calib_tim, round_jiffies(jiffies +
			msecs_to_jiffies(ath5k_calinterval * 1000)));
			msecs_to_jiffies(ath5k_calinterval * 1000)));
@@ -2558,7 +2596,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
		memmove(skb->data, skb->data+pad, hdrlen);
		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);
	spin_lock_irqsave(&sc->txbuflock, flags);
	if (list_empty(&sc->txbuf)) {
	if (list_empty(&sc->txbuf)) {
@@ -2597,11 +2635,6 @@ ath5k_reset(struct ieee80211_hw *hw)
	int ret;
	int ret;


	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
	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_hw_set_intr(ah, 0);
	ath5k_txq_cleanup(sc);
	ath5k_txq_cleanup(sc);
@@ -2692,6 +2725,9 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
	mutex_unlock(&sc->lock);
	mutex_unlock(&sc->lock);
}
}


/*
 * TODO: Phy disable/diversity etc
 */
static int
static int
ath5k_config(struct ieee80211_hw *hw,
ath5k_config(struct ieee80211_hw *hw,
			struct ieee80211_conf *conf)
			struct ieee80211_conf *conf)
@@ -2699,9 +2735,9 @@ ath5k_config(struct ieee80211_hw *hw,
	struct ath5k_softc *sc = hw->priv;
	struct ath5k_softc *sc = hw->priv;


	sc->bintval = conf->beacon_int;
	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
static int
+11 −3
Original line number Original line Diff line number Diff line
@@ -83,7 +83,7 @@ struct ath5k_txq {
#if CHAN_DEBUG
#if CHAN_DEBUG
#define ATH_CHAN_MAX	(26+26+26+200+200)
#define ATH_CHAN_MAX	(26+26+26+200+200)
#else
#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
#endif


/* Software Carrier, keeps track of the driver state
/* Software Carrier, keeps track of the driver state
@@ -95,12 +95,19 @@ struct ath5k_softc {
	struct ieee80211_tx_queue_stats tx_stats;
	struct ieee80211_tx_queue_stats tx_stats;
	struct ieee80211_low_level_stats ll_stats;
	struct ieee80211_low_level_stats ll_stats;
	struct ieee80211_hw	*hw;		/* IEEE 802.11 common */
	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_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;
	enum ieee80211_if_types	opmode;
	struct ath5k_hw		*ah;		/* Atheros HW */
	struct ath5k_hw		*ah;		/* Atheros HW */


	struct ieee80211_supported_band		*curband;

	u8			a_rates;
	u8			b_rates;
	u8			g_rates;
	u8			xr_rates;

#if ATH5K_DEBUG
#if ATH5K_DEBUG
	struct ath5k_dbg_info	debug;		/* debug info */
	struct ath5k_dbg_info	debug;		/* debug info */
#endif
#endif
@@ -169,6 +176,7 @@ struct ath5k_softc {
	unsigned int		nexttbtt;	/* next beacon time in TU */
	unsigned int		nexttbtt;	/* next beacon time in TU */


	struct timer_list	calib_tim;	/* calibration timer */
	struct timer_list	calib_tim;	/* calibration timer */
	int 			power_level;	/* Requested tx power in dbm */
};
};


#define ath5k_hw_hasbssidmask(_ah) \
#define ath5k_hw_hasbssidmask(_ah) \
Loading