]> 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 614600c5510d138c8918baa3e996411cac66d644..50775f9234cc72fb8a2dc34bf52ff59fc1c1fb53 100644 (file)
@@ -254,92 +254,33 @@ 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));
-}
-
-static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *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_CSR2, &mac,
+                                     (3 * sizeof(__le16)));
 }
 
-static void rt2500usb_config_packet_filter(struct rt2x00_dev *rt2x00dev,
-                                          const unsigned int filter)
+static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev,
+                                  __le32 *bssid)
 {
-       int promisc = !!(filter & IFF_PROMISC);
-       int multicast = !!(filter & IFF_MULTICAST);
-       int broadcast = !!(filter & IFF_BROADCAST);
-       u16 reg;
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME, !promisc);
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST, !multicast);
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, !broadcast);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, 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)
 {
        u16 reg;
 
        rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
 
-       /*
-        * Apply hardware packet filter.
-        */
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-
-       if (!is_monitor_present(&rt2x00dev->interface) &&
-           (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA))
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS, 1);
-       else
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS, 0);
-
-       /*
-        * If there is a non-monitor interface present
-        * the packet should be strict (even if a monitor interface is present!).
-        * When there is only 1 interface present which is in monitor mode
-        * we should start accepting _all_ frames.
-        */
-       if (is_interface_present(&rt2x00dev->interface)) {
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC, 1);
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL, 1);
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL, 1);
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
-       } else if (is_monitor_present(&rt2x00dev->interface)) {
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC, 0);
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL, 0);
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL, 0);
-               rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 0);
-       }
-
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
-
        /*
         * Enable beacon config
         */
        rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
        rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET,
-                          (PREAMBLE + get_duration(IEEE80211_HEADER, 2)) >> 6);
+                          (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6);
        if (type == IEEE80211_IF_TYPE_STA)
                rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
        else
@@ -354,73 +295,46 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type)
        rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
 
        rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-       if (is_interface_present(&rt2x00dev->interface)) {
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
-               rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
-       }
-
+       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 (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP)
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 2);
-       else if (type == IEEE80211_IF_TYPE_STA)
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 1);
-       else if (is_monitor_present(&rt2x00dev->interface) &&
-                !is_interface_present(&rt2x00dev->interface))
-               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 {
@@ -430,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.
@@ -456,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,
@@ -555,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);
 }
 
 /*
@@ -848,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 {
@@ -1084,7 +989,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
  */
 static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
                                    struct data_desc *txd,
-                                   struct data_entry_desc *desc,
+                                   struct txdata_entry_desc *desc,
                                    struct ieee80211_hdr *ieee80211hdr,
                                    unsigned int length,
                                    struct ieee80211_tx_control *control)
@@ -1126,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
  */
@@ -1156,8 +1076,8 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 /*
  * RX control handlers
  */
-static int rt2500usb_fill_rxdone(struct data_entry *entry,
-                                int *signal, int *rssi, int *ofdm, int *size)
+static void rt2500usb_fill_rxdone(struct data_entry *entry,
+                                 struct rxdata_entry_desc *desc)
 {
        struct urb *urb = entry->priv;
        struct data_desc *rxd = (struct data_desc *)(entry->skb->data +
@@ -1169,21 +1089,22 @@ static int rt2500usb_fill_rxdone(struct data_entry *entry,
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
 
-       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR) ||
-           rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR) ||
-           rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
-               return -EINVAL;
+       desc->flags = 0;
+       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+               desc->flags |= RX_FLAG_FAILED_FCS_CRC;
+       if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+               desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
 
        /*
         * Obtain the status about this packet.
         */
-       *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-       *rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
+       desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+       desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
            entry->ring->rt2x00dev->rssi_offset;
-       *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
-       *size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+       desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+       desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 
-       return 0;
+       return;
 }
 
 /*
@@ -1336,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;
        }
@@ -1549,9 +1470,7 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
            IEEE80211_HW_RX_INCLUDES_FCS |
-           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-           IEEE80211_HW_MONITOR_DURING_OPER |
-           IEEE80211_HW_NO_PROBE_FILTERING;
+           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
        rt2x00dev->hw->max_signal = MAX_SIGNAL;
        rt2x00dev->hw->max_rssi = MAX_RX_SSI;
@@ -1621,11 +1540,9 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        rt2500usb_probe_hw_mode(rt2x00dev);
 
        /*
-        * USB devices require scheduled packet filter toggling
-        *This device requires the beacon ring
+        * This device requires the beacon ring
         */
-       __set_bit(PACKET_FILTER_SCHEDULED, &rt2x00dev->flags);
-       __set_bit(REQUIRE_BEACON_RING, &rt2x00dev->flags);
+       __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
@@ -1638,6 +1555,82 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 /*
  * IEEE80211 stack callback functions.
  */
+static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
+                                      unsigned int changed_flags,
+                                      unsigned int *total_flags,
+                                      int mc_count,
+                                      struct dev_addr_list *mc_list)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct interface *intf = &rt2x00dev->interface;
+       u16 reg;
+
+       /*
+        * Mask off any flags we are going to ignore from
+        * the total_flags field.
+        */
+       *total_flags &=
+           FIF_ALLMULTI |
+           FIF_FCSFAIL |
+           FIF_PLCPFAIL |
+           FIF_CONTROL |
+           FIF_OTHER_BSS |
+           FIF_PROMISC_IN_BSS;
+
+       /*
+        * Apply some rules to the filters:
+        * - Some filters imply different filters to be set.
+        * - Some things we can't filter out at all.
+        * - Some filters are set based on interface type.
+        */
+       if (mc_count)
+               *total_flags |= FIF_ALLMULTI;
+       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;
+
+       /*
+        * Check if there is any work left for us.
+        */
+       if (intf->filter == *total_flags)
+               return;
+       intf->filter = *total_flags;
+
+       /*
+        * When in atomic context, reschedule and let rt2x00lib
+        * call this function again.
+        */
+       if (in_atomic()) {
+               queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+               return;
+       }
+
+       /*
+        * Start configuration steps.
+        * Note that the version error will always be dropped
+        * and broadcast frames will always be accepted since
+        * there is no filter for it at this time.
+        */
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
+                          !(*total_flags & FIF_FCSFAIL));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
+                          !(*total_flags & FIF_PLCPFAIL));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
+                          !(*total_flags & FIF_CONTROL));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
+                          !(*total_flags & FIF_PROMISC_IN_BSS));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
+                          !(*total_flags & FIF_PROMISC_IN_BSS));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
+                          !(*total_flags & FIF_ALLMULTI));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+}
+
 static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
                                   struct sk_buff *skb,
                                   struct ieee80211_tx_control *control)
@@ -1649,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;
 
        /*
@@ -1670,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;
@@ -1695,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);
 
        /*
@@ -1714,12 +1702,15 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
 
 static const struct ieee80211_ops rt2500usb_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
        .add_interface          = rt2x00mac_add_interface,
        .remove_interface       = rt2x00mac_remove_interface,
        .config                 = rt2x00mac_config,
        .config_interface       = rt2x00mac_config_interface,
-       .set_multicast_list     = rt2x00mac_set_multicast_list,
+       .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,
@@ -1735,12 +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_packet_filter   = rt2500usb_config_packet_filter,
        .config_type            = rt2500usb_config_type,
+       .config_preamble        = rt2500usb_config_preamble,
        .config                 = rt2500usb_config,
 };