rt2x00: Simplify TXD handling of beacons.
[safe/jmp/linux-2.6] / drivers / net / wireless / rt2x00 / rt61pci.c
index 687e17d..1be1d7d 100644 (file)
@@ -637,8 +637,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        rt61pci_bbp_read(rt2x00dev, 4, &r4);
        rt61pci_bbp_read(rt2x00dev, 77, &r77);
 
-       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
-                         rt2x00_rf(&rt2x00dev->chip, RF5325));
+       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325));
 
        /*
         * Configure the RX antenna.
@@ -684,8 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
        rt61pci_bbp_read(rt2x00dev, 4, &r4);
        rt61pci_bbp_read(rt2x00dev, 77, &r77);
 
-       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
-                         rt2x00_rf(&rt2x00dev->chip, RF2529));
+       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
        rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
                          !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
 
@@ -833,12 +831,11 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
 
        rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
 
-       if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
-           rt2x00_rf(&rt2x00dev->chip, RF5325))
+       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))
                rt61pci_config_antenna_5x(rt2x00dev, ant);
-       else if (rt2x00_rf(&rt2x00dev->chip, RF2527))
+       else if (rt2x00_rf(rt2x00dev, RF2527))
                rt61pci_config_antenna_2x(rt2x00dev, ant);
-       else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) {
+       else if (rt2x00_rf(rt2x00dev, RF2529)) {
                if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
                        rt61pci_config_antenna_2x(rt2x00dev, ant);
                else
@@ -879,8 +876,7 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
        rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
 
-       smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
-                 rt2x00_rf(&rt2x00dev->chip, RF2527));
+       smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
 
        rt61pci_bbp_read(rt2x00dev, 3, &r3);
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
@@ -1135,16 +1131,18 @@ dynamic_cca_tune:
  */
 static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
 {
+       u16 chip;
        char *fw_name;
 
-       switch (rt2x00dev->chip.rt) {
-       case RT2561:
+       pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip);
+       switch (chip) {
+       case RT2561_PCI_ID:
                fw_name = FIRMWARE_RT2561;
                break;
-       case RT2561s:
+       case RT2561s_PCI_ID:
                fw_name = FIRMWARE_RT2561s;
                break;
-       case RT2661:
+       case RT2661_PCI_ID:
                fw_name = FIRMWARE_RT2661;
                break;
        default:
@@ -1765,7 +1763,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                  struct txentry_desc *txdesc)
 {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-       __le32 *txd = skbdesc->desc;
+       struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+       __le32 *txd = entry_priv->desc;
        u32 word;
 
        /*
@@ -1803,17 +1802,23 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
        rt2x00_desc_write(txd, 5, word);
 
-       rt2x00_desc_read(txd, 6, &word);
-       rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
-                          skbdesc->skb_dma);
-       rt2x00_desc_write(txd, 6, word);
+       if (txdesc->queue != QID_BEACON) {
+               rt2x00_desc_read(txd, 6, &word);
+               rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
+                                  skbdesc->skb_dma);
+               rt2x00_desc_write(txd, 6, word);
 
-       if (skbdesc->desc_len > TXINFO_SIZE) {
                rt2x00_desc_read(txd, 11, &word);
-               rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len);
+               rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0,
+                                  txdesc->length);
                rt2x00_desc_write(txd, 11, word);
        }
 
+       /*
+        * Writing TXD word 0 must the last to prevent a race condition with
+        * the device, whereby the device may take hold of the TXD before we
+        * finished updating it.
+        */
        rt2x00_desc_read(txd, 0, &word);
        rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
        rt2x00_set_field32(&word, TXD_W0_VALID, 1);
@@ -1833,20 +1838,28 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
                           test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
-       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
+       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
        rt2x00_set_field32(&word, TXD_W0_BURST,
                           test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
        rt2x00_desc_write(txd, 0, word);
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->desc = txd;
+       skbdesc->desc_len =
+               (txdesc->queue == QID_BEACON) ?  TXINFO_SIZE : TXD_DESC_SIZE;
 }
 
 /*
  * TX data initialization
  */
-static void rt61pci_write_beacon(struct queue_entry *entry)
+static void rt61pci_write_beacon(struct queue_entry *entry,
+                                struct txentry_desc *txdesc)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        unsigned int beacon_base;
        u32 reg;
 
@@ -1862,14 +1875,25 @@ static void rt61pci_write_beacon(struct queue_entry *entry)
         * Write entire beacon with descriptor to register.
         */
        beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
-       rt2x00pci_register_multiwrite(rt2x00dev,
-                                     beacon_base,
-                                     skbdesc->desc, skbdesc->desc_len);
-       rt2x00pci_register_multiwrite(rt2x00dev,
-                                     beacon_base + skbdesc->desc_len,
+       rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
+                                     entry_priv->desc, TXINFO_SIZE);
+       rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
                                      entry->skb->data, entry->skb->len);
 
        /*
+        * Enable beaconing again.
+        *
+        * For Wi-Fi faily generated beacons between participating
+        * stations. Set TBTT phase adaptive adjustment step to 8us.
+        */
+       rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
         * Clean up beacon skb.
         */
        dev_kfree_skb_any(entry->skb);
@@ -1881,23 +1905,6 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       if (queue == QID_BEACON) {
-               /*
-                * For Wi-Fi faily generated beacons between participating
-                * stations. Set TBTT phase adaptive adjustment step to 8us.
-                */
-               rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
-
-               rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
-                       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-                       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
-                       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
-                       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
-               }
-               return;
-       }
-
        rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
        rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE));
        rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK));
@@ -1969,12 +1976,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
 
-       if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
-               rxdesc->cipher =
-                   rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
-               rxdesc->cipher_status =
-                   rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
-       }
+       rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
+       rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
 
        if (rxdesc->cipher != CIPHER_NONE) {
                _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]);
@@ -2119,6 +2122,14 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
        }
 }
 
+static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
+{
+       struct ieee80211_conf conf = { .flags = 0 };
+       struct rt2x00lib_conf libconf = { .conf = &conf };
+
+       rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
+}
+
 static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
 {
        struct rt2x00_dev *rt2x00dev = dev_instance;
@@ -2166,6 +2177,12 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
                rt2x00pci_register_write(rt2x00dev,
                                         M2H_CMD_DONE_CSR, 0xffffffff);
 
+       /*
+        * 4 - MCU Autowakeup interrupt.
+        */
+       if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
+               rt61pci_wakeup(rt2x00dev);
+
        return IRQ_HANDLED;
 }
 
@@ -2299,13 +2316,13 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         */
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
        rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
-       rt2x00_set_chip_rf(rt2x00dev, value, reg);
-       rt2x00_print_chip(rt2x00dev);
+       rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
+                       value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
 
-       if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
-           !rt2x00_rf(&rt2x00dev->chip, RF5325) &&
-           !rt2x00_rf(&rt2x00dev->chip, RF2527) &&
-           !rt2x00_rf(&rt2x00dev->chip, RF2529)) {
+       if (!rt2x00_rf(rt2x00dev, RF5225) &&
+           !rt2x00_rf(rt2x00dev, RF5325) &&
+           !rt2x00_rf(rt2x00dev, RF2527) &&
+           !rt2x00_rf(rt2x00dev, RF2529)) {
                ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
                return -ENODEV;
        }
@@ -2360,7 +2377,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * the antenna settings should be gathered from the NIC
         * eeprom word.
         */
-       if (rt2x00_rf(&rt2x00dev->chip, RF2529) &&
+       if (rt2x00_rf(rt2x00dev, RF2529) &&
            !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
                rt2x00dev->default_ant.rx =
                    ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
@@ -2539,6 +2556,11 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        unsigned int i;
 
        /*
+        * Disable powersaving as default.
+        */
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+       /*
         * Initialize all hw fields.
         */
        rt2x00dev->hw->flags =
@@ -2566,8 +2588,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                spec->channels = rf_vals_seq;
        }
 
-       if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
-           rt2x00_rf(&rt2x00dev->chip, RF5325)) {
+       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) {
                spec->supported_bands |= SUPPORT_BAND_5GHZ;
                spec->num_channels = ARRAY_SIZE(rf_vals_seq);
        }
@@ -2730,7 +2751,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .get_stats              = rt2x00mac_get_stats,
        .bss_info_changed       = rt2x00mac_bss_info_changed,
        .conf_tx                = rt61pci_conf_tx,
-       .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt61pci_get_tsf,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
 };
@@ -2807,7 +2827,7 @@ static const struct rt2x00_ops rt61pci_ops = {
 /*
  * RT61pci module information.
  */
-static struct pci_device_id rt61pci_device_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {
        /* RT2561s */
        { PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) },
        /* RT2561 v2 */