Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/linville/wireless-next-2.6

Conflicts:
	drivers/net/wireless/iwlwifi/iwl-core.h
  • Loading branch information
David S. Miller committed Jan 19, 2010
2 parents 6d95518 + 730dd70 commit 6373464
Show file tree
Hide file tree
Showing 92 changed files with 7,308 additions and 2,805 deletions.
2 changes: 1 addition & 1 deletion Documentation/DocBook/mac80211.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ usage should require reading the full document.
this though and the recommendation to allow only a single
interface in STA mode at first!
</para>
!Finclude/net/mac80211.h ieee80211_if_init_conf
!Finclude/net/mac80211.h ieee80211_vif
</chapter>

<chapter id="rx-tx">
Expand Down
24 changes: 6 additions & 18 deletions drivers/net/wireless/ath/ath5k/ath5k.h
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,7 @@ struct ath5k_hw {
u32 ah_cw_min;
u32 ah_cw_max;
u32 ah_limit_tx_retries;
u8 ah_coverage_class;

/* Antenna Control */
u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
Expand Down Expand Up @@ -1200,6 +1201,7 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);

/* Protocol Control Unit Functions */
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
/* BSSID Functions */
extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
extern void ath5k_hw_set_associd(struct ath5k_hw *ah);
Expand Down Expand Up @@ -1231,6 +1233,10 @@ extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
/* Clock rate related functions */
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah);
/* Key table (WEP) functions */
extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
Expand Down Expand Up @@ -1310,24 +1316,6 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
* Functions used internaly
*/

/*
* Translate usec to hw clock units
* TODO: Half/quarter rate
*/
static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
{
return turbo ? (usec * 80) : (usec * 40);
}

/*
* Translate hw clock units to usec
* TODO: Half/quarter rate
*/
static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
{
return turbo ? (clock / 80) : (clock / 40);
}

static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
{
return &ah->common;
Expand Down
22 changes: 22 additions & 0 deletions drivers/net/wireless/ath/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
u32 changes);
static void ath5k_sw_scan_start(struct ieee80211_hw *hw);
static void ath5k_sw_scan_complete(struct ieee80211_hw *hw);
static void ath5k_set_coverage_class(struct ieee80211_hw *hw,
u8 coverage_class);

static const struct ieee80211_ops ath5k_hw_ops = {
.tx = ath5k_tx,
Expand All @@ -274,6 +276,7 @@ static const struct ieee80211_ops ath5k_hw_ops = {
.bss_info_changed = ath5k_bss_info_changed,
.sw_scan_start = ath5k_sw_scan_start,
.sw_scan_complete = ath5k_sw_scan_complete,
.set_coverage_class = ath5k_set_coverage_class,
};

/*
Expand Down Expand Up @@ -3262,3 +3265,22 @@ static void ath5k_sw_scan_complete(struct ieee80211_hw *hw)
ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
AR5K_LED_ASSOC : AR5K_LED_INIT);
}

/**
* ath5k_set_coverage_class - Set IEEE 802.11 coverage class
*
* @hw: struct ieee80211_hw pointer
* @coverage_class: IEEE 802.11 coverage class number
*
* Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given
* coverage class. The values are persistent, they are restored after device
* reset.
*/
static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
{
struct ath5k_softc *sc = hw->priv;

mutex_lock(&sc->lock);
ath5k_hw_set_coverage_class(sc->ah, coverage_class);
mutex_unlock(&sc->lock);
}
32 changes: 29 additions & 3 deletions drivers/net/wireless/ath/ath5k/eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
int ret;
u16 val;
u32 cksum, offset;
u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX;

/*
* Read values from EEPROM and store them in the capability structure
Expand All @@ -116,12 +116,38 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
* Validate the checksum of the EEPROM date. There are some
* devices with invalid EEPROMs.
*/
for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val);
if (val) {
eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val);
eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE;

/*
* Fail safe check to prevent stupid loops due
* to busted EEPROMs. XXX: This value is likely too
* big still, waiting on a better value.
*/
if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) {
ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: "
"%d (0x%04x) max expected: %d (0x%04x)\n",
eep_max, eep_max,
3 * AR5K_EEPROM_INFO_MAX,
3 * AR5K_EEPROM_INFO_MAX);
return -EIO;
}
}

for (cksum = 0, offset = 0; offset < eep_max; offset++) {
AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
cksum ^= val;
}
if (cksum != AR5K_EEPROM_INFO_CKSUM) {
ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
ATH5K_ERR(ah->ah_sc, "Invalid EEPROM "
"checksum: 0x%04x eep_max: 0x%04x (%s)\n",
cksum, eep_max,
eep_max == AR5K_EEPROM_INFO_MAX ?
"default size" : "custom size");
return -EIO;
}

Expand Down
8 changes: 8 additions & 0 deletions drivers/net/wireless/ath/ath5k/eeprom.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@
#define AR5K_EEPROM_RFKILL_POLARITY_S 1

#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */

/* FLASH(EEPROM) Defines for AR531X chips */
#define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */
#define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */
#define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0
#define AR5K_EEPROM_SIZE_UPPER_SHIFT 4
#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12

#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
Expand Down
121 changes: 111 additions & 10 deletions drivers/net/wireless/ath/ath5k/pcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
{
ATH5K_TRACE(ah->ah_sc);

return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah,
AR5K_TIME_OUT), AR5K_TIME_OUT_ACK));
}

/**
Expand All @@ -200,12 +200,12 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
{
ATH5K_TRACE(ah->ah_sc);
if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
ah->ah_turbo) <= timeout)
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK))
<= timeout)
return -EINVAL;

AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
ath5k_hw_htoclock(timeout, ah->ah_turbo));
ath5k_hw_htoclock(ah, timeout));

return 0;
}
Expand All @@ -218,8 +218,8 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
{
ATH5K_TRACE(ah->ah_sc);
return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah,
AR5K_TIME_OUT), AR5K_TIME_OUT_CTS));
}

/**
Expand All @@ -231,16 +231,96 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
{
ATH5K_TRACE(ah->ah_sc);
if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
ah->ah_turbo) <= timeout)
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS))
<= timeout)
return -EINVAL;

AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
ath5k_hw_htoclock(timeout, ah->ah_turbo));
ath5k_hw_htoclock(ah, timeout));

return 0;
}

/**
* ath5k_hw_htoclock - Translate usec to hw clock units
*
* @ah: The &struct ath5k_hw
* @usec: value in microseconds
*/
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
{
return usec * ath5k_hw_get_clockrate(ah);
}

/**
* ath5k_hw_clocktoh - Translate hw clock units to usec
* @clock: value in hw clock units
*/
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
{
return clock / ath5k_hw_get_clockrate(ah);
}

/**
* ath5k_hw_get_clockrate - Get the clock rate for current mode
*
* @ah: The &struct ath5k_hw
*/
unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
{
struct ieee80211_channel *channel = ah->ah_current_channel;
int clock;

if (channel->hw_value & CHANNEL_5GHZ)
clock = 40; /* 802.11a */
else if (channel->hw_value & CHANNEL_CCK)
clock = 22; /* 802.11b */
else
clock = 44; /* 802.11g */

/* Clock rate in turbo modes is twice the normal rate */
if (channel->hw_value & CHANNEL_TURBO)
clock *= 2;

return clock;
}

/**
* ath5k_hw_get_default_slottime - Get the default slot time for current mode
*
* @ah: The &struct ath5k_hw
*/
unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
{
struct ieee80211_channel *channel = ah->ah_current_channel;

if (channel->hw_value & CHANNEL_TURBO)
return 6; /* both turbo modes */

if (channel->hw_value & CHANNEL_CCK)
return 20; /* 802.11b */

return 9; /* 802.11 a/g */
}

/**
* ath5k_hw_get_default_sifs - Get the default SIFS for current mode
*
* @ah: The &struct ath5k_hw
*/
unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
{
struct ieee80211_channel *channel = ah->ah_current_channel;

if (channel->hw_value & CHANNEL_TURBO)
return 8; /* both turbo modes */

if (channel->hw_value & CHANNEL_5GHZ)
return 16; /* 802.11a */

return 10; /* 802.11 b/g */
}

/**
* ath5k_hw_set_lladdr - Set station id
*
Expand Down Expand Up @@ -1050,3 +1130,24 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
return 0;
}

/**
* ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class
*
* @ah: The &struct ath5k_hw
* @coverage_class: IEEE 802.11 coverage class number
*
* Sets slot time, ACK timeout and CTS timeout for given coverage class.
*/
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
{
/* As defined by IEEE 802.11-2007 17.3.8.6 */
int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class;
int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
int cts_timeout = ack_timeout;

ath5k_hw_set_slot_time(ah, slot_time);
ath5k_hw_set_ack_timeout(ah, ack_timeout);
ath5k_hw_set_cts_timeout(ah, cts_timeout);

ah->ah_coverage_class = coverage_class;
}
20 changes: 13 additions & 7 deletions drivers/net/wireless/ath/ath5k/qcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,28 +520,34 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
*/
unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
{
unsigned int slot_time_clock;

ATH5K_TRACE(ah->ah_sc);

if (ah->ah_version == AR5K_AR5210)
return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME);
else
return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT);

return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff);
}

/*
* Set slot time on DCU
*/
int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
{
u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);

ATH5K_TRACE(ah->ah_sc);
if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)

if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
return -EINVAL;

if (ah->ah_version == AR5K_AR5210)
ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
ah->ah_turbo), AR5K_SLOT_TIME);
ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
else
ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);

return 0;
}
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/wireless/ath/ath5k/reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,11 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
!(channel->hw_value & CHANNEL_OFDM));

/* Get coefficient
* ALGO: coef = (5 * clock * carrier_freq) / 2)
* ALGO: coef = (5 * clock / carrier_freq) / 2
* we scale coef by shifting clock value by 24 for
* better precision since we use integers */
/* TODO: Half/quarter rate */
clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);

clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40;
coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;

/* Get exponent
Expand Down Expand Up @@ -1317,6 +1316,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* Restore antenna mode */
ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);

/* Restore slot time and ACK timeouts */
if (ah->ah_coverage_class > 0)
ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);

/*
* Configure QCUs/DCUs
*/
Expand Down
Loading

0 comments on commit 6373464

Please sign in to comment.