]> 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 7aacc7b5c1b203c3cca8ad78ac7253d254893786..50775f9234cc72fb8a2dc34bf52ff59fc1c1fb53 100644 (file)
@@ -254,37 +254,23 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = {
 /*
  * Configuration handlers.
  */
-static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *addr)
+static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev,
+                                     __le32 *mac)
 {
-       __le16 reg[3];
-
-       memset(&reg, 0, sizeof(reg));
-       memcpy(&reg, addr, ETH_ALEN);
-
-       /*
-        * The MAC address is passed to us as an array of bytes,
-        * that array is little endian, so no need for byte ordering.
-        */
-       rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, &reg, sizeof(reg));
+       rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, &mac,
+                                     (3 * sizeof(__le16)));
 }
 
-static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
+static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev,
+                                  __le32 *bssid)
 {
-       __le16 reg[3];
-
-       memset(&reg, 0, sizeof(reg));
-       memcpy(&reg, bssid, ETH_ALEN);
-
-       /*
-        * The BSSID is passed to us as an array of bytes,
-        * that array is little endian, so no need for byte ordering.
-        */
-       rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, &reg, sizeof(reg));
+       rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid,
+                                     (3 * sizeof(__le16)));
 }
 
-static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type)
+static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+                                 const int tsf_sync)
 {
-       struct interface *intf = &rt2x00dev->interface;
        u16 reg;
 
        rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
@@ -294,8 +280,8 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type)
         */
        rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
        rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET,
-                          (PREAMBLE + get_duration(IEEE80211_HEADER, 2)) >> 6);
-       if (is_interface_type(intf, IEEE80211_IF_TYPE_STA))
+                          (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6);
+       if (type == IEEE80211_IF_TYPE_STA)
                rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
        else
                rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 2);
@@ -312,66 +298,43 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type)
        rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
        rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
        rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
-       if (is_interface_type(intf, IEEE80211_IF_TYPE_IBSS) ||
-           is_interface_type(intf, IEEE80211_IF_TYPE_AP))
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 2);
-       else if (is_interface_type(intf, IEEE80211_IF_TYPE_STA))
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 1);
-       else
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, tsf_sync);
        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 {
@@ -381,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.
@@ -407,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,
@@ -506,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);
 }
 
 /*
@@ -799,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 {
@@ -1077,6 +1031,21 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_desc_write(txd, 0, word);
 }
 
+static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
+                                    struct sk_buff *skb)
+{
+       int length;
+
+       /*
+        * The length _must_ be a multiple of 2,
+        * but it must _not_ be a multiple of the USB packet size.
+        */
+       length = roundup(skb->len, 2);
+       length += (2 * !(length % rt2x00dev->usb_maxpacket));
+
+       return length;
+}
+
 /*
  * TX data initialization
  */
@@ -1288,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;
        }
@@ -1616,8 +1585,8 @@ static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
         */
        if (mc_count)
                *total_flags |= FIF_ALLMULTI;
-       if (changed_flags & FIF_OTHER_BSS ||
-           changed_flags & FIF_PROMISC_IN_BSS)
+       if (*total_flags & FIF_OTHER_BSS ||
+           *total_flags & FIF_PROMISC_IN_BSS)
                *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
        if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
                *total_flags |= FIF_PROMISC_IN_BSS;
@@ -1673,6 +1642,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
            rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
        struct data_entry *beacon;
        struct data_entry *guardian;
+       int pipe = usb_sndbulkpipe(usb_dev, 1);
        int length;
 
        /*
@@ -1694,21 +1664,16 @@ 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 passed to usb_fill_urb cannot be an odd number,
-        * so add 1 byte to make it even.
-        */
-       length = skb->len;
-       if (length % 2)
-               length++;
+       length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
 
-       usb_fill_bulk_urb(beacon->priv, usb_dev,
-                         usb_sndbulkpipe(usb_dev, 1),
+       usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
                          skb->data, length, rt2500usb_beacondone, beacon);
 
        beacon->skb = skb;
@@ -1719,8 +1684,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
         * the 'flags' field we are not using for beacons.
         */
        guardian->flags = 0;
-       usb_fill_bulk_urb(guardian->priv, usb_dev,
-                         usb_sndbulkpipe(usb_dev, 1),
+       usb_fill_bulk_urb(guardian->priv, usb_dev, pipe,
                          &guardian->flags, 1, rt2500usb_beacondone, guardian);
 
        /*
@@ -1746,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,
@@ -1761,11 +1726,13 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
        .link_tuner             = rt2500usb_link_tuner,
        .write_tx_desc          = rt2500usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
+       .get_tx_data_len        = rt2500usb_get_tx_data_len,
        .kick_tx_queue          = rt2500usb_kick_tx_queue,
        .fill_rxdone            = rt2500usb_fill_rxdone,
        .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,
 };