]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/rt2x00/rt61pci.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[karo-tx-linux.git] / drivers / net / wireless / rt2x00 / rt61pci.c
index e13ed5ced26e9d2014e1851e5007d9d9c83628f3..70ef7bf434ab44dee46e031999a19e1f7041e311 100644 (file)
@@ -330,6 +330,17 @@ static int rt61pci_blink_set(struct led_classdev *led_cdev,
 
        return 0;
 }
+
+static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00_led *led,
+                            enum led_type type)
+{
+       led->rt2x00dev = rt2x00dev;
+       led->type = type;
+       led->led_dev.brightness_set = rt61pci_brightness_set;
+       led->led_dev.blink_set = rt61pci_blink_set;
+       led->flags = LED_INITIALIZED;
+}
 #endif /* CONFIG_RT61PCI_LEDS */
 
 /*
@@ -1019,11 +1030,12 @@ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
                                 struct queue_entry *entry)
 {
        struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        u32 word;
 
        rt2x00_desc_read(entry_priv->desc, 5, &word);
        rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
-                          entry_priv->data_dma);
+                          skbdesc->skb_dma);
        rt2x00_desc_write(entry_priv->desc, 5, word);
 
        rt2x00_desc_read(entry_priv->desc, 0, &word);
@@ -1186,6 +1198,15 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg);
 
+       rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
 
        rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
@@ -1270,25 +1291,32 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
        return 0;
 }
 
-static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
+static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
 {
        unsigned int i;
-       u16 eeprom;
-       u8 reg_id;
        u8 value;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt61pci_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
-                       goto continue_csr_init;
-               NOTICE(rt2x00dev, "Waiting for BBP register.\n");
+                       return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
 
        ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
        return -EACCES;
+}
+
+static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u16 eeprom;
+       u8 reg_id;
+       u8 value;
+
+       if (unlikely(rt61pci_wait_bbp_ready(rt2x00dev)))
+               return -EACCES;
 
-continue_csr_init:
        rt61pci_bbp_write(rt2x00dev, 3, 0x00);
        rt61pci_bbp_write(rt2x00dev, 15, 0x30);
        rt61pci_bbp_write(rt2x00dev, 21, 0xc8);
@@ -1337,7 +1365,8 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 
        rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
-                          state == STATE_RADIO_RX_OFF);
+                          (state == STATE_RADIO_RX_OFF) ||
+                          (state == STATE_RADIO_RX_OFF_LINK));
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 }
 
@@ -1389,17 +1418,10 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize all registers.
         */
-       if (rt61pci_init_queues(rt2x00dev) ||
-           rt61pci_init_registers(rt2x00dev) ||
-           rt61pci_init_bbp(rt2x00dev)) {
-               ERROR(rt2x00dev, "Register initialization failed.\n");
+       if (unlikely(rt61pci_init_queues(rt2x00dev) ||
+                    rt61pci_init_registers(rt2x00dev) ||
+                    rt61pci_init_bbp(rt2x00dev)))
                return -EIO;
-       }
-
-       /*
-        * Enable interrupts.
-        */
-       rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
 
        /*
         * Enable RX.
@@ -1431,11 +1453,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
        rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
        rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-
-       /*
-        * Disable interrupts.
-        */
-       rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF);
 }
 
 static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
@@ -1443,7 +1460,6 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
        u32 reg;
        unsigned int i;
        char put_to_sleep;
-       char current_state;
 
        put_to_sleep = (state != STATE_AWAKE);
 
@@ -1459,16 +1475,12 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt2x00pci_register_read(rt2x00dev, MAC_CSR12, &reg);
-               current_state =
-                   rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
-               if (current_state == !put_to_sleep)
+               state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
+               if (state == !put_to_sleep)
                        return 0;
                msleep(10);
        }
 
-       NOTICE(rt2x00dev, "Device failed to enter state %d, "
-              "current device state %d.\n", !put_to_sleep, current_state);
-
        return -EBUSY;
 }
 
@@ -1486,11 +1498,13 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
-               rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
-               break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
-               rt61pci_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
+               rt61pci_toggle_rx(rt2x00dev, state);
+               break;
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               rt61pci_toggle_irq(rt2x00dev, state);
                break;
        case STATE_DEEP_SLEEP:
        case STATE_SLEEP:
@@ -1503,6 +1517,10 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
                break;
        }
 
+       if (unlikely(retval))
+               ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
+                     state, retval);
+
        return retval;
 }
 
@@ -1514,7 +1532,6 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    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;
        __le32 *txd = skbdesc->desc;
        u32 word;
 
@@ -1549,12 +1566,12 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 
        rt2x00_desc_read(txd, 6, &word);
        rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
-                          entry_priv->data_dma);
+                          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, skbdesc->data_len);
+               rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len);
                rt2x00_desc_write(txd, 11, word);
        }
 
@@ -1573,7 +1590,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
                           test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
        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_DATABYTE_COUNT, skb->len);
        rt2x00_set_field32(&word, TXD_W0_BURST,
                           test_bit(ENTRY_TXD_BURST, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
@@ -1583,6 +1600,41 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 /*
  * TX data initialization
  */
+static void rt61pci_write_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       unsigned int beacon_base;
+       u32 reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * 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,
+                                     entry->skb->data, entry->skb->len);
+
+       /*
+        * Clean up beacon skb.
+        */
+       dev_kfree_skb_any(entry->skb);
+       entry->skb = NULL;
+}
+
 static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
                                  const enum data_queue_qid queue)
 {
@@ -1759,7 +1811,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
                        __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
                        txdesc.retry = 0;
 
-                       rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
+                       rt2x00lib_txdone(entry_done, &txdesc);
                        entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                }
 
@@ -1779,7 +1831,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
                }
                txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
 
-               rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
+               rt2x00lib_txdone(entry, &txdesc);
        }
 }
 
@@ -1965,7 +2017,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * To determine the RT chip we have to read the
         * PCI header of the device.
         */
-       pci_read_config_word(rt2x00dev_pci(rt2x00dev),
+       pci_read_config_word(to_pci_dev(rt2x00dev->dev),
                             PCI_CONFIG_HEADER_DEVICE, &device);
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
        rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
@@ -2067,31 +2119,11 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
        value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
 
-       rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
-       rt2x00dev->led_radio.type = LED_TYPE_RADIO;
-       rt2x00dev->led_radio.led_dev.brightness_set =
-           rt61pci_brightness_set;
-       rt2x00dev->led_radio.led_dev.blink_set =
-           rt61pci_blink_set;
-       rt2x00dev->led_radio.flags = LED_INITIALIZED;
-
-       rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
-       rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
-       rt2x00dev->led_assoc.led_dev.brightness_set =
-           rt61pci_brightness_set;
-       rt2x00dev->led_assoc.led_dev.blink_set =
-           rt61pci_blink_set;
-       rt2x00dev->led_assoc.flags = LED_INITIALIZED;
-
-       if (value == LED_MODE_SIGNAL_STRENGTH) {
-               rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
-               rt2x00dev->led_qual.type = LED_TYPE_QUALITY;
-               rt2x00dev->led_qual.led_dev.brightness_set =
-                   rt61pci_brightness_set;
-               rt2x00dev->led_qual.led_dev.blink_set =
-                   rt61pci_blink_set;
-               rt2x00dev->led_qual.flags = LED_INITIALIZED;
-       }
+       rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+       rt61pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+       if (value == LED_MODE_SIGNAL_STRENGTH)
+               rt61pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
+                                LED_TYPE_QUALITY);
 
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
@@ -2251,7 +2283,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = 0;
 
-       SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
+       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
@@ -2314,9 +2346,10 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        rt61pci_probe_hw_mode(rt2x00dev);
 
        /*
-        * This device requires firmware.
+        * This device requires firmware and DMA mapped skbs.
         */
        __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
+       __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
@@ -2357,69 +2390,6 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
        return tsf;
 }
 
-static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
-       struct queue_entry_priv_pci *entry_priv;
-       struct skb_frame_desc *skbdesc;
-       struct txentry_desc txdesc;
-       unsigned int beacon_base;
-       u32 reg;
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-
-       /*
-        * Copy all TX descriptor information into txdesc,
-        * after that we are free to use the skb->cb array
-        * for our information.
-        */
-       intf->beacon->skb = skb;
-       rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
-
-       entry_priv = intf->beacon->priv_data;
-       memset(entry_priv->desc, 0, intf->beacon->queue->desc_size);
-
-       /*
-        * Fill in skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
-       skbdesc->data = skb->data;
-       skbdesc->data_len = skb->len;
-       skbdesc->desc = entry_priv->desc;
-       skbdesc->desc_len = intf->beacon->queue->desc_size;
-       skbdesc->entry = intf->beacon;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Write entire beacon with descriptor to register,
-        * and kick the beacon generator.
-        */
-       rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
-       beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-       rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
-                                     skbdesc->desc, skbdesc->desc_len);
-       rt2x00pci_register_multiwrite(rt2x00dev,
-                                     beacon_base + skbdesc->desc_len,
-                                     skbdesc->data, skbdesc->data_len);
-       rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON);
-
-       return 0;
-}
-
 static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
        .start                  = rt2x00mac_start,
@@ -2435,7 +2405,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt61pci_get_tsf,
-       .beacon_update          = rt61pci_beacon_update,
 };
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
@@ -2455,6 +2424,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
        .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,
        .fill_rxdone            = rt61pci_fill_rxdone,
        .config_filter          = rt61pci_config_filter,