/*
- 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
Supported chipsets: RT2561, RT2561s, RT2661.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt61pci"
-
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt61pci_bbp_check(const struct rt2x00_dev *rt2x00dev)
+static u32 rt61pci_bbp_check(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
return reg;
}
-static void rt61pci_bbp_write(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
}
-static void rt61pci_bbp_read(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u8 *value)
{
u32 reg;
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
}
-static void rt61pci_rf_write(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
rt2x00_rf_write(rt2x00dev, word, value);
}
-static void rt61pci_mcu_request(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 command, const u8 token,
const u8 arg0, const u8 arg1)
{
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-static void rt61pci_read_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_read_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 *data)
{
rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
}
-static void rt61pci_write_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_write_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 data)
{
rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
u32 reg;
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®);
- return rt2x00_get_field32(reg, MAC_CSR13_BIT5);;
+ return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
}
#else
#define rt61pci_rfkill_poll NULL
*/
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE,
+ (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
}
-static void rt61pci_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
+static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+ const int short_preamble,
+ const int ack_timeout,
+ const int ack_consume_time)
{
- struct ieee80211_conf *conf = &rt2x00dev->hw->conf;
u32 reg;
- u32 value;
- u32 preamble;
-
- if (DEVICE_GET_RATE_FIELD(rate, PREAMBLE))
- preamble = SHORT_PREAMBLE;
- else
- preamble = PREAMBLE;
-
- /*
- * Extract the allowed ratemask from the device specific rate value,
- * We need to set TXRX_CSR5 to the basic rate mask so we need to mask
- * off the non-basic rates.
- */
- reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATEMASK;
-
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
- value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
- SHORT_DIFS : DIFS) +
- PLCP + preamble + get_duration(ACK_SIZE, 10);
- rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, value);
+ rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®);
- if (preamble == SHORT_PREAMBLE)
- rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, 1);
- else
- rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, 0);
+ rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+ !!short_preamble);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
}
static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int phymode)
+ const int basic_rate_mask)
{
- struct ieee80211_hw_mode *mode;
- struct ieee80211_rate *rate;
-
- if (phymode == MODE_IEEE80211A)
- rt2x00dev->curr_hwmode = HWMODE_A;
- else if (phymode == MODE_IEEE80211B)
- rt2x00dev->curr_hwmode = HWMODE_B;
- else
- rt2x00dev->curr_hwmode = HWMODE_G;
-
- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
- rate = &mode->rates[mode->num_rates - 1];
-
- rt61pci_config_rate(rt2x00dev, rate->val2);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask);
}
-static void rt61pci_config_lock_channel(struct rt2x00_dev *rt2x00dev,
- struct rf_channel *rf,
- const int txpower)
+static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf, const int txpower)
{
u8 r3;
u8 r94;
msleep(1);
}
-static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
- const int index, const int channel,
- const int txpower)
-{
- struct rf_channel rf;
-
- /*
- * Fill rf_reg structure.
- */
- memcpy(&rf, &rt2x00dev->spec.channels[index], sizeof(rf));
-
- rt61pci_config_lock_channel(rt2x00dev, &rf, txpower);
-}
-
static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
const int txpower)
{
rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
- rt61pci_config_lock_channel(rt2x00dev, &rf, txpower);
+ rt61pci_config_channel(rt2x00dev, &rf, txpower);
}
static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx,
- const int antenna_rx)
+ struct antenna_setup *ant)
{
u8 r3;
u8 r4;
rt61pci_bbp_read(rt2x00dev, 77, &r77);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
- !rt2x00_rf(&rt2x00dev->chip, RF5225));
+ rt2x00_rf(&rt2x00dev->chip, RF5325));
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
- !!(rt2x00dev->curr_hwmode != HWMODE_A));
+ (rt2x00dev->curr_hwmode != HWMODE_A));
break;
case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+ 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)
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
else
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+ 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)
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
else
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
break;
}
}
static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx,
- const int antenna_rx)
+ struct antenna_setup *ant)
{
u8 r3;
u8 r4;
rt61pci_bbp_read(rt2x00dev, 77, &r77);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
- !rt2x00_rf(&rt2x00dev->chip, RF2527));
+ rt2x00_rf(&rt2x00dev->chip, RF2529));
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
!test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
break;
case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
break;
}
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®);
- if (p1 != 0xff) {
- rt2x00_set_field32(®, MAC_CSR13_BIT4, !!p1);
- rt2x00_set_field32(®, MAC_CSR13_BIT12, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
- }
- if (p2 != 0xff) {
- rt2x00_set_field32(®, MAC_CSR13_BIT3, !p2);
- rt2x00_set_field32(®, MAC_CSR13_BIT11, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
- }
+ rt2x00_set_field32(®, MAC_CSR13_BIT4, p1);
+ rt2x00_set_field32(®, MAC_CSR13_BIT12, 0);
+
+ rt2x00_set_field32(®, MAC_CSR13_BIT3, !p2);
+ rt2x00_set_field32(®, MAC_CSR13_BIT11, 0);
+
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
}
static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx,
- const int antenna_rx)
+ struct antenna_setup *ant)
{
- u16 eeprom;
u8 r3;
u8 r4;
u8 r77;
rt61pci_bbp_read(rt2x00dev, 3, &r3);
rt61pci_bbp_read(rt2x00dev, 4, &r4);
rt61pci_bbp_read(rt2x00dev, 77, &r77);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
- rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
-
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
- rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 1);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
- } else if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY)) {
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED) >= 2) {
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- }
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
- } else if (!rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
- rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
- switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
- case 0:
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
- break;
- case 1:
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 0);
- break;
- case 2:
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
- break;
- case 3:
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
- break;
- }
- } else if (!rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
- !rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+ /* FIXME: Antenna selection for the rf 2529 is very confusing in the
+ * legacy driver. The code below should be ok for non-diversity setups.
+ */
- switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
- case 0:
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
- break;
- case 1:
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 0);
- break;
- case 2:
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
- break;
- case 3:
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
- break;
- }
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
+ case ANTENNA_A:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
+ break;
+ case ANTENNA_SW_DIVERSITY:
+ case ANTENNA_HW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
+ case ANTENNA_B:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
+ break;
}
+ rt61pci_bbp_write(rt2x00dev, 77, r77);
rt61pci_bbp_write(rt2x00dev, 3, r3);
rt61pci_bbp_write(rt2x00dev, 4, r4);
}
};
static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx, const int antenna_rx)
+ struct antenna_setup *ant)
{
const struct antenna_sel *sel;
unsigned int lna;
unsigned int i;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®);
-
if (rt2x00dev->curr_hwmode == HWMODE_A) {
sel = antenna_sel_a;
lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
-
- rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 0);
- rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 1);
} else {
sel = antenna_sel_bg;
lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
-
- rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 1);
- rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 0);
}
for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
+ rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®);
+
+ rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG,
+ (rt2x00dev->curr_hwmode == HWMODE_B ||
+ rt2x00dev->curr_hwmode == HWMODE_G));
+ rt2x00_set_field32(®, PHY_CSR0_PA_PE_A,
+ (rt2x00dev->curr_hwmode == HWMODE_A));
+
rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
rt2x00_rf(&rt2x00dev->chip, RF5325))
- rt61pci_config_antenna_5x(rt2x00dev, antenna_tx, antenna_rx);
+ rt61pci_config_antenna_5x(rt2x00dev, ant);
else if (rt2x00_rf(&rt2x00dev->chip, RF2527))
- rt61pci_config_antenna_2x(rt2x00dev, antenna_tx, antenna_rx);
+ rt61pci_config_antenna_2x(rt2x00dev, ant);
else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) {
if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
- rt61pci_config_antenna_2x(rt2x00dev, antenna_tx,
- antenna_rx);
+ rt61pci_config_antenna_2x(rt2x00dev, ant);
else
- rt61pci_config_antenna_2529(rt2x00dev, antenna_tx,
- antenna_rx);
+ rt61pci_config_antenna_2529(rt2x00dev, ant);
}
}
static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
- const int short_slot_time,
- const int beacon_int)
+ struct rt2x00lib_conf *libconf)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®);
- rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME,
- short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+ rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, libconf->slot_time);
rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®);
- rt2x00_set_field32(®, MAC_CSR8_SIFS, SIFS);
+ rt2x00_set_field32(®, MAC_CSR8_SIFS, libconf->sifs);
rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
- rt2x00_set_field32(®, MAC_CSR8_EIFS, EIFS);
+ rt2x00_set_field32(®, MAC_CSR8_EIFS, libconf->eifs);
rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
- rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, beacon_int * 16);
+ rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL,
+ libconf->conf->beacon_int * 16);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
}
static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
const unsigned int flags,
- struct ieee80211_conf *conf)
+ struct rt2x00lib_conf *libconf)
{
- int short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
if (flags & CONFIG_UPDATE_PHYMODE)
- rt61pci_config_phymode(rt2x00dev, conf->phymode);
+ rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
if (flags & CONFIG_UPDATE_CHANNEL)
- rt61pci_config_channel(rt2x00dev, conf->channel_val,
- conf->channel, conf->power_level);
+ rt61pci_config_channel(rt2x00dev, &libconf->rf,
+ libconf->conf->power_level);
if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
- rt61pci_config_txpower(rt2x00dev, conf->power_level);
+ rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt61pci_config_antenna(rt2x00dev, conf->antenna_sel_tx,
- conf->antenna_sel_rx);
+ rt61pci_config_antenna(rt2x00dev, &libconf->ant);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
- rt61pci_config_duration(rt2x00dev, short_slot_time,
- conf->beacon_int);
+ rt61pci_config_duration(rt2x00dev, libconf);
}
/*
static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- u16 led_reg;
u8 arg0;
u8 arg1;
rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
- led_reg = rt2x00dev->led_reg;
- rt2x00_set_field16(&led_reg, MCU_LEDCS_RADIO_STATUS, 1);
- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A)
- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_A_STATUS, 1);
- else
- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_BG_STATUS, 1);
+ 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));
- arg0 = led_reg & 0xff;
- arg1 = (led_reg >> 8) & 0xff;
+ arg0 = rt2x00dev->led_reg & 0xff;
+ arg1 = (rt2x00dev->led_reg >> 8) & 0xff;
rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
}
/*
* Link tuning
*/
-static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
u32 reg;
* Update FCS error count from register.
*/
rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®);
- rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
+ qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®);
- rt2x00dev->link.false_cca =
- rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
+ qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
* r17 does not yet exceed upper limit, continue and base
* the r17 tuning on the false CCA count.
*/
- if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) {
+ if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
if (++r17 > up_bound)
r17 = up_bound;
rt61pci_bbp_write(rt2x00dev, 17, r17);
- } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
+ } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
if (--r17 < low_bound)
r17 = low_bound;
rt61pci_bbp_write(rt2x00dev, 17, r17);
return 0;
}
-static void rt61pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct queue_entry *entry)
{
- struct data_ring *ring = rt2x00dev->rx;
- struct data_desc *rxd;
- unsigned int i;
+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
u32 word;
- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- rxd = ring->entry[i].priv;
-
- rt2x00_desc_read(rxd, 5, &word);
- rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(rxd, 5, word);
-
- rt2x00_desc_read(rxd, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(rxd, 0, word);
- }
+ rt2x00_desc_read(priv_rx->desc, 5, &word);
+ rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, priv_rx->dma);
+ rt2x00_desc_write(priv_rx->desc, 5, word);
- rt2x00_ring_index_clear(rt2x00dev->rx);
+ rt2x00_desc_read(priv_rx->desc, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(priv_rx->desc, 0, word);
}
-static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct queue_entry *entry)
{
- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
- struct data_desc *txd;
- unsigned int i;
+ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
u32 word;
- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- txd = ring->entry[i].priv;
-
- rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 5, &word);
- rt2x00_set_field32(&word, TXD_W5_PID_TYPE, queue);
- rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, i);
- rt2x00_desc_write(txd, 5, word);
+ rt2x00_desc_read(priv_tx->desc, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
+ rt2x00_desc_write(priv_tx->desc, 1, word);
- rt2x00_desc_read(txd, 6, &word);
- rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(txd, 6, word);
+ rt2x00_desc_read(priv_tx->desc, 5, &word);
+ rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
+ rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
+ rt2x00_desc_write(priv_tx->desc, 5, word);
- rt2x00_desc_read(txd, 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_read(priv_tx->desc, 6, &word);
+ rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, priv_tx->dma);
+ rt2x00_desc_write(priv_tx->desc, 6, word);
- rt2x00_ring_index_clear(ring);
+ 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(priv_tx->desc, 0, word);
}
-static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
+static int rt61pci_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 rings.
- */
- rt61pci_init_rxring(rt2x00dev);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA2);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA3);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA4);
-
- /*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®);
rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
+ rt2x00dev->tx[0].limit);
rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
+ rt2x00dev->tx[1].limit);
rt2x00_set_field32(®, TX_RING_CSR0_AC2_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit);
+ rt2x00dev->tx[2].limit);
rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit);
+ rt2x00dev->tx[3].limit);
rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg);
rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®);
- rt2x00_set_field32(®, TX_RING_CSR1_MGMT_RING_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit);
rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size /
- 4);
+ rt2x00dev->tx[0].desc_size / 4);
rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
+ priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®);
- rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
+ rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, priv_tx->dma);
rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
+ priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®);
- rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
+ rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, priv_tx->dma);
rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
+ priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®);
- rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma);
+ rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, priv_tx->dma);
rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
+ priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®);
- rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma);
+ rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, priv_tx->dma);
rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, ®);
- rt2x00_set_field32(®, MGMT_BASE_CSR_RING_REGISTER,
- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma);
- rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg);
-
rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®);
- rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE,
- rt2x00dev->rx->stats.limit);
+ rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE,
rt2x00dev->rx->desc_size / 4);
rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
+ priv_rx = rt2x00dev->rx->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®);
- rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER,
- rt2x00dev->rx->data_dma);
+ rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, priv_rx->dma);
rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®);
rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
- rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1);
+ rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 0);
rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®);
/*
* Initialize all registers.
*/
- if (rt61pci_init_rings(rt2x00dev) ||
+ if (rt61pci_init_queues(rt2x00dev) ||
rt61pci_init_registers(rt2x00dev) ||
rt61pci_init_bbp(rt2x00dev)) {
ERROR(rt2x00dev, "Register initialization failed.\n");
rt61pci_disable_radio(rt2x00dev);
break;
case STATE_RADIO_RX_ON:
+ case STATE_RADIO_RX_ON_LINK:
+ rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
+ break;
case STATE_RADIO_RX_OFF:
- rt61pci_toggle_rx(rt2x00dev, state);
+ case STATE_RADIO_RX_OFF_LINK:
+ rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
break;
case STATE_DEEP_SLEEP:
case STATE_SLEEP:
* TX descriptor initialization
*/
static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
- struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
- struct ieee80211_tx_control *control)
+ struct sk_buff *skb,
+ struct txentry_desc *txdesc,
+ struct ieee80211_tx_control *control)
{
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;
/*
* 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_WAITING_DMA_DONE_INT, 1);
rt2x00_desc_write(txd, 5, word);
- rt2x00_desc_read(txd, 11, &word);
- rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, length);
- rt2x00_desc_write(txd, 11, word);
+ if (skbdesc->desc_len > TXINFO_SIZE) {
+ rt2x00_desc_read(txd, 11, &word);
+ rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
+ rt2x00_desc_write(txd, 11, 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,
- !(control->flags & IEEE80211_TXCTL_NO_ACK));
+ 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, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
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_CIPHER_ALG, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
}
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®);
- if (queue == IEEE80211_TX_QUEUE_DATA0)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA1)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA2)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA3)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA4)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_MGMT, 1);
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0,
+ (queue == IEEE80211_TX_QUEUE_DATA0));
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1,
+ (queue == IEEE80211_TX_QUEUE_DATA1));
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2,
+ (queue == IEEE80211_TX_QUEUE_DATA2));
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3,
+ (queue == IEEE80211_TX_QUEUE_DATA3));
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_MGMT,
+ (queue == IEEE80211_TX_QUEUE_DATA4));
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
}
return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
}
-static void rt61pci_fill_rxdone(struct data_entry *entry,
- struct rxdata_entry_desc *desc)
+static void rt61pci_fill_rxdone(struct queue_entry *entry,
+ struct rxdone_entry_desc *rxdesc)
{
- struct data_desc *rxd = entry->priv;
+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
u32 word0;
u32 word1;
- rt2x00_desc_read(rxd, 0, &word0);
- rt2x00_desc_read(rxd, 1, &word1);
+ rt2x00_desc_read(priv_rx->desc, 0, &word0);
+ rt2x00_desc_read(priv_rx->desc, 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 = rt61pci_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);
-
- return;
+ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+ rxdesc->rssi = rt61pci_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);
}
/*
*/
static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
{
- struct data_ring *ring;
- struct data_entry *entry;
- struct data_desc *txd;
+ struct data_queue *queue;
+ struct queue_entry *entry;
+ struct queue_entry *entry_done;
+ struct queue_entry_priv_pci_tx *priv_tx;
+ struct txdone_entry_desc txdesc;
u32 word;
u32 reg;
u32 old_reg;
int type;
int index;
- int tx_status;
- int retry;
/*
* During each loop we will compare the freshly read
/*
* Skip this entry when it contains an invalid
- * ring identication number.
+ * queue identication number.
*/
type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
- ring = rt2x00lib_get_ring(rt2x00dev, type);
- if (unlikely(!ring))
+ queue = rt2x00queue_get_queue(rt2x00dev, type);
+ if (unlikely(!queue))
continue;
/*
* index number.
*/
index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
- if (unlikely(index >= ring->stats.limit))
+ if (unlikely(index >= queue->limit))
continue;
- entry = &ring->entry[index];
- txd = entry->priv;
- rt2x00_desc_read(txd, 0, &word);
+ entry = &queue->entries[index];
+ 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))
return;
- /*
- * Obtain the status about this packet.
- */
- tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
- retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
+ entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ while (entry != entry_done) {
+ /* Catch up.
+ * Just report any entries we missed as failed.
+ */
+ WARNING(rt2x00dev,
+ "TX status report missed for entry %d\n",
+ entry_done->entry_idx);
- rt2x00lib_txdone(entry, tx_status, retry);
+ txdesc.status = TX_FAIL_OTHER;
+ txdesc.retry = 0;
- /*
- * Make this entry available for reuse.
- */
- entry->flags = 0;
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_desc_write(txd, 0, word);
- rt2x00_ring_index_done_inc(entry->ring);
+ rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
+ entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ }
/*
- * If the data ring 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.
+ * Obtain the status about this packet.
*/
- if (!rt2x00_ring_full(ring))
- ieee80211_wake_queue(rt2x00dev->hw,
- entry->tx_status.control.queue);
+ txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
+ txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
+
+ rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
}
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 2);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 2);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+ ANTENNA_B);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+ ANTENNA_B);
rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
}
/*
+ * Determine number of antenna's.
+ */
+ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
+ __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
+
+ /*
* Identify default antenna configuration.
*/
- rt2x00dev->hw->conf.antenna_sel_tx =
+ rt2x00dev->default_ant.tx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
- rt2x00dev->hw->conf.antenna_sel_rx =
+ rt2x00dev->default_ant.rx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
/*
__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
/*
- * Determine number of antenna's.
- */
- if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
- __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
-
- /*
* Detect if this device has an hardware controlled radio.
*/
#ifdef CONFIG_RT61PCI_RFKILL
__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
/*
+ * When working with a RF2529 chip without double antenna
+ * the antenna settings should be gathered from the NIC
+ * eeprom word.
+ */
+ if (rt2x00_rf(&rt2x00dev->chip, RF2529) &&
+ !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
+ switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
+ case 0:
+ rt2x00dev->default_ant.tx = ANTENNA_B;
+ rt2x00dev->default_ant.rx = ANTENNA_A;
+ break;
+ case 1:
+ rt2x00dev->default_ant.tx = ANTENNA_B;
+ rt2x00dev->default_ant.rx = ANTENNA_B;
+ break;
+ case 2:
+ rt2x00dev->default_ant.tx = ANTENNA_A;
+ rt2x00dev->default_ant.rx = ANTENNA_A;
+ break;
+ case 3:
+ rt2x00dev->default_ant.tx = ANTENNA_A;
+ rt2x00dev->default_ant.rx = ANTENNA_B;
+ break;
+ }
+
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY))
+ rt2x00dev->default_ant.tx = ANTENNA_SW_DIVERSITY;
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY))
+ rt2x00dev->default_ant.rx = ANTENNA_SW_DIVERSITY;
+ }
+
+ /*
* Store led settings, for correct led behaviour.
* If the eeprom value is invalid,
* switch to default led mode.
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;
/*
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;
/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;
/*
* Start configuration steps.
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct skb_frame_desc *skbdesc;
+ struct data_queue *queue;
+ struct queue_entry *entry;
/*
* Just in case the ieee80211 doesn't set this,
* initialization.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
+ queue = rt2x00queue_get_queue(rt2x00dev, control->queue);
+ entry = rt2x00queue_get_entry(queue, Q_INDEX);
/*
* We need to append the descriptor in front of the
* beacon frame.
*/
- if (skb_headroom(skb) < TXD_DESC_SIZE) {
- if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC)) {
+ if (skb_headroom(skb) < queue->desc_size) {
+ if (pskb_expand_head(skb, queue->desc_size, 0, GFP_ATOMIC)) {
dev_kfree_skb(skb);
return -ENOMEM;
}
}
/*
- * First we create the beacon.
+ * Add the descriptor in front of the skb.
*/
- skb_push(skb, TXD_DESC_SIZE);
- rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
- (struct ieee80211_hdr *)(skb->data +
- TXD_DESC_SIZE),
- skb->len - TXD_DESC_SIZE, control);
+ skb_push(skb, queue->desc_size);
+ memset(skb->data, 0, queue->desc_size);
+
+ /*
+ * Fill in skb descriptor
+ */
+ skbdesc = get_skb_frame_desc(skb);
+ memset(skbdesc, 0, sizeof(*skbdesc));
+ skbdesc->data = skb->data + queue->desc_size;
+ skbdesc->data_len = queue->data_size;
+ skbdesc->desc = skb->data;
+ skbdesc->desc_len = queue->desc_size;
+ skbdesc->entry = entry;
+
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Write entire beacon with descriptor to register,
.configure_filter = rt61pci_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt61pci_set_retry_limit,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt61pci_get_tsf,
.load_firmware = rt61pci_load_firmware,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
+ .init_rxentry = rt61pci_init_rxentry,
+ .init_txentry = rt61pci_init_txentry,
.set_device_state = rt61pci_set_device_state,
.rfkill_poll = rt61pci_rfkill_poll,
.link_stats = rt61pci_link_stats,
.config_mac_addr = rt61pci_config_mac_addr,
.config_bssid = rt61pci_config_bssid,
.config_type = rt61pci_config_type,
+ .config_preamble = rt61pci_config_preamble,
.config = rt61pci_config,
};
+static const struct data_queue_desc rt61pci_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 rt61pci_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 rt61pci_queue_bcn = {
+ .entry_num = BEACON_ENTRIES,
+ .data_size = MGMT_FRAME_SIZE,
+ .desc_size = TXINFO_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
+};
+
static const struct rt2x00_ops rt61pci_ops = {
- .name = DRV_NAME,
- .rxd_size = RXD_DESC_SIZE,
- .txd_size = TXD_DESC_SIZE,
+ .name = KBUILD_MODNAME,
.eeprom_size = EEPROM_SIZE,
.rf_size = RF_SIZE,
+ .rx = &rt61pci_queue_rx,
+ .tx = &rt61pci_queue_tx,
+ .bcn = &rt61pci_queue_bcn,
.lib = &rt61pci_rt2x00_ops,
.hw = &rt61pci_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
MODULE_LICENSE("GPL");
static struct pci_driver rt61pci_driver = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.id_table = rt61pci_device_table,
.probe = rt2x00pci_probe,
.remove = __devexit_p(rt2x00pci_remove),