From 811aa9cad1bd927999888ab56ed9592519d2fef6 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:42:53 +0100 Subject: rt2x00: Update copyright notice Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt61pci.h') diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 4c6524eedad0..e4578fbdb361 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify -- cgit v1.2.3-59-g8ed1b From 181d6902b6bad978d157e69479c95cc0ff213a76 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 5 Feb 2008 16:42:23 -0500 Subject: rt2x00: Queue handling overhaul This introduces a big queue handling overhaul, this also renames "ring" to "queues". Move queue handling into rt2x00queue.c and the matching header, use Kerneldoc to improve rt2x00 library documentation. Access to the queues is now protected under a spinlock, this to prevent race conditions which could corrupt the indexing system of the queue. Each queue entry allocates x bytes for driver/device specific data, this cleans up the queue structure significantly and improves code readability. rt2500usb no longer needs 2 entries in the beacon queue to correctly send out the guardian byte. This is now handled in the entry specific structure. rt61 and rt73 now use the correct descriptor size for beacon frames, since this data is written into the registers not the entire TXD descriptor was used but instead of a subset of it named TXINFO. Finally this also fixes numerous other bugs related to incorrect beacon handling or beacon related code. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Makefile | 2 +- drivers/net/wireless/rt2x00/rt2400pci.c | 204 ++++++++------ drivers/net/wireless/rt2x00/rt2500pci.c | 199 ++++++++------ drivers/net/wireless/rt2x00/rt2500usb.c | 201 ++++++++------ drivers/net/wireless/rt2x00/rt2x00.h | 133 ++++----- drivers/net/wireless/rt2x00/rt2x00debug.c | 32 +-- drivers/net/wireless/rt2x00/rt2x00dev.c | 403 +++++++-------------------- drivers/net/wireless/rt2x00/rt2x00dump.h | 6 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 10 + drivers/net/wireless/rt2x00/rt2x00mac.c | 55 ++-- drivers/net/wireless/rt2x00/rt2x00pci.c | 223 +++++++-------- drivers/net/wireless/rt2x00/rt2x00pci.h | 49 +++- drivers/net/wireless/rt2x00/rt2x00queue.c | 291 ++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00queue.h | 435 ++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00reg.h | 2 +- drivers/net/wireless/rt2x00/rt2x00ring.h | 290 -------------------- drivers/net/wireless/rt2x00/rt2x00usb.c | 290 +++++++++++--------- drivers/net/wireless/rt2x00/rt2x00usb.h | 48 +++- drivers/net/wireless/rt2x00/rt61pci.c | 256 +++++++++--------- drivers/net/wireless/rt2x00/rt61pci.h | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 134 +++++---- drivers/net/wireless/rt2x00/rt73usb.h | 1 + 22 files changed, 1881 insertions(+), 1384 deletions(-) create mode 100644 drivers/net/wireless/rt2x00/rt2x00queue.c create mode 100644 drivers/net/wireless/rt2x00/rt2x00queue.h delete mode 100644 drivers/net/wireless/rt2x00/rt2x00ring.h (limited to 'drivers/net/wireless/rt2x00/rt61pci.h') diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 30d654a42eea..ab40e1f6b303 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -1,4 +1,4 @@ -rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o +rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o rt2x00queue.o ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y) rt2x00lib-objs += rt2x00debug.o diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 763af7f19b8e..fc161084a8d3 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -498,13 +498,13 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, } static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, - struct ieee80211_tx_queue_params *params) + const int cw_min, const int cw_max) { u32 reg; rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_CWMIN, params->cw_min); - rt2x00_set_field32(®, CSR11_CWMAX, params->cw_max); + rt2x00_set_field32(®, CSR11_CWMIN, cw_min); + rt2x00_set_field32(®, CSR11_CWMAX, cw_max); rt2x00pci_register_write(rt2x00dev, CSR11, reg); } @@ -593,90 +593,89 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Initialization functions. */ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 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(priv_rx->desc, 2, &word); + rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->queue->data_size); + rt2x00_desc_write(priv_rx->desc, 2, 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_desc_read(priv_rx->desc, 1, &word); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->dma); + rt2x00_desc_write(priv_rx->desc, 1, word); - rt2x00_desc_read(rxd, 0, &word); + rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); + rt2x00_desc_write(priv_rx->desc, 0, word); } static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *txd = entry->priv; + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; u32 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(priv_tx->desc, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->dma); + rt2x00_desc_write(priv_tx->desc, 1, 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_desc_read(priv_tx->desc, 2, &word); + rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, + entry->queue->data_size); + rt2x00_desc_write(priv_tx->desc, 2, word); - rt2x00_desc_read(txd, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_set_field32(&word, TXD_W0_VALID, 0); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(txd, 0, word); + rt2x00_desc_write(priv_tx->desc, 0, word); } -static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev) +static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) { + struct queue_entry_priv_pci_rx *priv_rx; + struct queue_entry_priv_pci_tx *priv_tx; u32 reg; /* * Initialize registers. */ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); - rt2x00_set_field32(®, TXCSR2_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size); - rt2x00_set_field32(®, TXCSR2_NUM_TXD, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); - rt2x00_set_field32(®, TXCSR2_NUM_ATIM, - rt2x00dev->bcn[1].stats.limit); - rt2x00_set_field32(®, TXCSR2_NUM_PRIO, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); + rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); + rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit); + rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); + priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); - rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); + priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); - rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); + priv_tx = rt2x00dev->bcn[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); - rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, - rt2x00dev->bcn[1].data_dma); + rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); + priv_tx = rt2x00dev->bcn[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); - rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, - rt2x00dev->bcn[0].data_dma); + rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); - rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit); + rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); + priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; @@ -859,7 +858,7 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt2400pci_init_rings(rt2x00dev) || + if (rt2400pci_init_queues(rt2x00dev) || rt2400pci_init_registers(rt2x00dev) || rt2400pci_init_bbp(rt2x00dev)) { ERROR(rt2x00dev, "Register initialization failed.\n"); @@ -986,10 +985,10 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1001,19 +1000,19 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal); + rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->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, txdesc->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, desc->length_low); + rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->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_W4_PLCP_LENGTH_HIGH, txdesc->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); @@ -1022,14 +1021,14 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_RTS, - test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); @@ -1066,49 +1065,49 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, /* * RX control handlers */ -static void rt2400pci_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt2400pci_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word0; u32 word2; - rt2x00_desc_read(rxd, 0, &word0); - rt2x00_desc_read(rxd, 2, &word2); + rt2x00_desc_read(priv_rx->desc, 0, &word0); + rt2x00_desc_read(priv_rx->desc, 2, &word2); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - desc->flags |= RX_FLAG_FAILED_PLCP_CRC; + rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; /* * Obtain the status about this packet. */ - desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - - 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); + rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); + rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - + entry->queue->rt2x00dev->rssi_offset; + rxdesc->ofdm = 0; + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* * Interrupt functions. */ -static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) +static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, + const enum ieee80211_tx_queue queue_idx) { - struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); - struct data_entry *entry; - __le32 *txd; + struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + struct queue_entry_priv_pci_tx *priv_tx; + struct queue_entry *entry; + struct txdone_entry_desc txdesc; u32 word; - int tx_status; - int retry; - while (!rt2x00_ring_empty(ring)) { - entry = rt2x00_get_data_entry_done(ring); - txd = entry->priv; - rt2x00_desc_read(txd, 0, &word); + while (!rt2x00queue_empty(queue)) { + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + priv_tx = entry->priv_data; + rt2x00_desc_read(priv_tx->desc, 0, &word); if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || !rt2x00_get_field32(word, TXD_W0_VALID)) @@ -1117,10 +1116,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) /* * Obtain the status about this packet. */ - tx_status = rt2x00_get_field32(word, TXD_W0_RESULT); - retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); + txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT); + txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -1374,9 +1373,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) rt2400pci_probe_hw_mode(rt2x00dev); /* - * This device requires the beacon ring + * This device requires the atim queue */ - __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1481,7 +1480,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, /* * Write configuration to register. */ - rt2400pci_config_cw(rt2x00dev, &rt2x00dev->tx->tx_params); + rt2400pci_config_cw(rt2x00dev, + rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max); return 0; } @@ -1560,12 +1560,42 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .config = rt2400pci_config, }; +static const struct data_queue_desc rt2400pci_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_rx), +}; + +static const struct data_queue_desc rt2400pci_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt2400pci_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt2400pci_queue_atim = { + .entry_num = ATIM_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + static const struct rt2x00_ops rt2400pci_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt2400pci_queue_rx, + .tx = &rt2400pci_queue_tx, + .bcn = &rt2400pci_queue_bcn, + .atim = &rt2400pci_queue_atim, .lib = &rt2400pci_rt2x00_ops, .hw = &rt2400pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 884e225f7b9f..0a54b6512207 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -263,6 +263,8 @@ static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev, static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, const int tsf_sync) { + struct data_queue *queue = + rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); u32 reg; rt2x00pci_register_write(rt2x00dev, CSR14, 0); @@ -273,10 +275,7 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); rt2x00_set_field32(®, BCNCSR1_PRELOAD, PREAMBLE + get_duration(IEEE80211_HEADER, 20)); - rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, - rt2x00lib_get_ring(rt2x00dev, - IEEE80211_TX_QUEUE_BEACON) - ->tx_params.cw_min); + rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); /* @@ -684,82 +683,80 @@ dynamic_cca_tune: * Initialization functions. */ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 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_desc_read(priv_rx->desc, 1, &word); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->dma); + rt2x00_desc_write(priv_rx->desc, 1, word); - rt2x00_desc_read(rxd, 0, &word); + rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); + rt2x00_desc_write(priv_rx->desc, 0, word); } static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *txd = entry->priv; + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; u32 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(priv_tx->desc, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->dma); + rt2x00_desc_write(priv_tx->desc, 1, word); - rt2x00_desc_read(txd, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_set_field32(&word, TXD_W0_VALID, 0); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(txd, 0, word); + rt2x00_desc_write(priv_tx->desc, 0, word); } -static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev) +static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) { + struct queue_entry_priv_pci_rx *priv_rx; + struct queue_entry_priv_pci_tx *priv_tx; u32 reg; /* * Initialize registers. */ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); - rt2x00_set_field32(®, TXCSR2_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size); - rt2x00_set_field32(®, TXCSR2_NUM_TXD, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); - rt2x00_set_field32(®, TXCSR2_NUM_ATIM, - rt2x00dev->bcn[1].stats.limit); - rt2x00_set_field32(®, TXCSR2_NUM_PRIO, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); + rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); + rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit); + rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); + priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); - rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); + priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); - rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); + priv_tx = rt2x00dev->bcn[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); - rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, - rt2x00dev->bcn[1].data_dma); + rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); + priv_tx = rt2x00dev->bcn[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); - rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, - rt2x00dev->bcn[0].data_dma); + rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); - rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit); + rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); + priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; @@ -1011,7 +1008,7 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt2500pci_init_rings(rt2x00dev) || + if (rt2500pci_init_queues(rt2x00dev) || rt2500pci_init_registers(rt2x00dev) || rt2500pci_init_bbp(rt2x00dev)) { ERROR(rt2x00dev, "Register initialization failed.\n"); @@ -1138,10 +1135,10 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1150,36 +1147,36 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W2_AIFS, desc->aifs); - rt2x00_set_field32(&word, TXD_W2_CWMIN, desc->cw_min); - rt2x00_set_field32(&word, TXD_W2_CWMAX, desc->cw_max); + rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal); - rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, desc->length_low); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_desc_write(txd, 3, word); rt2x00_desc_read(txd, 10, &word); rt2x00_set_field32(&word, TXD_W10_RTS, - test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags)); + test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); rt2x00_desc_write(txd, 10, word); rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); + test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); @@ -1218,46 +1215,46 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, /* * RX control handlers */ -static void rt2500pci_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt2500pci_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word0; u32 word2; - rt2x00_desc_read(rxd, 0, &word0); - rt2x00_desc_read(rxd, 2, &word2); + rt2x00_desc_read(priv_rx->desc, 0, &word0); + rt2x00_desc_read(priv_rx->desc, 2, &word2); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - desc->flags |= RX_FLAG_FAILED_PLCP_CRC; - - desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - - 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); + rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; + + rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); + rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - + entry->queue->rt2x00dev->rssi_offset; + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* * Interrupt functions. */ -static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) +static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, + const enum ieee80211_tx_queue queue_idx) { - struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); - struct data_entry *entry; - __le32 *txd; + struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + struct queue_entry_priv_pci_tx *priv_tx; + struct queue_entry *entry; + struct txdone_entry_desc txdesc; u32 word; - int tx_status; - int retry; - while (!rt2x00_ring_empty(ring)) { - entry = rt2x00_get_data_entry_done(ring); - txd = entry->priv; - rt2x00_desc_read(txd, 0, &word); + while (!rt2x00queue_empty(queue)) { + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + priv_tx = entry->priv_data; + rt2x00_desc_read(priv_tx->desc, 0, &word); if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || !rt2x00_get_field32(word, TXD_W0_VALID)) @@ -1266,10 +1263,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) /* * Obtain the status about this packet. */ - tx_status = rt2x00_get_field32(word, TXD_W0_RESULT); - retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); + txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT); + txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -1705,9 +1702,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) rt2500pci_probe_hw_mode(rt2x00dev); /* - * This device requires the beacon ring + * This device requires the atim queue */ - __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1871,12 +1868,42 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .config = rt2500pci_config, }; +static const struct data_queue_desc rt2500pci_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_rx), +}; + +static const struct data_queue_desc rt2500pci_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt2500pci_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt2500pci_queue_atim = { + .entry_num = ATIM_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + static const struct rt2x00_ops rt2500pci_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt2500pci_queue_rx, + .tx = &rt2500pci_queue_tx, + .bcn = &rt2500pci_queue_bcn, + .atim = &rt2500pci_queue_atim, .lib = &rt2500pci_rt2x00_ops, .hw = &rt2500pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index bd4bbcc639c3..edc16a5fc754 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1027,10 +1027,10 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1039,31 +1039,31 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W1_AIFS, desc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); + rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, control->retry_limit); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); + test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); 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_IFS, txdesc->ifs); 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); @@ -1114,42 +1114,61 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, /* * RX control handlers */ -static void rt2500usb_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt2500usb_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - struct skb_desc *skbdesc = get_skb_desc(entry->skb); - struct urb *urb = entry->priv; - __le32 *rxd = (__le32 *)(entry->skb->data + - (urb->actual_length - entry->ring->desc_size)); + struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + __le32 *rxd = + (__le32 *)(entry->skb->data + + (priv_rx->urb->actual_length - entry->queue->desc_size)); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; + int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); u32 word0; u32 word1; rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - desc->flags |= RX_FLAG_FAILED_PLCP_CRC; + rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; /* * Obtain the status about this packet. */ - desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - - 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); + rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - + entry->queue->rt2x00dev->rssi_offset; + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); /* - * Set descriptor and data pointer. + * The data behind the ieee80211 header must be + * aligned on a 4 byte boundary. + */ + if (header_size % 4 == 0) { + skb_push(entry->skb, 2); + memmove(entry->skb->data, entry->skb->data + 2, + entry->skb->len - 2); + } + + /* + * Set descriptor 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; + skbdesc->data_len = entry->queue->data_size; + skbdesc->desc = entry->skb->data + rxdesc->size; + skbdesc->desc_len = entry->queue->desc_size; + + /* + * Remove descriptor from skb buffer and trim the whole thing + * down to only contain data. + */ + skb_trim(entry->skb, rxdesc->size); } /* @@ -1157,10 +1176,10 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry, */ static void rt2500usb_beacondone(struct urb *urb) { - struct data_entry *entry = (struct data_entry *)urb->context; - struct data_ring *ring = entry->ring; + struct queue_entry *entry = (struct queue_entry *)urb->context; + struct queue_entry_priv_usb_bcn *priv_bcn = entry->priv_data; - if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) + if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) return; /* @@ -1169,18 +1188,11 @@ static void rt2500usb_beacondone(struct urb *urb) * Otherwise we should free the sk_buffer, the device * should be doing the rest of the work now. */ - if (ring->index == 1) { - rt2x00_ring_index_done_inc(ring); - entry = rt2x00_get_data_entry(ring); - usb_submit_urb(entry->priv, GFP_ATOMIC); - rt2x00_ring_index_inc(ring); - } else if (ring->index_done == 1) { - entry = rt2x00_get_data_entry_done(ring); - if (entry->skb) { - dev_kfree_skb(entry->skb); - entry->skb = NULL; - } - rt2x00_ring_index_done_inc(ring); + if (priv_bcn->guardian_urb == urb) { + usb_submit_urb(priv_bcn->urb, GFP_ATOMIC); + } else if (priv_bcn->urb == urb) { + dev_kfree_skb(entry->skb); + entry->skb = NULL; } } @@ -1599,9 +1611,10 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) rt2500usb_probe_hw_mode(rt2x00dev); /* - * This device requires the beacon ring + * This device requires the atim queue */ - __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1691,12 +1704,11 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); - struct skb_desc *desc; - struct data_ring *ring; - struct data_entry *beacon; - struct data_entry *guardian; + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct queue_entry_priv_usb_bcn *priv_bcn; + struct skb_frame_desc *skbdesc; + struct data_queue *queue; + struct queue_entry *entry; int pipe = usb_sndbulkpipe(usb_dev, 1); int length; @@ -1706,32 +1718,26 @@ 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, - * the second for the actual beacon. - */ - guardian = rt2x00_get_data_entry(ring); - rt2x00_ring_index_inc(ring); - beacon = rt2x00_get_data_entry(ring); + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + entry = rt2x00queue_get_entry(queue, Q_INDEX); + priv_bcn = entry->priv_data; /* * Add the descriptor in front of the skb. */ - skb_push(skb, ring->desc_size); - memset(skb->data, 0, ring->desc_size); + skb_push(skb, queue->desc_size); + memset(skb->data, 0, queue->desc_size); /* * 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; + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data + queue->desc_size; + skbdesc->data_len = queue->data_size; + skbdesc->desc = skb->data; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); @@ -1742,22 +1748,23 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, */ length = rt2500usb_get_tx_data_len(rt2x00dev, skb); - usb_fill_bulk_urb(beacon->priv, usb_dev, pipe, - skb->data, length, rt2500usb_beacondone, beacon); + usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe, + skb->data, length, rt2500usb_beacondone, entry); /* * Second we need to create the guardian byte. * We only need a single byte, so lets recycle * the 'flags' field we are not using for beacons. */ - guardian->flags = 0; - usb_fill_bulk_urb(guardian->priv, usb_dev, pipe, - &guardian->flags, 1, rt2500usb_beacondone, guardian); + priv_bcn->guardian_data = 0; + usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe, + &priv_bcn->guardian_data, 1, rt2500usb_beacondone, + entry); /* * Send out the guardian byte. */ - usb_submit_urb(guardian->priv, GFP_ATOMIC); + usb_submit_urb(priv_bcn->guardian_urb, GFP_ATOMIC); /* * Enable beacon generation. @@ -1805,12 +1812,42 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .config = rt2500usb_config, }; +static const struct data_queue_desc rt2500usb_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_rx), +}; + +static const struct data_queue_desc rt2500usb_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_tx), +}; + +static const struct data_queue_desc rt2500usb_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_bcn), +}; + +static const struct data_queue_desc rt2500usb_queue_atim = { + .entry_num = ATIM_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_tx), +}; + static const struct rt2x00_ops rt2500usb_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt2500usb_queue_rx, + .tx = &rt2500usb_queue_tx, + .bcn = &rt2500usb_queue_bcn, + .atim = &rt2500usb_queue_atim, .lib = &rt2500usb_rt2x00_ops, .hw = &rt2500usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 86e4624a63ea..7b67f9666c3b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -27,7 +27,6 @@ #define RT2X00_H #include -#include #include #include #include @@ -38,7 +37,7 @@ #include "rt2x00debug.h" #include "rt2x00reg.h" -#include "rt2x00ring.h" +#include "rt2x00queue.h" /* * Module information. @@ -90,26 +89,6 @@ #define EEPROM(__dev, __msg, __args...) \ DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args) -/* - * Ring sizes. - * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes. - * DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings. - * MGMT_FRAME_SIZE is used for the BEACON ring. - */ -#define DATA_FRAME_SIZE 2432 -#define MGMT_FRAME_SIZE 256 - -/* - * Number of entries in a packet ring. - * PCI devices only need 1 Beacon entry, - * but USB devices require a second because they - * have to send a Guardian byte first. - */ -#define RX_ENTRIES 12 -#define TX_ENTRIES 12 -#define ATIM_ENTRIES 1 -#define BEACON_ENTRIES 2 - /* * Standard timing and size defines. * These values should follow the ieee80211 specifications. @@ -474,12 +453,12 @@ struct rt2x00lib_ops { void (*uninitialize) (struct rt2x00_dev *rt2x00dev); /* - * Ring initialization handlers + * queue initialization handlers */ void (*init_rxentry) (struct rt2x00_dev *rt2x00dev, - struct data_entry *entry); + struct queue_entry *entry); void (*init_txentry) (struct rt2x00_dev *rt2x00dev, - struct data_entry *entry); + struct queue_entry *entry); /* * Radio control handlers. @@ -497,10 +476,10 @@ struct rt2x00lib_ops { */ void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control); int (*write_tx_data) (struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control); int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); @@ -510,8 +489,8 @@ struct rt2x00lib_ops { /* * RX control handlers */ - void (*fill_rxdone) (struct data_entry *entry, - struct rxdata_entry_desc *desc); + void (*fill_rxdone) (struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc); /* * Configuration handlers. @@ -540,10 +519,12 @@ struct rt2x00lib_ops { */ struct rt2x00_ops { const char *name; - const unsigned int rxd_size; - const unsigned int txd_size; const unsigned int eeprom_size; const unsigned int rf_size; + const struct data_queue_desc *rx; + const struct data_queue_desc *tx; + const struct data_queue_desc *bcn; + const struct data_queue_desc *atim; const struct rt2x00lib_ops *lib; const struct ieee80211_ops *hw; #ifdef CONFIG_RT2X00_LIB_DEBUGFS @@ -570,7 +551,8 @@ enum rt2x00_flags { * Driver features */ DRIVER_REQUIRE_FIRMWARE, - DRIVER_REQUIRE_BEACON_RING, + DRIVER_REQUIRE_BEACON_GUARD, + DRIVER_REQUIRE_ATIM_QUEUE, /* * Driver configuration @@ -597,8 +579,10 @@ struct rt2x00_dev { * macro's should be used for correct typecasting. */ void *dev; -#define rt2x00dev_pci(__dev) ( (struct pci_dev*)(__dev)->dev ) -#define rt2x00dev_usb(__dev) ( (struct usb_interface*)(__dev)->dev ) +#define rt2x00dev_pci(__dev) ( (struct pci_dev *)(__dev)->dev ) +#define rt2x00dev_usb(__dev) ( (struct usb_interface *)(__dev)->dev ) +#define rt2x00dev_usb_dev(__dev)\ + ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) ) /* * Callback functions. @@ -757,14 +741,14 @@ struct rt2x00_dev { struct work_struct config_work; /* - * Data ring arrays for RX, TX and Beacon. - * The Beacon array also contains the Atim ring + * Data queue arrays for RX, TX and Beacon. + * The Beacon array also contains the Atim queue * if that is supported by the device. */ - int data_rings; - struct data_ring *rx; - struct data_ring *tx; - struct data_ring *bcn; + int data_queues; + struct data_queue *rx; + struct data_queue *tx; + struct data_queue *bcn; /* * Firmware image. @@ -772,37 +756,6 @@ struct rt2x00_dev { const struct firmware *fw; }; -/* - * For-each loop for the ring array. - * All rings have been allocated as a single array, - * this means we can create a very simply loop macro - * that is capable of looping through all rings. - * ring_end(), txring_end() and ring_loop() are helper macro's which - * should not be used directly. Instead the following should be used: - * ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim) - * txring_for_each() - Loops through TX data rings (TX only) - * txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim) - */ -#define ring_end(__dev) \ - &(__dev)->rx[(__dev)->data_rings] - -#define txring_end(__dev) \ - &(__dev)->tx[(__dev)->hw->queues] - -#define ring_loop(__entry, __start, __end) \ - for ((__entry) = (__start); \ - prefetch(&(__entry)[1]), (__entry) != (__end); \ - (__entry) = &(__entry)[1]) - -#define ring_for_each(__dev, __entry) \ - ring_loop(__entry, (__dev)->rx, ring_end(__dev)) - -#define txring_for_each(__dev, __entry) \ - ring_loop(__entry, (__dev)->tx, txring_end(__dev)) - -#define txringall_for_each(__dev, __entry) \ - ring_loop(__entry, (__dev)->tx, ring_end(__dev)) - /* * Generic RF access. * The RF is being accessed by word index. @@ -895,20 +848,42 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) return ((size * 8 * 10) % rate); } -/* - * Library functions. +/** + * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @queue: mac80211 queue index (see &enum ieee80211_tx_queue). */ -struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev, - const unsigned int queue); +struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, + const enum ieee80211_tx_queue queue); + +/** + * rt2x00queue_get_entry - Get queue entry where the given index points to. + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @index: Index identifier for obtaining the correct index. + */ +struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, + enum queue_index index); + +/** + * rt2x00queue_index_inc - Index incrementation function + * @queue: Queue (&struct data_queue) to perform the action on. + * @action: Index type (&enum queue_index) to perform the action on. + * + * This function will increase the requested index on the queue, + * it will grab the appropriate locks and handle queue overflow events by + * resetting the index to the start of the queue. + */ +void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); + /* * Interrupt context handlers. */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_txdone(struct data_entry *entry, - const int status, const int retry); -void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, - struct rxdata_entry_desc *desc); +void rt2x00lib_txdone(struct queue_entry *entry, + struct txdone_entry_desc *txdesc); +void rt2x00lib_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc); /* * TX descriptor initializer diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index d70ce6ec8de8..4e048ac0a684 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -116,7 +116,7 @@ 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 skb_frame_desc *desc = get_skb_frame_desc(skb); struct sk_buff *skbcopy; struct rt2x00dump_hdr *dump_hdr; struct timeval timestamp; @@ -147,7 +147,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, 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->queue_index = desc->entry->queue->qid; 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); @@ -186,7 +186,7 @@ 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) +static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file) { struct rt2x00debug_intf *intf = inode->i_private; int retval; @@ -203,7 +203,7 @@ static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file) return 0; } -static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file) +static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file) { struct rt2x00debug_intf *intf = inode->i_private; @@ -214,10 +214,10 @@ static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file) 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) +static ssize_t rt2x00debug_read_queue_dump(struct file *file, + char __user *buf, + size_t length, + loff_t *offset) { struct rt2x00debug_intf *intf = file->private_data; struct sk_buff *skb; @@ -248,8 +248,8 @@ exit: return status; } -static unsigned int rt2x00debug_poll_ring_dump(struct file *file, - poll_table *wait) +static unsigned int rt2x00debug_poll_queue_dump(struct file *file, + poll_table *wait) { struct rt2x00debug_intf *intf = file->private_data; @@ -261,12 +261,12 @@ static unsigned int rt2x00debug_poll_ring_dump(struct file *file, return 0; } -static const struct file_operations rt2x00debug_fop_ring_dump = { +static const struct file_operations rt2x00debug_fop_queue_dump = { .owner = THIS_MODULE, - .read = rt2x00debug_read_ring_dump, - .poll = rt2x00debug_poll_ring_dump, - .open = rt2x00debug_open_ring_dump, - .release = rt2x00debug_release_ring_dump, + .read = rt2x00debug_read_queue_dump, + .poll = rt2x00debug_poll_queue_dump, + .open = rt2x00debug_open_queue_dump, + .release = rt2x00debug_release_queue_dump, }; #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ @@ -503,7 +503,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) intf->frame_dump_entry = debugfs_create_file("dump", S_IRUGO, intf->frame_folder, - intf, &rt2x00debug_fop_ring_dump); + intf, &rt2x00debug_fop_queue_dump); if (IS_ERR(intf->frame_dump_entry)) goto exit; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 57355077fb7c..7620427887b6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -30,34 +30,6 @@ #include "rt2x00lib.h" #include "rt2x00dump.h" -/* - * Ring handler. - */ -struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev, - const unsigned int queue) -{ - int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); - - /* - * Check if we are requesting a reqular TX ring, - * or if we are requesting a Beacon or Atim ring. - * For Atim rings, we should check if it is supported. - */ - if (queue < rt2x00dev->hw->queues && rt2x00dev->tx) - return &rt2x00dev->tx[queue]; - - if (!rt2x00dev->bcn || !beacon) - return NULL; - - if (queue == IEEE80211_TX_QUEUE_BEACON) - return &rt2x00dev->bcn[0]; - else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON) - return &rt2x00dev->bcn[1]; - - return NULL; -} -EXPORT_SYMBOL_GPL(rt2x00lib_get_ring); - /* * Link tuning handlers */ @@ -112,46 +84,6 @@ static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev) cancel_delayed_work_sync(&rt2x00dev->link.work); } -/* - * 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. */ @@ -168,10 +100,10 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) return 0; /* - * Initialize all data rings. + * Initialize all data queues. */ - rt2x00lib_init_rxrings(rt2x00dev); - rt2x00lib_init_txrings(rt2x00dev); + rt2x00queue_init_rx(rt2x00dev); + rt2x00queue_init_tx(rt2x00dev); /* * Enable radio. @@ -504,19 +436,15 @@ static void rt2x00lib_beacondone_scheduled(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, beacon_work); - struct data_ring *ring = - rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); - struct data_entry *entry = rt2x00_get_data_entry(ring); + struct ieee80211_tx_control control; struct sk_buff *skb; skb = ieee80211_beacon_get(rt2x00dev->hw, - rt2x00dev->interface.id, - &entry->tx_status.control); + rt2x00dev->interface.id, &control); if (!skb) return; - rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, - &entry->tx_status.control); + rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, &control); dev_kfree_skb(skb); } @@ -530,58 +458,64 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); -void rt2x00lib_txdone(struct data_entry *entry, - const int status, const int retry) +void rt2x00lib_txdone(struct queue_entry *entry, + struct txdone_entry_desc *txdesc) { - struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; - struct ieee80211_tx_status *tx_status = &entry->tx_status; - struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats; - int success = !!(status == TX_SUCCESS || status == TX_SUCCESS_RETRY); - int fail = !!(status == TX_FAIL_RETRY || status == TX_FAIL_INVALID || - status == TX_FAIL_OTHER); + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct ieee80211_tx_status tx_status; + int success = !!(txdesc->status == TX_SUCCESS || + txdesc->status == TX_SUCCESS_RETRY); + int fail = !!(txdesc->status == TX_FAIL_RETRY || + txdesc->status == TX_FAIL_INVALID || + txdesc->status == TX_FAIL_OTHER); /* * Update TX statistics. */ - tx_status->flags = 0; - tx_status->ack_signal = 0; - tx_status->excessive_retries = (status == TX_FAIL_RETRY); - tx_status->retry_count = retry; rt2x00dev->link.qual.tx_success += success; - rt2x00dev->link.qual.tx_failed += retry + fail; + rt2x00dev->link.qual.tx_failed += txdesc->retry + fail; - if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) { + /* + * Initialize TX status + */ + tx_status.flags = 0; + tx_status.ack_signal = 0; + tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY); + tx_status.retry_count = txdesc->retry; + memcpy(&tx_status.control, txdesc->control, sizeof(txdesc->control)); + + if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) { if (success) - tx_status->flags |= IEEE80211_TX_STATUS_ACK; + tx_status.flags |= IEEE80211_TX_STATUS_ACK; else - stats->dot11ACKFailureCount++; + rt2x00dev->low_level_stats.dot11ACKFailureCount++; } - tx_status->queue_length = entry->ring->stats.limit; - tx_status->queue_number = tx_status->control.queue; + tx_status.queue_length = entry->queue->limit; + tx_status.queue_number = tx_status.control.queue; - if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { + if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { if (success) - stats->dot11RTSSuccessCount++; + rt2x00dev->low_level_stats.dot11RTSSuccessCount++; else - stats->dot11RTSFailureCount++; + rt2x00dev->low_level_stats.dot11RTSFailureCount++; } /* * Send the tx_status to mac80211 & debugfs. * mac80211 will clean up the skb structure. */ - get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE; + get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE; rt2x00debug_dump_frame(rt2x00dev, entry->skb); - ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status); + ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, &tx_status); entry->skb = NULL; } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); -void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, - struct rxdata_entry_desc *desc) +void rt2x00lib_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; struct ieee80211_hw_mode *mode; struct ieee80211_rate *rate; @@ -602,12 +536,12 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, * the signal is the PLCP value. If it was received with * a CCK bitrate the signal is the rate in 0.5kbit/s. */ - if (!desc->ofdm) + if (!rxdesc->ofdm) val = DEVICE_GET_RATE_FIELD(rate->val, RATE); else val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); - if (val == desc->signal) { + if (val == rxdesc->signal) { val = rate->val; break; } @@ -616,26 +550,28 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, /* * Only update link status if this is a beacon frame carrying our bssid. */ - hdr = (struct ieee80211_hdr*)skb->data; + hdr = (struct ieee80211_hdr*)entry->skb->data; fc = le16_to_cpu(hdr->frame_control); - if (is_beacon(fc) && desc->my_bss) - rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi); + if (is_beacon(fc) && rxdesc->my_bss) + rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->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; + rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi); + rx_status->ssi = rxdesc->rssi; + rx_status->flag = rxdesc->flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; /* - * Send frame to mac80211 & debugfs + * Send frame to mac80211 & debugfs. + * mac80211 will clean up the skb structure. */ - get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE; - rt2x00debug_dump_frame(rt2x00dev, skb); - ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status); + get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_RXDONE; + rt2x00debug_dump_frame(rt2x00dev, entry->skb); + ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); + entry->skb = NULL; } EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -646,9 +582,9 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct ieee80211_tx_control *control) { - struct txdata_entry_desc desc; - struct skb_desc *skbdesc = get_skb_desc(skb); - struct ieee80211_hdr *ieee80211hdr = skbdesc->data; + struct txentry_desc txdesc; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; int tx_rate; int bitrate; int length; @@ -657,22 +593,22 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, u16 frame_control; u16 seq_ctrl; - memset(&desc, 0, sizeof(desc)); + memset(&txdesc, 0, sizeof(txdesc)); - 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; + txdesc.cw_min = skbdesc->entry->queue->cw_min; + txdesc.cw_max = skbdesc->entry->queue->cw_max; + txdesc.aifs = skbdesc->entry->queue->aifs; /* * Identify queue */ if (control->queue < rt2x00dev->hw->queues) - desc.queue = control->queue; + txdesc.queue = control->queue; else if (control->queue == IEEE80211_TX_QUEUE_BEACON || control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON) - desc.queue = QUEUE_MGMT; + txdesc.queue = QID_MGMT; else - desc.queue = QUEUE_OTHER; + txdesc.queue = QID_OTHER; /* * Read required fields from ieee80211 header. @@ -686,18 +622,18 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Check whether this frame is to be acked */ if (!(control->flags & IEEE80211_TXCTL_NO_ACK)) - __set_bit(ENTRY_TXD_ACK, &desc.flags); + __set_bit(ENTRY_TXD_ACK, &txdesc.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); + __set_bit(ENTRY_TXD_BURST, &txdesc.flags); if (is_rts_frame(frame_control)) { - __set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags); - __set_bit(ENTRY_TXD_ACK, &desc.flags); + __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags); + __set_bit(ENTRY_TXD_ACK, &txdesc.flags); } else - __clear_bit(ENTRY_TXD_ACK, &desc.flags); + __clear_bit(ENTRY_TXD_ACK, &txdesc.flags); if (control->rts_cts_rate) tx_rate = control->rts_cts_rate; } @@ -706,14 +642,14 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Check for OFDM */ if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK) - __set_bit(ENTRY_TXD_OFDM_RATE, &desc.flags); + __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags); /* * Check if more fragments are pending */ if (ieee80211_get_morefrag(ieee80211hdr)) { - __set_bit(ENTRY_TXD_BURST, &desc.flags); - __set_bit(ENTRY_TXD_MORE_FRAG, &desc.flags); + __set_bit(ENTRY_TXD_BURST, &txdesc.flags); + __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags); } /* @@ -722,7 +658,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ if (control->queue == IEEE80211_TX_QUEUE_BEACON || is_probe_resp(frame_control)) - __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc.flags); + __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags); /* * Determine with what IFS priority this frame should be send. @@ -730,22 +666,22 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * or this fragment came after RTS/CTS. */ if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 || - test_bit(ENTRY_TXD_RTS_FRAME, &desc.flags)) - desc.ifs = IFS_SIFS; + test_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags)) + txdesc.ifs = IFS_SIFS; else - desc.ifs = IFS_BACKOFF; + txdesc.ifs = IFS_BACKOFF; /* * PLCP setup * Length calculation depends on OFDM/CCK rate. */ - desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); - desc.service = 0x04; + txdesc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); + txdesc.service = 0x04; - length = skbdesc->data_len + FCS_LEN; - if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) { - desc.length_high = (length >> 6) & 0x3f; - desc.length_low = length & 0x3f; + length = skb->len + FCS_LEN; + if (test_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags)) { + txdesc.length_high = (length >> 6) & 0x3f; + txdesc.length_low = length & 0x3f; } else { bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); @@ -762,27 +698,26 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Check if we need to set the Length Extension */ if (bitrate == 110 && residual <= 30) - desc.service |= 0x80; + txdesc.service |= 0x80; } - desc.length_high = (duration >> 8) & 0xff; - desc.length_low = duration & 0xff; + txdesc.length_high = (duration >> 8) & 0xff; + txdesc.length_low = duration & 0xff; /* * When preamble is enabled we should set the * preamble bit for the signal. */ if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) - desc.signal |= 0x08; + txdesc.signal |= 0x08; } - rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control); + rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &txdesc, control); /* - * Update ring entry. + * Update queue entry. */ skbdesc->entry->skb = skb; - memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control)); /* * The frame has been completely initialized and ready @@ -1012,86 +947,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) /* * Initialization/uninitialization handlers. */ -static int rt2x00lib_alloc_entries(struct data_ring *ring, - const u16 max_entries, const u16 data_size, - const u16 desc_size) -{ - struct data_entry *entry; - unsigned int i; - - ring->stats.limit = max_entries; - ring->data_size = data_size; - ring->desc_size = desc_size; - - /* - * Allocate all ring entries. - */ - entry = kzalloc(ring->stats.limit * sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - for (i = 0; i < ring->stats.limit; i++) { - entry[i].flags = 0; - entry[i].ring = ring; - entry[i].skb = NULL; - entry[i].entry_idx = i; - } - - ring->entry = entry; - - return 0; -} - -static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev) -{ - struct data_ring *ring; - - /* - * Allocate the RX ring. - */ - if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE, - rt2x00dev->ops->rxd_size)) - return -ENOMEM; - - /* - * First allocate the TX rings. - */ - txring_for_each(rt2x00dev, ring) { - if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE, - rt2x00dev->ops->txd_size)) - return -ENOMEM; - } - - if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)) - return 0; - - /* - * Allocate the BEACON ring. - */ - if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES, - MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size)) - return -ENOMEM; - - /* - * Allocate the Atim ring. - */ - if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES, - DATA_FRAME_SIZE, rt2x00dev->ops->txd_size)) - return -ENOMEM; - - return 0; -} - -static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev) -{ - struct data_ring *ring; - - ring_for_each(rt2x00dev, ring) { - kfree(ring->entry); - ring->entry = NULL; - } -} - static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) { if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags)) @@ -1108,9 +963,9 @@ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) rt2x00dev->ops->lib->uninitialize(rt2x00dev); /* - * Free allocated ring entries. + * Free allocated queue entries. */ - rt2x00lib_free_ring_entries(rt2x00dev); + rt2x00queue_uninitialize(rt2x00dev); } static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) @@ -1121,13 +976,11 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) return 0; /* - * Allocate all ring entries. + * Allocate all queue entries. */ - status = rt2x00lib_alloc_ring_entries(rt2x00dev); - if (status) { - ERROR(rt2x00dev, "Ring entries allocation failed.\n"); + status = rt2x00queue_initialize(rt2x00dev); + if (status) return status; - } /* * Initialize the device. @@ -1143,15 +996,12 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) */ status = rt2x00rfkill_register(rt2x00dev); if (status) - goto exit_unitialize; + goto exit; return 0; -exit_unitialize: - rt2x00lib_uninitialize(rt2x00dev); - exit: - rt2x00lib_free_ring_entries(rt2x00dev); + rt2x00lib_uninitialize(rt2x00dev); return status; } @@ -1211,65 +1061,6 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) /* * driver allocation handlers. */ -static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev) -{ - struct data_ring *ring; - unsigned int index; - - /* - * We need the following rings: - * RX: 1 - * TX: hw->queues - * Beacon: 1 (if required) - * Atim: 1 (if required) - */ - rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues + - (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)); - - ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL); - if (!ring) { - ERROR(rt2x00dev, "Ring allocation failed.\n"); - return -ENOMEM; - } - - /* - * Initialize pointers - */ - rt2x00dev->rx = ring; - rt2x00dev->tx = &rt2x00dev->rx[1]; - if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)) - rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues]; - - /* - * Initialize ring parameters. - * RX: queue_idx = 0 - * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index - * TX: cw_min: 2^5 = 32. - * TX: cw_max: 2^10 = 1024. - */ - 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; - } - - return 0; -} - -static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev) -{ - kfree(rt2x00dev->rx); - rt2x00dev->rx = NULL; - rt2x00dev->tx = NULL; - rt2x00dev->bcn = NULL; -} - int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; @@ -1297,9 +1088,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID; /* - * Allocate ring array. + * Allocate queue array. */ - retval = rt2x00lib_alloc_rings(rt2x00dev); + retval = rt2x00queue_allocate(rt2x00dev); if (retval) goto exit; @@ -1370,9 +1161,9 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) rt2x00lib_free_firmware(rt2x00dev); /* - * Free ring structures. + * Free queue structures. */ - rt2x00lib_free_rings(rt2x00dev); + rt2x00queue_free(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 93f8967e5dc4..7169c222a486 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -93,8 +93,8 @@ enum rt2x00_dump_type { * @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. + * @queue_index: The index number of the data queue. + * @entry_index: The index number of the entry inside the data queue. * @timestamp_sec: Timestamp - seconds * @timestamp_usec: Timestamp - microseconds */ @@ -111,7 +111,7 @@ struct rt2x00dump_hdr { __le32 chip_rev; __le16 type; - __u8 ring_index; + __u8 queue_index; __u8 entry_index; __le32 timestamp_sec; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 7540d29c47a0..5c835f42a455 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -58,6 +58,16 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config); +/* + * Queue handlers. + */ +void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev); +void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev); +int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); +void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev); +int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev); +void rt2x00queue_free(struct rt2x00_dev *rt2x00dev); + /* * Firmware handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index e638c653e094..411ed5d08598 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -30,7 +30,7 @@ #include "rt2x00lib.h" static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, + struct data_queue *queue, struct sk_buff *frag_skb, struct ieee80211_tx_control *control) { @@ -60,7 +60,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, frag_skb->data, frag_skb->len, control, (struct ieee80211_rts *)(skb->data)); - if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) { + if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) { WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); return NETDEV_TX_BUSY; } @@ -73,7 +73,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, { struct rt2x00_dev *rt2x00dev = hw->priv; struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; - struct data_ring *ring; + struct data_queue *queue; u16 frame_control; /* @@ -88,10 +88,10 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, } /* - * Determine which ring to put packet on. + * Determine which queue to put packet on. */ - ring = rt2x00lib_get_ring(rt2x00dev, control->queue); - if (unlikely(!ring)) { + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + if (unlikely(!queue)) { ERROR(rt2x00dev, "Attempt to send packet over invalid queue %d.\n" "Please file bug report to %s.\n", @@ -110,23 +110,23 @@ 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 (rt2x00queue_available(queue) <= 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, queue, 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, queue, skb, control)) { ieee80211_stop_queue(rt2x00dev->hw, control->queue); return NETDEV_TX_BUSY; } - if (rt2x00_ring_full(ring)) + if (rt2x00queue_full(queue)) ieee80211_stop_queue(rt2x00dev->hw, control->queue); if (rt2x00dev->ops->lib->kick_tx_queue) @@ -214,7 +214,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, !is_interface_present(intf)) return; - intf->id = 0; + intf->id = NULL; intf->type = IEEE80211_IF_TYPE_INVALID; memset(&intf->bssid, 0x00, ETH_ALEN); memset(&intf->mac, 0x00, ETH_ALEN); @@ -334,9 +334,11 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; unsigned int i; - for (i = 0; i < hw->queues; i++) - memcpy(&stats->data[i], &rt2x00dev->tx[i].stats, - sizeof(rt2x00dev->tx[i].stats)); + for (i = 0; i < hw->queues; i++) { + stats->data[i].len = rt2x00dev->tx[i].length; + stats->data[i].limit = rt2x00dev->tx[i].limit; + stats->data[i].count = rt2x00dev->tx[i].count; + } return 0; } @@ -380,14 +382,14 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue, +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue_idx, const struct ieee80211_tx_queue_params *params) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_ring *ring; + struct data_queue *queue; - ring = rt2x00lib_get_ring(rt2x00dev, queue); - if (unlikely(!ring)) + queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + if (unlikely(!queue)) return -EINVAL; /* @@ -395,24 +397,23 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue, * Ralink registers require to know the bit number 'n'. */ if (params->cw_min) - ring->tx_params.cw_min = fls(params->cw_min); + queue->cw_min = fls(params->cw_min); else - ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */ + queue->cw_min = 5; /* cw_min: 2^5 = 32. */ if (params->cw_max) - ring->tx_params.cw_max = fls(params->cw_max); + queue->cw_max = fls(params->cw_max); else - ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */ + queue->cw_max = 10; /* cw_min: 2^10 = 1024. */ if (params->aifs) - ring->tx_params.aifs = params->aifs; + queue->aifs = params->aifs; else - ring->tx_params.aifs = 2; + queue->aifs = 2; INFO(rt2x00dev, - "Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n", - queue, ring->tx_params.cw_min, ring->tx_params.cw_max, - ring->tx_params.aifs); + "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n", + queue_idx, queue->cw_min, queue->cw_max, queue->aifs); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 0f2590bc31ec..63cfe33e95da 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -38,9 +38,10 @@ int rt2x00pci_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; + struct queue_entry_priv_pci_tx *priv_tx; + struct skb_frame_desc *skbdesc; + struct data_queue *queue; + struct queue_entry *entry; /* * Just in case mac80211 doesn't set this correctly, @@ -48,21 +49,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); + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + entry = rt2x00queue_get_entry(queue, Q_INDEX); + priv_tx = entry->priv_data; /* * 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); + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data; + skbdesc->data_len = queue->data_size; + skbdesc->desc = priv_tx->desc; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; + + memcpy(priv_tx->data, skb->data, skb->len); rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* @@ -78,18 +80,18 @@ EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update); * TX data handlers. */ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control) { - struct data_entry *entry = rt2x00_get_data_entry(ring); - __le32 *txd = entry->priv; - struct skb_desc *desc; + struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; + struct skb_frame_desc *skbdesc; u32 word; - if (rt2x00_ring_full(ring)) + if (rt2x00queue_full(queue)) return -EINVAL; - rt2x00_desc_read(txd, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) || rt2x00_get_field32(word, TXD_ENTRY_VALID)) { @@ -103,18 +105,18 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, /* * 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); + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data; + skbdesc->data_len = queue->data_size; + skbdesc->desc = priv_tx->desc; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; + + memcpy(priv_tx->data, skb->data, skb->len); rt2x00lib_write_tx_desc(rt2x00dev, skb, control); - rt2x00_ring_index_inc(ring); + rt2x00queue_index_inc(queue, Q_INDEX); return 0; } @@ -125,29 +127,28 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); */ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring = rt2x00dev->rx; - struct data_entry *entry; - struct sk_buff *skb; + struct data_queue *queue = rt2x00dev->rx; + struct queue_entry *entry; + struct queue_entry_priv_pci_rx *priv_rx; struct ieee80211_hdr *hdr; - struct skb_desc *skbdesc; - struct rxdata_entry_desc desc; + struct skb_frame_desc *skbdesc; + struct rxdone_entry_desc rxdesc; int header_size; - __le32 *rxd; int align; u32 word; while (1) { - entry = rt2x00_get_data_entry(ring); - rxd = entry->priv; - rt2x00_desc_read(rxd, 0, &word); + entry = rt2x00queue_get_entry(queue, Q_INDEX); + priv_rx = entry->priv_data; + rt2x00_desc_read(priv_rx->desc, 0, &word); if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) break; - memset(&desc, 0, sizeof(desc)); - rt2x00dev->ops->lib->fill_rxdone(entry, &desc); + memset(&rxdesc, 0, sizeof(rxdesc)); + rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); - hdr = (struct ieee80211_hdr *)entry->data_addr; + hdr = (struct ieee80211_hdr *)priv_rx->data; header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); @@ -161,66 +162,68 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) * Allocate the sk_buffer, initialize it and copy * all data into it. */ - skb = dev_alloc_skb(desc.size + align); - if (!skb) + entry->skb = dev_alloc_skb(rxdesc.size + align); + if (!entry->skb) return; - skb_reserve(skb, align); - memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size); + skb_reserve(entry->skb, align); + memcpy(skb_put(entry->skb, rxdesc.size), + priv_rx->data, rxdesc.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 = get_skb_frame_desc(entry->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = entry->skb->data; + skbdesc->data_len = queue->data_size; + skbdesc->desc = priv_rx->desc; + skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry; /* * Send the frame to rt2x00lib for further processing. */ - rt2x00lib_rxdone(entry, skb, &desc); + rt2x00lib_rxdone(entry, &rxdesc); - if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) { + if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) { rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); + rt2x00_desc_write(priv_rx->desc, 0, word); } - rt2x00_ring_index_inc(ring); + rt2x00queue_index_inc(queue, Q_INDEX); } } EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); -void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry, - const int tx_status, const int retry) +void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, + struct txdone_entry_desc *txdesc) { + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; u32 word; - rt2x00lib_txdone(entry, tx_status, retry); + txdesc->control = &priv_tx->control; + rt2x00lib_txdone(entry, txdesc); /* * Make this entry available for reuse. */ entry->flags = 0; - rt2x00_desc_read(entry->priv, 0, &word); + rt2x00_desc_read(priv_tx->desc, 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_desc_write(priv_tx->desc, 0, word); - rt2x00_ring_index_done_inc(entry->ring); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* - * If the data ring was full before the txdone handler + * If the data queue 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); + if (!rt2x00queue_full(entry->queue)) + ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue); } EXPORT_SYMBOL_GPL(rt2x00pci_txdone); @@ -228,73 +231,83 @@ EXPORT_SYMBOL_GPL(rt2x00pci_txdone); /* * Device initialization handlers. */ -#define priv_offset(__ring, __i) \ -({ \ - ring->data_addr + (i * ring->desc_size); \ +#define dma_size(__queue) \ +({ \ + (__queue)->limit * \ + ((__queue)->desc_size + (__queue)->data_size);\ }) -#define data_addr_offset(__ring, __i) \ -({ \ - (__ring)->data_addr + \ - ((__ring)->stats.limit * (__ring)->desc_size) + \ - ((__i) * (__ring)->data_size); \ +#define priv_offset(__queue, __base, __i) \ +({ \ + (__base) + ((__i) * (__queue)->desc_size); \ }) -#define data_dma_offset(__ring, __i) \ -({ \ - (__ring)->data_dma + \ - ((__ring)->stats.limit * (__ring)->desc_size) + \ - ((__i) * (__ring)->data_size); \ +#define data_addr_offset(__queue, __base, __i) \ +({ \ + (__base) + \ + ((__queue)->limit * (__queue)->desc_size) + \ + ((__i) * (__queue)->data_size); \ }) -static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring) +#define data_dma_offset(__queue, __base, __i) \ +({ \ + (__base) + \ + ((__queue)->limit * (__queue)->desc_size) + \ + ((__i) * (__queue)->data_size); \ +}) + +static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, + struct data_queue *queue) { + struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); + struct queue_entry_priv_pci_tx *priv_tx; + void *data_addr; + dma_addr_t data_dma; unsigned int i; /* * Allocate DMA memory for descriptor and buffer. */ - ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev), - rt2x00_get_ring_size(ring), - &ring->data_dma); - if (!ring->data_addr) + data_addr = pci_alloc_consistent(pci_dev, dma_size(queue), &data_dma); + if (!data_addr) return -ENOMEM; /* - * Initialize all ring entries to contain valid - * addresses. + * Initialize all queue entries to contain valid addresses. */ - for (i = 0; i < ring->stats.limit; i++) { - ring->entry[i].priv = priv_offset(ring, i); - ring->entry[i].data_addr = data_addr_offset(ring, i); - ring->entry[i].data_dma = data_dma_offset(ring, i); + for (i = 0; i < queue->limit; i++) { + priv_tx = queue->entries[i].priv_data; + priv_tx->desc = priv_offset(queue, data_addr, i); + priv_tx->data = data_addr_offset(queue, data_addr, i); + priv_tx->dma = data_dma_offset(queue, data_dma, i); } return 0; } -static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring) +static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, + struct data_queue *queue) { - if (ring->data_addr) - pci_free_consistent(rt2x00dev_pci(rt2x00dev), - rt2x00_get_ring_size(ring), - ring->data_addr, ring->data_dma); - ring->data_addr = NULL; + struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); + struct queue_entry_priv_pci_tx *priv_tx = queue->entries[0].priv_data; + + if (priv_tx->data) + pci_free_consistent(pci_dev, dma_size(queue), + priv_tx->data, priv_tx->dma); + priv_tx->data = NULL; } int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) { struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); - struct data_ring *ring; + struct data_queue *queue; int status; /* * Allocate DMA */ - ring_for_each(rt2x00dev, ring) { - status = rt2x00pci_alloc_dma(rt2x00dev, ring); + queue_for_each(rt2x00dev, queue) { + status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue); if (status) goto exit; } @@ -321,7 +334,7 @@ EXPORT_SYMBOL_GPL(rt2x00pci_initialize); void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; + struct data_queue *queue; /* * Free irq line. @@ -331,8 +344,8 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) /* * Free DMA */ - ring_for_each(rt2x00dev, ring) - rt2x00pci_free_dma(rt2x00dev, ring); + queue_for_each(rt2x00dev, queue) + rt2x00pci_free_queue_dma(rt2x00dev, queue); } EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); @@ -530,5 +543,5 @@ EXPORT_SYMBOL_GPL(rt2x00pci_resume); */ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("rt2x00 library"); +MODULE_DESCRIPTION("rt2x00 pci library"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 9ac560b87b2b..3b1597ffb4f2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -97,15 +97,54 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * TX data handlers. */ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control); -/* - * RX/TX data handlers. +/** + * struct queue_entry_priv_pci_rx: Per RX entry PCI specific information + * + * @desc: Pointer to device descriptor. + * @data: Pointer to device's entry memory. + * @dma: DMA pointer to &data. + */ +struct queue_entry_priv_pci_rx { + __le32 *desc; + + void *data; + dma_addr_t dma; +}; + +/** + * struct queue_entry_priv_pci_tx: Per TX entry PCI specific information + * + * @desc: Pointer to device descriptor + * @data: Pointer to device's entry memory. + * @dma: DMA pointer to &data. + * @control: mac80211 control structure used to transmit data. + */ +struct queue_entry_priv_pci_tx { + __le32 *desc; + + void *data; + dma_addr_t dma; + + struct ieee80211_tx_control control; +}; + +/** + * rt2x00pci_rxdone - Handle RX done events + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. */ 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); + +/** + * rt2x00pci_txdone - Handle TX done events + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @entry: Entry which has completed the transmission of a frame. + * @desc: TX done descriptor + */ +void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, + struct txdone_entry_desc *desc); /* * Device initialization handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c new file mode 100644 index 000000000000..921eca35719d --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -0,0 +1,291 @@ +/* + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + + + 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: rt2x00lib + Abstract: rt2x00 queue specific routines. + */ + +#include +#include + +#include "rt2x00.h" +#include "rt2x00lib.h" + +struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, + const enum ieee80211_tx_queue queue) +{ + int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + + if (queue < rt2x00dev->hw->queues && rt2x00dev->tx) + return &rt2x00dev->tx[queue]; + + if (!rt2x00dev->bcn) + return NULL; + + if (queue == IEEE80211_TX_QUEUE_BEACON) + return &rt2x00dev->bcn[0]; + else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON && atim) + return &rt2x00dev->bcn[1]; + + return NULL; +} +EXPORT_SYMBOL_GPL(rt2x00queue_get_queue); + +struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, + enum queue_index index) +{ + struct queue_entry *entry; + + if (unlikely(index >= Q_INDEX_MAX)) { + ERROR(queue->rt2x00dev, + "Entry requested from invalid index type (%d)\n", index); + return NULL; + } + + spin_lock(&queue->lock); + + entry = &queue->entries[queue->index[index]]; + + spin_unlock(&queue->lock); + + return entry; +} +EXPORT_SYMBOL_GPL(rt2x00queue_get_entry); + +void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) +{ + if (unlikely(index >= Q_INDEX_MAX)) { + ERROR(queue->rt2x00dev, + "Index change on invalid index type (%d)\n", index); + return; + } + + spin_lock(&queue->lock); + + queue->index[index]++; + if (queue->index[index] >= queue->limit) + queue->index[index] = 0; + + queue->length--; + queue->count += (index == Q_INDEX_DONE); + + spin_unlock(&queue->lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_index_inc); + +static void rt2x00queue_reset(struct data_queue *queue) +{ + spin_lock(&queue->lock); + + queue->count = 0; + queue->length = 0; + memset(queue->index, 0, sizeof(queue->index)); + + spin_unlock(&queue->lock); +} + +void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue = rt2x00dev->rx; + unsigned int i; + + rt2x00queue_reset(queue); + + if (!rt2x00dev->ops->lib->init_rxentry) + return; + + for (i = 0; i < queue->limit; i++) + rt2x00dev->ops->lib->init_rxentry(rt2x00dev, + &queue->entries[i]); +} + +void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + unsigned int i; + + txall_queue_for_each(rt2x00dev, queue) { + rt2x00queue_reset(queue); + + if (!rt2x00dev->ops->lib->init_txentry) + continue; + + for (i = 0; i < queue->limit; i++) + rt2x00dev->ops->lib->init_txentry(rt2x00dev, + &queue->entries[i]); + } +} + +static int rt2x00queue_alloc_entries(struct data_queue *queue, + const struct data_queue_desc *qdesc) +{ + struct queue_entry *entries; + unsigned int entry_size; + unsigned int i; + + rt2x00queue_reset(queue); + + queue->limit = qdesc->entry_num; + queue->data_size = qdesc->data_size; + queue->desc_size = qdesc->desc_size; + + /* + * Allocate all queue entries. + */ + entry_size = sizeof(*entries) + qdesc->priv_size; + entries = kzalloc(queue->limit * entry_size, GFP_KERNEL); + if (!entries) + return -ENOMEM; + +#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \ + ( (__base) + ((__limit) * (__esize)) + ((__index) * (__psize)) ) + + for (i = 0; i < queue->limit; i++) { + entries[i].flags = 0; + entries[i].queue = queue; + entries[i].skb = NULL; + entries[i].entry_idx = i; + entries[i].priv_data = + QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit, + sizeof(*entries), qdesc->priv_size); + } + +#undef QUEUE_ENTRY_PRIV_OFFSET + + queue->entries = entries; + + return 0; +} + +int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + int status; + + + status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); + if (status) + goto exit; + + tx_queue_for_each(rt2x00dev, queue) { + status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx); + if (status) + goto exit; + } + + status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn); + if (status) + goto exit; + + if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) + return 0; + + status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], + rt2x00dev->ops->atim); + if (status) + goto exit; + + return 0; + +exit: + ERROR(rt2x00dev, "Queue entries allocation failed.\n"); + + rt2x00queue_uninitialize(rt2x00dev); + + return status; +} + +void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + queue_for_each(rt2x00dev, queue) { + kfree(queue->entries); + queue->entries = NULL; + } +} + +int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + enum data_queue_qid qid; + unsigned int req_atim = + !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + + /* + * We need the following queues: + * RX: 1 + * TX: hw->queues + * Beacon: 1 + * Atim: 1 (if required) + */ + rt2x00dev->data_queues = 2 + rt2x00dev->hw->queues + req_atim; + + queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL); + if (!queue) { + ERROR(rt2x00dev, "Queue allocation failed.\n"); + return -ENOMEM; + } + + /* + * Initialize pointers + */ + rt2x00dev->rx = queue; + rt2x00dev->tx = &queue[1]; + rt2x00dev->bcn = &queue[1 + rt2x00dev->hw->queues]; + + /* + * Initialize queue parameters. + * RX: qid = QID_RX + * TX: qid = QID_AC_BE + index + * TX: cw_min: 2^5 = 32. + * TX: cw_max: 2^10 = 1024. + * BCN & Atim: qid = QID_MGMT + */ + qid = QID_AC_BE; + queue_for_each(rt2x00dev, queue) { + spin_lock_init(&queue->lock); + + queue->rt2x00dev = rt2x00dev; + queue->qid = qid++; + queue->aifs = 2; + queue->cw_min = 5; + queue->cw_max = 10; + } + + /* + * Fix non-TX data qid's + */ + rt2x00dev->rx->qid = QID_RX; + rt2x00dev->bcn[0].qid = QID_MGMT; + if (req_atim) + rt2x00dev->bcn[1].qid = QID_MGMT; + + return 0; +} + +void rt2x00queue_free(struct rt2x00_dev *rt2x00dev) +{ + kfree(rt2x00dev->rx); + rt2x00dev->rx = NULL; + rt2x00dev->tx = NULL; + rt2x00dev->bcn = NULL; +} diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h new file mode 100644 index 000000000000..507116c6c9fe --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -0,0 +1,435 @@ +/* + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + + + 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: rt2x00 + Abstract: rt2x00 queue datastructures and routines + */ + +#ifndef RT2X00QUEUE_H +#define RT2X00QUEUE_H + +#include + +/** + * DOC: Entrie frame size + * + * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes, + * for USB devices this restriction does not apply, but the value of + * 2432 makes sense since it is big enough to contain the maximum fragment + * size according to the ieee802.11 specs. + */ +#define DATA_FRAME_SIZE 2432 +#define MGMT_FRAME_SIZE 256 + +/** + * DOC: Number of entries per queue + * + * After research it was concluded that 12 entries in a RX and TX + * queue would be sufficient. Although this is almost one third of + * the amount the legacy driver allocated, the queues aren't getting + * filled to the maximum even when working with the maximum rate. + * + * FIXME: For virtual interfaces we need a different number + * of beacons, since more interfaces require more beacons. + */ +#define RX_ENTRIES 12 +#define TX_ENTRIES 12 +#define BEACON_ENTRIES 1 +#define ATIM_ENTRIES 1 + +/** + * enum data_queue_qid: Queue identification + */ +enum data_queue_qid { + QID_AC_BE = 0, + QID_AC_BK = 1, + QID_AC_VI = 2, + QID_AC_VO = 3, + QID_HCCA = 4, + QID_MGMT = 13, + QID_RX = 14, + QID_OTHER = 15, +}; + +/** + * struct skb_frame_desc: Descriptor information for the skb buffer + * + * This structure is placed over the skb->cb array, this means that + * this structure should not exceed the size of that array (48 bytes). + * + * @flags: Frame flags. + * @frame_type: Frame type, see &enum rt2x00_dump_type. + * @data: Pointer to data part of frame (Start of ieee80211 header). + * @desc: Pointer to descriptor part of the frame. + * Note that this pointer could point to something outside + * of the scope of the skb->data pointer. + * @data_len: Length of the frame data. + * @desc_len: Length of the frame descriptor. + + * @entry: The entry to which this sk buffer belongs. + */ +struct skb_frame_desc { + unsigned int flags; + + unsigned int frame_type; + + void *data; + void *desc; + + unsigned int data_len; + unsigned int desc_len; + + struct queue_entry *entry; +}; + +static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(struct skb_frame_desc) > sizeof(skb->cb)); + return (struct skb_frame_desc *)&skb->cb[0]; +} + +/** + * struct rxdone_entry_desc: RX Entry descriptor + * + * Summary of information that has been read from the RX frame descriptor. + * + * @signal: Signal of the received frame. + * @rssi: RSSI of the received frame. + * @ofdm: Was frame send with an OFDM rate. + * @size: Data size of the received frame. + * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). + * @my_bss: Does this frame originate from device's BSS. + */ +struct rxdone_entry_desc { + int signal; + int rssi; + int ofdm; + int size; + int flags; + int my_bss; +}; + +/** + * struct txdone_entry_desc: TX done entry descriptor + * + * Summary of information that has been read from the TX frame descriptor + * after the device is done with transmission. + * + * @control: Control structure which was used to transmit the frame. + * @status: TX status (See &enum tx_status). + * @retry: Retry count. + */ +struct txdone_entry_desc { + struct ieee80211_tx_control *control; + int status; + int retry; +}; + +/** + * enum txentry_desc_flags: Status flags for TX entry descriptor + * + * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame. + * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate. + * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment. + * @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted. + * @ENTRY_TXD_BURST: This frame belongs to the same burst event. + * @ENTRY_TXD_ACK: An ACK is required for this frame. + */ +enum txentry_desc_flags { + ENTRY_TXD_RTS_FRAME, + ENTRY_TXD_OFDM_RATE, + ENTRY_TXD_MORE_FRAG, + ENTRY_TXD_REQ_TIMESTAMP, + ENTRY_TXD_BURST, + ENTRY_TXD_ACK, +}; + +/** + * struct txentry_desc: TX Entry descriptor + * + * Summary of information for the frame descriptor before sending a TX frame. + * + * @flags: Descriptor flags (See &enum queue_entry_flags). + * @queue: Queue identification (See &enum data_queue_qid). + * @length_high: PLCP length high word. + * @length_low: PLCP length low word. + * @signal: PLCP signal. + * @service: PLCP service. + * @aifs: AIFS value. + * @ifs: IFS value. + * @cw_min: cwmin value. + * @cw_max: cwmax value. + */ +struct txentry_desc { + unsigned long flags; + + enum data_queue_qid queue; + + u16 length_high; + u16 length_low; + u16 signal; + u16 service; + + int aifs; + int ifs; + int cw_min; + int cw_max; +}; + +/** + * enum queue_entry_flags: Status flags for queue entry + * + * @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface. + * As long as this bit is set, this entry may only be touched + * through the interface structure. + * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data + * transfer (either TX or RX depending on the queue). The entry should + * only be touched after the device has signaled it is done with it. + * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data + * encryption or decryption. The entry should only be touched after + * the device has signaled it is done with it. + */ + +enum queue_entry_flags { + ENTRY_BCN_ASSIGNED, + ENTRY_OWNER_DEVICE_DATA, + ENTRY_OWNER_DEVICE_CRYPTO, +}; + +/** + * struct queue_entry: Entry inside the &struct data_queue + * + * @flags: Entry flags, see &enum queue_entry_flags. + * @queue: The data queue (&struct data_queue) to which this entry belongs. + * @skb: The buffer which is currently being transmitted (for TX queue), + * or used to directly recieve data in (for RX queue). + * @entry_idx: The entry index number. + * @priv_data: Private data belonging to this queue entry. The pointer + * points to data specific to a particular driver and queue type. + */ +struct queue_entry { + unsigned long flags; + + struct data_queue *queue; + + struct sk_buff *skb; + + unsigned int entry_idx; + + void *priv_data; +}; + +/** + * enum queue_index: Queue index type + * + * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is + * owned by the hardware then the queue is considered to be full. + * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by + * the hardware and for which we need to run the txdone handler. If this + * entry is not owned by the hardware the queue is considered to be empty. + * @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription + * will be completed by the hardware next. + * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size + * of the index array. + */ +enum queue_index { + Q_INDEX, + Q_INDEX_DONE, + Q_INDEX_CRYPTO, + Q_INDEX_MAX, +}; + +/** + * struct data_queue: Data queue + * + * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to. + * @entries: Base address of the &struct queue_entry which are + * part of this queue. + * @qid: The queue identification, see &enum data_queue_qid. + * @lock: Spinlock to protect index handling. Whenever @index, @index_done or + * @index_crypt needs to be changed this lock should be grabbed to prevent + * index corruption due to concurrency. + * @count: Number of frames handled in the queue. + * @limit: Maximum number of entries in the queue. + * @length: Number of frames in queue. + * @index: Index pointers to entry positions in the queue, + * use &enum queue_index to get a specific index field. + * @aifs: The aifs value for outgoing frames (field ignored in RX queue). + * @cw_min: The cw min value for outgoing frames (field ignored in RX queue). + * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). + * @data_size: Maximum data size for the frames in this queue. + * @desc_size: Hardware descriptor size for the data in this queue. + */ +struct data_queue { + struct rt2x00_dev *rt2x00dev; + struct queue_entry *entries; + + enum data_queue_qid qid; + + spinlock_t lock; + unsigned int count; + unsigned short limit; + unsigned short length; + unsigned short index[Q_INDEX_MAX]; + + unsigned short aifs; + unsigned short cw_min; + unsigned short cw_max; + + unsigned short data_size; + unsigned short desc_size; +}; + +/** + * struct data_queue_desc: Data queue description + * + * The information in this structure is used by drivers + * to inform rt2x00lib about the creation of the data queue. + * + * @entry_num: Maximum number of entries for a queue. + * @data_size: Maximum data size for the frames in this queue. + * @desc_size: Hardware descriptor size for the data in this queue. + * @priv_size: Size of per-queue_entry private data. + */ +struct data_queue_desc { + unsigned short entry_num; + unsigned short data_size; + unsigned short desc_size; + unsigned short priv_size; +}; + +/** + * queue_end - Return pointer to the last queue (HELPER MACRO). + * @__dev: Pointer to &struct rt2x00_dev + * + * Using the base rx pointer and the maximum number of available queues, + * this macro will return the address of 1 position beyond the end of the + * queues array. + */ +#define queue_end(__dev) \ + &(__dev)->rx[(__dev)->data_queues] + +/** + * tx_queue_end - Return pointer to the last TX queue (HELPER MACRO). + * @__dev: Pointer to &struct rt2x00_dev + * + * Using the base tx pointer and the maximum number of available TX + * queues, this macro will return the address of 1 position beyond + * the end of the TX queue array. + */ +#define tx_queue_end(__dev) \ + &(__dev)->tx[(__dev)->hw->queues] + +/** + * queue_loop - Loop through the queues within a specific range (HELPER MACRO). + * @__entry: Pointer where the current queue entry will be stored in. + * @__start: Start queue pointer. + * @__end: End queue pointer. + * + * This macro will loop through all queues between &__start and &__end. + */ +#define queue_loop(__entry, __start, __end) \ + for ((__entry) = (__start); \ + prefetch(&(__entry)[1]), (__entry) != (__end); \ + (__entry) = &(__entry)[1]) + +/** + * queue_for_each - Loop through all queues + * @__dev: Pointer to &struct rt2x00_dev + * @__entry: Pointer where the current queue entry will be stored in. + * + * This macro will loop through all available queues. + */ +#define queue_for_each(__dev, __entry) \ + queue_loop(__entry, (__dev)->rx, queue_end(__dev)) + +/** + * tx_queue_for_each - Loop through the TX queues + * @__dev: Pointer to &struct rt2x00_dev + * @__entry: Pointer where the current queue entry will be stored in. + * + * This macro will loop through all TX related queues excluding + * the Beacon and Atim queues. + */ +#define tx_queue_for_each(__dev, __entry) \ + queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev)) + +/** + * txall_queue_for_each - Loop through all TX related queues + * @__dev: Pointer to &struct rt2x00_dev + * @__entry: Pointer where the current queue entry will be stored in. + * + * This macro will loop through all TX related queues including + * the Beacon and Atim queues. + */ +#define txall_queue_for_each(__dev, __entry) \ + queue_loop(__entry, (__dev)->tx, queue_end(__dev)) + +/** + * rt2x00queue_empty - Check if the queue is empty. + * @queue: Queue to check if empty. + */ +static inline int rt2x00queue_empty(struct data_queue *queue) +{ + return queue->length == 0; +} + +/** + * rt2x00queue_full - Check if the queue is full. + * @queue: Queue to check if full. + */ +static inline int rt2x00queue_full(struct data_queue *queue) +{ + return queue->length == queue->limit; +} + +/** + * rt2x00queue_free - Check the number of available entries in queue. + * @queue: Queue to check. + */ +static inline int rt2x00queue_available(struct data_queue *queue) +{ + return queue->limit - queue->length; +} + +/** + * rt2x00_desc_read - Read a word from the hardware descriptor. + * @desc: Base descriptor address + * @word: Word index from where the descriptor should be read. + * @value: Address where the descriptor value should be written into. + */ +static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value) +{ + *value = le32_to_cpu(desc[word]); +} + +/** + * rt2x00_desc_write - wrote a word to the hardware descriptor. + * @desc: Base descriptor address + * @word: Word index from where the descriptor should be written. + * @value: Value that should be written into the descriptor. + */ +static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value) +{ + desc[word] = cpu_to_le32(value); +} + +#endif /* RT2X00QUEUE_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index e99eab19e9d7..e0ebe51c082f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -29,7 +29,7 @@ /* * TX result flags. */ -enum TX_STATUS { +enum tx_status { TX_SUCCESS = 0, TX_SUCCESS_RETRY = 1, TX_FAIL_RETRY = 2, diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h deleted file mode 100644 index 764c2553d06c..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00ring.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project - - - 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: rt2x00 - Abstract: rt2x00 ring datastructures and routines - */ - -#ifndef RT2X00RING_H -#define RT2X00RING_H - -/* - * skb_desc - * Descriptor information for the skb buffer - */ -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 - * RX frame descriptor. - */ -struct rxdata_entry_desc { - int signal; - int rssi; - int ofdm; - int size; - int flags; - int my_bss; -}; - -/* - * txdata_entry_desc - * Summary of information that should be written into the - * descriptor for sending a TX frame. - */ -struct txdata_entry_desc { - unsigned long flags; -#define ENTRY_TXDONE 1 -#define ENTRY_TXD_RTS_FRAME 2 -#define ENTRY_TXD_OFDM_RATE 3 -#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 - */ - int queue; -#define QUEUE_MGMT 13 -#define QUEUE_RX 14 -#define QUEUE_OTHER 15 - - /* - * PLCP values. - */ - u16 length_high; - u16 length_low; - u16 signal; - u16 service; - - /* - * Timing information - */ - int aifs; - int ifs; - int cw_min; - int cw_max; -}; - -/* - * data_entry - * The data ring is a list of data entries. - * Each entry holds a reference to the descriptor - * and the data buffer. For TX rings the reference to the - * sk_buff of the packet being transmitted is also stored here. - */ -struct data_entry { - /* - * Status flags - */ - unsigned long flags; -#define ENTRY_OWNER_NIC 1 - - /* - * Ring we belong to. - */ - struct data_ring *ring; - - /* - * sk_buff for the packet which is being transmitted - * in this entry (Only used with TX related rings). - */ - struct sk_buff *skb; - - /* - * Store a ieee80211_tx_status structure in each - * ring entry, this will optimize the txdone - * handler. - */ - struct ieee80211_tx_status tx_status; - - /* - * private pointer specific to driver. - */ - void *priv; - - /* - * Data address for this entry. - */ - void *data_addr; - dma_addr_t data_dma; - - /* - * Entry identification number (index). - */ - unsigned int entry_idx; -}; - -/* - * data_ring - * Data rings are used by the device to send and receive packets. - * The data_addr is the base address of the data memory. - * To determine at which point in the ring we are, - * have to use the rt2x00_ring_index_*() functions. - */ -struct data_ring { - /* - * Pointer to main rt2x00dev structure where this - * ring belongs to. - */ - struct rt2x00_dev *rt2x00dev; - - /* - * Base address for the device specific data entries. - */ - struct data_entry *entry; - - /* - * TX queue statistic info. - */ - struct ieee80211_tx_queue_stats_data stats; - - /* - * TX Queue parameters. - */ - struct ieee80211_tx_queue_params tx_params; - - /* - * Base address for data ring. - */ - dma_addr_t data_dma; - void *data_addr; - - /* - * Queue identification number: - * RX: 0 - * TX: IEEE80211_TX_* - */ - unsigned int queue_idx; - - /* - * Index variables. - */ - u16 index; - u16 index_done; - - /* - * Size of packet and descriptor in bytes. - */ - u16 data_size; - u16 desc_size; -}; - -/* - * Handlers to determine the address of the current device specific - * data entry, where either index or index_done points to. - */ -static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring) -{ - return &ring->entry[ring->index]; -} - -static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring - *ring) -{ - return &ring->entry[ring->index_done]; -} - -/* - * Total ring memory - */ -static inline int rt2x00_get_ring_size(struct data_ring *ring) -{ - return ring->stats.limit * (ring->desc_size + ring->data_size); -} - -/* - * Ring index manipulation functions. - */ -static inline void rt2x00_ring_index_inc(struct data_ring *ring) -{ - ring->index++; - if (ring->index >= ring->stats.limit) - ring->index = 0; - ring->stats.len++; -} - -static inline void rt2x00_ring_index_done_inc(struct data_ring *ring) -{ - ring->index_done++; - if (ring->index_done >= ring->stats.limit) - ring->index_done = 0; - ring->stats.len--; - ring->stats.count++; -} - -static inline void rt2x00_ring_index_clear(struct data_ring *ring) -{ - ring->index = 0; - ring->index_done = 0; - ring->stats.len = 0; - ring->stats.count = 0; -} - -static inline int rt2x00_ring_empty(struct data_ring *ring) -{ - return ring->stats.len == 0; -} - -static inline int rt2x00_ring_full(struct data_ring *ring) -{ - return ring->stats.len == ring->stats.limit; -} - -static inline int rt2x00_ring_free(struct data_ring *ring) -{ - return ring->stats.limit - ring->stats.len; -} - -/* - * TX/RX Descriptor access functions. - */ -static inline void rt2x00_desc_read(__le32 *desc, - const u8 word, u32 *value) -{ - *value = le32_to_cpu(desc[word]); -} - -static inline void rt2x00_desc_write(__le32 *desc, - const u8 word, const u32 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 47cd0a5bf17c..fc606448908e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -40,8 +40,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, void *buffer, const u16 buffer_length, const int timeout) { - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); int status; unsigned int i; unsigned int pipe = @@ -128,15 +127,15 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); */ 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 queue_entry *entry = (struct queue_entry *)urb->context; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data; + struct txdone_entry_desc txdesc; __le32 *txd = (__le32 *)entry->skb->data; u32 word; - int tx_status; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || - !__test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags)) + !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; rt2x00_desc_read(txd, 0, &word); @@ -144,45 +143,46 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) /* * Remove the descriptor data from the buffer. */ - skb_pull(entry->skb, ring->desc_size); + skb_pull(entry->skb, entry->queue->desc_size); /* * Obtain the status about this packet. */ - tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY; + txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY; + txdesc.retry = 0; + txdesc.control = &priv_tx->control; - rt2x00lib_txdone(entry, tx_status, 0); + rt2x00lib_txdone(entry, &txdesc); /* * Make this entry available for reuse. */ entry->flags = 0; - rt2x00_ring_index_done_inc(entry->ring); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* - * If the data ring was full before the txdone handler + * If the data queue 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); + if (!rt2x00queue_full(entry->queue)) + ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue); } int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control) { - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); - struct data_entry *entry = rt2x00_get_data_entry(ring); - struct skb_desc *desc; + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); + struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data; + struct skb_frame_desc *skbdesc; u32 length; - if (rt2x00_ring_full(ring)) + if (rt2x00queue_full(queue)) return -EINVAL; - if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) { + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { ERROR(rt2x00dev, "Arrived at non-free entry in the non-full queue %d.\n" "Please file bug report to %s.\n", @@ -193,19 +193,19 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, /* * Add the descriptor in front of the skb. */ - skb_push(skb, ring->desc_size); - memset(skb->data, 0, ring->desc_size); + skb_push(skb, queue->desc_size); + memset(skb->data, 0, queue->desc_size); /* * 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; + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data + queue->desc_size; + skbdesc->data_len = queue->data_size; + skbdesc->desc = skb->data; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); @@ -219,12 +219,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, usb_sndbulkpipe(usb_dev, 1), + __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + usb_fill_bulk_urb(priv_tx->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1), skb->data, length, rt2x00usb_interrupt_txdone, entry); - usb_submit_urb(entry->priv, GFP_ATOMIC); + usb_submit_urb(priv_tx->urb, GFP_ATOMIC); - rt2x00_ring_index_inc(ring); + rt2x00queue_index_inc(queue, Q_INDEX); return 0; } @@ -233,20 +233,41 @@ EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); /* * RX data handlers. */ +static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue) +{ + struct sk_buff *skb; + unsigned int frame_size; + + /* + * As alignment we use 2 and not NET_IP_ALIGN because we need + * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN + * can be 0 on some hardware). We use these 2 bytes for frame + * alignment later, we assume that the chance that + * header_size % 4 == 2 is bigger then header_size % 2 == 0 + * and thus optimize alignment by reserving the 2 bytes in + * advance. + */ + frame_size = queue->data_size + queue->desc_size; + skb = dev_alloc_skb(frame_size + 2); + if (!skb) + return NULL; + + skb_reserve(skb, 2); + skb_put(skb, frame_size); + + return skb; +} + static void rt2x00usb_interrupt_rxdone(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 queue_entry *entry = (struct queue_entry *)urb->context; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct sk_buff *skb; - struct ieee80211_hdr *hdr; - struct skb_desc *skbdesc; - struct rxdata_entry_desc desc; - int header_size; - int frame_size; + struct skb_frame_desc *skbdesc; + struct rxdone_entry_desc rxdesc; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || - !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags)) + !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -254,67 +275,32 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * to be actually valid, or if the urb is signaling * a problem. */ - if (urb->actual_length < entry->ring->desc_size || urb->status) + if (urb->actual_length < entry->queue->desc_size || urb->status) goto skip_entry; /* * Fill in skb descriptor */ - skbdesc = get_skb_desc(entry->skb); - skbdesc->ring = ring; + skbdesc = get_skb_frame_desc(entry->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; - memset(&desc, 0, sizeof(desc)); - rt2x00dev->ops->lib->fill_rxdone(entry, &desc); + memset(&rxdesc, 0, sizeof(rxdesc)); + rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); /* * Allocate a new sk buffer to replace the current one. * If allocation fails, we should drop the current frame * so we can recycle the existing sk buffer for the new frame. - * As alignment we use 2 and not NET_IP_ALIGN because we need - * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN - * can be 0 on some hardware). We use these 2 bytes for frame - * alignment later, we assume that the chance that - * header_size % 4 == 2 is bigger then header_size % 2 == 0 - * and thus optimize alignment by reserving the 2 bytes in - * advance. */ - frame_size = entry->ring->data_size + entry->ring->desc_size; - skb = dev_alloc_skb(frame_size + 2); + skb = rt2x00usb_alloc_rxskb(entry->queue); if (!skb) goto skip_entry; - skb_reserve(skb, 2); - skb_put(skb, frame_size); - - /* - * The data behind the ieee80211 header must be - * aligned on a 4 byte boundary. - */ - hdr = (struct ieee80211_hdr *)entry->skb->data; - header_size = - ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); - - if (header_size % 4 == 0) { - 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); - /* * Send the frame to rt2x00lib for further processing. */ - rt2x00lib_rxdone(entry, entry->skb, &desc); + rt2x00lib_rxdone(entry, &rxdesc); /* * Replace current entry's skb with the newly allocated one, @@ -325,12 +311,12 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) urb->transfer_buffer_length = entry->skb->len; skip_entry: - if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) { - __set_bit(ENTRY_OWNER_NIC, &entry->flags); + if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) { + __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); usb_submit_urb(urb, GFP_ATOMIC); } - rt2x00_ring_index_inc(ring); + rt2x00queue_index_inc(entry->queue, Q_INDEX); } /* @@ -338,18 +324,27 @@ skip_entry: */ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; + struct queue_entry_priv_usb_rx *priv_rx; + struct queue_entry_priv_usb_tx *priv_tx; + struct data_queue *queue; unsigned int i; rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000, REGISTER_TIMEOUT); /* - * Cancel all rings. + * Cancel all queues. */ - ring_for_each(rt2x00dev, ring) { - for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(ring->entry[i].priv); + for (i = 0; i < rt2x00dev->rx->limit; i++) { + priv_rx = rt2x00dev->rx->entries[i].priv_data; + usb_kill_urb(priv_rx->urb); + } + + txall_queue_for_each(rt2x00dev, queue) { + for (i = 0; i < queue->limit; i++) { + priv_tx = queue->entries[i].priv_data; + usb_kill_urb(priv_tx->urb); + } } } EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); @@ -358,64 +353,108 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); * Device initialization handlers. */ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data; - usb_fill_bulk_urb(entry->priv, usb_dev, + usb_fill_bulk_urb(priv_rx->urb, 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); + __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + usb_submit_urb(priv_rx->urb, GFP_ATOMIC); } EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry); void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { entry->flags = 0; } EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry); static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring) + struct data_queue *queue) { + struct queue_entry_priv_usb_rx *priv_rx; + struct queue_entry_priv_usb_tx *priv_tx; + struct queue_entry_priv_usb_bcn *priv_bcn; + struct urb *urb; + unsigned int guardian = + test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); unsigned int i; /* * Allocate the URB's */ - for (i = 0; i < ring->stats.limit; i++) { - ring->entry[i].priv = usb_alloc_urb(0, GFP_KERNEL); - if (!ring->entry[i].priv) + for (i = 0; i < queue->limit; i++) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) return -ENOMEM; + + if (queue->qid == QID_RX) { + priv_rx = queue->entries[i].priv_data; + priv_rx->urb = urb; + } else if (queue->qid == QID_MGMT && guardian) { + priv_bcn = queue->entries[i].priv_data; + priv_bcn->urb = urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + priv_bcn->guardian_urb = urb; + } else { + priv_tx = queue->entries[i].priv_data; + priv_tx->urb = urb; + } } return 0; } static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring) + struct data_queue *queue) { + struct queue_entry_priv_usb_rx *priv_rx; + struct queue_entry_priv_usb_tx *priv_tx; + struct queue_entry_priv_usb_bcn *priv_bcn; + struct urb *urb; + unsigned int guardian = + test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); unsigned int i; - if (!ring->entry) + if (!queue->entries) return; - for (i = 0; i < ring->stats.limit; i++) { - usb_kill_urb(ring->entry[i].priv); - usb_free_urb(ring->entry[i].priv); - if (ring->entry[i].skb) - kfree_skb(ring->entry[i].skb); + for (i = 0; i < queue->limit; i++) { + if (queue->qid == QID_RX) { + priv_rx = queue->entries[i].priv_data; + urb = priv_rx->urb; + } else if (queue->qid == QID_MGMT && guardian) { + priv_bcn = queue->entries[i].priv_data; + + usb_kill_urb(priv_bcn->guardian_urb); + usb_free_urb(priv_bcn->guardian_urb); + + urb = priv_bcn->urb; + } else { + priv_tx = queue->entries[i].priv_data; + urb = priv_tx->urb; + } + + usb_kill_urb(urb); + usb_free_urb(urb); + if (queue->entries[i].skb) + kfree_skb(queue->entries[i].skb); } } int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; + struct data_queue *queue; struct sk_buff *skb; unsigned int entry_size; unsigned int i; @@ -424,25 +463,22 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) /* * Allocate DMA */ - ring_for_each(rt2x00dev, ring) { - status = rt2x00usb_alloc_urb(rt2x00dev, ring); + queue_for_each(rt2x00dev, queue) { + status = rt2x00usb_alloc_urb(rt2x00dev, queue); if (status) goto exit; } /* - * For the RX ring, skb's should be allocated. + * For the RX queue, skb's should be allocated. */ entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size; - for (i = 0; i < rt2x00dev->rx->stats.limit; i++) { - skb = dev_alloc_skb(NET_IP_ALIGN + entry_size); + for (i = 0; i < rt2x00dev->rx->limit; i++) { + skb = rt2x00usb_alloc_rxskb(rt2x00dev->rx); if (!skb) goto exit; - skb_reserve(skb, NET_IP_ALIGN); - skb_put(skb, entry_size); - - rt2x00dev->rx->entry[i].skb = skb; + rt2x00dev->rx->entries[i].skb = skb; } return 0; @@ -456,10 +492,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize); void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; + struct data_queue *queue; - ring_for_each(rt2x00dev, ring) - rt2x00usb_free_urb(rt2x00dev, ring); + queue_for_each(rt2x00dev, queue) + rt2x00usb_free_urb(rt2x00dev, queue); } EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize); @@ -627,9 +663,9 @@ EXPORT_SYMBOL_GPL(rt2x00usb_resume); #endif /* CONFIG_PM */ /* - * rt2x00pci module information. + * rt2x00usb module information. */ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("rt2x00 library"); +MODULE_DESCRIPTION("rt2x00 usb library"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index b5c1d176c481..af606638e227 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -160,16 +160,58 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev); * TX data handlers. */ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control); +/** + * struct queue_entry_priv_usb_rx: Per RX entry USB specific information + * + * @urb: Urb structure used for device communication. + */ +struct queue_entry_priv_usb_rx { + struct urb *urb; +}; + +/** + * struct queue_entry_priv_usb_tx: Per TX entry USB specific information + * + * @urb: Urb structure used for device communication. + * @control: mac80211 control structure used to transmit data. + */ +struct queue_entry_priv_usb_tx { + struct urb *urb; + + struct ieee80211_tx_control control; +}; + +/** + * struct queue_entry_priv_usb_tx: Per TX entry USB specific information + * + * The first section should match &struct queue_entry_priv_usb_tx exactly. + * rt2500usb can use this structure to send a guardian byte when working + * with beacons. + * + * @urb: Urb structure used for device communication. + * @control: mac80211 control structure used to transmit data. + * @guardian_data: Set to 0, used for sending the guardian data. + * @guardian_urb: Urb structure used to send the guardian data. + */ +struct queue_entry_priv_usb_bcn { + struct urb *urb; + + struct ieee80211_tx_control control; + + unsigned int guardian_data; + struct urb *guardian_urb; +}; + /* * Device initialization handlers. */ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry); + struct queue_entry *entry); void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry); + struct queue_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 42cd1dc09164..547fa33e99dd 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -262,7 +262,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) u32 reg; rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); - return rt2x00_get_field32(reg, MAC_CSR13_BIT5);; + return rt2x00_get_field32(reg, MAC_CSR13_BIT5); } #else #define rt61pci_rfkill_poll NULL @@ -990,49 +990,49 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, } static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 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(priv_rx->desc, 5, &word); + rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, priv_rx->dma); + rt2x00_desc_write(priv_rx->desc, 5, word); - rt2x00_desc_read(rxd, 0, &word); + rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); + rt2x00_desc_write(priv_rx->desc, 0, word); } static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *txd = entry->priv; + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; u32 word; - rt2x00_desc_read(txd, 1, &word); + rt2x00_desc_read(priv_tx->desc, 1, &word); rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1); - rt2x00_desc_write(txd, 1, word); + rt2x00_desc_write(priv_tx->desc, 1, word); - rt2x00_desc_read(txd, 5, &word); - rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx); + rt2x00_desc_read(priv_tx->desc, 5, &word); + rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid); rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx); - rt2x00_desc_write(txd, 5, word); + rt2x00_desc_write(priv_tx->desc, 5, 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_desc_read(priv_tx->desc, 6, &word); + rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, priv_tx->dma); + rt2x00_desc_write(priv_tx->desc, 6, word); - rt2x00_desc_read(txd, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_set_field32(&word, TXD_W0_VALID, 0); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(txd, 0, word); + rt2x00_desc_write(priv_tx->desc, 0, word); } -static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) +static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) { + struct queue_entry_priv_pci_rx *priv_rx; + struct queue_entry_priv_pci_tx *priv_tx; u32 reg; /* @@ -1040,59 +1040,50 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) */ rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®); rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00dev->tx[0].limit); rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); + rt2x00dev->tx[1].limit); rt2x00_set_field32(®, TX_RING_CSR0_AC2_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit); + rt2x00dev->tx[2].limit); rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit); + rt2x00dev->tx[3].limit); rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg); rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®); - rt2x00_set_field32(®, TX_RING_CSR1_MGMT_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit); rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size / - 4); + rt2x00dev->tx[0].desc_size / 4); rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg); + priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®); - rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg); + priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®); - rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg); + priv_tx = rt2x00dev->tx[2].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®); - rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma); + rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg); + priv_tx = rt2x00dev->tx[3].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®); - rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma); + rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg); - rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, ®); - rt2x00_set_field32(®, MGMT_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma); - rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg); - rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®); - rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, - rt2x00dev->rx->stats.limit); + rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit); rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE, rt2x00dev->rx->desc_size / 4); rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4); rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg); + priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®); - rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, priv_rx->dma); rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®); @@ -1108,7 +1099,7 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1); rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1); rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1); - rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1); + rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 0); rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); @@ -1375,7 +1366,7 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt61pci_init_rings(rt2x00dev) || + if (rt61pci_init_queues(rt2x00dev) || rt61pci_init_registers(rt2x00dev) || rt61pci_init_bbp(rt2x00dev)) { ERROR(rt2x00dev, "Register initialization failed.\n"); @@ -1508,10 +1499,10 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1519,19 +1510,19 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Start writing the descriptor words. */ rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue); - rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); + rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); @@ -1548,21 +1539,21 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); rt2x00_set_field32(&word, TXD_W0_BURST, - test_bit(ENTRY_TXD_BURST, &desc->flags)); + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } @@ -1648,28 +1639,28 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; } -static void rt61pci_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt61pci_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word0; u32 word1; - rt2x00_desc_read(rxd, 0, &word0); - rt2x00_desc_read(rxd, 1, &word1); + rt2x00_desc_read(priv_rx->desc, 0, &word0); + rt2x00_desc_read(priv_rx->desc, 1, &word1); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; /* * Obtain the status about this packet. */ - desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1); - desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); - desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1); + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* @@ -1677,17 +1668,16 @@ static void rt61pci_fill_rxdone(struct data_entry *entry, */ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; - struct data_entry *entry; - struct data_entry *entry_done; - __le32 *txd; + struct data_queue *queue; + struct queue_entry *entry; + struct queue_entry *entry_done; + struct queue_entry_priv_pci_tx *priv_tx; + struct txdone_entry_desc txdesc; u32 word; u32 reg; u32 old_reg; int type; int index; - int tx_status; - int retry; /* * During each loop we will compare the freshly read @@ -1710,11 +1700,11 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) /* * Skip this entry when it contains an invalid - * ring identication number. + * queue identication number. */ type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE); - ring = rt2x00lib_get_ring(rt2x00dev, type); - if (unlikely(!ring)) + queue = rt2x00queue_get_queue(rt2x00dev, type); + if (unlikely(!queue)) continue; /* @@ -1722,36 +1712,40 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) * index number. */ index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE); - if (unlikely(index >= ring->stats.limit)) + if (unlikely(index >= queue->limit)) continue; - entry = &ring->entry[index]; - txd = entry->priv; - rt2x00_desc_read(txd, 0, &word); + entry = &queue->entries[index]; + priv_tx = entry->priv_data; + rt2x00_desc_read(priv_tx->desc, 0, &word); if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || !rt2x00_get_field32(word, TXD_W0_VALID)) return; - entry_done = rt2x00_get_data_entry_done(ring); + entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); while (entry != entry_done) { - /* Catch up. Just report any entries we missed as - * failed. */ + /* Catch up. + * Just report any entries we missed as failed. + */ WARNING(rt2x00dev, - "TX status report missed for entry %p\n", - entry_done); - rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER, - 0); - entry_done = rt2x00_get_data_entry_done(ring); + "TX status report missed for entry %d\n", + entry_done->entry_idx); + + txdesc.status = TX_FAIL_OTHER; + txdesc.retry = 0; + + rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc); + entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); } /* * Obtain the status about this packet. */ - tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT); - retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); + txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT); + txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); - rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -2381,9 +2375,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; + struct skb_frame_desc *skbdesc; + struct data_queue *queue; + struct queue_entry *entry; /* * Just in case the ieee80211 doesn't set this, @@ -2391,15 +2385,15 @@ 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); + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + entry = rt2x00queue_get_entry(queue, Q_INDEX); /* * We need to append the descriptor in front of the * beacon frame. */ - if (skb_headroom(skb) < TXD_DESC_SIZE) { - if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC)) { + if (skb_headroom(skb) < queue->desc_size) { + if (pskb_expand_head(skb, queue->desc_size, 0, GFP_ATOMIC)) { dev_kfree_skb(skb); return -ENOMEM; } @@ -2408,19 +2402,19 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, /* * Add the descriptor in front of the skb. */ - skb_push(skb, ring->desc_size); - memset(skb->data, 0, ring->desc_size); + skb_push(skb, queue->desc_size); + memset(skb->data, 0, queue->desc_size); /* * 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; + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data + queue->desc_size; + skbdesc->data_len = queue->data_size; + skbdesc->desc = skb->data; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); @@ -2479,12 +2473,34 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .config = rt61pci_config, }; +static const struct data_queue_desc rt61pci_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_rx), +}; + +static const struct data_queue_desc rt61pci_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt61pci_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXINFO_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + static const struct rt2x00_ops rt61pci_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt61pci_queue_rx, + .tx = &rt61pci_queue_tx, + .bcn = &rt61pci_queue_bcn, .lib = &rt61pci_rt2x00_ops, .hw = &rt61pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e4578fbdb361..10519f8c5783 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1247,6 +1247,7 @@ struct hw_pairwise_ta_entry { * DMA descriptor defines. */ #define TXD_DESC_SIZE ( 16 * sizeof(__le32) ) +#define TXINFO_SIZE ( 6 * sizeof(__le32) ) #define RXD_DESC_SIZE ( 16 * sizeof(__le32) ) /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 416e44943e71..4e6466b13af1 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1234,10 +1234,10 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1245,19 +1245,19 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Start writing the descriptor words. */ rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue); - rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); + rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); @@ -1268,24 +1268,24 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_BURST, - test_bit(ENTRY_TXD_BURST, &desc->flags)); + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); rt2x00_set_field32(&word, TXD_W0_BURST2, - test_bit(ENTRY_TXD_BURST, &desc->flags)); + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } @@ -1377,37 +1377,57 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; } -static void rt73usb_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt73usb_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - struct skb_desc *skbdesc = get_skb_desc(entry->skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); __le32 *rxd = (__le32 *)entry->skb->data; + struct ieee80211_hdr *hdr = + (struct ieee80211_hdr *)entry->skb->data + entry->queue->desc_size; + int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); u32 word0; u32 word1; rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; /* * Obtain the status about this packet. */ - desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - desc->rssi = 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); + rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1); + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + + /* + * The data behind the ieee80211 header must be + * aligned on a 4 byte boundary. + */ + if (header_size % 4 == 0) { + skb_push(entry->skb, 2); + memmove(entry->skb->data, entry->skb->data + 2, + entry->skb->len - 2); + } /* * Set descriptor and data pointer. */ + skbdesc->data = entry->skb->data + entry->queue->desc_size; + skbdesc->data_len = entry->queue->data_size; 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; + skbdesc->desc_len = entry->queue->desc_size; + + /* + * Remove descriptor from skb buffer and trim the whole thing + * down to only contain data. + */ + skb_pull(entry->skb, skbdesc->desc_len); + skb_trim(entry->skb, rxdesc->size); } /* @@ -1967,9 +1987,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; + struct skb_frame_desc *skbdesc; + struct data_queue *queue; + struct queue_entry *entry; int timeout; /* @@ -1978,25 +1998,25 @@ 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); + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + entry = rt2x00queue_get_entry(queue, Q_INDEX); /* * Add the descriptor in front of the skb. */ - skb_push(skb, ring->desc_size); - memset(skb->data, 0, ring->desc_size); + skb_push(skb, queue->desc_size); + memset(skb->data, 0, queue->desc_size); /* * 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; + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data + queue->desc_size; + skbdesc->data_len = queue->data_size; + skbdesc->desc = skb->data; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); @@ -2057,12 +2077,34 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .config = rt73usb_config, }; +static const struct data_queue_desc rt73usb_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_rx), +}; + +static const struct data_queue_desc rt73usb_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_tx), +}; + +static const struct data_queue_desc rt73usb_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXINFO_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_tx), +}; + static const struct rt2x00_ops rt73usb_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt73usb_queue_rx, + .tx = &rt73usb_queue_tx, + .bcn = &rt73usb_queue_bcn, .lib = &rt73usb_rt2x00_ops, .hw = &rt73usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index bc635908c470..da62b4f091a7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -867,6 +867,7 @@ struct hw_pairwise_ta_entry { * DMA descriptor defines. */ #define TXD_DESC_SIZE ( 6 * sizeof(__le32) ) +#define TXINFO_SIZE ( 6 * sizeof(__le32) ) #define RXD_DESC_SIZE ( 6 * sizeof(__le32) ) /* -- cgit v1.2.3-59-g8ed1b From 6bb40dd13b458beb55f5c60dba1cb28e814bd640 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:49:59 +0100 Subject: rt2x00: Add per-interface structure Rework the interface handling. Delete the interface structure and replace it with a per-interface structure. This changes the way rt2x00 handles the active interface drastically. Copy ieee80211_bss_conf to the this rt2x00_intf structure during the bss_info_changed() callback function. This will allow us to reference it later, and removes the requirement for the device flag SHORT_PREAMBLE flag which is interface specific. Drivers receive the option to give the maximum number of virtual interfaces the device can handle. Virtual interface support: rt2400pci: 1 sta or 1 ap, * monitor interfaces rt2500pci: 1 sta or 1 ap, * monitor interfaces rt2500usb: 1 sta or 1 ap, * monitor interfaces rt61pci: 1 sta or 4 ap, * monitor interfaces rt73usb: 1 sta or 4 ap, * monitor interfaces At the moment none of the drivers support AP and STA interfaces simultaneously, this is a hardware limitation so future support will be very unlikely. Each interface structure receives its dedicated beacon entry, with this we can easily work with beaconing while multiple master mode interfaces are currently active. The configuration handlers for the MAC, BSSID and type are often called together since they all belong to the interface configuration. Merge the 3 configuration calls and cleanup the API between rt2x00lib and the drivers. While we are cleaning up the interface configuration anyway, we might as well clean up the configuration handler as well. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 84 ++++++------ drivers/net/wireless/rt2x00/rt2500pci.c | 98 +++++++------- drivers/net/wireless/rt2x00/rt2500usb.c | 207 ++++++++++++++++------------- drivers/net/wireless/rt2x00/rt2500usb.h | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 113 +++++++++++----- drivers/net/wireless/rt2x00/rt2x00config.c | 119 ++++++++++------- drivers/net/wireless/rt2x00/rt2x00dev.c | 154 ++++++++++++++------- drivers/net/wireless/rt2x00/rt2x00lib.h | 10 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 152 ++++++++++++++------- drivers/net/wireless/rt2x00/rt2x00pci.c | 32 ++--- drivers/net/wireless/rt2x00/rt2x00queue.h | 3 - drivers/net/wireless/rt2x00/rt61pci.c | 169 ++++++++++++----------- drivers/net/wireless/rt2x00/rt61pci.h | 18 ++- drivers/net/wireless/rt2x00/rt73usb.c | 179 ++++++++++++++----------- drivers/net/wireless/rt2x00/rt73usb.h | 17 ++- 15 files changed, 826 insertions(+), 530 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt61pci.h') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index fc161084a8d3..61766ed800e3 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -246,50 +246,50 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) +static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac, - (2 * sizeof(__le32))); -} + unsigned int bcn_preload; + u32 reg; -static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_TYPE) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); -static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); + rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); + rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); - rt2x00pci_register_write(rt2x00dev, CSR14, 0); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + } - /* - * Enable beacon config - */ - rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); - rt2x00_set_field32(®, BCNCSR1_PRELOAD, - PREAMBLE + get_duration(IEEE80211_HEADER, 20)); - rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); + if (flags & CONFIG_UPDATE_MAC) + rt2x00pci_register_multiwrite(rt2x00dev, CSR3, + conf->mac, sizeof(conf->mac)); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 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); + if (flags & CONFIG_UPDATE_BSSID) + rt2x00pci_register_multiwrite(rt2x00dev, CSR5, + conf->bssid, sizeof(conf->bssid)); } -static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { int preamble_mask; u32 reg; @@ -327,6 +327,8 @@ static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + + return 0; } static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -481,8 +483,8 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -1553,9 +1555,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, - .config_mac_addr = rt2400pci_config_mac_addr, - .config_bssid = rt2400pci_config_bssid, - .config_type = rt2400pci_config_type, + .config_intf = rt2400pci_config_intf, .config_preamble = rt2400pci_config_preamble, .config = rt2400pci_config, }; @@ -1590,6 +1590,8 @@ static const struct data_queue_desc rt2400pci_queue_atim = { static const struct rt2x00_ops rt2400pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2400pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0a54b6512207..6a558bf74f11 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -246,53 +246,53 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac, - (2 * sizeof(__le32))); -} - -static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid, - (2 * sizeof(__le32))); -} - -static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) +static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + unsigned int bcn_preload; u32 reg; - rt2x00pci_register_write(rt2x00dev, CSR14, 0); + if (flags & CONFIG_UPDATE_TYPE) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); - /* - * Enable beacon config - */ - rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); - rt2x00_set_field32(®, BCNCSR1_PRELOAD, - PREAMBLE + get_duration(IEEE80211_HEADER, 20)); - rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); - rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); + rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); + rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); + rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 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); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + } + + if (flags & CONFIG_UPDATE_MAC) + rt2x00pci_register_multiwrite(rt2x00dev, CSR3, + conf->mac, sizeof(conf->mac)); + + if (flags & CONFIG_UPDATE_BSSID) + rt2x00pci_register_multiwrite(rt2x00dev, CSR5, + conf->bssid, sizeof(conf->bssid)); } -static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { int preamble_mask; u32 reg; @@ -330,6 +330,8 @@ static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + + return 0; } static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -529,8 +531,8 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -609,9 +611,10 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * To prevent collisions with MAC ASIC on chipsets * up to version C the link tuning should halt after 20 - * seconds. + * seconds while being associated. */ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && + rt2x00dev->intf_associated && rt2x00dev->link.count > 20) return; @@ -619,9 +622,12 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Chipset versions C and lower should directly continue - * to the dynamic CCA tuning. + * to the dynamic CCA tuning. Chipset version D and higher + * should go straight to dynamic CCA tuning when they + * are not associated. */ - if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D) + if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D || + !rt2x00dev->intf_associated) goto dynamic_cca_tune; /* @@ -1861,9 +1867,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, - .config_mac_addr = rt2500pci_config_mac_addr, - .config_bssid = rt2500pci_config_bssid, - .config_type = rt2500pci_config_type, + .config_intf = rt2500pci_config_intf, .config_preamble = rt2500pci_config_preamble, .config = rt2500pci_config, }; @@ -1898,6 +1902,8 @@ static const struct data_queue_desc rt2500pci_queue_atim = { static const struct rt2x00_ops rt2500pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2500pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index edc16a5fc754..31258ee24ee3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -285,70 +285,65 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = { /* * Configuration handlers. */ -static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) -{ - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (3 * sizeof(__le16))); -} - -static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid, - (3 * sizeof(__le16))); -} - -static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) +static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { + unsigned int bcn_preload; u16 reg; - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); + if (flags & CONFIG_UPDATE_TYPE) { + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); - /* - * Enable beacon config - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); - rt2x00_set_field16(®, TXRX_CSR20_OFFSET, - (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6); - if (type == IEEE80211_IF_TYPE_STA) - rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 0); - else - rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 2); - rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); + rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); + rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, + 2 * (conf->type != IEEE80211_IF_TYPE_STA)); + rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); - /* - * Enable synchronisation. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + /* + * Enable synchronisation. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); + rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); + rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + } - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 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); + if (flags & CONFIG_UPDATE_MAC) + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac, + (3 * sizeof(__le16))); + + if (flags & CONFIG_UPDATE_BSSID) + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid, + (3 * sizeof(__le16))); } -static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u16 reg; /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. + * When in atomic context, we should let rt2x00lib + * try this configuration again later. */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work); - return; - } + if (in_atomic()) + return -EAGAIN; rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout); @@ -358,6 +353,8 @@ static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, !!short_preamble); rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); + + return 0; } static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -518,8 +515,8 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2500usb_config_phymode(rt2x00dev, libconf->phymode, @@ -625,6 +622,24 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) u8 up_bound; u8 low_bound; + /* + * Read current r17 value, as well as the sensitivity values + * for the r17 register. + */ + rt2500usb_bbp_read(rt2x00dev, 17, &r17); + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); + up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); + low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER); + + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Determine the BBP tuning threshold and correctly * set BBP 24, 25 and 61. @@ -650,13 +665,6 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) rt2500usb_bbp_write(rt2x00dev, 25, r25); rt2500usb_bbp_write(rt2x00dev, 61, r61); - /* - * Read current r17 value, as well as the sensitivity values - * for the r17 register. - */ - rt2500usb_bbp_read(rt2x00dev, 17, &r17); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens); - /* * A too low RSSI will cause too much false CCA which will * then corrupt the R17 tuning. To remidy this the tuning should @@ -692,14 +700,9 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Leave short or middle distance condition, restore r17 * to the dynamic tuning range. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); - vgc_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); - low_bound = 0x32; - if (rssi >= -77) - up_bound = vgc_bound; - else - up_bound = vgc_bound - (-77 - rssi); + if (rssi < -77) + up_bound -= (-77 - rssi); if (up_bound < low_bound) up_bound = low_bound; @@ -707,7 +710,16 @@ 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.qual.false_cca > 512 && r17 < up_bound) { + return; + } + +dynamic_cca_tune: + + /* + * R17 is inside the dynamic tuning range, + * start tuning the link based on the false cca counter. + */ + 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.qual.false_cca < 100 && r17 > low_bound) { @@ -1203,6 +1215,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) { u16 word; u8 *mac; + u8 bbp; rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); @@ -1257,9 +1270,17 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word); } + /* + * Switch lower vgc bound to current BBP R17 value, + * lower the value a bit for better quality. + */ + rt2500usb_bbp_read(rt2x00dev, 17, &bbp); + bbp -= 6; + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word); if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40); + rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word); } @@ -1270,6 +1291,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word); EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word); + } else { + rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); + rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); } rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word); @@ -1705,40 +1729,40 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, { struct rt2x00_dev *rt2x00dev = hw->priv; struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_usb_bcn *priv_bcn; struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; int pipe = usb_sndbulkpipe(usb_dev, 1); int length; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); - priv_bcn = entry->priv_data; + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + priv_bcn = intf->beacon->priv_data; /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case mac80211 doesn't set this correctly, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* @@ -1749,7 +1773,8 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, length = rt2500usb_get_tx_data_len(rt2x00dev, skb); usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe, - skb->data, length, rt2500usb_beacondone, entry); + skb->data, length, rt2500usb_beacondone, + intf->beacon); /* * Second we need to create the guardian byte. @@ -1759,7 +1784,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, priv_bcn->guardian_data = 0; usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe, &priv_bcn->guardian_data, 1, rt2500usb_beacondone, - entry); + intf->beacon); /* * Send out the guardian byte. @@ -1769,7 +1794,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, /* * Enable beacon generation. */ - rt2500usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt2500usb_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -1805,9 +1830,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, - .config_mac_addr = rt2500usb_config_mac_addr, - .config_bssid = rt2500usb_config_bssid, - .config_type = rt2500usb_config_type, + .config_intf = rt2500usb_config_intf, .config_preamble = rt2500usb_config_preamble, .config = rt2500usb_config, }; @@ -1842,6 +1865,8 @@ static const struct data_queue_desc rt2500usb_queue_atim = { static const struct rt2x00_ops rt2500usb_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2500usb_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index e9f2cd90da58..23ba0c15741f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -686,6 +686,7 @@ */ #define EEPROM_BBPTUNE_VGC 0x0034 #define EEPROM_BBPTUNE_VGCUPPER FIELD16(0x00ff) +#define EEPROM_BBPTUNE_VGCLOWER FIELD16(0xff00) /* * EEPROM BBP R17 Tuning. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6a25195816db..2363ca4903cc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -343,20 +343,22 @@ static inline int rt2x00_update_ant_rssi(struct link *link, int rssi) /* * Interface structure - * Configuration details about the current interface. + * Per interface configuration details, this structure + * is allocated as the private data for ieee80211_vif. */ -struct interface { +struct rt2x00_intf { /* - * Interface identification. The value is assigned - * to us by the 80211 stack, and is used to request - * new beacons. + * All fields within the rt2x00_intf structure + * must be protected with a spinlock. */ - struct ieee80211_vif *id; + spinlock_t lock; /* - * Current working type (IEEE80211_IF_TYPE_*). + * BSS configuration. Copied from the structure + * passed to us through the bss_info_changed() + * callback funtion. */ - int type; + struct ieee80211_bss_conf conf; /* * MAC of the device. @@ -367,16 +369,25 @@ struct interface { * BBSID of the AP to associate with. */ u8 bssid[ETH_ALEN]; -}; -static inline int is_interface_present(struct interface *intf) -{ - return !!intf->id; -} + /* + * Entry in the beacon queue which belongs to + * this interface. Each interface has its own + * dedicated beacon entry. + */ + struct queue_entry *beacon; -static inline int is_interface_type(struct interface *intf, int type) + /* + * Actions that needed rescheduling. + */ + unsigned int delayed_flags; +#define DELAYED_UPDATE_BEACON 0x00000001 +#define DELAYED_CONFIG_PREAMBLE 0x00000002 +}; + +static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) { - return intf->type == type; + return (struct rt2x00_intf *)vif->drv_priv; } /* @@ -429,6 +440,37 @@ struct rt2x00lib_conf { short eifs; }; +/* + * Configuration structure wrapper around the + * rt2x00 interface configuration handler. + */ +struct rt2x00intf_conf { + /* + * Interface type + */ + enum ieee80211_if_types type; + + /* + * TSF sync value, this is dependant on the operation type. + */ + enum tsf_sync sync; + + /* + * The MAC and BSSID addressess are simple array of bytes, + * these arrays are little endian, so when sending the addressess + * to the drivers, copy the it into a endian-signed variable. + * + * Note that all devices (except rt2500usb) have 32 bits + * register word sizes. This means that whatever variable we + * pass _must_ be a multiple of 32 bits. Otherwise the device + * might not accept what we are sending to it. + * This will also make it easier for the driver to write + * the data to the device. + */ + __le32 mac[2]; + __le32 bssid[2]; +}; + /* * rt2x00lib callback functions. */ @@ -495,16 +537,21 @@ struct rt2x00lib_ops { /* * Configuration handlers. */ - void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac); - void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid); - void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync); - void (*config_preamble) (struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time); - void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags, - struct rt2x00lib_conf *libconf); + void (*config_intf) (struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags); +#define CONFIG_UPDATE_TYPE ( 1 << 1 ) +#define CONFIG_UPDATE_MAC ( 1 << 2 ) +#define CONFIG_UPDATE_BSSID ( 1 << 3 ) + + int (*config_preamble) (struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time); + void (*config) (struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags); #define CONFIG_UPDATE_PHYMODE ( 1 << 1 ) #define CONFIG_UPDATE_CHANNEL ( 1 << 2 ) #define CONFIG_UPDATE_TXPOWER ( 1 << 3 ) @@ -519,6 +566,8 @@ struct rt2x00lib_ops { */ struct rt2x00_ops { const char *name; + const unsigned int max_sta_intf; + const unsigned int max_ap_intf; const unsigned int eeprom_size; const unsigned int rf_size; const struct data_queue_desc *rx; @@ -550,6 +599,7 @@ enum rt2x00_flags { /* * Driver features */ + DRIVER_SUPPORT_MIXED_INTERFACES, DRIVER_REQUIRE_FIRMWARE, DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, DRIVER_REQUIRE_FIRMWARE_CCITT, @@ -566,7 +616,6 @@ enum rt2x00_flags { CONFIG_EXTERNAL_LNA_BG, CONFIG_DOUBLE_ANTENNA, CONFIG_DISABLE_LINK_TUNING, - CONFIG_SHORT_PREAMBLE, }; /* @@ -670,9 +719,14 @@ struct rt2x00_dev { unsigned int packet_filter; /* - * Interface configuration. + * Interface details: + * - Open ap interface count. + * - Open sta interface count. + * - Association count. */ - struct interface interface; + unsigned int intf_ap_count; + unsigned int intf_sta_count; + unsigned int intf_associated; /* * Link quality @@ -738,9 +792,8 @@ struct rt2x00_dev { /* * Scheduled work. */ - struct work_struct beacon_work; + struct work_struct intf_work; struct work_struct filter_work; - struct work_struct config_work; /* * Data queue arrays for RX, TX and Beacon. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index c247ee77b3a3..20231e0c53fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -29,64 +29,89 @@ #include "rt2x00.h" #include "rt2x00lib.h" - -/* - * The MAC and BSSID addressess are simple array of bytes, - * these arrays are little endian, so when sending the addressess - * to the drivers, copy the it into a endian-signed variable. - * - * Note that all devices (except rt2500usb) have 32 bits - * register word sizes. This means that whatever variable we - * pass _must_ be a multiple of 32 bits. Otherwise the device - * might not accept what we are sending to it. - * This will also make it easier for the driver to write - * the data to the device. - * - * Also note that when NULL is passed as address the - * we will send 00:00:00:00:00 to the device to clear the address. - * This will prevent the device being confused when it wants - * to ACK frames or consideres itself associated. - */ -void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac) +void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + enum ieee80211_if_types type, + u8 *mac, u8 *bssid) { - __le32 reg[2]; - - memset(®, 0, sizeof(reg)); - if (mac) - memcpy(®, mac, ETH_ALEN); - - rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, ®[0]); -} + struct rt2x00intf_conf conf; + unsigned int flags = 0; -void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) -{ - __le32 reg[2]; - - memset(®, 0, sizeof(reg)); - if (bssid) - memcpy(®, bssid, ETH_ALEN); - - rt2x00dev->ops->lib->config_bssid(rt2x00dev, ®[0]); -} - -void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type) -{ - int tsf_sync; + conf.type = type; switch (type) { case IEEE80211_IF_TYPE_IBSS: case IEEE80211_IF_TYPE_AP: - tsf_sync = TSF_SYNC_BEACON; + conf.sync = TSF_SYNC_BEACON; break; case IEEE80211_IF_TYPE_STA: - tsf_sync = TSF_SYNC_INFRA; + conf.sync = TSF_SYNC_INFRA; break; default: - tsf_sync = TSF_SYNC_NONE; + conf.sync = TSF_SYNC_NONE; break; } - rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync); + /* + * Note that when NULL is passed as address we will send + * 00:00:00:00:00 to the device to clear the address. + * This will prevent the device being confused when it wants + * to ACK frames or consideres itself associated. + */ + memset(&conf.mac, 0, sizeof(conf.mac)); + if (mac) + memcpy(&conf.mac, mac, ETH_ALEN); + + memset(&conf.bssid, 0, sizeof(conf.bssid)); + if (bssid) + memcpy(&conf.bssid, bssid, ETH_ALEN); + + flags |= CONFIG_UPDATE_TYPE; + if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) + flags |= CONFIG_UPDATE_MAC; + if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) + flags |= CONFIG_UPDATE_BSSID; + + rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags); +} + +void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + const unsigned int short_preamble) +{ + int retval; + int ack_timeout; + int ack_consume_time; + + ack_timeout = PLCP + get_duration(ACK_SIZE, 10); + ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); + + if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) + ack_timeout += SHORT_DIFS; + else + ack_timeout += DIFS; + + if (short_preamble) { + ack_timeout += SHORT_PREAMBLE; + ack_consume_time += SHORT_PREAMBLE; + } else { + ack_timeout += PREAMBLE; + ack_consume_time += PREAMBLE; + } + + retval = rt2x00dev->ops->lib->config_preamble(rt2x00dev, + short_preamble, + ack_timeout, + ack_consume_time); + + spin_lock(&intf->lock); + + if (retval) { + intf->delayed_flags |= DELAYED_CONFIG_PREAMBLE; + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + } + + spin_unlock(&intf->lock); } void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, @@ -113,7 +138,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, * 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); + rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA); rt2x00lib_reset_link_tuner(rt2x00dev); rt2x00dev->link.ant.active.rx = libconf.ant.rx; @@ -266,7 +291,7 @@ config: /* * Start configuration. */ - rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf); + rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags); /* * Some configuration changes affect the link quality diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index bc07c56f89b3..014c307c270c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -136,12 +136,10 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Stop all scheduled work. */ - if (work_pending(&rt2x00dev->beacon_work)) - cancel_work_sync(&rt2x00dev->beacon_work); + if (work_pending(&rt2x00dev->intf_work)) + cancel_work_sync(&rt2x00dev->intf_work); if (work_pending(&rt2x00dev->filter_work)) cancel_work_sync(&rt2x00dev->filter_work); - if (work_pending(&rt2x00dev->config_work)) - cancel_work_sync(&rt2x00dev->config_work); /* * Stop the TX queues. @@ -173,7 +171,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) * When we are enabling the RX, we should also start the link tuner. */ if (state == STATE_RADIO_RX_ON && - is_interface_present(&rt2x00dev->interface)) + (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count)) rt2x00lib_start_link_tuner(rt2x00dev); } @@ -401,10 +399,10 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) unsigned int filter = rt2x00dev->packet_filter; /* - * Since we had stored the filter inside interface.filter, + * Since we had stored the filter inside rt2x00dev->packet_filter, * we should now clear that field. Otherwise the driver will * assume nothing has changed (*total_flags will be compared - * to interface.filter to determine if any action is required). + * to rt2x00dev->packet_filter to determine if any action is required). */ rt2x00dev->packet_filter = 0; @@ -412,41 +410,72 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) filter, &filter, 0, NULL); } -static void rt2x00lib_configuration_scheduled(struct work_struct *work) +static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) { - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, config_work); - struct ieee80211_bss_conf bss_conf; + struct rt2x00_dev *rt2x00dev = data; + struct rt2x00_intf *intf = vif_to_intf(vif); + struct sk_buff *skb; + struct ieee80211_tx_control control; + struct ieee80211_bss_conf conf; + int delayed_flags; + + /* + * Copy all data we need during this action under the protection + * of a spinlock. Otherwise race conditions might occur which results + * into an invalid configuration. + */ + spin_lock(&intf->lock); + + memcpy(&conf, &intf->conf, sizeof(conf)); + delayed_flags = intf->delayed_flags; + intf->delayed_flags = 0; + + spin_unlock(&intf->lock); + + if (delayed_flags & DELAYED_UPDATE_BEACON) { + skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); + if (skb) { + rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, + &control); + dev_kfree_skb(skb); + } + } + + if (delayed_flags & DELAYED_CONFIG_PREAMBLE) + rt2x00lib_config_preamble(rt2x00dev, intf, + intf->conf.use_short_preamble); +} - bss_conf.use_short_preamble = - test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); +static void rt2x00lib_intf_scheduled(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, intf_work); /* - * FIXME: shouldn't invoke it this way because all other contents - * of bss_conf is invalid. + * Iterate over each interface and perform the + * requested configurations. */ - rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id, - &bss_conf, BSS_CHANGED_ERP_PREAMBLE); + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_intf_scheduled_iter, + rt2x00dev); } /* * Interrupt context handlers. */ -static void rt2x00lib_beacondone_scheduled(struct work_struct *work) +static void rt2x00lib_beacondone_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) { - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, beacon_work); - struct ieee80211_tx_control control; - struct sk_buff *skb; + struct rt2x00_intf *intf = vif_to_intf(vif); - skb = ieee80211_beacon_get(rt2x00dev->hw, - rt2x00dev->interface.id, &control); - if (!skb) + if (vif->type != IEEE80211_IF_TYPE_AP && + vif->type != IEEE80211_IF_TYPE_IBSS) return; - rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, &control); - - dev_kfree_skb(skb); + spin_lock(&intf->lock); + intf->delayed_flags |= DELAYED_UPDATE_BEACON; + spin_unlock(&intf->lock); } void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) @@ -454,7 +483,11 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) return; - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work); + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_beacondone_iter, + rt2x00dev); + + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -1037,6 +1070,10 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) return retval; } + rt2x00dev->intf_ap_count = 0; + rt2x00dev->intf_sta_count = 0; + rt2x00dev->intf_associated = 0; + __set_bit(DEVICE_STARTED, &rt2x00dev->flags); return 0; @@ -1053,6 +1090,10 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) */ rt2x00lib_disable_radio(rt2x00dev); + rt2x00dev->intf_ap_count = 0; + rt2x00dev->intf_sta_count = 0; + rt2x00dev->intf_associated = 0; + __clear_bit(DEVICE_STARTED, &rt2x00dev->flags); } @@ -1063,6 +1104,12 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; + /* + * Make room for rt2x00_intf inside the per-interface + * structure ieee80211_vif. + */ + rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); + /* * Let the driver probe the device to detect the capabilities. */ @@ -1075,16 +1122,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize configuration work. */ - INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled); + INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); - INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); - /* - * Reset current working type. - */ - rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID; - /* * Allocate queue array. */ @@ -1203,9 +1244,30 @@ exit: } EXPORT_SYMBOL_GPL(rt2x00lib_suspend); +static void rt2x00lib_resume_intf(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rt2x00_dev *rt2x00dev = data; + struct rt2x00_intf *intf = vif_to_intf(vif); + + spin_lock(&intf->lock); + + rt2x00lib_config_intf(rt2x00dev, intf, + vif->type, intf->mac, intf->bssid); + + + /* + * Master or Ad-hoc mode require a new beacon update. + */ + if (vif->type == IEEE80211_IF_TYPE_AP || + vif->type == IEEE80211_IF_TYPE_IBSS) + intf->delayed_flags |= DELAYED_UPDATE_BEACON; + + spin_unlock(&intf->lock); +} + int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) { - struct interface *intf = &rt2x00dev->interface; int retval; NOTICE(rt2x00dev, "Waking up.\n"); @@ -1235,9 +1297,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) if (!rt2x00dev->hw->conf.radio_enabled) rt2x00lib_disable_radio(rt2x00dev); - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); - rt2x00lib_config_type(rt2x00dev, intf->type); + /* + * Iterator over each active interface to + * reconfigure the hardware. + */ + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_resume_intf, rt2x00dev); /* * We are ready again to receive requests from mac80211. @@ -1253,12 +1318,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) ieee80211_start_queues(rt2x00dev->hw); /* - * When in Master or Ad-hoc mode, - * restart Beacon transmitting by faking a beacondone event. + * During interface iteration we might have changed the + * delayed_flags, time to handles the event by calling + * the work handler directly. */ - if (intf->type == IEEE80211_IF_TYPE_AP || - intf->type == IEEE80211_IF_TYPE_IBSS) - rt2x00lib_beacondone(rt2x00dev); + rt2x00lib_intf_scheduled(&rt2x00dev->intf_work); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 5c835f42a455..f6789fdaaf6e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -50,9 +50,13 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev); /* * Configuration handlers. */ -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_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + enum ieee80211_if_types type, + u8 *mac, u8 *bssid); +void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + const unsigned int short_preamble); void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, enum antenna rx, enum antenna tx); void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f08c151ee4ba..65a2bcd18aa1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -52,11 +52,11 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, skb_put(skb, size); if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) - ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id, + ieee80211_ctstoself_get(rt2x00dev->hw, control->vif, frag_skb->data, frag_skb->len, control, (struct ieee80211_cts *)(skb->data)); else - ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id, + ieee80211_rts_get(rt2x00dev->hw, control->vif, frag_skb->data, frag_skb->len, control, (struct ieee80211_rts *)(skb->data)); @@ -162,19 +162,67 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(conf->vif); + struct data_queue *queue = + rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + struct queue_entry *entry = NULL; + unsigned int i; /* - * Don't allow interfaces to be added while - * either the device has disappeared or when - * another interface is already present. + * Don't allow interfaces to be added + * the device has disappeared. */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || - is_interface_present(intf)) + !test_bit(DEVICE_STARTED, &rt2x00dev->flags)) + return -ENODEV; + + /* + * When we don't support mixed interfaces (a combination + * of sta and ap virtual interfaces) then we can only + * add this interface when the rival interface count is 0. + */ + if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) && + ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) || + (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count))) + return -ENOBUFS; + + /* + * Check if we exceeded the maximum amount of supported interfaces. + */ + if ((conf->type == IEEE80211_IF_TYPE_AP && + rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) || + (conf->type != IEEE80211_IF_TYPE_AP && + rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf)) + return -ENOBUFS; + + /* + * Loop through all beacon queues to find a free + * entry. Since there are as much beacon entries + * as the maximum interfaces, this search shouldn't + * fail. + */ + for (i = 0; i < queue->limit; i++) { + entry = &queue->entries[i]; + if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags)) + break; + } + + if (unlikely(i == queue->limit)) return -ENOBUFS; - intf->id = conf->vif; - intf->type = conf->type; + /* + * We are now absolutely sure the interface can be created, + * increase interface count and start initialization. + */ + + if (conf->type == IEEE80211_IF_TYPE_AP) + rt2x00dev->intf_ap_count++; + else + rt2x00dev->intf_sta_count++; + + spin_lock_init(&intf->lock); + intf->beacon = entry; + if (conf->type == IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); @@ -184,8 +232,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * has been initialized. Otherwise the device can reset * the MAC registers. */ - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_type(rt2x00dev, conf->type); + rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); return 0; } @@ -195,7 +242,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(conf->vif); /* * Don't allow interfaces to be remove while @@ -203,21 +250,27 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, * no interface is present. */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || - !is_interface_present(intf)) + (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) || + (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count)) return; - intf->id = NULL; - intf->type = IEEE80211_IF_TYPE_INVALID; - memset(&intf->bssid, 0x00, ETH_ALEN); - memset(&intf->mac, 0x00, ETH_ALEN); + if (conf->type == IEEE80211_IF_TYPE_AP) + rt2x00dev->intf_ap_count--; + else + rt2x00dev->intf_sta_count--; + + /* + * Release beacon entry so it is available for + * new interfaces again. + */ + __clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags); /* * Make sure the bssid and mac address registers * are cleared to prevent false ACKing of frames. */ - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); - rt2x00lib_config_type(rt2x00dev, intf->type); + rt2x00lib_config_intf(rt2x00dev, intf, + IEEE80211_IF_TYPE_INVALID, NULL, NULL); } EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); @@ -262,7 +315,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_if_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(vif); int status; /* @@ -272,12 +325,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) return 0; - /* - * If the given type does not match the configured type, - * there has been a problem. - */ - if (conf->type != intf->type) - return -EINVAL; + spin_lock(&intf->lock); /* * If the interface does not work in master mode, @@ -286,7 +334,9 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, */ if (conf->type != IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->bssid, ETH_ALEN); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); + rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, intf->bssid); + + spin_unlock(&intf->lock); /* * We only need to initialize the beacon when master mode is enabled. @@ -342,35 +392,35 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct rt2x00_dev *rt2x00dev = hw->priv; - int short_preamble; - int ack_timeout; - int ack_consume_time; - int difs; - int preamble; + struct rt2x00_intf *intf = vif_to_intf(vif); /* - * We only support changing preamble mode. + * When the association status has changed we must reset the link + * tuner counter. This is because some drivers determine if they + * should perform link tuning based on the number of seconds + * while associated or not associated. */ - if (!(changes & BSS_CHANGED_ERP_PREAMBLE)) - return; - - short_preamble = bss_conf->use_short_preamble; - preamble = bss_conf->use_short_preamble ? - SHORT_PREAMBLE : PREAMBLE; + if (changes & BSS_CHANGED_ASSOC) { + rt2x00dev->link.count = 0; - difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? - SHORT_DIFS : DIFS; - ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10); - - ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10); + if (bss_conf->assoc) + rt2x00dev->intf_associated++; + else + rt2x00dev->intf_associated--; + } - if (short_preamble) - __set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); - else - __clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); + /* + * When the preamble mode has changed, we should perform additional + * configuration steps. For all other changes we are already done. + */ + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + rt2x00lib_config_preamble(rt2x00dev, intf, + bss_conf->use_short_preamble); - rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble, - ack_timeout, ack_consume_time); + spin_lock(&intf->lock); + memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); + spin_unlock(&intf->lock); + } } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 63cfe33e95da..764147dd5aea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -38,20 +38,14 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_pci_tx *priv_tx; struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; - /* - * Just in case mac80211 doesn't set this correctly, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); - priv_tx = entry->priv_data; + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + priv_tx = intf->beacon->priv_data; /* * Fill in skb descriptor @@ -59,17 +53,25 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->data = skb->data; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->desc; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; - memcpy(priv_tx->data, skb->data, skb->len); + /* + * Just in case mac80211 doesn't set this correctly, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Enable beacon generation. + * Write entire beacon with descriptor to register, + * and kick the beacon generator. */ + memcpy(priv_tx->data, skb->data, skb->len); rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 507116c6c9fe..75af48eddc25 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -46,9 +46,6 @@ * queue would be sufficient. Although this is almost one third of * the amount the legacy driver allocated, the queues aren't getting * filled to the maximum even when working with the maximum rate. - * - * FIXME: For virtual interfaces we need a different number - * of beacons, since more interfaces require more beacons. */ #define RX_ENTRIES 12 #define TX_ENTRIES 12 diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b5ab771bbac2..b432cc21d248 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -271,63 +271,60 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) +static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - u32 tmp; - - tmp = le32_to_cpu(mac[1]); - rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - mac[1] = cpu_to_le32(tmp); - - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (2 * sizeof(__le32))); -} + unsigned int beacon_base; + u32 reg; -static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) -{ - u32 tmp; + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); + rt2x00pci_register_write(rt2x00dev, beacon_base, 0); - tmp = le32_to_cpu(bssid[1]); - rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); - bssid[1] = cpu_to_le32(tmp); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + } - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); -static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, + conf->mac, sizeof(conf->mac)); + } - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); + conf->bssid[1] = cpu_to_le32(reg); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 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); + rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, + conf->bssid, sizeof(conf->bssid)); + } } -static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u32 reg; @@ -339,6 +336,8 @@ static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!short_preamble); rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); + + return 0; } static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -667,8 +666,8 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt61pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt61pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -815,6 +814,13 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) } } + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Special big-R17 for very short distance */ @@ -866,6 +872,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) return; } +dynamic_cca_tune: + /* * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. @@ -1214,6 +1222,17 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48); rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + /* * We must clear the error counters. * These registers are cleared on read, @@ -2378,25 +2397,20 @@ 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 rt2x00_intf *intf = vif_to_intf(control->vif); struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; + unsigned int beacon_base; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); + if (unlikely(!intf->beacon)) + return -ENOBUFS; /* * We need to append the descriptor in front of the * beacon frame. */ - if (skb_headroom(skb) < queue->desc_size) { - if (pskb_expand_head(skb, queue->desc_size, 0, GFP_ATOMIC)) { + if (skb_headroom(skb) < intf->beacon->queue->desc_size) { + if (pskb_expand_head(skb, intf->beacon->queue->desc_size, + 0, GFP_ATOMIC)) { dev_kfree_skb(skb); return -ENOMEM; } @@ -2405,29 +2419,36 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case the ieee80211 doesn't set this, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Write entire beacon with descriptor to register, * and kick the beacon generator. */ - rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0, + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, skb->data, skb->len); - rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt61pci_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -2469,9 +2490,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, - .config_mac_addr = rt61pci_config_mac_addr, - .config_bssid = rt61pci_config_bssid, - .config_type = rt61pci_config_type, + .config_intf = rt61pci_config_intf, .config_preamble = rt61pci_config_preamble, .config = rt61pci_config, }; @@ -2491,7 +2510,7 @@ static const struct data_queue_desc rt61pci_queue_tx = { }; static const struct data_queue_desc rt61pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 4 * BEACON_ENTRIES, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci_tx), @@ -2499,6 +2518,8 @@ static const struct data_queue_desc rt61pci_queue_bcn = { static const struct rt2x00_ops rt61pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt61pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 10519f8c5783..d291c0fe405c 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -161,7 +161,9 @@ struct hw_pairwise_ta_entry { #define HW_BEACON_BASE1 0x2d00 #define HW_BEACON_BASE2 0x2e00 #define HW_BEACON_BASE3 0x2f00 -#define HW_BEACON_OFFSET 0x0100 + +#define HW_BEACON_OFFSET(__index) \ + ( HW_BEACON_BASE0 + (__index * 0x0100) ) /* * HOST-MCU shared memory. @@ -234,6 +236,11 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR3: STA MAC register 1. + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK */ #define MAC_CSR3 0x300c #define MAC_CSR3_BYTE4 FIELD32(0x000000ff) @@ -251,7 +258,14 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR5: BSSID register 1. - * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID. + * BSS_ID_MASK: + * This mask is used to mask off bits 0 and 1 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 2-BSSID mode (BSS index: byte5, bit 1) + * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1) */ #define MAC_CSR5 0x3014 #define MAC_CSR5_BYTE4 FIELD32(0x000000ff) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 8ebf3fed9815..7907fd0d4aa5 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -281,74 +281,69 @@ static const struct rt2x00debug rt73usb_rt2x00debug = { /* * Configuration handlers. */ -static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) +static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - u32 tmp; - - tmp = le32_to_cpu(mac[1]); - rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - mac[1] = cpu_to_le32(tmp); - - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (2 * sizeof(__le32))); -} + unsigned int beacon_base; + u32 reg; -static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) -{ - u32 tmp; + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); + rt73usb_register_write(rt2x00dev, beacon_base, 0); - tmp = le32_to_cpu(bssid[1]); - rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); - bssid[1] = cpu_to_le32(tmp); + /* + * Enable synchronisation. + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + } - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); -static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, + conf->mac, sizeof(conf->mac)); + } - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); + conf->bssid[1] = cpu_to_le32(reg); - /* - * Enable synchronisation. - */ - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 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); + rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, + conf->bssid, sizeof(conf->bssid)); + } } -static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u32 reg; /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. + * When in atomic context, we should let rt2x00lib + * try this configuration again later. */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work); - return; - } + if (in_atomic()) + return -EAGAIN; rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); @@ -358,6 +353,8 @@ static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!short_preamble); rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); + + return 0; } static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -617,8 +614,8 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt73usb_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt73usb_config_phymode(rt2x00dev, libconf->basic_rates); @@ -765,6 +762,13 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) } } + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Special big-R17 for very short distance */ @@ -815,6 +819,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) return; } +dynamic_cca_tune: + /* * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. @@ -1020,6 +1026,17 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + /* * We must clear the error counters. * These registers are cleared on read, @@ -1985,52 +2002,52 @@ static void rt73usb_reset_tsf(struct ieee80211_hw *hw) } static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ieee80211_tx_control *control) + struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; - int timeout; + unsigned int beacon_base; + unsigned int timeout; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); + if (unlikely(!intf->beacon)) + return -ENOBUFS; /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case the ieee80211 doesn't set this, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Write entire beacon with descriptor to register, * and kick the beacon generator. */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32)); rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - HW_BEACON_BASE0, 0x0000, + USB_VENDOR_REQUEST_OUT, beacon_base, 0, skb->data, skb->len, timeout); - rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt73usb_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -2071,9 +2088,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, - .config_mac_addr = rt73usb_config_mac_addr, - .config_bssid = rt73usb_config_bssid, - .config_type = rt73usb_config_type, + .config_intf = rt73usb_config_intf, .config_preamble = rt73usb_config_preamble, .config = rt73usb_config, }; @@ -2093,7 +2108,7 @@ static const struct data_queue_desc rt73usb_queue_tx = { }; static const struct data_queue_desc rt73usb_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 4 * BEACON_ENTRIES, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb_tx), @@ -2101,6 +2116,8 @@ static const struct data_queue_desc rt73usb_queue_bcn = { static const struct rt2x00_ops rt73usb_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt73usb_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index da62b4f091a7..3f9675655eb9 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -114,6 +114,9 @@ struct hw_pairwise_ta_entry { #define HW_BEACON_BASE2 0x2600 #define HW_BEACON_BASE3 0x2700 +#define HW_BEACON_OFFSET(__index) \ + ( HW_BEACON_BASE0 + (__index * 0x0100) ) + /* * MAC Control/Status Registers(CSR). * Some values are set in TU, whereas 1 TU == 1024 us. @@ -146,6 +149,11 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR3: STA MAC register 1. + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK */ #define MAC_CSR3 0x300c #define MAC_CSR3_BYTE4 FIELD32(0x000000ff) @@ -163,7 +171,14 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR5: BSSID register 1. - * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID. + * BSS_ID_MASK: + * This mask is used to mask off bits 0 and 1 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 2-BSSID mode (BSS index: byte5, bit 1) + * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1) */ #define MAC_CSR5 0x3014 #define MAC_CSR5_BYTE4 FIELD32(0x000000ff) -- cgit v1.2.3-59-g8ed1b From 16938a24ae19562f078fd43a28500526ff78cd87 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:47:46 +0100 Subject: rt2x00: Remove MGMT ring initialization Remove the last remnants of the MGMT ring initialization from rt61pci.ko Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 2 -- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt61pci.h') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 25b3c6e2a556..a8ec910e5475 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1070,7 +1070,6 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC1, 2); rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC2, 2); rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC3, 2); - rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_MGMT, 0); rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg); rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®); @@ -1078,7 +1077,6 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1); rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1); rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1); - rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 0); rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index d291c0fe405c..2f9a8899a3e8 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -880,7 +880,7 @@ struct hw_pairwise_ta_entry { #define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000) /* - * LOAD_TX_RING_CSR: Load RX de + * LOAD_TX_RING_CSR: Load RX desriptor */ #define LOAD_TX_RING_CSR 0x3434 #define LOAD_TX_RING_CSR_LOAD_TXD_AC0 FIELD32(0x00000001) -- cgit v1.2.3-59-g8ed1b From e542239f639fa4e7b13a949d39d44ff1eccf7e3a Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:33:13 +0100 Subject: rt2x00: Filter ACK_CTS based on FIF_CONTROL The ACK_CTS frame is a control frame, this means dropping the frame depends on the FIF_CONTROL flag for filtering. This also fixes an obvious typo in register definition. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 5 +++-- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt61pci.h') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 357f2c4183f6..75f61f3c47b6 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2325,8 +2325,9 @@ static void rt61pci_configure_filter(struct ieee80211_hw *hw, rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, + !(*total_flags & FIF_CONTROL)); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); } diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 2f9a8899a3e8..d504e70125d5 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -405,7 +405,7 @@ struct hw_pairwise_ta_entry { #define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000) #define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000) #define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000) -#define TXRX_CSR0_DROP_BORADCAST FIELD32(0x01000000) +#define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000) #define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000) #define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index afd8533267a7..c3d4e9307785 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1929,7 +1929,8 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw, rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, !(*total_flags & FIF_ALLMULTI)); rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, + !(*total_flags & FIF_CONTROL)); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); } -- cgit v1.2.3-59-g8ed1b From de99ff82cdc2e5b596d01000eed9e0d05566f2d7 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:34:26 +0100 Subject: rt2x00: Rename dscape -> mac80211 The dscape stack was renamed to mac80211 a long time ago, we are long overdue with fixing all comments to reflect this. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 2 +- drivers/net/wireless/rt2x00/rt2400pci.h | 6 +++--- drivers/net/wireless/rt2x00/rt2500pci.h | 4 ++-- drivers/net/wireless/rt2x00/rt2500usb.h | 4 ++-- drivers/net/wireless/rt2x00/rt61pci.h | 4 ++-- drivers/net/wireless/rt2x00/rt73usb.h | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt61pci.h') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 108b85e295ba..d5240aa06233 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -5,7 +5,7 @@ config RT2X00 This will enable the experimental support for the Ralink drivers, developed in the rt2x00 project . - These drivers will make use of the Devicescape ieee80211 stack. + These drivers will make use of the mac80211 stack. When building one of the individual drivers, the rt2x00 library will also be created. That library (when the driver is built as diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index 3d59d6621145..da178d44660e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -923,13 +923,13 @@ #define RXD_W7_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. * NOTE: Logics in rt2400pci for txpower are reversed * compared to the other rt2x00 drivers. A higher txpower * value means that the txpower must be lowered. This is * important when converting the value coming from the - * dscape stack to the rt2400 acceptable value. + * mac80211 stack to the rt2400 acceptable value. */ #define MIN_TXPOWER 31 #define MAX_TXPOWER 62 diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index 0af130ca23c5..13899550465a 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1213,8 +1213,8 @@ #define RXD_W10_DROP FIELD32(0x00000001) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 #define MAX_TXPOWER 31 diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 647cd2d56ab9..a37a068d0c71 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -787,8 +787,8 @@ #define RXD_W3_EIV FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 #define MAX_TXPOWER 31 diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index d504e70125d5..4ef7ef32d76d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1455,8 +1455,8 @@ struct hw_pairwise_ta_entry { #define RXD_W15_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 #define MAX_TXPOWER 31 diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 3f9675655eb9..06d687425fef 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -1023,8 +1023,8 @@ struct hw_pairwise_ta_entry { #define RXD_W5_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 #define MAX_TXPOWER 31 -- cgit v1.2.3-59-g8ed1b From ce359f90d3c65bf0a575683a28d25672facd3df0 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:36:33 +0100 Subject: rt2x00: Fix MAC address defines in rt61pci The MAC address offset defines were incorrect because the byte offset was used instead of word index. This bug had no affect on normal operations since these defines weren't used. (EEPROM_MAC_ADDR_0 was used to read 6 bytes from). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt61pci.h') diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 4ef7ef32d76d..3511bba7ff65 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1130,10 +1130,10 @@ struct hw_pairwise_ta_entry { #define EEPROM_MAC_ADDR_0 0x0002 #define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) #define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR1 0x0004 +#define EEPROM_MAC_ADDR1 0x0003 #define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) #define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0006 +#define EEPROM_MAC_ADDR_2 0x0004 #define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) #define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) -- cgit v1.2.3-59-g8ed1b