]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/rt2x00/rt2500usb.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
[linux-2.6] / drivers / net / wireless / rt2x00 / rt2500usb.c
index f536ff1b5c4708c491384b1470336c4f9cd9fca2..50775f9234cc72fb8a2dc34bf52ff59fc1c1fb53 100644 (file)
@@ -302,56 +302,39 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
        rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
 }
 
-static void rt2500usb_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
+static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
+                                     const int short_preamble,
+                                     const int ack_timeout,
+                                     const int ack_consume_time)
 {
-       struct ieee80211_conf *conf = &rt2x00dev->hw->conf;
        u16 reg;
-       u16 value;
-       u16 preamble;
-
-       if (DEVICE_GET_RATE_FIELD(rate, PREAMBLE))
-               preamble = SHORT_PREAMBLE;
-       else
-               preamble = PREAMBLE;
 
-       reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATEMASK;
-
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR11, reg);
+       /*
+        * When in atomic context, reschedule and let rt2x00lib
+        * call this function again.
+        */
+       if (in_atomic()) {
+               queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
+               return;
+       }
 
        rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
-       value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
-                SHORT_DIFS : DIFS) +
-           PLCP + preamble + get_duration(ACK_SIZE, 10);
-       rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, value);
+       rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, ack_timeout);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
 
        rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
-       if (preamble == SHORT_PREAMBLE)
-               rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE, 1);
-       else
-               rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
+                          !!short_preamble);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
 }
 
 static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
-                                    const int phymode)
+                                    const int phymode,
+                                    const int basic_rate_mask)
 {
-       struct ieee80211_hw_mode *mode;
-       struct ieee80211_rate *rate;
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
 
-       if (phymode == MODE_IEEE80211A)
-               rt2x00dev->curr_hwmode = HWMODE_A;
-       else if (phymode == MODE_IEEE80211B)
-               rt2x00dev->curr_hwmode = HWMODE_B;
-       else
-               rt2x00dev->curr_hwmode = HWMODE_G;
-
-       mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
-       rate = &mode->rates[mode->num_rates - 1];
-
-       rt2500usb_config_rate(rt2x00dev, rate->val2);
-
-       if (phymode == MODE_IEEE80211B) {
+       if (phymode == HWMODE_B) {
                rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b);
                rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040);
        } else {
@@ -361,20 +344,12 @@ static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
 }
 
 static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
-                                    const int index, const int channel,
-                                    const int txpower)
+                                    struct rf_channel *rf, const int txpower)
 {
-       struct rf_channel reg;
-
-       /*
-        * Fill rf_reg structure.
-        */
-       memcpy(&reg, &rt2x00dev->spec.channels[index], sizeof(reg));
-
        /*
         * Set TXpower.
         */
-       rt2x00_set_field32(&reg.rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
 
        /*
         * For RT2525E we should first set the channel to half band higher.
@@ -387,16 +362,16 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
                        0x00000902, 0x00000906
                };
 
-               rt2500usb_rf_write(rt2x00dev, 2, vals[channel - 1]);
-               if (reg.rf4)
-                       rt2500usb_rf_write(rt2x00dev, 4, reg.rf4);
+               rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
+               if (rf->rf4)
+                       rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
        }
 
-       rt2500usb_rf_write(rt2x00dev, 1, reg.rf1);
-       rt2500usb_rf_write(rt2x00dev, 2, reg.rf2);
-       rt2500usb_rf_write(rt2x00dev, 3, reg.rf3);
-       if (reg.rf4)
-               rt2500usb_rf_write(rt2x00dev, 4, reg.rf4);
+       rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
+       rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
+       if (rf->rf4)
+               rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
 }
 
 static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
@@ -486,38 +461,37 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
 }
 
 static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
-                                     const int short_slot_time,
-                                     const int beacon_int)
+                                     struct rt2x00lib_conf *libconf)
 {
        u16 reg;
 
-       rt2500usb_register_write(rt2x00dev, MAC_CSR10,
-                                short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time);
 
        rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL, beacon_int * 4);
+       rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
+                          libconf->conf->beacon_int * 4);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
 }
 
 static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
                             const unsigned int flags,
-                            struct ieee80211_conf *conf)
+                            struct rt2x00lib_conf *libconf)
 {
-       int short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
        if (flags & CONFIG_UPDATE_PHYMODE)
-               rt2500usb_config_phymode(rt2x00dev, conf->phymode);
+               rt2500usb_config_phymode(rt2x00dev, libconf->phymode,
+                                        libconf->basic_rates);
        if (flags & CONFIG_UPDATE_CHANNEL)
-               rt2500usb_config_channel(rt2x00dev, conf->channel_val,
-                                        conf->channel, conf->power_level);
+               rt2500usb_config_channel(rt2x00dev, &libconf->rf,
+                                        libconf->conf->power_level);
        if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
-               rt2500usb_config_txpower(rt2x00dev, conf->power_level);
+               rt2500usb_config_txpower(rt2x00dev,
+                                        libconf->conf->power_level);
        if (flags & CONFIG_UPDATE_ANTENNA)
-               rt2500usb_config_antenna(rt2x00dev, conf->antenna_sel_tx,
-                                        conf->antenna_sel_rx);
+               rt2500usb_config_antenna(rt2x00dev,
+                                        libconf->conf->antenna_sel_tx,
+                                        libconf->conf->antenna_sel_rx);
        if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
-               rt2500usb_config_duration(rt2x00dev, short_slot_time,
-                                         conf->beacon_int);
+               rt2500usb_config_duration(rt2x00dev, libconf);
 }
 
 /*
@@ -779,7 +753,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
        rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       if (rt2x00_get_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
+       if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
                rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
                reg &= ~0x0002;
        } else {
@@ -1058,7 +1032,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 }
 
 static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
-                                    int maxpacket, struct sk_buff *skb)
+                                    struct sk_buff *skb)
 {
        int length;
 
@@ -1067,7 +1041,7 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
         * but it must _not_ be a multiple of the USB packet size.
         */
        length = roundup(skb->len, 2);
-       length += (2 * !(length % maxpacket));
+       length += (2 * !(length % rt2x00dev->usb_maxpacket));
 
        return length;
 }
@@ -1283,7 +1257,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
        rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
 
-       if (rt2x00_rev(&rt2x00dev->chip, 0xffff0)) {
+       if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) {
                ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
                return -ENODEV;
        }
@@ -1669,7 +1643,6 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
        struct data_entry *beacon;
        struct data_entry *guardian;
        int pipe = usb_sndbulkpipe(usb_dev, 1);
-       int max_packet = usb_maxpacket(usb_dev, pipe, 1);
        int length;
 
        /*
@@ -1691,12 +1664,14 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
         * First we create the beacon.
         */
        skb_push(skb, ring->desc_size);
+       memset(skb->data, 0, ring->desc_size);
+
        rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
                                (struct ieee80211_hdr *)(skb->data +
                                                         ring->desc_size),
                                skb->len - ring->desc_size, control);
 
-       length = rt2500usb_get_tx_data_len(rt2x00dev, max_packet, skb);
+       length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
 
        usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
                          skb->data, length, rt2500usb_beacondone, beacon);
@@ -1735,6 +1710,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
        .config_interface       = rt2x00mac_config_interface,
        .configure_filter       = rt2500usb_configure_filter,
        .get_stats              = rt2x00mac_get_stats,
+       .erp_ie_changed         = rt2x00mac_erp_ie_changed,
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .beacon_update          = rt2500usb_beacon_update,
@@ -1756,6 +1732,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
        .config_mac_addr        = rt2500usb_config_mac_addr,
        .config_bssid           = rt2500usb_config_bssid,
        .config_type            = rt2500usb_config_type,
+       .config_preamble        = rt2500usb_config_preamble,
        .config                 = rt2500usb_config,
 };