diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00')
25 files changed, 2040 insertions, 1154 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 31c1dd271627..d6cba138c7ab 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -24,11 +24,6 @@ Supported chipsets: RT2460. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2400pci" - #include <linux/delay.h> #include <linux/etherdevice.h> #include <linux/init.h> @@ -54,7 +49,7 @@ * the access attempt is considered to have failed, * and we will print an error. */ -static u32 rt2400pci_bbp_check(const struct rt2x00_dev *rt2x00dev) +static u32 rt2400pci_bbp_check(struct rt2x00_dev *rt2x00dev) { u32 reg; unsigned int i; @@ -69,7 +64,7 @@ static u32 rt2400pci_bbp_check(const struct rt2x00_dev *rt2x00dev) return reg; } -static void rt2400pci_bbp_write(const struct rt2x00_dev *rt2x00dev, +static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { u32 reg; @@ -95,7 +90,7 @@ static void rt2400pci_bbp_write(const struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); } -static void rt2400pci_bbp_read(const struct rt2x00_dev *rt2x00dev, +static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u8 *value) { u32 reg; @@ -132,7 +127,7 @@ static void rt2400pci_bbp_read(const struct rt2x00_dev *rt2x00dev, *value = rt2x00_get_field32(reg, BBPCSR_VALUE); } -static void rt2400pci_rf_write(const struct rt2x00_dev *rt2x00dev, +static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u32 reg; @@ -195,13 +190,13 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom) #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) ) -static void rt2400pci_read_csr(const struct rt2x00_dev *rt2x00dev, +static void rt2400pci_read_csr(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 *data) { rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data); } -static void rt2400pci_write_csr(const struct rt2x00_dev *rt2x00dev, +static void rt2400pci_write_csr(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 data) { rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data); @@ -285,7 +280,7 @@ static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, */ rt2x00pci_register_read(rt2x00dev, CSR14, ®); rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, 1); + rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON)); rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync); rt2x00pci_register_write(rt2x00dev, CSR14, reg); @@ -397,7 +392,7 @@ static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) } static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, - int antenna_tx, int antenna_rx) + struct antenna_setup *ant) { u8 r1; u8 r4; @@ -408,14 +403,20 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the TX antenna. */ - switch (antenna_tx) { - case ANTENNA_SW_DIVERSITY: + switch (ant->tx) { case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1); break; case ANTENNA_A: rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0); 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(&r1, BBP_R1_TX_ANTENNA, 2); break; @@ -424,14 +425,20 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the RX antenna. */ - switch (antenna_rx) { - case ANTENNA_SW_DIVERSITY: + switch (ant->rx) { case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); break; case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0); 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, 2); break; @@ -485,9 +492,7 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, rt2400pci_config_txpower(rt2x00dev, libconf->conf->power_level); if (flags & CONFIG_UPDATE_ANTENNA) - rt2400pci_config_antenna(rt2x00dev, - libconf->conf->antenna_sel_tx, - libconf->conf->antenna_sel_rx); + rt2400pci_config_antenna(rt2x00dev, &libconf->ant); if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) rt2400pci_config_duration(rt2x00dev, libconf); } @@ -514,18 +519,10 @@ static void rt2400pci_enable_led(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70); rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30); - - if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) { - rt2x00_set_field32(®, LEDCSR_LINK, 1); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0); - } else if (rt2x00dev->led_mode == LED_MODE_ASUS) { - rt2x00_set_field32(®, LEDCSR_LINK, 0); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, 1); - } else { - rt2x00_set_field32(®, LEDCSR_LINK, 1); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, 1); - } - + rt2x00_set_field32(®, LEDCSR_LINK, + (rt2x00dev->led_mode != LED_MODE_ASUS)); + rt2x00_set_field32(®, LEDCSR_ACTIVITY, + (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY)); rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); } @@ -542,7 +539,8 @@ static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev) /* * Link tuning */ -static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev) +static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { u32 reg; u8 bbp; @@ -551,13 +549,13 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev) * Update FCS error count from register. */ rt2x00pci_register_read(rt2x00dev, CNT0, ®); - rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); + qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); /* * Update False CCA count from register. */ rt2400pci_bbp_read(rt2x00dev, 39, &bbp); - rt2x00dev->link.false_cca = bbp; + qual->false_cca = bbp; } static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev) @@ -582,10 +580,10 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) */ rt2400pci_bbp_read(rt2x00dev, 13, ®); - if (rt2x00dev->link.false_cca > 512 && reg < 0x20) { + if (rt2x00dev->link.qual.false_cca > 512 && reg < 0x20) { rt2400pci_bbp_write(rt2x00dev, 13, ++reg); rt2x00dev->link.vgc_level = reg; - } else if (rt2x00dev->link.false_cca < 100 && reg > 0x08) { + } else if (rt2x00dev->link.qual.false_cca < 100 && reg > 0x08) { rt2400pci_bbp_write(rt2x00dev, 13, --reg); rt2x00dev->link.vgc_level = reg; } @@ -594,65 +592,43 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Initialization functions. */ -static void rt2400pci_init_rxring(struct rt2x00_dev *rt2x00dev) +static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry) { - struct data_ring *ring = rt2x00dev->rx; - struct data_desc *rxd; - unsigned int i; + __le32 *rxd = entry->priv; 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, 2, &word); - rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, - ring->data_size); - rt2x00_desc_write(rxd, 2, word); - - rt2x00_desc_read(rxd, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, - ring->entry[i].data_dma); - rt2x00_desc_write(rxd, 1, word); + rt2x00_desc_read(rxd, 2, &word); + rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size); + rt2x00_desc_write(rxd, 2, word); - rt2x00_desc_read(rxd, 0, &word); - rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); - } + rt2x00_desc_read(rxd, 1, &word); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma); + rt2x00_desc_write(rxd, 1, word); - rt2x00_ring_index_clear(rt2x00dev->rx); + rt2x00_desc_read(rxd, 0, &word); + rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); + rt2x00_desc_write(rxd, 0, word); } -static void rt2400pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue) +static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry) { - struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); - struct data_desc *txd; - unsigned int i; + __le32 *txd = entry->priv; 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_ADDRESS, - ring->entry[i].data_dma); - rt2x00_desc_write(txd, 1, word); - - rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, - ring->data_size); - rt2x00_desc_write(txd, 2, word); + rt2x00_desc_read(txd, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma); + rt2x00_desc_write(txd, 1, word); - rt2x00_desc_read(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(txd, 2, &word); + rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size); + rt2x00_desc_write(txd, 2, word); - rt2x00_ring_index_clear(ring); + 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); } static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev) @@ -660,15 +636,6 @@ static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev) u32 reg; /* - * Initialize rings. - */ - rt2400pci_init_rxring(rt2x00dev); - rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0); - rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1); - rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON); - rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); - - /* * Initialize registers. */ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); @@ -1014,53 +981,37 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_desc *txd, + struct sk_buff *skb, struct txdata_entry_desc *desc, - struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control) { + struct skb_desc *skbdesc = get_skb_desc(skb); + __le32 *txd = skbdesc->desc; u32 word; - u32 signal = 0; - u32 service = 0; - u32 length_high = 0; - u32 length_low = 0; - - /* - * The PLCP values should be treated as if they - * were BBP values. - */ - rt2x00_set_field32(&signal, BBPCSR_VALUE, desc->signal); - rt2x00_set_field32(&signal, BBPCSR_REGNUM, 5); - rt2x00_set_field32(&signal, BBPCSR_BUSY, 1); - - rt2x00_set_field32(&service, BBPCSR_VALUE, desc->service); - rt2x00_set_field32(&service, BBPCSR_REGNUM, 6); - rt2x00_set_field32(&service, BBPCSR_BUSY, 1); - - rt2x00_set_field32(&length_high, BBPCSR_VALUE, desc->length_high); - rt2x00_set_field32(&length_high, BBPCSR_REGNUM, 7); - rt2x00_set_field32(&length_high, BBPCSR_BUSY, 1); - - rt2x00_set_field32(&length_low, BBPCSR_VALUE, desc->length_low); - rt2x00_set_field32(&length_low, BBPCSR_REGNUM, 8); - rt2x00_set_field32(&length_low, BBPCSR_BUSY, 1); /* * Start writing the descriptor words. */ rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, length); + rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skbdesc->data_len); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, signal); - rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, service); + rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal); + rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5); + rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1); + rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service); + rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6); + rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1); rt2x00_desc_write(txd, 3, word); rt2x00_desc_read(txd, 4, &word); - rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, length_low); - rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, length_high); + rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, desc->length_low); + rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8); + rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1); + rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7); + rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1); rt2x00_desc_write(txd, 4, word); rt2x00_desc_read(txd, 0, &word); @@ -1069,7 +1020,7 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - !(control->flags & IEEE80211_TXCTL_NO_ACK)); + test_bit(ENTRY_TXD_ACK, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_RTS, @@ -1099,12 +1050,12 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, } rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - if (queue == IEEE80211_TX_QUEUE_DATA0) - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); - else if (queue == IEEE80211_TX_QUEUE_DATA1) - rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); - else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON) - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); + rt2x00_set_field32(®, TXCSR0_KICK_PRIO, + (queue == IEEE80211_TX_QUEUE_DATA0)); + rt2x00_set_field32(®, TXCSR0_KICK_TX, + (queue == IEEE80211_TX_QUEUE_DATA1)); + rt2x00_set_field32(®, TXCSR0_KICK_ATIM, + (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } @@ -1114,7 +1065,7 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, static void rt2400pci_fill_rxdone(struct data_entry *entry, struct rxdata_entry_desc *desc) { - struct data_desc *rxd = entry->priv; + __le32 *rxd = entry->priv; u32 word0; u32 word2; @@ -1135,6 +1086,7 @@ static void rt2400pci_fill_rxdone(struct data_entry *entry, entry->ring->rt2x00dev->rssi_offset; desc->ofdm = 0; desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* @@ -1144,7 +1096,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) { struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); struct data_entry *entry; - struct data_desc *txd; + __le32 *txd; u32 word; int tx_status; int retry; @@ -1164,26 +1116,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) tx_status = rt2x00_get_field32(word, TXD_W0_RESULT); retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00lib_txdone(entry, tx_status, retry); - - /* - * 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(ring); + rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); } - - /* - * 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. - */ - entry = ring->entry; - if (!rt2x00_ring_full(ring)) - ieee80211_wake_queue(rt2x00dev->hw, - entry->tx_status.control.queue); } static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) @@ -1315,12 +1249,23 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * 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); /* + * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead. + * I am not 100% sure about this, but the legacy drivers do not + * indicate antenna swapping in software is required when + * diversity is enabled. + */ + if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) + rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; + if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) + rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; + + /* * Store led mode, for correct led behaviour. */ rt2x00dev->led_mode = @@ -1447,7 +1392,6 @@ static void rt2400pci_configure_filter(struct ieee80211_hw *hw, struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; u32 reg; /* @@ -1466,21 +1410,18 @@ static void rt2400pci_configure_filter(struct ieee80211_hw *hw, * 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. */ *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. @@ -1583,7 +1524,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .configure_filter = rt2400pci_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt2400pci_set_retry_limit, - .erp_ie_changed = rt2x00mac_erp_ie_changed, + .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2400pci_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2400pci_get_tsf, @@ -1597,6 +1538,8 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .probe_hw = rt2400pci_probe_hw, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize, + .init_rxentry = rt2400pci_init_rxentry, + .init_txentry = rt2400pci_init_txentry, .set_device_state = rt2400pci_set_device_state, .rfkill_poll = rt2400pci_rfkill_poll, .link_stats = rt2400pci_link_stats, @@ -1614,7 +1557,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { }; static const struct rt2x00_ops rt2400pci_ops = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .rxd_size = RXD_DESC_SIZE, .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, @@ -1642,7 +1585,7 @@ MODULE_DEVICE_TABLE(pci, rt2400pci_device_table); MODULE_LICENSE("GPL"); static struct pci_driver rt2400pci_driver = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .id_table = rt2400pci_device_table, .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index ae22501f085d..369aac6d0336 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -803,8 +803,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 8 * sizeof(struct data_desc) ) -#define RXD_DESC_SIZE ( 8 * sizeof(struct data_desc) ) +#define TXD_DESC_SIZE ( 8 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 8 * sizeof(__le32) ) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. @@ -839,11 +839,21 @@ /* * Word3 & 4: PLCP information - */ -#define TXD_W3_PLCP_SIGNAL FIELD32(0x0000ffff) -#define TXD_W3_PLCP_SERVICE FIELD32(0xffff0000) -#define TXD_W4_PLCP_LENGTH_LOW FIELD32(0x0000ffff) -#define TXD_W4_PLCP_LENGTH_HIGH FIELD32(0xffff0000) + * The PLCP values should be treated as if they were BBP values. + */ +#define TXD_W3_PLCP_SIGNAL FIELD32(0x000000ff) +#define TXD_W3_PLCP_SIGNAL_REGNUM FIELD32(0x00007f00) +#define TXD_W3_PLCP_SIGNAL_BUSY FIELD32(0x00008000) +#define TXD_W3_PLCP_SERVICE FIELD32(0x00ff0000) +#define TXD_W3_PLCP_SERVICE_REGNUM FIELD32(0x7f000000) +#define TXD_W3_PLCP_SERVICE_BUSY FIELD32(0x80000000) + +#define TXD_W4_PLCP_LENGTH_LOW FIELD32(0x000000ff) +#define TXD_W3_PLCP_LENGTH_LOW_REGNUM FIELD32(0x00007f00) +#define TXD_W3_PLCP_LENGTH_LOW_BUSY FIELD32(0x00008000) +#define TXD_W4_PLCP_LENGTH_HIGH FIELD32(0x00ff0000) +#define TXD_W3_PLCP_LENGTH_HIGH_REGNUM FIELD32(0x7f000000) +#define TXD_W3_PLCP_LENGTH_HIGH_BUSY FIELD32(0x80000000) /* * Word5 diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 702321c30164..e874fdcae204 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -24,11 +24,6 @@ Supported chipsets: RT2560. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2500pci" - #include <linux/delay.h> #include <linux/etherdevice.h> #include <linux/init.h> @@ -54,7 +49,7 @@ * the access attempt is considered to have failed, * and we will print an error. */ -static u32 rt2500pci_bbp_check(const struct rt2x00_dev *rt2x00dev) +static u32 rt2500pci_bbp_check(struct rt2x00_dev *rt2x00dev) { u32 reg; unsigned int i; @@ -69,7 +64,7 @@ static u32 rt2500pci_bbp_check(const struct rt2x00_dev *rt2x00dev) return reg; } -static void rt2500pci_bbp_write(const struct rt2x00_dev *rt2x00dev, +static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { u32 reg; @@ -95,7 +90,7 @@ static void rt2500pci_bbp_write(const struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); } -static void rt2500pci_bbp_read(const struct rt2x00_dev *rt2x00dev, +static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u8 *value) { u32 reg; @@ -132,7 +127,7 @@ static void rt2500pci_bbp_read(const struct rt2x00_dev *rt2x00dev, *value = rt2x00_get_field32(reg, BBPCSR_VALUE); } -static void rt2500pci_rf_write(const struct rt2x00_dev *rt2x00dev, +static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u32 reg; @@ -195,13 +190,13 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom) #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) ) -static void rt2500pci_read_csr(const struct rt2x00_dev *rt2x00dev, +static void rt2500pci_read_csr(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 *data) { rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data); } -static void rt2500pci_write_csr(const struct rt2x00_dev *rt2x00dev, +static void rt2500pci_write_csr(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 data) { rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data); @@ -289,7 +284,7 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, */ rt2x00pci_register_read(rt2x00dev, CSR14, ®); rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, 1); + rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON)); rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync); rt2x00pci_register_write(rt2x00dev, CSR14, reg); @@ -424,7 +419,7 @@ static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, } static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, const int antenna_rx) + struct antenna_setup *ant) { u32 reg; u8 r14; @@ -437,18 +432,20 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the TX antenna. */ - switch (antenna_tx) { - case ANTENNA_SW_DIVERSITY: - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); - rt2x00_set_field32(®, BBPCSR1_CCK, 2); - rt2x00_set_field32(®, BBPCSR1_OFDM, 2); - break; + switch (ant->tx) { case ANTENNA_A: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0); rt2x00_set_field32(®, BBPCSR1_CCK, 0); rt2x00_set_field32(®, BBPCSR1_OFDM, 0); break; + case ANTENNA_HW_DIVERSITY: + 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(&r2, BBP_R2_TX_ANTENNA, 2); rt2x00_set_field32(®, BBPCSR1_CCK, 2); @@ -459,14 +456,18 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the RX antenna. */ - switch (antenna_rx) { - case ANTENNA_SW_DIVERSITY: - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); - break; + switch (ant->rx) { case ANTENNA_A: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); break; + case ANTENNA_HW_DIVERSITY: + 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(&r14, BBP_R14_RX_ANTENNA, 2); break; @@ -541,9 +542,7 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, rt2500pci_config_txpower(rt2x00dev, libconf->conf->power_level); if (flags & CONFIG_UPDATE_ANTENNA) - rt2500pci_config_antenna(rt2x00dev, - libconf->conf->antenna_sel_tx, - libconf->conf->antenna_sel_rx); + rt2500pci_config_antenna(rt2x00dev, &libconf->ant); if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) rt2500pci_config_duration(rt2x00dev, libconf); } @@ -559,18 +558,10 @@ static void rt2500pci_enable_led(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70); rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30); - - if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) { - rt2x00_set_field32(®, LEDCSR_LINK, 1); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0); - } else if (rt2x00dev->led_mode == LED_MODE_ASUS) { - rt2x00_set_field32(®, LEDCSR_LINK, 0); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, 1); - } else { - rt2x00_set_field32(®, LEDCSR_LINK, 1); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, 1); - } - + rt2x00_set_field32(®, LEDCSR_LINK, + (rt2x00dev->led_mode != LED_MODE_ASUS)); + rt2x00_set_field32(®, LEDCSR_ACTIVITY, + (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY)); rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); } @@ -587,7 +578,8 @@ static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev) /* * Link tuning */ -static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev) +static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { u32 reg; @@ -595,13 +587,13 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev) * Update FCS error count from register. */ rt2x00pci_register_read(rt2x00dev, CNT0, ®); - rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); + qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); /* * Update False CCA count from register. */ rt2x00pci_register_read(rt2x00dev, CNT3, ®); - rt2x00dev->link.false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); + qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); } static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev) @@ -679,10 +671,10 @@ dynamic_cca_tune: * R17 is inside the dynamic tuning range, * start tuning the link based on the false cca counter. */ - if (rt2x00dev->link.false_cca > 512 && r17 < 0x40) { + if (rt2x00dev->link.qual.false_cca > 512 && r17 < 0x40) { rt2500pci_bbp_write(rt2x00dev, 17, ++r17); rt2x00dev->link.vgc_level = r17; - } else if (rt2x00dev->link.false_cca < 100 && r17 > 0x32) { + } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > 0x32) { rt2500pci_bbp_write(rt2x00dev, 17, --r17); rt2x00dev->link.vgc_level = r17; } @@ -691,55 +683,35 @@ dynamic_cca_tune: /* * Initialization functions. */ -static void rt2500pci_init_rxring(struct rt2x00_dev *rt2x00dev) +static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry) { - struct data_ring *ring = rt2x00dev->rx; - struct data_desc *rxd; - unsigned int i; + __le32 *rxd = entry->priv; 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, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, - ring->entry[i].data_dma); - rt2x00_desc_write(rxd, 1, 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(rxd, 1, &word); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma); + rt2x00_desc_write(rxd, 1, word); - rt2x00_ring_index_clear(rt2x00dev->rx); + rt2x00_desc_read(rxd, 0, &word); + rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); + rt2x00_desc_write(rxd, 0, word); } -static void rt2500pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue) +static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry) { - struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); - struct data_desc *txd; - unsigned int i; + __le32 *txd = entry->priv; 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_ADDRESS, - ring->entry[i].data_dma); - rt2x00_desc_write(txd, 1, 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(txd, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma); + rt2x00_desc_write(txd, 1, word); - rt2x00_ring_index_clear(ring); + 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); } static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev) @@ -747,15 +719,6 @@ static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev) u32 reg; /* - * Initialize rings. - */ - rt2500pci_init_rxring(rt2x00dev); - rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0); - rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1); - rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON); - rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); - - /* * Initialize registers. */ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); @@ -1170,12 +1133,12 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_desc *txd, + struct sk_buff *skb, struct txdata_entry_desc *desc, - struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control) { + struct skb_desc *skbdesc = get_skb_desc(skb); + __le32 *txd = skbdesc->desc; u32 word; /* @@ -1206,7 +1169,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - !(control->flags & IEEE80211_TXCTL_NO_ACK)); + test_bit(ENTRY_TXD_ACK, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, @@ -1216,7 +1179,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); - 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_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } @@ -1239,12 +1202,12 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, } rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - if (queue == IEEE80211_TX_QUEUE_DATA0) - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); - else if (queue == IEEE80211_TX_QUEUE_DATA1) - rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); - else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON) - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); + rt2x00_set_field32(®, TXCSR0_KICK_PRIO, + (queue == IEEE80211_TX_QUEUE_DATA0)); + rt2x00_set_field32(®, TXCSR0_KICK_TX, + (queue == IEEE80211_TX_QUEUE_DATA1)); + rt2x00_set_field32(®, TXCSR0_KICK_ATIM, + (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } @@ -1254,7 +1217,7 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, static void rt2500pci_fill_rxdone(struct data_entry *entry, struct rxdata_entry_desc *desc) { - struct data_desc *rxd = entry->priv; + __le32 *rxd = entry->priv; u32 word0; u32 word2; @@ -1272,6 +1235,7 @@ static void rt2500pci_fill_rxdone(struct data_entry *entry, entry->ring->rt2x00dev->rssi_offset; desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* @@ -1281,7 +1245,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) { struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); struct data_entry *entry; - struct data_desc *txd; + __le32 *txd; u32 word; int tx_status; int retry; @@ -1301,26 +1265,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) tx_status = rt2x00_get_field32(word, TXD_W0_RESULT); retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00lib_txdone(entry, tx_status, retry); - - /* - * 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(ring); + rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); } - - /* - * 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. - */ - entry = ring->entry; - if (!rt2x00_ring_full(ring)) - ieee80211_wake_queue(rt2x00dev->hw, - entry->tx_status.control.queue); } static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) @@ -1420,9 +1366,12 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) 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, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, 0); + rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, + ANTENNA_SW_DIVERSITY); + rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, + ANTENNA_SW_DIVERSITY); + rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, + LED_MODE_DEFAULT); rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0); rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0); rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522); @@ -1481,9 +1430,9 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * 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); /* @@ -1774,7 +1723,6 @@ static void rt2500pci_configure_filter(struct ieee80211_hw *hw, struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; u32 reg; /* @@ -1793,22 +1741,19 @@ static void rt2500pci_configure_filter(struct ieee80211_hw *hw, * 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. @@ -1890,7 +1835,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .configure_filter = rt2500pci_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt2500pci_set_retry_limit, - .erp_ie_changed = rt2x00mac_erp_ie_changed, + .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2500pci_get_tsf, @@ -1904,6 +1849,8 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .probe_hw = rt2500pci_probe_hw, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize, + .init_rxentry = rt2500pci_init_rxentry, + .init_txentry = rt2500pci_init_txentry, .set_device_state = rt2500pci_set_device_state, .rfkill_poll = rt2500pci_rfkill_poll, .link_stats = rt2500pci_link_stats, @@ -1921,7 +1868,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { }; static const struct rt2x00_ops rt2500pci_ops = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .rxd_size = RXD_DESC_SIZE, .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, @@ -1949,7 +1896,7 @@ MODULE_DEVICE_TABLE(pci, rt2500pci_device_table); MODULE_LICENSE("GPL"); static struct pci_driver rt2500pci_driver = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .id_table = rt2500pci_device_table, .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index d92aa56b2f4b..92ba0902d107 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1082,8 +1082,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 11 * sizeof(struct data_desc) ) -#define RXD_DESC_SIZE ( 11 * sizeof(struct data_desc) ) +#define TXD_DESC_SIZE ( 11 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 11 * sizeof(__le32) ) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 18b1f9145389..86ded4066f5b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -24,11 +24,6 @@ Supported chipsets: RT2570. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2500usb" - #include <linux/delay.h> #include <linux/etherdevice.h> #include <linux/init.h> @@ -52,8 +47,10 @@ * between each attampt. When the busy bit is still set at that time, * the access attempt is considered to have failed, * and we will print an error. + * If the usb_cache_mutex is already held then the _lock variants must + * be used instead. */ -static inline void rt2500usb_register_read(const struct rt2x00_dev *rt2x00dev, +static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, const unsigned int offset, u16 *value) { @@ -64,8 +61,18 @@ static inline void rt2500usb_register_read(const struct rt2x00_dev *rt2x00dev, *value = le16_to_cpu(reg); } -static inline void rt2500usb_register_multiread(const struct rt2x00_dev - *rt2x00dev, +static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u16 *value) +{ + __le16 reg; + rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + ®, sizeof(u16), REGISTER_TIMEOUT); + *value = le16_to_cpu(reg); +} + +static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev, const unsigned int offset, void *value, const u16 length) { @@ -75,7 +82,7 @@ static inline void rt2500usb_register_multiread(const struct rt2x00_dev value, length, timeout); } -static inline void rt2500usb_register_write(const struct rt2x00_dev *rt2x00dev, +static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, const unsigned int offset, u16 value) { @@ -85,8 +92,17 @@ static inline void rt2500usb_register_write(const struct rt2x00_dev *rt2x00dev, ®, sizeof(u16), REGISTER_TIMEOUT); } -static inline void rt2500usb_register_multiwrite(const struct rt2x00_dev - *rt2x00dev, +static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u16 value) +{ + __le16 reg = cpu_to_le16(value); + rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + ®, sizeof(u16), REGISTER_TIMEOUT); +} + +static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, const unsigned int offset, void *value, const u16 length) { @@ -96,13 +112,13 @@ static inline void rt2500usb_register_multiwrite(const struct rt2x00_dev value, length, timeout); } -static u16 rt2500usb_bbp_check(const struct rt2x00_dev *rt2x00dev) +static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev) { u16 reg; unsigned int i; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_register_read(rt2x00dev, PHY_CSR8, ®); + rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, ®); if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY)) break; udelay(REGISTER_BUSY_DELAY); @@ -111,17 +127,20 @@ static u16 rt2500usb_bbp_check(const struct rt2x00_dev *rt2x00dev) return reg; } -static void rt2500usb_bbp_write(const struct rt2x00_dev *rt2x00dev, +static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { u16 reg; + mutex_lock(&rt2x00dev->usb_cache_mutex); + /* * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); + mutex_unlock(&rt2x00dev->usb_cache_mutex); return; } @@ -133,14 +152,18 @@ static void rt2500usb_bbp_write(const struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); - rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); + + mutex_unlock(&rt2x00dev->usb_cache_mutex); } -static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev, +static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u8 *value) { u16 reg; + mutex_lock(&rt2x00dev->usb_cache_mutex); + /* * Wait until the BBP becomes ready. */ @@ -157,7 +180,7 @@ static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); - rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); /* * Wait until the BBP becomes ready. @@ -166,14 +189,17 @@ static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev, if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); *value = 0xff; + mutex_unlock(&rt2x00dev->usb_cache_mutex); return; } - rt2500usb_register_read(rt2x00dev, PHY_CSR7, ®); + rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); + + mutex_unlock(&rt2x00dev->usb_cache_mutex); } -static void rt2500usb_rf_write(const struct rt2x00_dev *rt2x00dev, +static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u16 reg; @@ -182,20 +208,23 @@ static void rt2500usb_rf_write(const struct rt2x00_dev *rt2x00dev, if (!word) return; + mutex_lock(&rt2x00dev->usb_cache_mutex); + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_register_read(rt2x00dev, PHY_CSR10, ®); + rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY)) goto rf_write; udelay(REGISTER_BUSY_DELAY); } + mutex_unlock(&rt2x00dev->usb_cache_mutex); ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); return; rf_write: reg = 0; rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); - rt2500usb_register_write(rt2x00dev, PHY_CSR9, reg); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); reg = 0; rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); @@ -203,20 +232,22 @@ rf_write: rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); - rt2500usb_register_write(rt2x00dev, PHY_CSR10, reg); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); rt2x00_rf_write(rt2x00dev, word, value); + + mutex_unlock(&rt2x00dev->usb_cache_mutex); } #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u16)) ) -static void rt2500usb_read_csr(const struct rt2x00_dev *rt2x00dev, +static void rt2500usb_read_csr(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 *data) { rt2500usb_register_read(rt2x00dev, CSR_OFFSET(word), (u16 *) data); } -static void rt2500usb_write_csr(const struct rt2x00_dev *rt2x00dev, +static void rt2500usb_write_csr(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 data) { rt2500usb_register_write(rt2x00dev, CSR_OFFSET(word), data); @@ -296,7 +327,8 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, + (tsf_sync == TSF_SYNC_BEACON)); rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, tsf_sync); rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); @@ -385,7 +417,7 @@ static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev, } static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, const int antenna_rx) + struct antenna_setup *ant) { u8 r2; u8 r14; @@ -400,8 +432,7 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the TX antenna. */ - switch (antenna_tx) { - case ANTENNA_SW_DIVERSITY: + switch (ant->tx) { case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1); rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1); @@ -412,6 +443,13 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0); rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0); 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(&r2, BBP_R2_TX_ANTENNA, 2); rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2); @@ -422,14 +460,20 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the RX antenna. */ - switch (antenna_rx) { - case ANTENNA_SW_DIVERSITY: + switch (ant->rx) { case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1); break; case ANTENNA_A: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); 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(&r14, BBP_R14_RX_ANTENNA, 2); break; @@ -487,9 +531,7 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, rt2500usb_config_txpower(rt2x00dev, libconf->conf->power_level); if (flags & CONFIG_UPDATE_ANTENNA) - rt2500usb_config_antenna(rt2x00dev, - libconf->conf->antenna_sel_tx, - libconf->conf->antenna_sel_rx); + rt2500usb_config_antenna(rt2x00dev, &libconf->ant); if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) rt2500usb_config_duration(rt2x00dev, libconf); } @@ -507,18 +549,10 @@ static void rt2500usb_enable_led(struct rt2x00_dev *rt2x00dev) rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg); rt2500usb_register_read(rt2x00dev, MAC_CSR20, ®); - - if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) { - rt2x00_set_field16(®, MAC_CSR20_LINK, 1); - rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, 0); - } else if (rt2x00dev->led_mode == LED_MODE_ASUS) { - rt2x00_set_field16(®, MAC_CSR20_LINK, 0); - rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, 1); - } else { - rt2x00_set_field16(®, MAC_CSR20_LINK, 1); - rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, 1); - } - + rt2x00_set_field16(®, MAC_CSR20_LINK, + (rt2x00dev->led_mode != LED_MODE_ASUS)); + rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, + (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY)); rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg); } @@ -535,7 +569,8 @@ static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev) /* * Link tuning */ -static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev) +static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { u16 reg; @@ -543,14 +578,13 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev) * Update FCS error count from register. */ rt2500usb_register_read(rt2x00dev, STA_CSR0, ®); - rt2x00dev->link.rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR); + qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR); /* * Update False CCA count from register. */ rt2500usb_register_read(rt2x00dev, STA_CSR3, ®); - rt2x00dev->link.false_cca = - rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR); + qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR); } static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) @@ -673,10 +707,10 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) if (r17 > up_bound) { rt2500usb_bbp_write(rt2x00dev, 17, up_bound); rt2x00dev->link.vgc_level = up_bound; - } else if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) { + } else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { rt2500usb_bbp_write(rt2x00dev, 17, ++r17); rt2x00dev->link.vgc_level = r17; - } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) { + } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { rt2500usb_bbp_write(rt2x00dev, 17, --r17); rt2x00dev->link.vgc_level = r17; } @@ -755,9 +789,11 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); - reg &= ~0x0002; + rt2x00_set_field16(®, PHY_CSR2_LNA, 0); } else { - reg = 0x3002; + reg = 0; + rt2x00_set_field16(®, PHY_CSR2_LNA, 1); + rt2x00_set_field16(®, PHY_CSR2_LNA_MODE, 3); } rt2500usb_register_write(rt2x00dev, PHY_CSR2, reg); @@ -884,8 +920,6 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev) return -EIO; } - rt2x00usb_enable_radio(rt2x00dev); - /* * Enable LED */ @@ -988,12 +1022,12 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_desc *txd, + struct sk_buff *skb, struct txdata_entry_desc *desc, - struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control) { + struct skb_desc *skbdesc = get_skb_desc(skb); + __le32 *txd = skbdesc->desc; u32 word; /* @@ -1018,7 +1052,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - !(control->flags & IEEE80211_TXCTL_NO_ACK)); + test_bit(ENTRY_TXD_ACK, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, @@ -1026,7 +1060,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, !!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)); rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } @@ -1079,10 +1113,10 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, static void rt2500usb_fill_rxdone(struct data_entry *entry, struct rxdata_entry_desc *desc) { + struct skb_desc *skbdesc = get_skb_desc(entry->skb); struct urb *urb = entry->priv; - struct data_desc *rxd = (struct data_desc *)(entry->skb->data + - (urb->actual_length - - entry->ring->desc_size)); + __le32 *rxd = (__le32 *)(entry->skb->data + + (urb->actual_length - entry->ring->desc_size)); u32 word0; u32 word1; @@ -1103,8 +1137,15 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry, entry->ring->rt2x00dev->rssi_offset; desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); - return; + /* + * Set descriptor and data pointer. + */ + skbdesc->desc = entry->skb->data + desc->size; + skbdesc->desc_len = entry->ring->desc_size; + skbdesc->data = entry->skb->data; + skbdesc->data_len = desc->size; } /* @@ -1163,9 +1204,12 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) 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, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, 0); + rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, + ANTENNA_SW_DIVERSITY); + rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, + ANTENNA_SW_DIVERSITY); + rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, + LED_MODE_DEFAULT); rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0); rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0); rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522); @@ -1275,12 +1319,23 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * 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); /* + * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead. + * I am not 100% sure about this, but the legacy drivers do not + * indicate antenna swapping in software is required when + * diversity is enabled. + */ + if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) + rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; + if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) + rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; + + /* * Store led mode, for correct led behaviour. */ rt2x00dev->led_mode = @@ -1562,7 +1617,6 @@ static void rt2500usb_configure_filter(struct ieee80211_hw *hw, struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; u16 reg; /* @@ -1581,22 +1635,19 @@ static void rt2500usb_configure_filter(struct ieee80211_hw *hw, * 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; /* * When in atomic context, reschedule and let rt2x00lib @@ -1638,8 +1689,8 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; struct usb_device *usb_dev = interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); - struct data_ring *ring = - rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + struct skb_desc *desc; + struct data_ring *ring; struct data_entry *beacon; struct data_entry *guardian; int pipe = usb_sndbulkpipe(usb_dev, 1); @@ -1651,6 +1702,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, * initialization. */ control->queue = IEEE80211_TX_QUEUE_BEACON; + ring = rt2x00lib_get_ring(rt2x00dev, control->queue); /* * Obtain 2 entries, one for the guardian byte, @@ -1661,23 +1713,34 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, beacon = rt2x00_get_data_entry(ring); /* - * First we create the beacon. + * Add the descriptor in front of the skb. */ skb_push(skb, ring->desc_size); memset(skb->data, 0, ring->desc_size); - rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data, - (struct ieee80211_hdr *)(skb->data + - ring->desc_size), - skb->len - ring->desc_size, control); + /* + * Fill in skb descriptor + */ + desc = get_skb_desc(skb); + desc->desc_len = ring->desc_size; + desc->data_len = skb->len - ring->desc_size; + desc->desc = skb->data; + desc->data = skb->data + ring->desc_size; + desc->ring = ring; + desc->entry = beacon; + + rt2x00lib_write_tx_desc(rt2x00dev, skb, control); + /* + * USB devices cannot blindly pass the skb->len as the + * length of the data to usb_fill_bulk_urb. Pass the skb + * to the driver to determine what the length should be. + */ length = rt2500usb_get_tx_data_len(rt2x00dev, skb); usb_fill_bulk_urb(beacon->priv, usb_dev, pipe, skb->data, length, rt2500usb_beacondone, beacon); - beacon->skb = skb; - /* * Second we need to create the guardian byte. * We only need a single byte, so lets recycle @@ -1710,7 +1773,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .config_interface = rt2x00mac_config_interface, .configure_filter = rt2500usb_configure_filter, .get_stats = rt2x00mac_get_stats, - .erp_ie_changed = rt2x00mac_erp_ie_changed, + .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .beacon_update = rt2500usb_beacon_update, @@ -1720,6 +1783,8 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .probe_hw = rt2500usb_probe_hw, .initialize = rt2x00usb_initialize, .uninitialize = rt2x00usb_uninitialize, + .init_rxentry = rt2x00usb_init_rxentry, + .init_txentry = rt2x00usb_init_txentry, .set_device_state = rt2500usb_set_device_state, .link_stats = rt2500usb_link_stats, .reset_tuner = rt2500usb_reset_tuner, @@ -1737,7 +1802,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { }; static const struct rt2x00_ops rt2500usb_ops = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .rxd_size = RXD_DESC_SIZE, .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, @@ -1809,7 +1874,7 @@ MODULE_DEVICE_TABLE(usb, rt2500usb_device_table); MODULE_LICENSE("GPL"); static struct usb_driver rt2500usb_driver = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .id_table = rt2500usb_device_table, .probe = rt2x00usb_probe, .disconnect = rt2x00usb_disconnect, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b18d56e73cf1..9e0433722e3d 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -430,10 +430,21 @@ /* * MAC configuration registers. + */ + +/* * PHY_CSR2: TX MAC configuration. - * PHY_CSR3: RX MAC configuration. + * NOTE: Both register fields are complete dummy, + * documentation and legacy drivers are unclear un + * what this register means or what fields exists. */ #define PHY_CSR2 0x04c4 +#define PHY_CSR2_LNA FIELD16(0x0002) +#define PHY_CSR2_LNA_MODE FIELD16(0x3000) + +/* + * PHY_CSR3: RX MAC configuration. + */ #define PHY_CSR3 0x04c6 /* @@ -692,8 +703,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 5 * sizeof(struct data_desc) ) -#define RXD_DESC_SIZE ( 4 * sizeof(struct data_desc) ) +#define TXD_DESC_SIZE ( 5 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 4 * sizeof(__le32) ) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c8f16f161c28..05927b908f80 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -31,6 +31,8 @@ #include <linux/skbuff.h> #include <linux/workqueue.h> #include <linux/firmware.h> +#include <linux/mutex.h> +#include <linux/etherdevice.h> #include <net/mac80211.h> @@ -40,9 +42,8 @@ /* * Module information. - * DRV_NAME should be set within the individual module source files. */ -#define DRV_VERSION "2.0.10" +#define DRV_VERSION "2.0.14" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* @@ -55,7 +56,7 @@ #define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \ printk(__kernlvl "%s -> %s: %s - " __msg, \ - DRV_NAME, __FUNCTION__, __lvl, ##__args) + KBUILD_MODNAME, __FUNCTION__, __lvl, ##__args) #ifdef CONFIG_RT2X00_DEBUG #define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ @@ -133,20 +134,26 @@ */ static inline int is_rts_frame(u16 fc) { - return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)); + return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)); } static inline int is_cts_frame(u16 fc) { - return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS)); + return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS)); } static inline int is_probe_resp(u16 fc) { - return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)); + return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)); +} + +static inline int is_beacon(u16 fc) +{ + return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)); } /* @@ -180,18 +187,17 @@ struct rf_channel { }; /* - * To optimize the quality of the link we need to store - * the quality of received frames and periodically - * optimize the link. + * Antenna setup values. */ -struct link { - /* - * Link tuner counter - * The number of times the link has been tuned - * since the radio has been switched on. - */ - u32 count; +struct antenna_setup { + enum antenna rx; + enum antenna tx; +}; +/* + * Quality statistics about the currently active link. + */ +struct link_qual { /* * Statistics required for Link tuning. * For the average RSSI value we use the "Walking average" approach. @@ -211,7 +217,6 @@ struct link { * the new values correctly allowing a effective link tuning. */ int avg_rssi; - int vgc_level; int false_cca; /* @@ -240,6 +245,72 @@ struct link { #define WEIGHT_RSSI 20 #define WEIGHT_RX 40 #define WEIGHT_TX 40 +}; + +/* + * Antenna settings about the currently active link. + */ +struct link_ant { + /* + * Antenna flags + */ + unsigned int flags; +#define ANTENNA_RX_DIVERSITY 0x00000001 +#define ANTENNA_TX_DIVERSITY 0x00000002 +#define ANTENNA_MODE_SAMPLE 0x00000004 + + /* + * Currently active TX/RX antenna setup. + * When software diversity is used, this will indicate + * which antenna is actually used at this time. + */ + struct antenna_setup active; + + /* + * RSSI information for the different antenna's. + * These statistics are used to determine when + * to switch antenna when using software diversity. + * + * rssi[0] -> Antenna A RSSI + * rssi[1] -> Antenna B RSSI + */ + int rssi_history[2]; + + /* + * Current RSSI average of the currently active antenna. + * Similar to the avg_rssi in the link_qual structure + * this value is updated by using the walking average. + */ + int rssi_ant; +}; + +/* + * To optimize the quality of the link we need to store + * the quality of received frames and periodically + * optimize the link. + */ +struct link { + /* + * Link tuner counter + * The number of times the link has been tuned + * since the radio has been switched on. + */ + u32 count; + + /* + * Quality measurement values. + */ + struct link_qual qual; + + /* + * TX/RX antenna setup. + */ + struct link_ant ant; + + /* + * Active VGC level + */ + int vgc_level; /* * Work structure for scheduling periodic link tuning. @@ -248,36 +319,47 @@ struct link { }; /* - * Clear all counters inside the link structure. - * This can be easiest achieved by memsetting everything - * except for the work structure at the end. + * Small helper macro to work with moving/walking averages. */ -static inline void rt2x00_clear_link(struct link *link) -{ - memset(link, 0x00, sizeof(*link) - sizeof(link->work)); - link->rx_percentage = 50; - link->tx_percentage = 50; -} +#define MOVING_AVERAGE(__avg, __val, __samples) \ + ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) ) /* - * Update the rssi using the walking average approach. + * When we lack RSSI information return something less then -80 to + * tell the driver to tune the device to maximum sensitivity. */ -static inline void rt2x00_update_link_rssi(struct link *link, int rssi) -{ - if (!link->avg_rssi) - link->avg_rssi = rssi; - else - link->avg_rssi = ((link->avg_rssi * 7) + rssi) / 8; -} +#define DEFAULT_RSSI ( -128 ) /* - * When the avg_rssi is unset or no frames have been received), - * we need to return the default value which needs to be less - * than -80 so the device will select the maximum sensitivity. + * Link quality access functions. */ static inline int rt2x00_get_link_rssi(struct link *link) { - return (link->avg_rssi && link->rx_success) ? link->avg_rssi : -128; + if (link->qual.avg_rssi && link->qual.rx_success) + return link->qual.avg_rssi; + return DEFAULT_RSSI; +} + +static inline int rt2x00_get_link_ant_rssi(struct link *link) +{ + if (link->ant.rssi_ant && link->qual.rx_success) + return link->ant.rssi_ant; + return DEFAULT_RSSI; +} + +static inline int rt2x00_get_link_ant_rssi_history(struct link *link, + enum antenna ant) +{ + if (link->ant.rssi_history[ant - ANTENNA_A]) + return link->ant.rssi_history[ant - ANTENNA_A]; + return DEFAULT_RSSI; +} + +static inline int rt2x00_update_ant_rssi(struct link *link, int rssi) +{ + int old_rssi = link->ant.rssi_history[link->ant.active.rx - ANTENNA_A]; + link->ant.rssi_history[link->ant.active.rx - ANTENNA_A] = rssi; + return old_rssi; } /* @@ -290,14 +372,12 @@ struct interface { * to us by the 80211 stack, and is used to request * new beacons. */ - int id; + struct ieee80211_vif *id; /* * Current working type (IEEE80211_IF_TYPE_*). - * When set to INVALID_INTERFACE, no interface is configured. */ int type; -#define INVALID_INTERFACE IEEE80211_IF_TYPE_INVALID /* * MAC of the device. @@ -308,11 +388,6 @@ struct interface { * BBSID of the AP to associate with. */ u8 bssid[ETH_ALEN]; - - /* - * Store the packet filter mode for the current interface. - */ - unsigned int filter; }; static inline int is_interface_present(struct interface *intf) @@ -362,6 +437,8 @@ struct rt2x00lib_conf { struct ieee80211_conf *conf; struct rf_channel rf; + struct antenna_setup ant; + int phymode; int basic_rates; @@ -397,12 +474,21 @@ struct rt2x00lib_ops { void (*uninitialize) (struct rt2x00_dev *rt2x00dev); /* + * Ring initialization handlers + */ + void (*init_rxentry) (struct rt2x00_dev *rt2x00dev, + struct data_entry *entry); + void (*init_txentry) (struct rt2x00_dev *rt2x00dev, + struct data_entry *entry); + + /* * Radio control handlers. */ int (*set_device_state) (struct rt2x00_dev *rt2x00dev, enum dev_state state); int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev); - void (*link_stats) (struct rt2x00_dev *rt2x00dev); + void (*link_stats) (struct rt2x00_dev *rt2x00dev, + struct link_qual *qual); void (*reset_tuner) (struct rt2x00_dev *rt2x00dev); void (*link_tuner) (struct rt2x00_dev *rt2x00dev); @@ -410,10 +496,8 @@ struct rt2x00lib_ops { * TX control handlers */ void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, - struct data_desc *txd, + struct sk_buff *skb, struct txdata_entry_desc *desc, - struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control); int (*write_tx_data) (struct rt2x00_dev *rt2x00dev, struct data_ring *ring, struct sk_buff *skb, @@ -545,7 +629,7 @@ struct rt2x00_dev { * required for deregistration of debugfs. */ #ifdef CONFIG_RT2X00_LIB_DEBUGFS - const struct rt2x00debug_intf *debugfs_intf; + struct rt2x00debug_intf *debugfs_intf; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ /* @@ -566,6 +650,13 @@ struct rt2x00_dev { struct hw_mode_spec spec; /* + * This is the default TX/RX antenna setup as indicated + * by the device's EEPROM. When mac80211 sets its + * antenna value to 0 we should be using these values. + */ + struct antenna_setup default_ant; + + /* * Register pointers * csr_addr: Base register address. (PCI) * csr_cache: CSR cache for usb_control_msg. (USB) @@ -574,6 +665,25 @@ struct rt2x00_dev { void *csr_cache; /* + * Mutex to protect register accesses on USB devices. + * There are 2 reasons this is needed, one is to ensure + * use of the csr_cache (for USB devices) by one thread + * isn't corrupted by another thread trying to access it. + * The other is that access to BBP and RF registers + * require multiple BUS transactions and if another thread + * attempted to access one of those registers at the same + * time one of the writes could silently fail. + */ + struct mutex usb_cache_mutex; + + /* + * Current packet filter configuration for the device. + * This contains all currently active FIF_* flags send + * to us by mac80211 during configure_filter(). + */ + unsigned int packet_filter; + + /* * Interface configuration. */ struct interface interface; @@ -697,13 +807,13 @@ struct rt2x00_dev { * Generic RF access. * The RF is being accessed by word index. */ -static inline void rt2x00_rf_read(const struct rt2x00_dev *rt2x00dev, +static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 *data) { *data = rt2x00dev->rf[word]; } -static inline void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev, +static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 data) { rt2x00dev->rf[word] = data; @@ -713,19 +823,19 @@ static inline void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev, * Generic EEPROM access. * The EEPROM is being accessed by word index. */ -static inline void *rt2x00_eeprom_addr(const struct rt2x00_dev *rt2x00dev, +static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev, const unsigned int word) { return (void *)&rt2x00dev->eeprom[word]; } -static inline void rt2x00_eeprom_read(const struct rt2x00_dev *rt2x00dev, +static inline void rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u16 *data) { *data = le16_to_cpu(rt2x00dev->eeprom[word]); } -static inline void rt2x00_eeprom_write(const struct rt2x00_dev *rt2x00dev, +static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, u16 data) { rt2x00dev->eeprom[word] = cpu_to_le16(data); @@ -804,9 +914,7 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, * TX descriptor initializer */ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_desc *txd, - struct ieee80211_hdr *ieee80211hdr, - unsigned int length, + struct sk_buff *skb, struct ieee80211_tx_control *control); /* @@ -821,14 +929,17 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, void rt2x00mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf); int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); -int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id, +int rt2x00mac_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct ieee80211_if_conf *conf); int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats); -void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes, - int cts_protection, int preamble); +void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue, const struct ieee80211_tx_queue_params *params); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 12914cf7156c..72cfe00c1ed7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -23,11 +23,6 @@ Abstract: rt2x00 generic configuration routines. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2x00lib" - #include <linux/kernel.h> #include <linux/module.h> @@ -94,12 +89,44 @@ void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type) rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync); } +void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, + enum antenna rx, enum antenna tx) +{ + struct rt2x00lib_conf libconf; + + libconf.ant.rx = rx; + libconf.ant.tx = tx; + + /* + * Antenna setup changes require the RX to be disabled, + * else the changes will be ignored by the device. + */ + if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) + rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + + /* + * Write new antenna setup to device and reset the link tuner. + * The latter is required since we need to recalibrate the + * noise-sensitivity ratio for the new setup. + */ + rt2x00dev->ops->lib->config(rt2x00dev, CONFIG_UPDATE_ANTENNA, &libconf); + rt2x00lib_reset_link_tuner(rt2x00dev); + + rt2x00dev->link.ant.active.rx = libconf.ant.rx; + rt2x00dev->link.ant.active.tx = libconf.ant.tx; + + if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) + rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); +} + void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config) { struct rt2x00lib_conf libconf; struct ieee80211_hw_mode *mode; struct ieee80211_rate *rate; + struct antenna_setup *default_ant = &rt2x00dev->default_ant; + struct antenna_setup *active_ant = &rt2x00dev->link.ant.active; int flags = 0; int short_slot_time; @@ -122,7 +149,39 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, flags |= CONFIG_UPDATE_CHANNEL; if (rt2x00dev->tx_power != conf->power_level) flags |= CONFIG_UPDATE_TXPOWER; - if (rt2x00dev->rx_status.antenna == conf->antenna_sel_rx) + + /* + * Determining changes in the antenna setups request several checks: + * antenna_sel_{r,t}x = 0 + * -> Does active_{r,t}x match default_{r,t}x + * -> Is default_{r,t}x SW_DIVERSITY + * antenna_sel_{r,t}x = 1/2 + * -> Does active_{r,t}x match antenna_sel_{r,t}x + * The reason for not updating the antenna while SW diversity + * should be used is simple: Software diversity means that + * we should switch between the antenna's based on the + * quality. This means that the current antenna is good enough + * to work with untill the link tuner decides that an antenna + * switch should be performed. + */ + if (!conf->antenna_sel_rx && + default_ant->rx != ANTENNA_SW_DIVERSITY && + default_ant->rx != active_ant->rx) + flags |= CONFIG_UPDATE_ANTENNA; + else if (conf->antenna_sel_rx && + conf->antenna_sel_rx != active_ant->rx) + flags |= CONFIG_UPDATE_ANTENNA; + else if (active_ant->rx == ANTENNA_SW_DIVERSITY) + flags |= CONFIG_UPDATE_ANTENNA; + + if (!conf->antenna_sel_tx && + default_ant->tx != ANTENNA_SW_DIVERSITY && + default_ant->tx != active_ant->tx) + flags |= CONFIG_UPDATE_ANTENNA; + else if (conf->antenna_sel_tx && + conf->antenna_sel_tx != active_ant->tx) + flags |= CONFIG_UPDATE_ANTENNA; + else if (active_ant->tx == ANTENNA_SW_DIVERSITY) flags |= CONFIG_UPDATE_ANTENNA; /* @@ -171,6 +230,22 @@ config: sizeof(libconf.rf)); } + if (flags & CONFIG_UPDATE_ANTENNA) { + if (conf->antenna_sel_rx) + libconf.ant.rx = conf->antenna_sel_rx; + else if (default_ant->rx != ANTENNA_SW_DIVERSITY) + libconf.ant.rx = default_ant->rx; + else if (active_ant->rx == ANTENNA_SW_DIVERSITY) + libconf.ant.rx = ANTENNA_B; + + if (conf->antenna_sel_tx) + libconf.ant.tx = conf->antenna_sel_tx; + else if (default_ant->tx != ANTENNA_SW_DIVERSITY) + libconf.ant.tx = default_ant->tx; + else if (active_ant->tx == ANTENNA_SW_DIVERSITY) + libconf.ant.tx = ANTENNA_B; + } + if (flags & CONFIG_UPDATE_SLOT_TIME) { short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME; @@ -196,10 +271,17 @@ config: if (flags & (CONFIG_UPDATE_CHANNEL | CONFIG_UPDATE_ANTENNA)) rt2x00lib_reset_link_tuner(rt2x00dev); - rt2x00dev->curr_hwmode = libconf.phymode; - rt2x00dev->rx_status.phymode = conf->phymode; + if (flags & CONFIG_UPDATE_PHYMODE) { + rt2x00dev->curr_hwmode = libconf.phymode; + rt2x00dev->rx_status.phymode = conf->phymode; + } + rt2x00dev->rx_status.freq = conf->freq; rt2x00dev->rx_status.channel = conf->channel; rt2x00dev->tx_power = conf->power_level; - rt2x00dev->rx_status.antenna = conf->antenna_sel_rx; + + if (flags & CONFIG_UPDATE_ANTENNA) { + rt2x00dev->link.ant.active.rx = libconf.ant.rx; + rt2x00dev->link.ant.active.tx = libconf.ant.tx; + } } diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 9275d6f9517e..b44a9f4b9b7f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -23,18 +23,15 @@ Abstract: rt2x00 debugfs specific routines. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2x00lib" - #include <linux/debugfs.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/poll.h> #include <linux/uaccess.h> #include "rt2x00.h" #include "rt2x00lib.h" +#include "rt2x00dump.h" #define PRINT_LINE_LEN_MAX 32 @@ -55,18 +52,22 @@ struct rt2x00debug_intf { /* * Debugfs entries for: * - driver folder - * - driver file - * - chipset file - * - device flags file - * - register offset/value files - * - eeprom offset/value files - * - bbp offset/value files - * - rf offset/value files + * - driver file + * - chipset file + * - device flags file + * - register folder + * - csr offset/value files + * - eeprom offset/value files + * - bbp offset/value files + * - rf offset/value files + * - frame dump folder + * - frame dump file */ struct dentry *driver_folder; struct dentry *driver_entry; struct dentry *chipset_entry; struct dentry *dev_flags; + struct dentry *register_folder; struct dentry *csr_off_entry; struct dentry *csr_val_entry; struct dentry *eeprom_off_entry; @@ -75,6 +76,24 @@ struct rt2x00debug_intf { struct dentry *bbp_val_entry; struct dentry *rf_off_entry; struct dentry *rf_val_entry; + struct dentry *frame_folder; + struct dentry *frame_dump_entry; + + /* + * The frame dump file only allows a single reader, + * so we need to store the current state here. + */ + unsigned long frame_dump_flags; +#define FRAME_DUMP_FILE_OPEN 1 + + /* + * We queue each frame before dumping it to the user, + * per read command we will pass a single skb structure + * so we should be prepared to queue multiple sk buffers + * before sending it to userspace. + */ + struct sk_buff_head frame_dump_skbqueue; + wait_queue_head_t frame_dump_waitqueue; /* * Driver and chipset files will use a data buffer @@ -93,6 +112,59 @@ struct rt2x00debug_intf { unsigned int offset_rf; }; +void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb) +{ + struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; + struct skb_desc *desc = get_skb_desc(skb); + struct sk_buff *skbcopy; + struct rt2x00dump_hdr *dump_hdr; + struct timeval timestamp; + + do_gettimeofday(×tamp); + + if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) + return; + + if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) { + DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n"); + return; + } + + skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + desc->data_len, + GFP_ATOMIC); + if (!skbcopy) { + DEBUG(rt2x00dev, "Failed to copy skb for dump.\n"); + return; + } + + dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr)); + dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION); + dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr)); + dump_hdr->desc_length = cpu_to_le32(desc->desc_len); + dump_hdr->data_length = cpu_to_le32(desc->data_len); + dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); + dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); + dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev); + dump_hdr->type = cpu_to_le16(desc->frame_type); + dump_hdr->ring_index = desc->ring->queue_idx; + dump_hdr->entry_index = desc->entry->entry_idx; + dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec); + dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec); + + memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len); + memcpy(skb_put(skbcopy, desc->data_len), desc->data, desc->data_len); + + skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy); + wake_up_interruptible(&intf->frame_dump_waitqueue); + + /* + * Verify that the file has not been closed while we were working. + */ + if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) + skb_queue_purge(&intf->frame_dump_skbqueue); +} + static int rt2x00debug_file_open(struct inode *inode, struct file *file) { struct rt2x00debug_intf *intf = inode->i_private; @@ -114,13 +186,96 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file) return 0; } +static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file) +{ + struct rt2x00debug_intf *intf = inode->i_private; + int retval; + + retval = rt2x00debug_file_open(inode, file); + if (retval) + return retval; + + if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) { + rt2x00debug_file_release(inode, file); + return -EBUSY; + } + + return 0; +} + +static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file) +{ + struct rt2x00debug_intf *intf = inode->i_private; + + skb_queue_purge(&intf->frame_dump_skbqueue); + + clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags); + + return rt2x00debug_file_release(inode, file); +} + +static ssize_t rt2x00debug_read_ring_dump(struct file *file, + char __user *buf, + size_t length, + loff_t *offset) +{ + struct rt2x00debug_intf *intf = file->private_data; + struct sk_buff *skb; + size_t status; + int retval; + + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + retval = + wait_event_interruptible(intf->frame_dump_waitqueue, + (skb = + skb_dequeue(&intf->frame_dump_skbqueue))); + if (retval) + return retval; + + status = min((size_t)skb->len, length); + if (copy_to_user(buf, skb->data, status)) { + status = -EFAULT; + goto exit; + } + + *offset += status; + +exit: + kfree_skb(skb); + + return status; +} + +static unsigned int rt2x00debug_poll_ring_dump(struct file *file, + poll_table *wait) +{ + struct rt2x00debug_intf *intf = file->private_data; + + poll_wait(file, &intf->frame_dump_waitqueue, wait); + + if (!skb_queue_empty(&intf->frame_dump_skbqueue)) + return POLLOUT | POLLWRNORM; + + return 0; +} + +static const struct file_operations rt2x00debug_fop_ring_dump = { + .owner = THIS_MODULE, + .read = rt2x00debug_read_ring_dump, + .poll = rt2x00debug_poll_ring_dump, + .open = rt2x00debug_open_ring_dump, + .release = rt2x00debug_release_ring_dump, +}; + #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ static ssize_t rt2x00debug_read_##__name(struct file *file, \ char __user *buf, \ size_t length, \ loff_t *offset) \ { \ - struct rt2x00debug_intf *intf = file->private_data; \ + struct rt2x00debug_intf *intf = file->private_data; \ const struct rt2x00debug *debug = intf->debug; \ char line[16]; \ size_t size; \ @@ -150,7 +305,7 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \ size_t length, \ loff_t *offset) \ { \ - struct rt2x00debug_intf *intf = file->private_data; \ + struct rt2x00debug_intf *intf = file->private_data; \ const struct rt2x00debug *debug = intf->debug; \ char line[16]; \ size_t size; \ @@ -254,11 +409,15 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, const struct rt2x00debug *debug = intf->debug; char *data; - data = kzalloc(4 * PRINT_LINE_LEN_MAX, GFP_KERNEL); + data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL); if (!data) return NULL; blob->data = data; + data += sprintf(data, "rt chip: %04x\n", intf->rt2x00dev->chip.rt); + data += sprintf(data, "rf chip: %04x\n", intf->rt2x00dev->chip.rf); + data += sprintf(data, "revision:%08x\n", intf->rt2x00dev->chip.rev); + data += sprintf(data, "\n"); data += sprintf(data, "csr length: %d\n", debug->csr.word_count); data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count); data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count); @@ -306,12 +465,17 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) if (IS_ERR(intf->dev_flags)) goto exit; -#define RT2X00DEBUGFS_CREATE_ENTRY(__intf, __name) \ + intf->register_folder = + debugfs_create_dir("register", intf->driver_folder); + if (IS_ERR(intf->register_folder)) + goto exit; + +#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \ ({ \ (__intf)->__name##_off_entry = \ debugfs_create_u32(__stringify(__name) "_offset", \ S_IRUGO | S_IWUSR, \ - (__intf)->driver_folder, \ + (__intf)->register_folder, \ &(__intf)->offset_##__name); \ if (IS_ERR((__intf)->__name##_off_entry)) \ goto exit; \ @@ -319,18 +483,32 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) (__intf)->__name##_val_entry = \ debugfs_create_file(__stringify(__name) "_value", \ S_IRUGO | S_IWUSR, \ - (__intf)->driver_folder, \ + (__intf)->register_folder, \ (__intf), &rt2x00debug_fop_##__name);\ if (IS_ERR((__intf)->__name##_val_entry)) \ goto exit; \ }) - RT2X00DEBUGFS_CREATE_ENTRY(intf, csr); - RT2X00DEBUGFS_CREATE_ENTRY(intf, eeprom); - RT2X00DEBUGFS_CREATE_ENTRY(intf, bbp); - RT2X00DEBUGFS_CREATE_ENTRY(intf, rf); + RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr); + RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom); + RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp); + RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf); -#undef RT2X00DEBUGFS_CREATE_ENTRY +#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY + + intf->frame_folder = + debugfs_create_dir("frame", intf->driver_folder); + if (IS_ERR(intf->frame_folder)) + goto exit; + + intf->frame_dump_entry = + debugfs_create_file("dump", S_IRUGO, intf->frame_folder, + intf, &rt2x00debug_fop_ring_dump); + if (IS_ERR(intf->frame_dump_entry)) + goto exit; + + skb_queue_head_init(&intf->frame_dump_skbqueue); + init_waitqueue_head(&intf->frame_dump_waitqueue); return; @@ -343,11 +521,15 @@ exit: void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) { - const struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; + struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; if (unlikely(!intf)) return; + skb_queue_purge(&intf->frame_dump_skbqueue); + + debugfs_remove(intf->frame_dump_entry); + debugfs_remove(intf->frame_folder); debugfs_remove(intf->rf_val_entry); debugfs_remove(intf->rf_off_entry); debugfs_remove(intf->bbp_val_entry); @@ -356,6 +538,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) debugfs_remove(intf->eeprom_off_entry); debugfs_remove(intf->csr_val_entry); debugfs_remove(intf->csr_off_entry); + debugfs_remove(intf->register_folder); debugfs_remove(intf->dev_flags); debugfs_remove(intf->chipset_entry); debugfs_remove(intf->driver_entry); diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h index 860e8fa3a0da..d37efbd09c41 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.h +++ b/drivers/net/wireless/rt2x00/rt2x00debug.h @@ -30,9 +30,9 @@ struct rt2x00_dev; #define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type) \ struct reg##__name { \ - void (*read)(const struct rt2x00_dev *rt2x00dev, \ + void (*read)(struct rt2x00_dev *rt2x00dev, \ const unsigned int word, __type *data); \ - void (*write)(const struct rt2x00_dev *rt2x00dev, \ + void (*write)(struct rt2x00_dev *rt2x00dev, \ const unsigned int word, __type data); \ \ unsigned int word_size; \ diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index ff399f8083e9..c4be2ac4d7a4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -23,16 +23,12 @@ Abstract: rt2x00 generic device routines. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2x00lib" - #include <linux/kernel.h> #include <linux/module.h> #include "rt2x00.h" #include "rt2x00lib.h" +#include "rt2x00dump.h" /* * Ring handler. @@ -67,7 +63,21 @@ EXPORT_SYMBOL_GPL(rt2x00lib_get_ring); */ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) { - rt2x00_clear_link(&rt2x00dev->link); + rt2x00dev->link.count = 0; + rt2x00dev->link.vgc_level = 0; + + memset(&rt2x00dev->link.qual, 0, sizeof(rt2x00dev->link.qual)); + + /* + * The RX and TX percentage should start at 50% + * this will assure we will get at least get some + * decent value when the link tuner starts. + * The value will be dropped and overwritten with + * the correct (measured )value anyway during the + * first run of the link tuner. + */ + rt2x00dev->link.qual.rx_percentage = 50; + rt2x00dev->link.qual.tx_percentage = 50; /* * Reset the link tuner. @@ -93,6 +103,46 @@ void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev) } /* + * Ring initialization + */ +static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev) +{ + struct data_ring *ring = rt2x00dev->rx; + unsigned int i; + + if (!rt2x00dev->ops->lib->init_rxentry) + return; + + if (ring->data_addr) + memset(ring->data_addr, 0, rt2x00_get_ring_size(ring)); + + for (i = 0; i < ring->stats.limit; i++) + rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]); + + rt2x00_ring_index_clear(ring); +} + +static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev) +{ + struct data_ring *ring; + unsigned int i; + + if (!rt2x00dev->ops->lib->init_txentry) + return; + + txringall_for_each(rt2x00dev, ring) { + if (ring->data_addr) + memset(ring->data_addr, 0, rt2x00_get_ring_size(ring)); + + for (i = 0; i < ring->stats.limit; i++) + rt2x00dev->ops->lib->init_txentry(rt2x00dev, + &ring->entry[i]); + + rt2x00_ring_index_clear(ring); + } +} + +/* * Radio control handlers. */ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) @@ -108,6 +158,12 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) return 0; /* + * Initialize all data rings. + */ + rt2x00lib_init_rxrings(rt2x00dev); + rt2x00lib_init_txrings(rt2x00dev); + + /* * Enable radio. */ status = rt2x00dev->ops->lib->set_device_state(rt2x00dev, @@ -179,26 +235,153 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) rt2x00lib_start_link_tuner(rt2x00dev); } -static void rt2x00lib_precalculate_link_signal(struct link *link) +static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev) { - if (link->rx_failed || link->rx_success) - link->rx_percentage = - (link->rx_success * 100) / - (link->rx_failed + link->rx_success); + enum antenna rx = rt2x00dev->link.ant.active.rx; + enum antenna tx = rt2x00dev->link.ant.active.tx; + int sample_a = + rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A); + int sample_b = + rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B); + + /* + * We are done sampling. Now we should evaluate the results. + */ + rt2x00dev->link.ant.flags &= ~ANTENNA_MODE_SAMPLE; + + /* + * During the last period we have sampled the RSSI + * from both antenna's. It now is time to determine + * which antenna demonstrated the best performance. + * When we are already on the antenna with the best + * performance, then there really is nothing for us + * left to do. + */ + if (sample_a == sample_b) + return; + + if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) { + if (sample_a > sample_b && rx == ANTENNA_B) + rx = ANTENNA_A; + else if (rx == ANTENNA_A) + rx = ANTENNA_B; + } + + if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) { + if (sample_a > sample_b && tx == ANTENNA_B) + tx = ANTENNA_A; + else if (tx == ANTENNA_A) + tx = ANTENNA_B; + } + + rt2x00lib_config_antenna(rt2x00dev, rx, tx); +} + +static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev) +{ + enum antenna rx = rt2x00dev->link.ant.active.rx; + enum antenna tx = rt2x00dev->link.ant.active.tx; + int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link); + int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr); + + /* + * Legacy driver indicates that we should swap antenna's + * when the difference in RSSI is greater that 5. This + * also should be done when the RSSI was actually better + * then the previous sample. + * When the difference exceeds the threshold we should + * sample the rssi from the other antenna to make a valid + * comparison between the 2 antennas. + */ + if ((rssi_curr - rssi_old) > -5 || (rssi_curr - rssi_old) < 5) + return; + + rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE; + + if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) + rx = (rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; + + if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) + tx = (tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; + + rt2x00lib_config_antenna(rt2x00dev, rx, tx); +} + +static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev) +{ + /* + * Determine if software diversity is enabled for + * either the TX or RX antenna (or both). + * Always perform this check since within the link + * tuner interval the configuration might have changed. + */ + rt2x00dev->link.ant.flags &= ~ANTENNA_RX_DIVERSITY; + rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY; + + if (rt2x00dev->hw->conf.antenna_sel_rx == 0 && + rt2x00dev->default_ant.rx != ANTENNA_SW_DIVERSITY) + rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY; + if (rt2x00dev->hw->conf.antenna_sel_tx == 0 && + rt2x00dev->default_ant.tx != ANTENNA_SW_DIVERSITY) + rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY; + + if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) && + !(rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)) { + rt2x00dev->link.ant.flags &= ~ANTENNA_MODE_SAMPLE; + return; + } + + /* + * If we have only sampled the data over the last period + * we should now harvest the data. Otherwise just evaluate + * the data. The latter should only be performed once + * every 2 seconds. + */ + if (rt2x00dev->link.ant.flags & ANTENNA_MODE_SAMPLE) + rt2x00lib_evaluate_antenna_sample(rt2x00dev); + else if (rt2x00dev->link.count & 1) + rt2x00lib_evaluate_antenna_eval(rt2x00dev); +} + +static void rt2x00lib_update_link_stats(struct link *link, int rssi) +{ + int avg_rssi = rssi; + + /* + * Update global RSSI + */ + if (link->qual.avg_rssi) + avg_rssi = MOVING_AVERAGE(link->qual.avg_rssi, rssi, 8); + link->qual.avg_rssi = avg_rssi; + + /* + * Update antenna RSSI + */ + if (link->ant.rssi_ant) + rssi = MOVING_AVERAGE(link->ant.rssi_ant, rssi, 8); + link->ant.rssi_ant = rssi; +} + +static void rt2x00lib_precalculate_link_signal(struct link_qual *qual) +{ + if (qual->rx_failed || qual->rx_success) + qual->rx_percentage = + (qual->rx_success * 100) / + (qual->rx_failed + qual->rx_success); else - link->rx_percentage = 50; + qual->rx_percentage = 50; - if (link->tx_failed || link->tx_success) - link->tx_percentage = - (link->tx_success * 100) / - (link->tx_failed + link->tx_success); + if (qual->tx_failed || qual->tx_success) + qual->tx_percentage = + (qual->tx_success * 100) / + (qual->tx_failed + qual->tx_success); else - link->tx_percentage = 50; + qual->tx_percentage = 50; - link->rx_success = 0; - link->rx_failed = 0; - link->tx_success = 0; - link->tx_failed = 0; + qual->rx_success = 0; + qual->rx_failed = 0; + qual->tx_success = 0; + qual->tx_failed = 0; } static int rt2x00lib_calculate_link_signal(struct rt2x00_dev *rt2x00dev, @@ -225,8 +408,8 @@ static int rt2x00lib_calculate_link_signal(struct rt2x00_dev *rt2x00dev, * defines to calculate the current link signal. */ signal = ((WEIGHT_RSSI * rssi_percentage) + - (WEIGHT_TX * rt2x00dev->link.tx_percentage) + - (WEIGHT_RX * rt2x00dev->link.rx_percentage)) / 100; + (WEIGHT_TX * rt2x00dev->link.qual.tx_percentage) + + (WEIGHT_RX * rt2x00dev->link.qual.rx_percentage)) / 100; return (signal > 100) ? 100 : signal; } @@ -246,10 +429,9 @@ static void rt2x00lib_link_tuner(struct work_struct *work) /* * Update statistics. */ - rt2x00dev->ops->lib->link_stats(rt2x00dev); - + rt2x00dev->ops->lib->link_stats(rt2x00dev, &rt2x00dev->link.qual); rt2x00dev->low_level_stats.dot11FCSErrorCount += - rt2x00dev->link.rx_failed; + rt2x00dev->link.qual.rx_failed; /* * Only perform the link tuning when Link tuning @@ -259,10 +441,15 @@ static void rt2x00lib_link_tuner(struct work_struct *work) rt2x00dev->ops->lib->link_tuner(rt2x00dev); /* + * Evaluate antenna setup. + */ + rt2x00lib_evaluate_antenna(rt2x00dev); + + /* * Precalculate a portion of the link signal which is * in based on the tx/rx success/failure counters. */ - rt2x00lib_precalculate_link_signal(&rt2x00dev->link); + rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual); /* * Increase tuner counter, and reschedule the next link tuner run. @@ -276,7 +463,7 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, filter_work); - unsigned int filter = rt2x00dev->interface.filter; + unsigned int filter = rt2x00dev->packet_filter; /* * Since we had stored the filter inside interface.filter, @@ -284,7 +471,7 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) * assume nothing has changed (*total_flags will be compared * to interface.filter to determine if any action is required). */ - rt2x00dev->interface.filter = 0; + rt2x00dev->packet_filter = 0; rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw, filter, &filter, 0, NULL); @@ -294,10 +481,17 @@ static void rt2x00lib_configuration_scheduled(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, config_work); - int preamble = !test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); + struct ieee80211_bss_conf bss_conf; - rt2x00mac_erp_ie_changed(rt2x00dev->hw, - IEEE80211_ERP_CHANGE_PREAMBLE, 0, preamble); + bss_conf.use_short_preamble = + test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); + + /* + * FIXME: shouldn't invoke it this way because all other contents + * of bss_conf is invalid. + */ + rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id, + &bss_conf, BSS_CHANGED_ERP_PREAMBLE); } /* @@ -350,8 +544,8 @@ void rt2x00lib_txdone(struct data_entry *entry, tx_status->ack_signal = 0; tx_status->excessive_retries = (status == TX_FAIL_RETRY); tx_status->retry_count = retry; - rt2x00dev->link.tx_success += success; - rt2x00dev->link.tx_failed += retry + fail; + rt2x00dev->link.qual.tx_success += success; + rt2x00dev->link.qual.tx_failed += retry + fail; if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) { if (success) @@ -371,9 +565,11 @@ void rt2x00lib_txdone(struct data_entry *entry, } /* - * Send the tx_status to mac80211, - * that method also cleans up the skb structure. + * Send the tx_status to mac80211 & debugfs. + * mac80211 will clean up the skb structure. */ + get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE; + rt2x00debug_dump_frame(rt2x00dev, entry->skb); ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status); entry->skb = NULL; } @@ -386,8 +582,10 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; struct ieee80211_hw_mode *mode; struct ieee80211_rate *rate; + struct ieee80211_hdr *hdr; unsigned int i; int val = 0; + u16 fc; /* * Update RX statistics. @@ -412,17 +610,28 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, } } - rt2x00_update_link_rssi(&rt2x00dev->link, desc->rssi); - rt2x00dev->link.rx_success++; + /* + * Only update link status if this is a beacon frame carrying our bssid. + */ + hdr = (struct ieee80211_hdr*)skb->data; + fc = le16_to_cpu(hdr->frame_control); + if (is_beacon(fc) && desc->my_bss) + rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi); + + rt2x00dev->link.qual.rx_success++; + rx_status->rate = val; rx_status->signal = rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi); rx_status->ssi = desc->rssi; rx_status->flag = desc->flags; + rx_status->antenna = rt2x00dev->link.ant.active.rx; /* - * Send frame to mac80211 + * Send frame to mac80211 & debugfs */ + get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE; + rt2x00debug_dump_frame(rt2x00dev, skb); ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status); } EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -431,36 +640,25 @@ EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); * TX descriptor initializer */ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_desc *txd, - struct ieee80211_hdr *ieee80211hdr, - unsigned int length, + struct sk_buff *skb, struct ieee80211_tx_control *control) { struct txdata_entry_desc desc; - struct data_ring *ring; + struct skb_desc *skbdesc = get_skb_desc(skb); + struct ieee80211_hdr *ieee80211hdr = skbdesc->data; int tx_rate; int bitrate; + int length; int duration; int residual; u16 frame_control; u16 seq_ctrl; - /* - * Make sure the descriptor is properly cleared. - */ - memset(&desc, 0x00, sizeof(desc)); + memset(&desc, 0, sizeof(desc)); - /* - * Get ring pointer, if we fail to obtain the - * correct ring, then use the first TX ring. - */ - ring = rt2x00lib_get_ring(rt2x00dev, control->queue); - if (!ring) - ring = rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0); - - desc.cw_min = ring->tx_params.cw_min; - desc.cw_max = ring->tx_params.cw_max; - desc.aifs = ring->tx_params.aifs; + desc.cw_min = skbdesc->ring->tx_params.cw_min; + desc.cw_max = skbdesc->ring->tx_params.cw_max; + desc.aifs = skbdesc->ring->tx_params.aifs; /* * Identify queue @@ -482,12 +680,21 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, tx_rate = control->tx_rate; /* + * Check whether this frame is to be acked + */ + if (!(control->flags & IEEE80211_TXCTL_NO_ACK)) + __set_bit(ENTRY_TXD_ACK, &desc.flags); + + /* * Check if this is a RTS/CTS frame */ if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { __set_bit(ENTRY_TXD_BURST, &desc.flags); - if (is_rts_frame(frame_control)) + if (is_rts_frame(frame_control)) { __set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags); + __set_bit(ENTRY_TXD_ACK, &desc.flags); + } else + __clear_bit(ENTRY_TXD_ACK, &desc.flags); if (control->rts_cts_rate) tx_rate = control->rts_cts_rate; } @@ -532,17 +739,18 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); desc.service = 0x04; + length = skbdesc->data_len + FCS_LEN; if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) { - desc.length_high = ((length + FCS_LEN) >> 6) & 0x3f; - desc.length_low = ((length + FCS_LEN) & 0x3f); + desc.length_high = (length >> 6) & 0x3f; + desc.length_low = length & 0x3f; } else { bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); /* * Convert length to microseconds. */ - residual = get_duration_res(length + FCS_LEN, bitrate); - duration = get_duration(length + FCS_LEN, bitrate); + residual = get_duration_res(length, bitrate); + duration = get_duration(length, bitrate); if (residual != 0) { duration++; @@ -565,8 +773,22 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, desc.signal |= 0x08; } - rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, txd, &desc, - ieee80211hdr, length, control); + rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control); + + /* + * Update ring entry. + */ + skbdesc->entry->skb = skb; + memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control)); + + /* + * The frame has been completely initialized and ready + * for sending to the device. The caller will push the + * frame to the device, but we are going to push the + * frame to debugfs here. + */ + skbdesc->frame_type = DUMP_FRAME_TX; + rt2x00debug_dump_frame(rt2x00dev, skb); } EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); @@ -809,6 +1031,7 @@ static int rt2x00lib_alloc_entries(struct data_ring *ring, entry[i].flags = 0; entry[i].ring = ring; entry[i].skb = NULL; + entry[i].entry_idx = i; } ring->entry = entry; @@ -866,7 +1089,7 @@ static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev) } } -void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) +static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) { if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags)) return; @@ -887,7 +1110,7 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) rt2x00lib_free_ring_entries(rt2x00dev); } -int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) +static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) { int status; @@ -930,12 +1153,65 @@ exit: return status; } +int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) +{ + int retval; + + if (test_bit(DEVICE_STARTED, &rt2x00dev->flags)) + return 0; + + /* + * If this is the first interface which is added, + * we should load the firmware now. + */ + if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) { + retval = rt2x00lib_load_firmware(rt2x00dev); + if (retval) + return retval; + } + + /* + * Initialize the device. + */ + retval = rt2x00lib_initialize(rt2x00dev); + if (retval) + return retval; + + /* + * Enable radio. + */ + retval = rt2x00lib_enable_radio(rt2x00dev); + if (retval) { + rt2x00lib_uninitialize(rt2x00dev); + return retval; + } + + __set_bit(DEVICE_STARTED, &rt2x00dev->flags); + + return 0; +} + +void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) +{ + if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags)) + return; + + /* + * Perhaps we can add something smarter here, + * but for now just disabling the radio should do. + */ + rt2x00lib_disable_radio(rt2x00dev); + + __clear_bit(DEVICE_STARTED, &rt2x00dev->flags); +} + /* * driver allocation handlers. */ static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; + unsigned int index; /* * We need the following rings: @@ -963,11 +1239,18 @@ static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev) /* * Initialize ring parameters. - * cw_min: 2^5 = 32. - * cw_max: 2^10 = 1024. + * RX: queue_idx = 0 + * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index + * TX: cw_min: 2^5 = 32. + * TX: cw_max: 2^10 = 1024. */ - ring_for_each(rt2x00dev, ring) { + rt2x00dev->rx->rt2x00dev = rt2x00dev; + rt2x00dev->rx->queue_idx = 0; + + index = IEEE80211_TX_QUEUE_DATA0; + txring_for_each(rt2x00dev, ring) { ring->rt2x00dev = rt2x00dev; + ring->queue_idx = index++; ring->tx_params.aifs = 2; ring->tx_params.cw_min = 5; ring->tx_params.cw_max = 10; @@ -1008,7 +1291,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Reset current working type. */ - rt2x00dev->interface.type = INVALID_INTERFACE; + rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID; /* * Allocate ring array. @@ -1112,7 +1395,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) * Disable radio and unitialize all items * that must be recreated on resume. */ - rt2x00mac_stop(rt2x00dev->hw); + rt2x00lib_stop(rt2x00dev); rt2x00lib_uninitialize(rt2x00dev); rt2x00debug_deregister(rt2x00dev); @@ -1134,7 +1417,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) int retval; NOTICE(rt2x00dev, "Waking up.\n"); - __set_bit(DEVICE_PRESENT, &rt2x00dev->flags); /* * Open the debugfs entry. @@ -1150,7 +1432,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) /* * Reinitialize device and all active interfaces. */ - retval = rt2x00mac_start(rt2x00dev->hw); + retval = rt2x00lib_start(rt2x00dev); if (retval) goto exit; @@ -1166,6 +1448,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) rt2x00lib_config_type(rt2x00dev, intf->type); /* + * We are ready again to receive requests from mac80211. + */ + __set_bit(DEVICE_PRESENT, &rt2x00dev->flags); + + /* * It is possible that during that mac80211 has attempted * to send frames while we were suspending or resuming. * In that case we have disabled the TX queue and should diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h new file mode 100644 index 000000000000..99f3f367adce --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -0,0 +1,121 @@ +/* + Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + <http://rt2x00.serialmonkey.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2x00dump + Abstract: Data structures for the rt2x00debug & userspace. + */ + +#ifndef RT2X00DUMP_H +#define RT2X00DUMP_H + +/** + * DOC: Introduction + * + * This header is intended to be exported to userspace, + * to make the structures and enumerations available to userspace + * applications. This means that all data types should be exportable. + * + * When rt2x00 is compiled with debugfs support enabled, + * it is possible to capture all data coming in and out of the device + * by reading the frame dump file. This file can have only a single reader. + * The following frames will be reported: + * - All incoming frames (rx) + * - All outgoing frames (tx, including beacon and atim) + * - All completed frames (txdone including atim) + * + * The data is send to the file using the following format: + * + * [rt2x00dump header][hardware descriptor][ieee802.11 frame] + * + * rt2x00dump header: The description of the dumped frame, as well as + * additional information usefull for debugging. See &rt2x00dump_hdr. + * hardware descriptor: Descriptor that was used to receive or transmit + * the frame. + * ieee802.11 frame: The actual frame that was received or transmitted. + */ + +/** + * enum rt2x00_dump_type - Frame type + * + * These values are used for the @type member of &rt2x00dump_hdr. + * @DUMP_FRAME_RXDONE: This frame has been received by the hardware. + * @DUMP_FRAME_TX: This frame is queued for transmission to the hardware. + * @DUMP_FRAME_TXDONE: This frame indicates the device has handled + * the tx event which has either succeeded or failed. A frame + * with this type should also have been reported with as a + * %DUMP_FRAME_TX frame. + */ +enum rt2x00_dump_type { + DUMP_FRAME_RXDONE = 1, + DUMP_FRAME_TX = 2, + DUMP_FRAME_TXDONE = 3, +}; + +/** + * struct rt2x00dump_hdr - Dump frame header + * + * Each frame dumped to the debugfs file starts with this header + * attached. This header contains the description of the actual + * frame which was dumped. + * + * New fields inside the structure must be appended to the end of + * the structure. This way userspace tools compiled for earlier + * header versions can still correctly handle the frame dump + * (although they will not handle all data passed to them in the dump). + * + * @version: Header version should always be set to %DUMP_HEADER_VERSION. + * This field must be checked by userspace to determine if it can + * handle this frame. + * @header_length: The length of the &rt2x00dump_hdr structure. This is + * used for compatibility reasons so userspace can easily determine + * the location of the next field in the dump. + * @desc_length: The length of the device descriptor. + * @data_length: The length of the frame data (including the ieee802.11 header. + * @chip_rt: RT chipset + * @chip_rf: RF chipset + * @chip_rev: Chipset revision + * @type: The frame type (&rt2x00_dump_type) + * @ring_index: The index number of the data ring. + * @entry_index: The index number of the entry inside the data ring. + * @timestamp_sec: Timestamp - seconds + * @timestamp_usec: Timestamp - microseconds + */ +struct rt2x00dump_hdr { + __le32 version; +#define DUMP_HEADER_VERSION 2 + + __le32 header_length; + __le32 desc_length; + __le32 data_length; + + __le16 chip_rt; + __le16 chip_rf; + __le32 chip_rev; + + __le16 type; + __u8 ring_index; + __u8 entry_index; + + __le32 timestamp_sec; + __le32 timestamp_usec; +}; + +#endif /* RT2X00DUMP_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index 236025f8b90f..0a475e4e2442 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -23,11 +23,6 @@ Abstract: rt2x00 firmware loading routines. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2x00lib" - #include <linux/crc-itu-t.h> #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 06d9bc0015c0..1adbd28e0973 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -44,8 +44,8 @@ void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev); /* * Initialization handlers. */ -int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev); +int rt2x00lib_start(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev); /* * Configuration handlers. @@ -53,6 +53,8 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev); void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac); void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid); void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type); +void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, + enum antenna rx, enum antenna tx); void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config); @@ -78,6 +80,7 @@ static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT2X00_LIB_DEBUGFS void rt2x00debug_register(struct rt2x00_dev *rt2x00dev); void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev); +void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); #else static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) { @@ -86,6 +89,11 @@ static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) { } + +static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb) +{ +} #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 85ea8a8e658e..e3f15e518c76 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -23,11 +23,6 @@ Abstract: rt2x00 generic mac80211 routines. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2x00lib" - #include <linux/kernel.h> #include <linux/module.h> @@ -89,7 +84,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) { ieee80211_stop_queues(hw); - return 0; + return NETDEV_TX_OK; } /* @@ -115,15 +110,24 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) && (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS | IEEE80211_TXCTL_USE_CTS_PROTECT))) { - if (rt2x00_ring_free(ring) <= 1) + if (rt2x00_ring_free(ring) <= 1) { + ieee80211_stop_queue(rt2x00dev->hw, control->queue); return NETDEV_TX_BUSY; + } - if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) + if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) { + ieee80211_stop_queue(rt2x00dev->hw, control->queue); return NETDEV_TX_BUSY; + } } - if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) + if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) { + ieee80211_stop_queue(rt2x00dev->hw, control->queue); return NETDEV_TX_BUSY; + } + + if (rt2x00_ring_full(ring)) + ieee80211_stop_queue(rt2x00dev->hw, control->queue); if (rt2x00dev->ops->lib->kick_tx_queue) rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue); @@ -135,41 +139,11 @@ EXPORT_SYMBOL_GPL(rt2x00mac_tx); int rt2x00mac_start(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; - int status; - if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || - test_bit(DEVICE_STARTED, &rt2x00dev->flags)) + if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) return 0; - /* - * If this is the first interface which is added, - * we should load the firmware now. - */ - if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) { - status = rt2x00lib_load_firmware(rt2x00dev); - if (status) - return status; - } - - /* - * Initialize the device. - */ - status = rt2x00lib_initialize(rt2x00dev); - if (status) - return status; - - /* - * Enable radio. - */ - status = rt2x00lib_enable_radio(rt2x00dev); - if (status) { - rt2x00lib_uninitialize(rt2x00dev); - return status; - } - - __set_bit(DEVICE_STARTED, &rt2x00dev->flags); - - return 0; + return rt2x00lib_start(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00mac_start); @@ -180,13 +154,7 @@ void rt2x00mac_stop(struct ieee80211_hw *hw) if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) return; - /* - * Perhaps we can add something smarter here, - * but for now just disabling the radio should do. - */ - rt2x00lib_disable_radio(rt2x00dev); - - __clear_bit(DEVICE_STARTED, &rt2x00dev->flags); + rt2x00lib_stop(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00mac_stop); @@ -213,7 +181,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, is_interface_present(intf)) return -ENOBUFS; - intf->id = conf->if_id; + intf->id = conf->vif; intf->type = conf->type; if (conf->type == IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); @@ -247,7 +215,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, return; intf->id = 0; - intf->type = INVALID_INTERFACE; + intf->type = IEEE80211_IF_TYPE_INVALID; memset(&intf->bssid, 0x00, ETH_ALEN); memset(&intf->mac, 0x00, ETH_ALEN); @@ -297,7 +265,8 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) } EXPORT_SYMBOL_GPL(rt2x00mac_config); -int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id, +int rt2x00mac_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -373,23 +342,27 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats); -void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes, - int cts_protection, int preamble) +void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) { struct rt2x00_dev *rt2x00dev = hw->priv; int short_preamble; int ack_timeout; int ack_consume_time; int difs; + int preamble; /* * We only support changing preamble mode. */ - if (!(changes & IEEE80211_ERP_CHANGE_PREAMBLE)) + if (!(changes & BSS_CHANGED_ERP_PREAMBLE)) return; - short_preamble = !preamble; - preamble = !!(preamble) ? PREAMBLE : SHORT_PREAMBLE; + short_preamble = bss_conf->use_short_preamble; + preamble = bss_conf->use_short_preamble ? + SHORT_PREAMBLE : PREAMBLE; difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? SHORT_DIFS : DIFS; @@ -405,7 +378,7 @@ void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes, rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble, ack_timeout, ack_consume_time); } -EXPORT_SYMBOL_GPL(rt2x00mac_erp_ie_changed); +EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue, const struct ieee80211_tx_queue_params *params) diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 04663eb31950..804a9980055d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -23,11 +23,6 @@ Abstract: rt2x00 generic pci device routines. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2x00pci" - #include <linux/dma-mapping.h> #include <linux/kernel.h> #include <linux/module.h> @@ -43,9 +38,9 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_ring *ring = - rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); - struct data_entry *entry = rt2x00_get_data_entry(ring); + struct skb_desc *desc; + struct data_ring *ring; + struct data_entry *entry; /* * Just in case mac80211 doesn't set this correctly, @@ -53,14 +48,22 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * initialization. */ control->queue = IEEE80211_TX_QUEUE_BEACON; + ring = rt2x00lib_get_ring(rt2x00dev, control->queue); + entry = rt2x00_get_data_entry(ring); /* - * Update the beacon entry. + * Fill in skb descriptor */ + desc = get_skb_desc(skb); + desc->desc_len = ring->desc_size; + desc->data_len = skb->len; + desc->desc = entry->priv; + desc->data = skb->data; + desc->ring = ring; + desc->entry = entry; + memcpy(entry->data_addr, skb->data, skb->len); - rt2x00lib_write_tx_desc(rt2x00dev, entry->priv, - (struct ieee80211_hdr *)skb->data, - skb->len, control); + rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Enable beacon generation. @@ -78,15 +81,13 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, struct data_ring *ring, struct sk_buff *skb, struct ieee80211_tx_control *control) { - struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; struct data_entry *entry = rt2x00_get_data_entry(ring); - struct data_desc *txd = entry->priv; + __le32 *txd = entry->priv; + struct skb_desc *desc; u32 word; - if (rt2x00_ring_full(ring)) { - ieee80211_stop_queue(rt2x00dev->hw, control->queue); + if (rt2x00_ring_full(ring)) return -EINVAL; - } rt2x00_desc_read(txd, 0, &word); @@ -96,37 +97,42 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, "Arrived at non-free entry in the non-full queue %d.\n" "Please file bug report to %s.\n", control->queue, DRV_PROJECT); - ieee80211_stop_queue(rt2x00dev->hw, control->queue); return -EINVAL; } - entry->skb = skb; - memcpy(&entry->tx_status.control, control, sizeof(*control)); + /* + * Fill in skb descriptor + */ + desc = get_skb_desc(skb); + desc->desc_len = ring->desc_size; + desc->data_len = skb->len; + desc->desc = entry->priv; + desc->data = skb->data; + desc->ring = ring; + desc->entry = entry; + memcpy(entry->data_addr, skb->data, skb->len); - rt2x00lib_write_tx_desc(rt2x00dev, txd, ieee80211hdr, - skb->len, control); + rt2x00lib_write_tx_desc(rt2x00dev, skb, control); rt2x00_ring_index_inc(ring); - if (rt2x00_ring_full(ring)) - ieee80211_stop_queue(rt2x00dev->hw, control->queue); - return 0; } EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); /* - * RX data handlers. + * TX/RX data handlers. */ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring = rt2x00dev->rx; struct data_entry *entry; - struct data_desc *rxd; struct sk_buff *skb; struct ieee80211_hdr *hdr; + struct skb_desc *skbdesc; struct rxdata_entry_desc desc; int header_size; + __le32 *rxd; int align; u32 word; @@ -138,7 +144,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) break; - memset(&desc, 0x00, sizeof(desc)); + memset(&desc, 0, sizeof(desc)); rt2x00dev->ops->lib->fill_rxdone(entry, &desc); hdr = (struct ieee80211_hdr *)entry->data_addr; @@ -163,6 +169,17 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size); /* + * Fill in skb descriptor + */ + skbdesc = get_skb_desc(skb); + skbdesc->desc_len = entry->ring->desc_size; + skbdesc->data_len = skb->len; + skbdesc->desc = entry->priv; + skbdesc->data = skb->data; + skbdesc->ring = ring; + skbdesc->entry = entry; + + /* * Send the frame to rt2x00lib for further processing. */ rt2x00lib_rxdone(entry, skb, &desc); @@ -177,6 +194,37 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); +void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry, + const int tx_status, const int retry) +{ + u32 word; + + rt2x00lib_txdone(entry, tx_status, retry); + + /* + * Make this entry available for reuse. + */ + entry->flags = 0; + + rt2x00_desc_read(entry->priv, 0, &word); + rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0); + rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0); + rt2x00_desc_write(entry->priv, 0, word); + + rt2x00_ring_index_done_inc(entry->ring); + + /* + * 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. + */ + if (!rt2x00_ring_full(entry->ring)) + ieee80211_wake_queue(rt2x00dev->hw, + entry->tx_status.control.queue); + +} +EXPORT_SYMBOL_GPL(rt2x00pci_txdone); + /* * Device initialization handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 82adeac061d0..2d1eb8144da4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -57,7 +57,7 @@ /* * Register access. */ -static inline void rt2x00pci_register_read(const struct rt2x00_dev *rt2x00dev, +static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, const unsigned long offset, u32 *value) { @@ -65,14 +65,14 @@ static inline void rt2x00pci_register_read(const struct rt2x00_dev *rt2x00dev, } static inline void -rt2x00pci_register_multiread(const struct rt2x00_dev *rt2x00dev, +rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, const unsigned long offset, void *value, const u16 length) { memcpy_fromio(value, rt2x00dev->csr_addr + offset, length); } -static inline void rt2x00pci_register_write(const struct rt2x00_dev *rt2x00dev, +static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev, const unsigned long offset, u32 value) { @@ -80,7 +80,7 @@ static inline void rt2x00pci_register_write(const struct rt2x00_dev *rt2x00dev, } static inline void -rt2x00pci_register_multiwrite(const struct rt2x00_dev *rt2x00dev, +rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, const unsigned long offset, void *value, const u16 length) { @@ -101,9 +101,11 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, struct ieee80211_tx_control *control); /* - * RX data handlers. + * RX/TX data handlers. */ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); +void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry, + const int tx_status, const int retry); /* * Device initialization handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index a0f8b8e0a24b..34a96d44e306 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -23,11 +23,6 @@ Abstract: rt2x00 rfkill routines. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2x00lib" - #include <linux/input-polldev.h> #include <linux/kernel.h> #include <linux/module.h> @@ -68,8 +63,10 @@ static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev) struct rt2x00_dev *rt2x00dev = poll_dev->private; int state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); - if (rt2x00dev->rfkill->state != state) + if (rt2x00dev->rfkill->state != state) { input_report_key(poll_dev->input, KEY_WLAN, 1); + input_report_key(poll_dev->input, KEY_WLAN, 0); + } } int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) @@ -92,6 +89,13 @@ int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) return retval; } + /* + * Force initial poll which will detect the initial device state, + * and correctly sends the signal to the rfkill layer about this + * state. + */ + rt2x00rfkill_poll(rt2x00dev->poll_dev); + return 0; } @@ -114,26 +118,41 @@ int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) rt2x00dev->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); if (!rt2x00dev->rfkill) { ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n"); - return -ENOMEM; + goto exit; } rt2x00dev->rfkill->name = rt2x00dev->ops->name; rt2x00dev->rfkill->data = rt2x00dev; - rt2x00dev->rfkill->state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); + rt2x00dev->rfkill->state = -1; rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; rt2x00dev->poll_dev = input_allocate_polled_device(); if (!rt2x00dev->poll_dev) { ERROR(rt2x00dev, "Failed to allocate polled device.\n"); - rfkill_free(rt2x00dev->rfkill); - return -ENOMEM; + goto exit_free_rfkill; } rt2x00dev->poll_dev->private = rt2x00dev; rt2x00dev->poll_dev->poll = rt2x00rfkill_poll; rt2x00dev->poll_dev->poll_interval = RFKILL_POLL_INTERVAL; + rt2x00dev->poll_dev->input->name = rt2x00dev->ops->name; + rt2x00dev->poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy); + rt2x00dev->poll_dev->input->id.bustype = BUS_HOST; + rt2x00dev->poll_dev->input->id.vendor = 0x1814; + rt2x00dev->poll_dev->input->id.product = rt2x00dev->chip.rt; + rt2x00dev->poll_dev->input->id.version = rt2x00dev->chip.rev; + rt2x00dev->poll_dev->input->dev.parent = device; + rt2x00dev->poll_dev->input->evbit[0] = BIT(EV_KEY); + set_bit(KEY_WLAN, rt2x00dev->poll_dev->input->keybit); + return 0; + +exit_free_rfkill: + rfkill_free(rt2x00dev->rfkill); + +exit: + return -ENOMEM; } void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h index 1a864d32cfbd..1caa6d688c40 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ring.h +++ b/drivers/net/wireless/rt2x00/rt2x00ring.h @@ -27,19 +27,27 @@ #define RT2X00RING_H /* - * data_desc - * Each data entry also contains a descriptor which is used by the - * device to determine what should be done with the packet and - * what the current status is. - * This structure is greatly simplified, but the descriptors - * are basically a list of little endian 32 bit values. - * Make the array by default 1 word big, this will allow us - * to use sizeof() correctly. + * skb_desc + * Descriptor information for the skb buffer */ -struct data_desc { - __le32 word[1]; +struct skb_desc { + unsigned int frame_type; + + unsigned int desc_len; + unsigned int data_len; + + void *desc; + void *data; + + struct data_ring *ring; + struct data_entry *entry; }; +static inline struct skb_desc* get_skb_desc(struct sk_buff *skb) +{ + return (struct skb_desc*)&skb->cb[0]; +} + /* * rxdata_entry_desc * Summary of information that has been read from the @@ -51,6 +59,7 @@ struct rxdata_entry_desc { int ofdm; int size; int flags; + int my_bss; }; /* @@ -66,6 +75,7 @@ struct txdata_entry_desc { #define ENTRY_TXD_MORE_FRAG 4 #define ENTRY_TXD_REQ_TIMESTAMP 5 #define ENTRY_TXD_BURST 6 +#define ENTRY_TXD_ACK 7 /* * Queue ID. ID's 0-4 are data TX rings @@ -134,6 +144,11 @@ struct data_entry { */ void *data_addr; dma_addr_t data_dma; + + /* + * Entry identification number (index). + */ + unsigned int entry_idx; }; /* @@ -172,6 +187,13 @@ struct data_ring { void *data_addr; /* + * Queue identification number: + * RX: 0 + * TX: IEEE80211_TX_* + */ + unsigned int queue_idx; + + /* * Index variables. */ u16 index; @@ -253,16 +275,16 @@ static inline int rt2x00_ring_free(struct data_ring *ring) /* * TX/RX Descriptor access functions. */ -static inline void rt2x00_desc_read(struct data_desc *desc, +static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value) { - *value = le32_to_cpu(desc->word[word]); + *value = le32_to_cpu(desc[word]); } -static inline void rt2x00_desc_write(struct data_desc *desc, +static inline void rt2x00_desc_write(__le32 *desc, const u8 word, const u32 value) { - desc->word[word] = cpu_to_le32(value); + desc[word] = cpu_to_le32(value); } #endif /* RT2X00RING_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 568d73847dca..84e9bdb73910 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -23,14 +23,10 @@ Abstract: rt2x00 generic usb device routines. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt2x00usb" - #include <linux/kernel.h> #include <linux/module.h> #include <linux/usb.h> +#include <linux/bug.h> #include "rt2x00.h" #include "rt2x00usb.h" @@ -38,7 +34,7 @@ /* * Interfacing with the HW. */ -int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev, +int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, const u8 request, const u8 requesttype, const u16 offset, const u16 value, void *buffer, const u16 buffer_length, @@ -52,6 +48,7 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev, (requesttype == USB_VENDOR_REQUEST_IN) ? usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0); + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { status = usb_control_msg(usb_dev, pipe, request, requesttype, value, offset, buffer, buffer_length, @@ -76,13 +73,15 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request); -int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, void *buffer, - const u16 buffer_length, const int timeout) +int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, + const u8 request, const u8 requesttype, + const u16 offset, void *buffer, + const u16 buffer_length, const int timeout) { int status; + BUG_ON(!mutex_is_locked(&rt2x00dev->usb_cache_mutex)); + /* * Check for Cache availability. */ @@ -103,6 +102,25 @@ int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev, return status; } +EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock); + +int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, + const u8 request, const u8 requesttype, + const u16 offset, void *buffer, + const u16 buffer_length, const int timeout) +{ + int status; + + mutex_lock(&rt2x00dev->usb_cache_mutex); + + status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, + requesttype, offset, buffer, + buffer_length, timeout); + + mutex_unlock(&rt2x00dev->usb_cache_mutex); + + return status; +} EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); /* @@ -113,7 +131,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) struct data_entry *entry = (struct data_entry *)urb->context; struct data_ring *ring = entry->ring; struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; - struct data_desc *txd = (struct data_desc *)entry->skb->data; + __le32 *txd = (__le32 *)entry->skb->data; u32 word; int tx_status; @@ -158,20 +176,17 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, struct usb_device *usb_dev = interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); struct data_entry *entry = rt2x00_get_data_entry(ring); - int pipe = usb_sndbulkpipe(usb_dev, 1); + struct skb_desc *desc; u32 length; - if (rt2x00_ring_full(ring)) { - ieee80211_stop_queue(rt2x00dev->hw, control->queue); + if (rt2x00_ring_full(ring)) return -EINVAL; - } if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) { ERROR(rt2x00dev, "Arrived at non-free entry in the non-full queue %d.\n" "Please file bug report to %s.\n", control->queue, DRV_PROJECT); - ieee80211_stop_queue(rt2x00dev->hw, control->queue); return -EINVAL; } @@ -181,12 +196,18 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, skb_push(skb, ring->desc_size); memset(skb->data, 0, ring->desc_size); - rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data, - (struct ieee80211_hdr *)(skb->data + - ring->desc_size), - skb->len - ring->desc_size, control); - memcpy(&entry->tx_status.control, control, sizeof(*control)); - entry->skb = skb; + /* + * Fill in skb descriptor + */ + desc = get_skb_desc(skb); + desc->desc_len = ring->desc_size; + desc->data_len = skb->len - ring->desc_size; + desc->desc = skb->data; + desc->data = skb->data + ring->desc_size; + desc->ring = ring; + desc->entry = entry; + + rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * USB devices cannot blindly pass the skb->len as the @@ -199,15 +220,12 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, * Initialize URB and send the frame to the device. */ __set_bit(ENTRY_OWNER_NIC, &entry->flags); - usb_fill_bulk_urb(entry->priv, usb_dev, pipe, + usb_fill_bulk_urb(entry->priv, usb_dev, usb_sndbulkpipe(usb_dev, 1), skb->data, length, rt2x00usb_interrupt_txdone, entry); usb_submit_urb(entry->priv, GFP_ATOMIC); rt2x00_ring_index_inc(ring); - if (rt2x00_ring_full(ring)) - ieee80211_stop_queue(rt2x00dev->hw, control->queue); - return 0; } EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); @@ -222,6 +240,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; struct sk_buff *skb; struct ieee80211_hdr *hdr; + struct skb_desc *skbdesc; struct rxdata_entry_desc desc; int header_size; int frame_size; @@ -238,7 +257,14 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) if (urb->actual_length < entry->ring->desc_size || urb->status) goto skip_entry; - memset(&desc, 0x00, sizeof(desc)); + /* + * Fill in skb descriptor + */ + skbdesc = get_skb_desc(entry->skb); + skbdesc->ring = ring; + skbdesc->entry = entry; + + memset(&desc, 0, sizeof(desc)); rt2x00dev->ops->lib->fill_rxdone(entry, &desc); /* @@ -264,9 +290,6 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. - * After that trim the entire buffer down to only - * contain the valid frame data excluding the device - * descriptor. */ hdr = (struct ieee80211_hdr *)entry->skb->data; header_size = @@ -276,6 +299,16 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) skb_push(entry->skb, 2); memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2); } + + /* + * Trim the entire buffer down to only contain the valid frame data + * excluding the device descriptor. The position of the descriptor + * varies. This means that we should check where the descriptor is + * and decide if we need to pull the data pointer to exclude the + * device descriptor. + */ + if (skbdesc->data > skbdesc->desc) + skb_pull(entry->skb, skbdesc->desc_len); skb_trim(entry->skb, desc.size); /* @@ -303,43 +336,6 @@ skip_entry: /* * Radio handlers */ -void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev) -{ - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); - struct data_ring *ring; - struct data_entry *entry; - unsigned int i; - - /* - * Initialize the TX rings - */ - txringall_for_each(rt2x00dev, ring) { - for (i = 0; i < ring->stats.limit; i++) - ring->entry[i].flags = 0; - - rt2x00_ring_index_clear(ring); - } - - /* - * Initialize and start the RX ring. - */ - rt2x00_ring_index_clear(rt2x00dev->rx); - - for (i = 0; i < rt2x00dev->rx->stats.limit; i++) { - entry = &rt2x00dev->rx->entry[i]; - - usb_fill_bulk_urb(entry->priv, usb_dev, - usb_rcvbulkpipe(usb_dev, 1), - entry->skb->data, entry->skb->len, - rt2x00usb_interrupt_rxdone, entry); - - __set_bit(ENTRY_OWNER_NIC, &entry->flags); - usb_submit_urb(entry->priv, GFP_ATOMIC); - } -} -EXPORT_SYMBOL_GPL(rt2x00usb_enable_radio); - void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; @@ -361,6 +357,29 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); /* * Device initialization handlers. */ +void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry) +{ + struct usb_device *usb_dev = + interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); + + usb_fill_bulk_urb(entry->priv, usb_dev, + usb_rcvbulkpipe(usb_dev, 1), + entry->skb->data, entry->skb->len, + rt2x00usb_interrupt_rxdone, entry); + + __set_bit(ENTRY_OWNER_NIC, &entry->flags); + usb_submit_urb(entry->priv, GFP_ATOMIC); +} +EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry); + +void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry) +{ + entry->flags = 0; +} +EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry); + static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, struct data_ring *ring) { @@ -400,7 +419,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) struct sk_buff *skb; unsigned int entry_size; unsigned int i; - int status; + int uninitialized_var(status); /* * Allocate DMA @@ -507,6 +526,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, rt2x00dev->dev = usb_intf; rt2x00dev->ops = ops; rt2x00dev->hw = hw; + mutex_init(&rt2x00dev->usb_cache_mutex); rt2x00dev->usb_maxpacket = usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 2681abe4d49e..e40df4050cd0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -91,7 +91,7 @@ * a buffer allocated by kmalloc. Failure to do so can lead * to unexpected behavior depending on the architecture. */ -int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev, +int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, const u8 request, const u8 requesttype, const u16 offset, const u16 value, void *buffer, const u16 buffer_length, @@ -107,18 +107,25 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev, * kmalloc. Hence the reason for using a previously allocated cache * which has been allocated properly. */ -int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev, +int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, const u8 request, const u8 requesttype, const u16 offset, void *buffer, const u16 buffer_length, const int timeout); /* + * A version of rt2x00usb_vendor_request_buff which must be called + * if the usb_cache_mutex is already held. */ +int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, + const u8 request, const u8 requesttype, + const u16 offset, void *buffer, + const u16 buffer_length, const int timeout); + +/* * Simple wrapper around rt2x00usb_vendor_request to write a single * command to the device. Since we don't use the buffer argument we * don't have to worry about kmalloc here. */ -static inline int rt2x00usb_vendor_request_sw(const struct rt2x00_dev - *rt2x00dev, +static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev, const u8 request, const u16 offset, const u16 value, @@ -134,8 +141,8 @@ static inline int rt2x00usb_vendor_request_sw(const struct rt2x00_dev * from the device. Note that the eeprom argument _must_ be allocated using * kmalloc for correct handling inside the kernel USB layer. */ -static inline int rt2x00usb_eeprom_read(const struct rt2x00_dev *rt2x00dev, - __le16 *eeprom, const u16 lenght) +static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, + __le16 *eeprom, const u16 lenght) { int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16)); @@ -147,7 +154,6 @@ static inline int rt2x00usb_eeprom_read(const struct rt2x00_dev *rt2x00dev, /* * Radio handlers */ -void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev); void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev); /* @@ -160,6 +166,10 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, /* * Device initialization handlers. */ +void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry); +void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry); int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev); void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index ecae968ce091..ab52f221cd71 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -24,11 +24,6 @@ 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> @@ -52,7 +47,7 @@ * 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; @@ -67,7 +62,7 @@ static u32 rt61pci_bbp_check(const struct rt2x00_dev *rt2x00dev) 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; @@ -93,7 +88,7 @@ static void rt61pci_bbp_write(const struct rt2x00_dev *rt2x00dev, 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; @@ -130,7 +125,7 @@ static void rt61pci_bbp_read(const struct rt2x00_dev *rt2x00dev, *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; @@ -160,7 +155,7 @@ rf_write: 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) { @@ -220,13 +215,13 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom) #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); @@ -322,7 +317,8 @@ static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, */ 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); @@ -411,8 +407,7 @@ static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev, } 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; @@ -423,32 +418,39 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, 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; } @@ -458,8 +460,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, } 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; @@ -470,22 +471,31 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, 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; } @@ -501,23 +511,18 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev, 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; @@ -525,70 +530,36 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev, 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); } @@ -625,46 +596,44 @@ static const struct antenna_sel antenna_sel_bg[] = { }; 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); } } @@ -709,8 +678,7 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev, if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL)) rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level); if (flags & CONFIG_UPDATE_ANTENNA) - rt61pci_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx, - libconf->conf->antenna_sel_rx); + rt61pci_config_antenna(rt2x00dev, &libconf->ant); if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) rt61pci_config_duration(rt2x00dev, libconf); } @@ -721,7 +689,6 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev, static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev) { u32 reg; - u16 led_reg; u8 arg0; u8 arg1; @@ -730,15 +697,14 @@ static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev) 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); } @@ -792,7 +758,8 @@ static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi) /* * 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; @@ -800,14 +767,13 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev) * 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) @@ -904,11 +870,11 @@ static void rt61pci_link_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); @@ -1023,64 +989,46 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, return 0; } -static void rt61pci_init_rxring(struct rt2x00_dev *rt2x00dev) +static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry) { - struct data_ring *ring = rt2x00dev->rx; - struct data_desc *rxd; - unsigned int i; + __le32 *rxd = entry->priv; 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, 5, &word); + rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, + entry->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_ring_index_clear(rt2x00dev->rx); + rt2x00_desc_read(rxd, 0, &word); + rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); + rt2x00_desc_write(rxd, 0, word); } -static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue) +static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry) { - struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); - struct data_desc *txd; - unsigned int i; + __le32 *txd = entry->priv; 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(txd, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1); + rt2x00_desc_write(txd, 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(txd, 5, &word); + rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx); + rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx); + rt2x00_desc_write(txd, 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(txd, 6, &word); + rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, + entry->data_dma); + rt2x00_desc_write(txd, 6, word); - rt2x00_ring_index_clear(ring); + 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); } static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) @@ -1088,16 +1036,6 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) 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, ®); @@ -1565,12 +1503,12 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, * 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 txdata_entry_desc *desc, + struct ieee80211_tx_control *control) { + struct skb_desc *skbdesc = get_skb_desc(skb); + __le32 *txd = skbdesc->desc; u32 word; /* @@ -1599,7 +1537,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 5, word); rt2x00_desc_read(txd, 11, &word); - rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, length); + rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len); rt2x00_desc_write(txd, 11, word); rt2x00_desc_read(txd, 0, &word); @@ -1608,7 +1546,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - !(control->flags & IEEE80211_TXCTL_NO_ACK)); + test_bit(ENTRY_TXD_ACK, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, @@ -1618,7 +1556,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, !!(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)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); @@ -1649,16 +1587,16 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, } 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); } @@ -1709,7 +1647,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) static void rt61pci_fill_rxdone(struct data_entry *entry, struct rxdata_entry_desc *desc) { - struct data_desc *rxd = entry->priv; + __le32 *rxd = entry->priv; u32 word0; u32 word1; @@ -1727,8 +1665,7 @@ static void rt61pci_fill_rxdone(struct data_entry *entry, 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; + desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* @@ -1739,7 +1676,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) struct data_ring *ring; struct data_entry *entry; struct data_entry *entry_done; - struct data_desc *txd; + __le32 *txd; u32 word; u32 reg; u32 old_reg; @@ -1809,24 +1746,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT); retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); - rt2x00lib_txdone(entry, tx_status, retry); - - /* - * 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); - - /* - * 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. - */ - if (!rt2x00_ring_full(ring)) - ieee80211_wake_queue(rt2x00dev->hw, - entry->tx_status.control.queue); + rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); } } @@ -1920,8 +1840,10 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) 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); @@ -2025,11 +1947,17 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) } /* + * 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); /* @@ -2039,12 +1967,6 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) __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 @@ -2072,6 +1994,38 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) __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. @@ -2325,7 +2279,6 @@ static void rt61pci_configure_filter(struct ieee80211_hw *hw, struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; u32 reg; /* @@ -2344,22 +2297,19 @@ static void rt61pci_configure_filter(struct ieee80211_hw *hw, * 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. @@ -2426,6 +2376,9 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct skb_desc *desc; + struct data_ring *ring; + struct data_entry *entry; /* * Just in case the ieee80211 doesn't set this, @@ -2433,6 +2386,8 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * initialization. */ control->queue = IEEE80211_TX_QUEUE_BEACON; + ring = rt2x00lib_get_ring(rt2x00dev, control->queue); + entry = rt2x00_get_data_entry(ring); /* * We need to append the descriptor in front of the @@ -2446,15 +2401,23 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, } /* - * First we create the beacon. + * Add the descriptor in front of the skb. + */ + skb_push(skb, ring->desc_size); + memset(skb->data, 0, ring->desc_size); + + /* + * Fill in skb descriptor */ - skb_push(skb, TXD_DESC_SIZE); - memset(skb->data, 0, TXD_DESC_SIZE); + desc = get_skb_desc(skb); + desc->desc_len = ring->desc_size; + desc->data_len = skb->len - ring->desc_size; + desc->desc = skb->data; + desc->data = skb->data + ring->desc_size; + desc->ring = ring; + desc->entry = entry; - rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data, - (struct ieee80211_hdr *)(skb->data + - TXD_DESC_SIZE), - skb->len - TXD_DESC_SIZE, control); + rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Write entire beacon with descriptor to register, @@ -2478,7 +2441,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .configure_filter = rt61pci_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt61pci_set_retry_limit, - .erp_ie_changed = rt2x00mac_erp_ie_changed, + .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt61pci_get_tsf, @@ -2493,6 +2456,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .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, @@ -2510,7 +2475,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { }; static const struct rt2x00_ops rt61pci_ops = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .rxd_size = RXD_DESC_SIZE, .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, @@ -2547,7 +2512,7 @@ MODULE_FIRMWARE(FIRMWARE_RT2661); 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), diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 6721d7dd32bc..4c6524eedad0 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1077,13 +1077,19 @@ struct hw_pairwise_ta_entry { * R4: RX antenna control * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529) */ -#define BBP_R4_RX_ANTENNA FIELD8(0x03) + +/* + * ANTENNA_CONTROL semantics (guessed): + * 0x1: Software controlled antenna switching (fixed or SW diversity) + * 0x2: Hardware diversity. + */ +#define BBP_R4_RX_ANTENNA_CONTROL FIELD8(0x03) #define BBP_R4_RX_FRAME_END FIELD8(0x20) /* * R77 */ -#define BBP_R77_PAIR FIELD8(0x03) +#define BBP_R77_RX_ANTENNA FIELD8(0x03) /* * RF registers @@ -1240,8 +1246,8 @@ struct hw_pairwise_ta_entry { /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 16 * sizeof(struct data_desc) ) -#define RXD_DESC_SIZE ( 16 * sizeof(struct data_desc) ) +#define TXD_DESC_SIZE ( 16 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 16 * sizeof(__le32) ) /* * TX descriptor format for TX, PRIO and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index c0671c2e6e73..4d576ab3e7f9 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -24,11 +24,6 @@ Supported chipsets: rt2571W & rt2671. */ -/* - * Set enviroment defines for rt2x00.h - */ -#define DRV_NAME "rt73usb" - #include <linux/delay.h> #include <linux/etherdevice.h> #include <linux/init.h> @@ -52,8 +47,9 @@ * between each attampt. When the busy bit is still set at that time, * the access attempt is considered to have failed, * and we will print an error. + * The _lock versions must be used if you already hold the usb_cache_mutex */ -static inline void rt73usb_register_read(const struct rt2x00_dev *rt2x00dev, +static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, const unsigned int offset, u32 *value) { __le32 reg; @@ -63,8 +59,17 @@ static inline void rt73usb_register_read(const struct rt2x00_dev *rt2x00dev, *value = le32_to_cpu(reg); } -static inline void rt73usb_register_multiread(const struct rt2x00_dev - *rt2x00dev, +static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 *value) +{ + __le32 reg; + rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + ®, sizeof(u32), REGISTER_TIMEOUT); + *value = le32_to_cpu(reg); +} + +static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev, const unsigned int offset, void *value, const u32 length) { @@ -74,7 +79,7 @@ static inline void rt73usb_register_multiread(const struct rt2x00_dev value, length, timeout); } -static inline void rt73usb_register_write(const struct rt2x00_dev *rt2x00dev, +static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev, const unsigned int offset, u32 value) { __le32 reg = cpu_to_le32(value); @@ -83,8 +88,16 @@ static inline void rt73usb_register_write(const struct rt2x00_dev *rt2x00dev, ®, sizeof(u32), REGISTER_TIMEOUT); } -static inline void rt73usb_register_multiwrite(const struct rt2x00_dev - *rt2x00dev, +static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 value) +{ + __le32 reg = cpu_to_le32(value); + rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + ®, sizeof(u32), REGISTER_TIMEOUT); +} + +static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, const unsigned int offset, void *value, const u32 length) { @@ -94,13 +107,13 @@ static inline void rt73usb_register_multiwrite(const struct rt2x00_dev value, length, timeout); } -static u32 rt73usb_bbp_check(const struct rt2x00_dev *rt2x00dev) +static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev) { u32 reg; unsigned int i; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt73usb_register_read(rt2x00dev, PHY_CSR3, ®); + rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, ®); if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) break; udelay(REGISTER_BUSY_DELAY); @@ -109,17 +122,20 @@ static u32 rt73usb_bbp_check(const struct rt2x00_dev *rt2x00dev) return reg; } -static void rt73usb_bbp_write(const struct rt2x00_dev *rt2x00dev, +static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { u32 reg; + mutex_lock(&rt2x00dev->usb_cache_mutex); + /* * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); + mutex_unlock(&rt2x00dev->usb_cache_mutex); return; } @@ -132,20 +148,24 @@ static void rt73usb_bbp_write(const struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); - rt73usb_register_write(rt2x00dev, PHY_CSR3, reg); + rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); + mutex_unlock(&rt2x00dev->usb_cache_mutex); } -static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev, +static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u8 *value) { u32 reg; + mutex_lock(&rt2x00dev->usb_cache_mutex); + /* * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); + mutex_unlock(&rt2x00dev->usb_cache_mutex); return; } @@ -157,7 +177,7 @@ static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); - rt73usb_register_write(rt2x00dev, PHY_CSR3, reg); + rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); /* * Wait until the BBP becomes ready. @@ -170,9 +190,10 @@ static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev, } *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); + mutex_unlock(&rt2x00dev->usb_cache_mutex); } -static void rt73usb_rf_write(const struct rt2x00_dev *rt2x00dev, +static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u32 reg; @@ -181,13 +202,16 @@ static void rt73usb_rf_write(const struct rt2x00_dev *rt2x00dev, if (!word) return; + mutex_lock(&rt2x00dev->usb_cache_mutex); + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt73usb_register_read(rt2x00dev, PHY_CSR4, ®); + rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, ®); if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) goto rf_write; udelay(REGISTER_BUSY_DELAY); } + mutex_unlock(&rt2x00dev->usb_cache_mutex); ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); return; @@ -200,25 +224,26 @@ rf_write: * all others contain 20 bits. */ rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, - 20 + !!(rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527))); + 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || + rt2x00_rf(&rt2x00dev->chip, RF2527))); rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); - rt73usb_register_write(rt2x00dev, PHY_CSR4, reg); + rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); rt2x00_rf_write(rt2x00dev, word, value); + mutex_unlock(&rt2x00dev->usb_cache_mutex); } #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) ) -static void rt73usb_read_csr(const struct rt2x00_dev *rt2x00dev, +static void rt73usb_read_csr(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 *data) { rt73usb_register_read(rt2x00dev, CSR_OFFSET(word), data); } -static void rt73usb_write_csr(const struct rt2x00_dev *rt2x00dev, +static void rt73usb_write_csr(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 data) { rt73usb_register_write(rt2x00dev, CSR_OFFSET(word), data); @@ -302,7 +327,8 @@ static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, */ rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 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); rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); @@ -396,12 +422,12 @@ static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev, } static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, - const int antenna_rx) + struct antenna_setup *ant) { u8 r3; u8 r4; u8 r77; + u8 temp; rt73usb_bbp_read(rt2x00dev, 3, &r3); rt73usb_bbp_read(rt2x00dev, 4, &r4); @@ -409,30 +435,38 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); - 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_FRAME_END, - !!(rt2x00dev->curr_hwmode != HWMODE_A)); + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); + temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags) + && (rt2x00dev->curr_hwmode != HWMODE_A); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); 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; } @@ -442,8 +476,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, } static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, - const int antenna_rx) + struct antenna_setup *ant) { u8 r3; u8 r4; @@ -457,18 +490,27 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, 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(&r77, BBP_R77_RX_ANTENNA, 3); + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); 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(&r77, BBP_R77_RX_ANTENNA, 0); + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); break; } @@ -509,40 +551,40 @@ static const struct antenna_sel antenna_sel_bg[] = { }; static void rt73usb_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; - rt73usb_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++) rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); + rt73usb_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)); + rt73usb_register_write(rt2x00dev, PHY_CSR0, reg); if (rt2x00_rf(&rt2x00dev->chip, RF5226) || rt2x00_rf(&rt2x00dev->chip, RF5225)) - rt73usb_config_antenna_5x(rt2x00dev, antenna_tx, antenna_rx); + rt73usb_config_antenna_5x(rt2x00dev, ant); else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || rt2x00_rf(&rt2x00dev->chip, RF2527)) - rt73usb_config_antenna_2x(rt2x00dev, antenna_tx, antenna_rx); + rt73usb_config_antenna_2x(rt2x00dev, ant); } static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, @@ -586,8 +628,7 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev, if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL)) rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level); if (flags & CONFIG_UPDATE_ANTENNA) - rt73usb_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx, - libconf->conf->antenna_sel_rx); + rt73usb_config_antenna(rt2x00dev, &libconf->ant); if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) rt73usb_config_duration(rt2x00dev, libconf); } @@ -605,12 +646,10 @@ static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev) rt73usb_register_write(rt2x00dev, MAC_CSR14, reg); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) - rt2x00_set_field16(&rt2x00dev->led_reg, - MCU_LEDCS_LINK_A_STATUS, 1); - else - rt2x00_set_field16(&rt2x00dev->led_reg, - MCU_LEDCS_LINK_BG_STATUS, 1); + rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, + (rt2x00dev->rx_status.phymode == MODE_IEEE80211A)); + rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, + (rt2x00dev->rx_status.phymode != MODE_IEEE80211A)); rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, rt2x00dev->led_reg, REGISTER_TIMEOUT); @@ -659,7 +698,8 @@ static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi) /* * Link tuning */ -static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev) +static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { u32 reg; @@ -667,15 +707,13 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev) * Update FCS error count from register. */ rt73usb_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. */ rt73usb_register_read(rt2x00dev, STA_CSR1, ®); - reg = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); - 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 rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev) @@ -781,12 +819,12 @@ static void rt73usb_link_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) { r17 += 4; if (r17 > up_bound) r17 = up_bound; rt73usb_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) { r17 -= 4; if (r17 < low_bound) r17 = low_bound; @@ -1098,8 +1136,6 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) return -EIO; } - rt2x00usb_enable_radio(rt2x00dev); - /* * Enable LED */ @@ -1193,12 +1229,12 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt73usb_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 txdata_entry_desc *desc, + struct ieee80211_tx_control *control) { + struct skb_desc *skbdesc = get_skb_desc(skb); + __le32 *txd = skbdesc->desc; u32 word; /* @@ -1233,7 +1269,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - !(control->flags & IEEE80211_TXCTL_NO_ACK)); + test_bit(ENTRY_TXD_ACK, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, @@ -1243,7 +1279,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, !!(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_BURST2, test_bit(ENTRY_TXD_BURST, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); @@ -1340,7 +1376,8 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) static void rt73usb_fill_rxdone(struct data_entry *entry, struct rxdata_entry_desc *desc) { - struct data_desc *rxd = (struct data_desc *)entry->skb->data; + struct skb_desc *skbdesc = get_skb_desc(entry->skb); + __le32 *rxd = (__le32 *)entry->skb->data; u32 word0; u32 word1; @@ -1358,13 +1395,15 @@ static void rt73usb_fill_rxdone(struct data_entry *entry, desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1); desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); /* - * Pull the skb to clear the descriptor area. + * Set descriptor and data pointer. */ - skb_pull(entry->skb, entry->ring->desc_size); - - return; + skbdesc->desc = entry->skb->data; + skbdesc->desc_len = entry->ring->desc_size; + skbdesc->data = entry->skb->data + entry->ring->desc_size; + skbdesc->data_len = desc->size; } /* @@ -1392,8 +1431,10 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) 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); @@ -1502,9 +1543,9 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * 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); /* @@ -1806,7 +1847,6 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw, struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; u32 reg; /* @@ -1825,22 +1865,19 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw, * 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; /* * When in atomic context, reschedule and let rt2x00lib @@ -1926,6 +1963,9 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct skb_desc *desc; + struct data_ring *ring; + struct data_entry *entry; int timeout; /* @@ -1934,17 +1974,27 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * initialization. */ control->queue = IEEE80211_TX_QUEUE_BEACON; + ring = rt2x00lib_get_ring(rt2x00dev, control->queue); + entry = rt2x00_get_data_entry(ring); + + /* + * Add the descriptor in front of the skb. + */ + skb_push(skb, ring->desc_size); + memset(skb->data, 0, ring->desc_size); /* - * First we create the beacon. + * Fill in skb descriptor */ - skb_push(skb, TXD_DESC_SIZE); - memset(skb->data, 0, TXD_DESC_SIZE); + desc = get_skb_desc(skb); + desc->desc_len = ring->desc_size; + desc->data_len = skb->len - ring->desc_size; + desc->desc = skb->data; + desc->data = skb->data + ring->desc_size; + desc->ring = ring; + desc->entry = entry; - rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data, - (struct ieee80211_hdr *)(skb->data + - TXD_DESC_SIZE), - skb->len - TXD_DESC_SIZE, control); + rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Write entire beacon with descriptor to register, @@ -1971,7 +2021,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .configure_filter = rt73usb_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt73usb_set_retry_limit, - .erp_ie_changed = rt2x00mac_erp_ie_changed, + .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt73usb_get_tsf, @@ -1985,6 +2035,8 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .load_firmware = rt73usb_load_firmware, .initialize = rt2x00usb_initialize, .uninitialize = rt2x00usb_uninitialize, + .init_rxentry = rt2x00usb_init_rxentry, + .init_txentry = rt2x00usb_init_txentry, .set_device_state = rt73usb_set_device_state, .link_stats = rt73usb_link_stats, .reset_tuner = rt73usb_reset_tuner, @@ -2002,7 +2054,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { }; static const struct rt2x00_ops rt73usb_ops = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .rxd_size = RXD_DESC_SIZE, .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, @@ -2089,7 +2141,7 @@ MODULE_FIRMWARE(FIRMWARE_RT2571); MODULE_LICENSE("GPL"); static struct usb_driver rt73usb_driver = { - .name = DRV_NAME, + .name = KBUILD_MODNAME, .id_table = rt73usb_device_table, .probe = rt2x00usb_probe, .disconnect = rt2x00usb_disconnect, diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index f0951519f74b..d49dcaacecee 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -713,13 +713,19 @@ struct hw_pairwise_ta_entry { * R4: RX antenna control * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529) */ -#define BBP_R4_RX_ANTENNA FIELD8(0x03) + +/* + * ANTENNA_CONTROL semantics (guessed): + * 0x1: Software controlled antenna switching (fixed or SW diversity) + * 0x2: Hardware diversity. + */ +#define BBP_R4_RX_ANTENNA_CONTROL FIELD8(0x03) #define BBP_R4_RX_FRAME_END FIELD8(0x20) /* * R77 */ -#define BBP_R77_PAIR FIELD8(0x03) +#define BBP_R77_RX_ANTENNA FIELD8(0x03) /* * RF registers @@ -860,8 +866,8 @@ struct hw_pairwise_ta_entry { /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 6 * sizeof(struct data_desc) ) -#define RXD_DESC_SIZE ( 6 * sizeof(struct data_desc) ) +#define TXD_DESC_SIZE ( 6 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 6 * sizeof(__le32) ) /* * TX descriptor format for TX, PRIO and Beacon Ring. |