tree-wide: fix assorted typos all over the place
[safe/jmp/linux-2.6] / drivers / net / wireless / zd1211rw / zd_mac.c
index 4d7b98b..2b7f965 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
  * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
  * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
- * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (C) 2007-2008 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "zd_def.h"
 #include "zd_chip.h"
 #include "zd_mac.h"
-#include "zd_ieee80211.h"
 #include "zd_rf.h"
 
+struct zd_reg_alpha2_map {
+       u32 reg;
+       char alpha2[2];
+};
+
+static struct zd_reg_alpha2_map reg_alpha2_map[] = {
+       { ZD_REGDOMAIN_FCC, "US" },
+       { ZD_REGDOMAIN_IC, "CA" },
+       { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
+       { ZD_REGDOMAIN_JAPAN, "JP" },
+       { ZD_REGDOMAIN_JAPAN_ADD, "JP" },
+       { ZD_REGDOMAIN_SPAIN, "ES" },
+       { ZD_REGDOMAIN_FRANCE, "FR" },
+};
+
 /* This table contains the hardware specific values for the modulation rates. */
 static const struct ieee80211_rate zd_rates[] = {
        { .bitrate = 10,
@@ -95,6 +109,21 @@ static void housekeeping_init(struct zd_mac *mac);
 static void housekeeping_enable(struct zd_mac *mac);
 static void housekeeping_disable(struct zd_mac *mac);
 
+static int zd_reg2alpha2(u8 regdomain, char *alpha2)
+{
+       unsigned int i;
+       struct zd_reg_alpha2_map *reg_map;
+       for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
+               reg_map = &reg_alpha2_map[i];
+               if (regdomain == reg_map->reg) {
+                       alpha2[0] = reg_map->alpha2[0];
+                       alpha2[1] = reg_map->alpha2[1];
+                       return 0;
+               }
+       }
+       return 1;
+}
+
 int zd_mac_preinit_hw(struct ieee80211_hw *hw)
 {
        int r;
@@ -115,6 +144,7 @@ int zd_mac_init_hw(struct ieee80211_hw *hw)
        int r;
        struct zd_mac *mac = zd_hw_mac(hw);
        struct zd_chip *chip = &mac->chip;
+       char alpha2[2];
        u8 default_regdomain;
 
        r = zd_chip_enable_int(chip);
@@ -139,9 +169,11 @@ int zd_mac_init_hw(struct ieee80211_hw *hw)
        if (r)
                goto disable_int;
 
-       zd_geo_init(hw, mac->regdomain);
+       r = zd_reg2alpha2(mac->regdomain, alpha2);
+       if (r)
+               goto disable_int;
 
-       r = 0;
+       r = regulatory_hint(hw->wiphy, alpha2);
 disable_int:
        zd_chip_disable_int(chip);
 out:
@@ -255,7 +287,7 @@ static void zd_op_stop(struct ieee80211_hw *hw)
  * @skb - a sk-buffer
  * @flags: extra flags to set in the TX status info
  * @ackssi: ACK signal strength
- * @success - True for successfull transmission of the frame
+ * @success - True for successful transmission of the frame
  *
  * This information calls ieee80211_tx_status_irqsafe() if required by the
  * control information. It copies the control information into the status
@@ -264,15 +296,14 @@ static void zd_op_stop(struct ieee80211_hw *hw)
  * If no status information has been requested, the skb is freed.
  */
 static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
-                     u32 flags, int ackssi, bool success)
+                     int ackssi, bool success)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
-       memset(&info->status, 0, sizeof(info->status));
+       ieee80211_tx_info_clear_status(info);
 
-       if (!success)
-               info->status.excessive_retries = 1;
-       info->flags |= flags;
+       if (success)
+               info->flags |= IEEE80211_TX_STAT_ACK;
        info->status.ack_signal = ackssi;
        ieee80211_tx_status_irqsafe(hw, skb);
 }
@@ -281,7 +312,7 @@ static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
  * zd_mac_tx_failed - callback for failed frames
  * @dev: the mac80211 wireless device
  *
- * This function is called if a frame couldn't be succesfully be
+ * This function is called if a frame couldn't be successfully be
  * transferred. The first frame from the tx queue, will be selected and
  * reported as error to the upper layers.
  */
@@ -294,7 +325,7 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
        if (skb == NULL)
                return;
 
-       tx_status(hw, skb, 0, 0, 0);
+       tx_status(hw, skb, 0, 0);
 }
 
 /**
@@ -310,12 +341,12 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
 void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hw *hw = info->driver_data[0];
+       struct ieee80211_hw *hw = info->rate_driver_data[0];
 
        skb_pull(skb, sizeof(struct zd_ctrlset));
        if (unlikely(error ||
            (info->flags & IEEE80211_TX_CTL_NO_ACK))) {
-               tx_status(hw, skb, 0, 0, !error);
+               tx_status(hw, skb, 0, !error);
        } else {
                struct sk_buff_head *q =
                        &zd_hw_mac(hw)->ack_wait_queue;
@@ -374,7 +405,8 @@ static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
 }
 
 static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
-                          struct ieee80211_hdr *header, u32 flags)
+                          struct ieee80211_hdr *header,
+                          struct ieee80211_tx_info *info)
 {
        /*
         * CONTROL TODO:
@@ -385,21 +417,21 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
        cs->control = 0;
 
        /* First fragment */
-       if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+       if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
                cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
 
-       /* Multicast */
-       if (is_multicast_ether_addr(header->addr1))
-               cs->control |= ZD_CS_MULTICAST;
+       /* No ACK expected (multicast, etc.) */
+       if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+               cs->control |= ZD_CS_NO_ACK;
 
        /* PS-POLL */
        if (ieee80211_is_pspoll(header->frame_control))
                cs->control |= ZD_CS_PS_POLL_FRAME;
 
-       if (flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
                cs->control |= ZD_CS_RTS;
 
-       if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
                cs->control |= ZD_CS_SELF_CTS;
 
        /* FIXME: Management frame? */
@@ -485,12 +517,12 @@ static int fill_ctrlset(struct zd_mac *mac,
        txrate = ieee80211_get_tx_rate(mac->hw, info);
 
        cs->modulation = txrate->hw_value;
-       if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
+       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
                cs->modulation = txrate->hw_value_short;
 
        cs->tx_length = cpu_to_le16(frag_len);
 
-       cs_set_control(mac, cs, hdr, info->flags);
+       cs_set_control(mac, cs, hdr, info);
 
        packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
        ZD_ASSERT(packet_length <= 0xffff);
@@ -543,13 +575,17 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
        r = fill_ctrlset(mac, skb);
        if (r)
-               return r;
+               goto fail;
 
-       info->driver_data[0] = hw;
+       info->rate_driver_data[0] = hw;
 
        r = zd_usb_tx(&mac->chip.usb, skb);
        if (r)
-               return r;
+               goto fail;
+       return 0;
+
+fail:
+       dev_kfree_skb(skb);
        return 0;
 }
 
@@ -579,14 +615,14 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
 
        q = &zd_hw_mac(hw)->ack_wait_queue;
        spin_lock_irqsave(&q->lock, flags);
-       for (skb = q->next; skb != (struct sk_buff *)q; skb = skb->next) {
+       skb_queue_walk(q, skb) {
                struct ieee80211_hdr *tx_hdr;
 
                tx_hdr = (struct ieee80211_hdr *)skb->data;
-               if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
+               if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN)))
                {
                        __skb_unlink(skb, q);
-                       tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1);
+                       tx_status(hw, skb, stats->signal, 1);
                        goto out;
                }
        }
@@ -662,7 +698,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
                        && !mac->pass_ctrl)
                return 0;
 
-       fc = *(__le16 *)buffer;
+       fc = get_unaligned((__le16*)buffer);
        need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
 
        skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
@@ -675,7 +711,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
 
        memcpy(skb_put(skb, length), buffer, length);
 
-       ieee80211_rx_irqsafe(hw, skb, &stats);
+       memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
+       ieee80211_rx_irqsafe(hw, skb);
        return 0;
 }
 
@@ -684,15 +721,15 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
 {
        struct zd_mac *mac = zd_hw_mac(hw);
 
-       /* using IEEE80211_IF_TYPE_INVALID to indicate no mode selected */
-       if (mac->type != IEEE80211_IF_TYPE_INVALID)
+       /* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */
+       if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
                return -EOPNOTSUPP;
 
        switch (conf->type) {
-       case IEEE80211_IF_TYPE_MNTR:
-       case IEEE80211_IF_TYPE_MESH_POINT:
-       case IEEE80211_IF_TYPE_STA:
-       case IEEE80211_IF_TYPE_IBSS:
+       case NL80211_IFTYPE_MONITOR:
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
                mac->type = conf->type;
                break;
        default:
@@ -706,63 +743,28 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
                                    struct ieee80211_if_init_conf *conf)
 {
        struct zd_mac *mac = zd_hw_mac(hw);
-       mac->type = IEEE80211_IF_TYPE_INVALID;
+       mac->type = NL80211_IFTYPE_UNSPECIFIED;
        zd_set_beacon_interval(&mac->chip, 0);
        zd_write_mac_addr(&mac->chip, NULL);
 }
 
-static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
 {
        struct zd_mac *mac = zd_hw_mac(hw);
-       return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
-}
+       struct ieee80211_conf *conf = &hw->conf;
 
-static int zd_op_config_interface(struct ieee80211_hw *hw,
-                                 struct ieee80211_vif *vif,
-                                  struct ieee80211_if_conf *conf)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       int associated;
-       int r;
-
-       if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
-           mac->type == IEEE80211_IF_TYPE_IBSS) {
-               associated = true;
-               if (conf->changed & IEEE80211_IFCC_BEACON) {
-                       struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-
-                       if (!beacon)
-                               return -ENOMEM;
-                       r = zd_mac_config_beacon(hw, beacon);
-                       if (r < 0)
-                               return r;
-                       r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
-                                       hw->conf.beacon_int);
-                       if (r < 0)
-                               return r;
-                       kfree_skb(beacon);
-               }
-       } else
-               associated = is_valid_ether_addr(conf->bssid);
-
-       spin_lock_irq(&mac->lock);
-       mac->associated = associated;
-       spin_unlock_irq(&mac->lock);
-
-       /* TODO: do hardware bssid filtering */
-       return 0;
+       return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
 }
 
-void zd_process_intr(struct work_struct *work)
+static void zd_process_intr(struct work_struct *work)
 {
        u16 int_status;
        struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
 
        int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4));
-       if (int_status & INT_CFG_NEXT_BCN) {
-               if (net_ratelimit())
-                       dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
-       } else
+       if (int_status & INT_CFG_NEXT_BCN)
+               dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
+       else
                dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
 
        zd_chip_enable_hwint(&mac->chip);
@@ -794,18 +796,40 @@ static void set_rx_filter_handler(struct work_struct *work)
                dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r);
 }
 
+static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw,
+                                  int mc_count, struct dev_addr_list *mclist)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct zd_mc_hash hash;
+       int i;
+
+       zd_mc_clear(&hash);
+
+       for (i = 0; i < mc_count; i++) {
+               if (!mclist)
+                       break;
+               dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr);
+               zd_mc_add_addr(&hash, mclist->dmi_addr);
+               mclist = mclist->next;
+       }
+
+       return hash.low | ((u64)hash.high << 32);
+}
+
 #define SUPPORTED_FIF_FLAGS \
        (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
        FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
 static void zd_op_configure_filter(struct ieee80211_hw *hw,
                        unsigned int changed_flags,
                        unsigned int *new_flags,
-                       int mc_count, struct dev_mc_list *mclist)
+                       u64 multicast)
 {
-       struct zd_mc_hash hash;
+       struct zd_mc_hash hash = {
+               .low = multicast,
+               .high = multicast >> 32,
+       };
        struct zd_mac *mac = zd_hw_mac(hw);
        unsigned long flags;
-       int i;
 
        /* Only deal with supported flags */
        changed_flags &= SUPPORTED_FIF_FLAGS;
@@ -817,27 +841,16 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
        if (!changed_flags)
                return;
 
-       if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) {
+       if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI))
                zd_mc_add_all(&hash);
-       } else {
-               DECLARE_MAC_BUF(macbuf);
-
-               zd_mc_clear(&hash);
-               for (i = 0; i < mc_count; i++) {
-                       if (!mclist)
-                               break;
-                       dev_dbg_f(zd_mac_dev(mac), "mc addr %s\n",
-                                 print_mac(macbuf, mclist->dmi_addr));
-                       zd_mc_add_addr(&hash, mclist->dmi_addr);
-                       mclist = mclist->next;
-               }
-       }
 
        spin_lock_irqsave(&mac->lock, flags);
        mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
        mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
        mac->multicast_hash = hash;
        spin_unlock_irqrestore(&mac->lock, flags);
+
+       /* XXX: these can be called here now, can sleep now! */
        queue_work(zd_workqueue, &mac->set_multicast_hash_work);
 
        if (changed_flags & FIF_CONTROL)
@@ -878,9 +891,42 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
 {
        struct zd_mac *mac = zd_hw_mac(hw);
        unsigned long flags;
+       int associated;
 
        dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
 
+       if (mac->type == NL80211_IFTYPE_MESH_POINT ||
+           mac->type == NL80211_IFTYPE_ADHOC) {
+               associated = true;
+               if (changes & BSS_CHANGED_BEACON) {
+                       struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+
+                       if (beacon) {
+                               zd_mac_config_beacon(hw, beacon);
+                               kfree_skb(beacon);
+                       }
+               }
+
+               if (changes & BSS_CHANGED_BEACON_ENABLED) {
+                       u32 interval;
+
+                       if (bss_conf->enable_beacon)
+                               interval = BCN_MODE_IBSS |
+                                               bss_conf->beacon_int;
+                       else
+                               interval = 0;
+
+                       zd_set_beacon_interval(&mac->chip, interval);
+               }
+       } else
+               associated = is_valid_ether_addr(bss_conf->bssid);
+
+       spin_lock_irq(&mac->lock);
+       mac->associated = associated;
+       spin_unlock_irq(&mac->lock);
+
+       /* TODO: do hardware bssid filtering */
+
        if (changes & BSS_CHANGED_ERP_PREAMBLE) {
                spin_lock_irqsave(&mac->lock, flags);
                mac->short_preamble = bss_conf->use_short_preamble;
@@ -894,6 +940,12 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
        }
 }
 
+static u64 zd_op_get_tsf(struct ieee80211_hw *hw)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       return zd_chip_get_tsf(&mac->chip);
+}
+
 static const struct ieee80211_ops zd_ops = {
        .tx                     = zd_op_tx,
        .start                  = zd_op_start,
@@ -901,9 +953,10 @@ static const struct ieee80211_ops zd_ops = {
        .add_interface          = zd_op_add_interface,
        .remove_interface       = zd_op_remove_interface,
        .config                 = zd_op_config,
-       .config_interface       = zd_op_config_interface,
+       .prepare_multicast      = zd_op_prepare_multicast,
        .configure_filter       = zd_op_configure_filter,
        .bss_info_changed       = zd_op_bss_info_changed,
+       .get_tsf                = zd_op_get_tsf,
 };
 
 struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
@@ -923,7 +976,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
        spin_lock_init(&mac->lock);
        mac->hw = hw;
 
-       mac->type = IEEE80211_IF_TYPE_INVALID;
+       mac->type = NL80211_IFTYPE_UNSPECIFIED;
 
        memcpy(mac->channels, zd_channels, sizeof(zd_channels));
        memcpy(mac->rates, zd_rates, sizeof(zd_rates));
@@ -935,7 +988,12 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
        hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
 
        hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-                   IEEE80211_HW_SIGNAL_DB;
+                   IEEE80211_HW_SIGNAL_UNSPEC;
+
+       hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_MESH_POINT) |
+               BIT(NL80211_IFTYPE_STATION) |
+               BIT(NL80211_IFTYPE_ADHOC);
 
        hw->max_signal = 100;
        hw->queues = 1;
@@ -969,7 +1027,7 @@ static void link_led_handler(struct work_struct *work)
        spin_unlock_irq(&mac->lock);
 
        r = zd_chip_control_leds(chip,
-                                is_associated ? LED_ASSOCIATED : LED_SCANNING);
+                                is_associated ? ZD_LED_ASSOCIATED : ZD_LED_SCANNING);
        if (r)
                dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
 
@@ -994,5 +1052,5 @@ static void housekeeping_disable(struct zd_mac *mac)
        dev_dbg_f(zd_mac_dev(mac), "\n");
        cancel_rearming_delayed_workqueue(zd_workqueue,
                &mac->housekeeping.link_led_work);
-       zd_chip_control_leds(&mac->chip, LED_OFF);
+       zd_chip_control_leds(&mac->chip, ZD_LED_OFF);
 }