rt2x00: Optimize TX descriptor handling
authorHelmut Schaa <helmut.schaa@googlemail.com>
Thu, 3 Mar 2011 18:42:35 +0000 (19:42 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 4 Mar 2011 19:06:47 +0000 (14:06 -0500)
HT and no-HT rt2x00 devices use a partly different TX descriptor.
Optimize the tx desciptor memory layout by putting the PLCP and HT
substructs into a union and introduce a new driver flag to decide which
TX desciptor format is used by the device.

This saves us the expensive PLCP calculation fOr HT devices and the HT
descriptor setup on no-HT devices.

Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
12 files changed:
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00ht.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c

index d38acf4b65e12ecbec9009baae3a5bb47b2a35ab..60d75962b805d5a7117509cd3a98f586b8ec77cb 100644 (file)
@@ -1131,19 +1131,21 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
        rt2x00_desc_write(txd, 2, word);
 
        rt2x00_desc_read(txd, 3, &word);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.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, txdesc->service);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.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, txdesc->length_low);
+       rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.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, txdesc->length_high);
+       rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.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);
index b00e4d483c58891de751b7796ed7d657ef1cdc77..53ff64e196489c266e11461faf398a3b29fb2531 100644 (file)
@@ -1287,10 +1287,12 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
        rt2x00_desc_write(txd, 2, word);
 
        rt2x00_desc_read(txd, 3, &word);
-       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_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
        rt2x00_desc_write(txd, 3, word);
 
        rt2x00_desc_read(txd, 10, &word);
index b71df29436e75d24fc0a4e521ff523b0716f035e..ed5bc9c6224f35584b4f8270582cf92af8344a1b 100644 (file)
@@ -1114,10 +1114,12 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
        rt2x00_desc_write(txd, 1, word);
 
        rt2x00_desc_read(txd, 2, &word);
-       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_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
        rt2x00_desc_write(txd, 2, word);
 
        if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
index ad90c86810d777447d039555bbca8785d94a04cc..553d4d01a4395add1b87526becd06f3518954278 100644 (file)
@@ -472,14 +472,15 @@ void rt2800_write_tx_data(struct queue_entry *entry,
                           test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
        rt2x00_set_field32(&word, TXWI_W0_AMPDU,
                           test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
-       rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop);
-       rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
+       rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY,
+                          txdesc->u.ht.mpdu_density);
+       rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->u.ht.txop);
+       rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->u.ht.mcs);
        rt2x00_set_field32(&word, TXWI_W0_BW,
                           test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
        rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
                           test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc);
+       rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->u.ht.stbc);
        rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
        rt2x00_desc_write(txwi, 0, word);
 
@@ -488,7 +489,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
                           test_bit(ENTRY_TXD_ACK, &txdesc->flags));
        rt2x00_set_field32(&word, TXWI_W1_NSEQ,
                           test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
+       rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
        rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
                           test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
                           txdesc->key_idx : 0xff);
index 046a7b7d1241f434085929ff7fa23653963352d9..49ea189c9821ddafd69944660d389ad7e1fd8d53 100644 (file)
@@ -979,6 +979,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (!modparam_nohwcrypt)
                __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
        __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+       __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
index 5d91561e0de7794330d73b7967a4116caba9c151..f1a92144996fae7e367aca206c66ceed544e9a93 100644 (file)
@@ -565,6 +565,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
                __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
        __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
        __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
+       __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
index 9067c917c659ca5b34eb5dcf86fe3ca0cc93432c..81a0f8bed6ae89a0b3948c0281b7574dc47947dc 100644 (file)
@@ -663,6 +663,7 @@ enum rt2x00_flags {
        DRIVER_REQUIRE_TXSTATUS_FIFO,
        DRIVER_REQUIRE_TASKLET_CONTEXT,
        DRIVER_REQUIRE_SW_SEQNO,
+       DRIVER_REQUIRE_HT_TX_DESC,
 
        /*
         * Driver features
index 03d9579da6815d209abba9a5dfaecd71e87f61d5..78a0e7386a78488bc46c223600c87d265be721da 100644 (file)
@@ -38,12 +38,12 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
 
        if (tx_info->control.sta)
-               txdesc->mpdu_density =
+               txdesc->u.ht.mpdu_density =
                    tx_info->control.sta->ht_cap.ampdu_density;
 
-       txdesc->ba_size = 7;    /* FIXME: What value is needed? */
+       txdesc->u.ht.ba_size = 7;       /* FIXME: What value is needed? */
 
-       txdesc->stbc =
+       txdesc->u.ht.stbc =
            (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT;
 
        /*
@@ -51,22 +51,22 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
         * mcs rate to be used
         */
        if (txrate->flags & IEEE80211_TX_RC_MCS) {
-               txdesc->mcs = txrate->idx;
+               txdesc->u.ht.mcs = txrate->idx;
 
                /*
                 * MIMO PS should be set to 1 for STA's using dynamic SM PS
                 * when using more then one tx stream (>MCS7).
                 */
-               if (tx_info->control.sta && txdesc->mcs > 7 &&
+               if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
                    ((tx_info->control.sta->ht_cap.cap &
                      IEEE80211_HT_CAP_SM_PS) >>
                     IEEE80211_HT_CAP_SM_PS_SHIFT) ==
                    WLAN_HT_CAP_SM_PS_DYNAMIC)
                        __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
        } else {
-               txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+               txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
                if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-                       txdesc->mcs |= 0x08;
+                       txdesc->u.ht.mcs |= 0x08;
        }
 
        /*
@@ -105,11 +105,11 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
         * for frames not transmitted with TXOP_HTTXOP
         */
        if (ieee80211_is_mgmt(hdr->frame_control))
-               txdesc->txop = TXOP_BACKOFF;
+               txdesc->u.ht.txop = TXOP_BACKOFF;
        else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
-               txdesc->txop = TXOP_SIFS;
+               txdesc->u.ht.txop = TXOP_SIFS;
        else
-               txdesc->txop = TXOP_HTTXOP;
+               txdesc->u.ht.txop = TXOP_HTTXOP;
 }
 
 u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
index eebb564ee4da4fefe2e083858aedcebf7ae5bf73..7816c1c39d6eaa61fed46917678989ecb443efcb 100644 (file)
@@ -270,12 +270,12 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
         * PLCP setup
         * Length calculation depends on OFDM/CCK rate.
         */
-       txdesc->signal = hwrate->plcp;
-       txdesc->service = 0x04;
+       txdesc->u.plcp.signal = hwrate->plcp;
+       txdesc->u.plcp.service = 0x04;
 
        if (hwrate->flags & DEV_RATE_OFDM) {
-               txdesc->length_high = (data_length >> 6) & 0x3f;
-               txdesc->length_low = data_length & 0x3f;
+               txdesc->u.plcp.length_high = (data_length >> 6) & 0x3f;
+               txdesc->u.plcp.length_low = data_length & 0x3f;
        } else {
                /*
                 * Convert length to microseconds.
@@ -290,18 +290,18 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
                         * Check if we need to set the Length Extension
                         */
                        if (hwrate->bitrate == 110 && residual <= 30)
-                               txdesc->service |= 0x80;
+                               txdesc->u.plcp.service |= 0x80;
                }
 
-               txdesc->length_high = (duration >> 8) & 0xff;
-               txdesc->length_low = duration & 0xff;
+               txdesc->u.plcp.length_high = (duration >> 8) & 0xff;
+               txdesc->u.plcp.length_low = duration & 0xff;
 
                /*
                 * When preamble is enabled we should set the
                 * preamble bit for the signal.
                 */
                if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-                       txdesc->signal |= 0x08;
+                       txdesc->u.plcp.signal |= 0x08;
        }
 }
 
@@ -397,9 +397,12 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
         * Apply TX descriptor handling by components
         */
        rt2x00crypto_create_tx_descriptor(entry, txdesc);
-       rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
        rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
-       rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
+
+       if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags))
+               rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
+       else
+               rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
 
 static int rt2x00queue_write_tx_data(struct queue_entry *entry,
index fab8e2687f293847ffe82a194fa9986e8a230ac8..3305520464403a2d77997921b94ec21d8e6d5be0 100644 (file)
@@ -305,20 +305,27 @@ struct txentry_desc {
        u16 length;
        u16 header_length;
 
-       u16 length_high;
-       u16 length_low;
-       u16 signal;
-       u16 service;
-
-       u16 mcs;
-       u16 stbc;
-       u16 ba_size;
+       union {
+               struct {
+                       u16 length_high;
+                       u16 length_low;
+                       u16 signal;
+                       u16 service;
+               } plcp;
+
+               struct {
+                       u16 mcs;
+                       u16 stbc;
+                       u16 ba_size;
+                       u16 mpdu_density;
+                       short txop;
+               } ht;
+       } u;
+
        u16 rate_mode;
-       u16 mpdu_density;
 
        short retry_limit;
        short ifs;
-       short txop;
 
        enum cipher cipher;
        u16 key_idx;
index 2ed845b1ea3cf849159ac210762884ed2fb4b89f..c01b811a50d5fc8b95481aced399f294e134fa57 100644 (file)
@@ -1898,10 +1898,12 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
        rt2x00_desc_write(txd, 1, word);
 
        rt2x00_desc_read(txd, 2, &word);
-       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_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
        rt2x00_desc_write(txd, 2, word);
 
        if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
index a799c262c1dbc6278b1dd714b773bc95af76ef27..a4c9a3e20ec45ed84b044ce2093cedb3702ac044 100644 (file)
@@ -1499,10 +1499,12 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
        rt2x00_desc_write(txd, 1, word);
 
        rt2x00_desc_read(txd, 2, &word);
-       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_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
        rt2x00_desc_write(txd, 2, word);
 
        if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {