]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/wireless/rt2x00/rt61pci.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus
[mv-sheeva.git] / drivers / net / wireless / rt2x00 / rt61pci.c
index 6a74baf4e934b97e4ac3978341736790f18fb6e3..af548c87f1084a6d641430bfd5fbf84bef52b8a0 100644 (file)
@@ -594,7 +594,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
 }
 
 static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
-                              struct rt2x00lib_erp *erp)
+                              struct rt2x00lib_erp *erp,
+                              u32 changed)
 {
        u32 reg;
 
@@ -603,28 +604,36 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 
-       rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
-                          !!erp->short_preamble);
-       rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+               rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
+               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+                                  !!erp->short_preamble);
+               rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+       }
 
-       rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
+       if (changed & BSS_CHANGED_BASIC_RATES)
+               rt2x00pci_register_write(rt2x00dev, TXRX_CSR5,
+                                        erp->basic_rates);
 
-       rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
-                          erp->beacon_int * 16);
-       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+       if (changed & BSS_CHANGED_BEACON_INT) {
+               rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+                                  erp->beacon_int * 16);
+               rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+       }
 
-       rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
-       rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+               rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
 
-       rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
-       rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-       rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
-       rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+               rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+               rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+               rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+               rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+       }
 }
 
 static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -931,6 +940,9 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
        u32 reg;
 
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
        rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
                           libconf->conf->long_frame_max_tx_count);
        rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
@@ -1047,7 +1059,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
        /*
         * Determine r17 bounds.
         */
-       if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
                low_bound = 0x28;
                up_bound = 0x48;
                if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
@@ -1619,7 +1631,8 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
                               enum dev_state state)
 {
-       int mask = (state == STATE_RADIO_IRQ_OFF);
+       int mask = (state == STATE_RADIO_IRQ_OFF) ||
+                  (state == STATE_RADIO_IRQ_OFF_ISR);
        u32 reg;
 
        /*
@@ -1641,6 +1654,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
        rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
        rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
        rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, mask);
        rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, mask);
        rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
        rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
@@ -1654,6 +1668,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_5, mask);
        rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_6, mask);
        rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_TWAKEUP, mask);
        rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
 }
 
@@ -1736,7 +1751,9 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
                rt61pci_toggle_rx(rt2x00dev, state);
                break;
        case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_ON_ISR:
        case STATE_RADIO_IRQ_OFF:
+       case STATE_RADIO_IRQ_OFF_ISR:
                rt61pci_toggle_irq(rt2x00dev, state);
                break;
        case STATE_DEEP_SLEEP:
@@ -1760,12 +1777,11 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 /*
  * TX descriptor initialization
  */
-static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-                                 struct sk_buff *skb,
+static void rt61pci_write_tx_desc(struct queue_entry *entry,
                                  struct txentry_desc *txdesc)
 {
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-       struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       struct queue_entry_priv_pci *entry_priv = entry->priv_data;
        __le32 *txd = entry_priv->desc;
        u32 word;
 
@@ -1773,7 +1789,7 @@ 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, txdesc->queue);
+       rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid);
        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);
@@ -1796,15 +1812,15 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        }
 
        rt2x00_desc_read(txd, 5, &word);
-       rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid);
+       rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
        rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
                           skbdesc->entry->entry_idx);
        rt2x00_set_field32(&word, TXD_W5_TX_POWER,
-                          TXPOWER_TO_DEV(rt2x00dev->tx_power));
+                          TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
        rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
        rt2x00_desc_write(txd, 5, word);
 
-       if (txdesc->queue != QID_BEACON) {
+       if (txdesc->qid != QID_BEACON) {
                rt2x00_desc_read(txd, 6, &word);
                rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
                                   skbdesc->skb_dma);
@@ -1851,7 +1867,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
         */
        skbdesc->desc = txd;
        skbdesc->desc_len =
-               (txdesc->queue == QID_BEACON) ?  TXINFO_SIZE : TXD_DESC_SIZE;
+               (txdesc->qid == QID_BEACON) ?  TXINFO_SIZE : TXD_DESC_SIZE;
 }
 
 /*
@@ -1873,6 +1889,16 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 
+       /*
+        * Write the TX descriptor for the beacon.
+        */
+       rt61pci_write_tx_desc(entry, txdesc);
+
+       /*
+        * Dump beacon to userspace through debugfs.
+        */
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
+
        /*
         * Write entire beacon with descriptor to register.
         */
@@ -1902,34 +1928,34 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
        entry->skb = NULL;
 }
 
-static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-                                 const enum data_queue_qid queue)
+static void rt61pci_kick_tx_queue(struct data_queue *queue)
 {
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
        u32 reg;
 
        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));
-       rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue == QID_AC_VI));
-       rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue == QID_AC_VO));
+       rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue->qid == QID_AC_BE));
+       rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue->qid == QID_AC_BK));
+       rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue->qid == QID_AC_VI));
+       rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue->qid == QID_AC_VO));
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
 }
 
-static void rt61pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
-                                 const enum data_queue_qid qid)
+static void rt61pci_kill_tx_queue(struct data_queue *queue)
 {
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
        u32 reg;
 
-       if (qid == QID_BEACON) {
+       if (queue->qid == QID_BEACON) {
                rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
                return;
        }
 
        rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-       rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, (qid == QID_AC_BE));
-       rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, (qid == QID_AC_BK));
-       rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, (qid == QID_AC_VI));
-       rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, (qid == QID_AC_VO));
+       rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, (queue->qid == QID_AC_BE));
+       rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, (queue->qid == QID_AC_BK));
+       rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, (queue->qid == QID_AC_VI));
+       rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, (queue->qid == QID_AC_VO));
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
 }
 
@@ -1956,7 +1982,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
                return 0;
        }
 
-       if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
                if (lna == 3 || lna == 2)
                        offset += 10;
        }
@@ -2039,29 +2065,24 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
        struct txdone_entry_desc txdesc;
        u32 word;
        u32 reg;
-       u32 old_reg;
        int type;
        int index;
+       int i;
 
        /*
-        * During each loop we will compare the freshly read
-        * STA_CSR4 register value with the value read from
-        * the previous loop. If the 2 values are equal then
-        * we should stop processing because the chance is
-        * quite big that the device has been unplugged and
-        * we risk going into an endless loop.
+        * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
+        * at most X times and also stop processing once the TX_STA_FIFO_VALID
+        * flag is not set anymore.
+        *
+        * The legacy drivers use X=TX_RING_SIZE but state in a comment
+        * that the TX_STA_FIFO stack has a size of 16. We stick to our
+        * tx ring size for now.
         */
-       old_reg = 0;
-
-       while (1) {
+       for (i = 0; i < TX_ENTRIES; i++) {
                rt2x00pci_register_read(rt2x00dev, STA_CSR4, &reg);
                if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
                        break;
 
-               if (old_reg == reg)
-                       break;
-               old_reg = reg;
-
                /*
                 * Skip this entry when it contains an invalid
                 * queue identication number.
@@ -2096,11 +2117,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
                                "TX status report missed for entry %d\n",
                                entry_done->entry_idx);
 
-                       txdesc.flags = 0;
-                       __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
-                       txdesc.retry = 0;
-
-                       rt2x00lib_txdone(entry_done, &txdesc);
+                       rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN);
                        entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                }
 
@@ -2120,6 +2137,13 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
                }
                txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
 
+               /*
+                * the frame was retried at least once
+                * -> hw used fallback rates
+                */
+               if (txdesc.retry)
+                       __set_bit(TXDONE_FALLBACK, &txdesc.flags);
+
                rt2x00lib_txdone(entry, &txdesc);
        }
 }
@@ -2132,27 +2156,11 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
        rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
+static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance)
 {
        struct rt2x00_dev *rt2x00dev = dev_instance;
-       u32 reg_mcu;
-       u32 reg;
-
-       /*
-        * Get the interrupt sources & saved to local variable.
-        * Write register value back to clear pending interrupts.
-        */
-       rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
-       rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
-
-       rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-       rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
-       if (!reg && !reg_mcu)
-               return IRQ_NONE;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return IRQ_HANDLED;
+       u32 reg = rt2x00dev->irqvalue[0];
+       u32 reg_mcu = rt2x00dev->irqvalue[1];
 
        /*
         * Handle interrupts, walk through all bits
@@ -2185,9 +2193,51 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
        if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
                rt61pci_wakeup(rt2x00dev);
 
+       /*
+        * 5 - Beacon done interrupt.
+        */
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
+               rt2x00lib_beacondone(rt2x00dev);
+
+       /* Enable interrupts again. */
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+                                             STATE_RADIO_IRQ_ON_ISR);
        return IRQ_HANDLED;
 }
 
+
+static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
+{
+       struct rt2x00_dev *rt2x00dev = dev_instance;
+       u32 reg_mcu;
+       u32 reg;
+
+       /*
+        * Get the interrupt sources & saved to local variable.
+        * Write register value back to clear pending interrupts.
+        */
+       rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
+       rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
+
+       rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+       rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+       if (!reg && !reg_mcu)
+               return IRQ_NONE;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return IRQ_HANDLED;
+
+       /* Store irqvalues for use in the interrupt thread. */
+       rt2x00dev->irqvalue[0] = reg;
+       rt2x00dev->irqvalue[1] = reg_mcu;
+
+       /* Disable interrupts, will be enabled again in the interrupt thread. */
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+                                             STATE_RADIO_IRQ_OFF_ISR);
+       return IRQ_WAKE_THREAD;
+}
+
 /*
  * Device probe functions.
  */
@@ -2576,6 +2626,19 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
 
+       /*
+        * As rt61 has a global fallback table we cannot specify
+        * more then one tx rate per frame but since the hw will
+        * try several rates (based on the fallback table) we should
+        * initialize max_report_rates to the maximum number of rates
+        * we are going to try. Otherwise mac80211 will truncate our
+        * reported tx rates and the rc algortihm will end up with
+        * incorrect data.
+        */
+       rt2x00dev->hw->max_rates = 1;
+       rt2x00dev->hw->max_report_rates = 7;
+       rt2x00dev->hw->max_rate_tries = 1;
+
        /*
         * Initialize hw_mode information.
         */
@@ -2598,20 +2661,24 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        /*
         * Create channel information array
         */
-       info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
        spec->channels_info = info;
 
        tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
-       for (i = 0; i < 14; i++)
-               info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+       for (i = 0; i < 14; i++) {
+               info[i].max_power = MAX_TXPOWER;
+               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+       }
 
        if (spec->num_channels > 14) {
                tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
-               for (i = 14; i < spec->num_channels; i++)
-                       info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+               for (i = 14; i < spec->num_channels; i++) {
+                       info[i].max_power = MAX_TXPOWER;
+                       info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+               }
        }
 
        return 0;
@@ -2657,6 +2724,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
        if (!modparam_nohwcrypt)
                __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
+       __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
@@ -2748,8 +2816,9 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .remove_interface       = rt2x00mac_remove_interface,
        .config                 = rt2x00mac_config,
        .configure_filter       = rt2x00mac_configure_filter,
-       .set_tim                = rt2x00mac_set_tim,
        .set_key                = rt2x00mac_set_key,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
        .get_stats              = rt2x00mac_get_stats,
        .bss_info_changed       = rt2x00mac_bss_info_changed,
        .conf_tx                = rt61pci_conf_tx,
@@ -2759,6 +2828,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
        .irq_handler            = rt61pci_interrupt,
+       .irq_handler_thread     = rt61pci_interrupt_thread,
        .probe_hw               = rt61pci_probe_hw,
        .get_firmware_name      = rt61pci_get_firmware_name,
        .check_firmware         = rt61pci_check_firmware,
@@ -2773,7 +2843,6 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
        .reset_tuner            = rt61pci_reset_tuner,
        .link_tuner             = rt61pci_link_tuner,
        .write_tx_desc          = rt61pci_write_tx_desc,
-       .write_tx_data          = rt2x00pci_write_tx_data,
        .write_beacon           = rt61pci_write_beacon,
        .kick_tx_queue          = rt61pci_kick_tx_queue,
        .kill_tx_queue          = rt61pci_kill_tx_queue,