Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[pandora-kernel.git] / drivers / net / wireless / zd1211rw / zd_mac.c
index 418606a..feaf43d 100644 (file)
@@ -224,36 +224,6 @@ out:
        return r;
 }
 
-/**
- * clear_tx_skb_control_block - clears the control block of tx skbuffs
- * @skb: a &struct sk_buff pointer
- *
- * This clears the control block of skbuff buffers, which were transmitted to
- * the device. Notify that the function is not thread-safe, so prevent
- * multiple calls.
- */
-static void clear_tx_skb_control_block(struct sk_buff *skb)
-{
-       struct zd_tx_skb_control_block *cb =
-               (struct zd_tx_skb_control_block *)skb->cb;
-
-       kfree(cb->control);
-       cb->control = NULL;
-}
-
-/**
- * kfree_tx_skb - frees a tx skbuff
- * @skb: a &struct sk_buff pointer
- *
- * Frees the tx skbuff. Frees also the allocated control structure in the
- * control block if necessary.
- */
-static void kfree_tx_skb(struct sk_buff *skb)
-{
-       clear_tx_skb_control_block(skb);
-       dev_kfree_skb_any(skb);
-}
-
 static void zd_op_stop(struct ieee80211_hw *hw)
 {
        struct zd_mac *mac = zd_hw_mac(hw);
@@ -276,40 +246,15 @@ static void zd_op_stop(struct ieee80211_hw *hw)
 
 
        while ((skb = skb_dequeue(ack_wait_queue)))
-               kfree_tx_skb(skb);
-}
-
-/**
- * init_tx_skb_control_block - initializes skb control block
- * @skb: a &sk_buff pointer
- * @dev: pointer to the mac80221 device
- * @control: mac80211 tx control applying for the frame in @skb
- *
- * Initializes the control block of the skbuff to be transmitted.
- */
-static int init_tx_skb_control_block(struct sk_buff *skb,
-                                    struct ieee80211_hw *hw,
-                                    struct ieee80211_tx_control *control)
-{
-       struct zd_tx_skb_control_block *cb =
-               (struct zd_tx_skb_control_block *)skb->cb;
-
-       ZD_ASSERT(sizeof(*cb) <= sizeof(skb->cb));
-       memset(cb, 0, sizeof(*cb));
-       cb->hw= hw;
-       cb->control = kmalloc(sizeof(*control), GFP_ATOMIC);
-       if (cb->control == NULL)
-               return -ENOMEM;
-       memcpy(cb->control, control, sizeof(*control));
-
-       return 0;
+               dev_kfree_skb_any(skb);
 }
 
 /**
  * tx_status - reports tx status of a packet if required
  * @hw - a &struct ieee80211_hw pointer
  * @skb - a sk-buffer
- * @status - the tx status of the packet without control information
+ * @flags: extra flags to set in the TX status info
+ * @ackssi: ACK signal strength
  * @success - True for successfull transmission of the frame
  *
  * This information calls ieee80211_tx_status_irqsafe() if required by the
@@ -319,18 +264,17 @@ static int init_tx_skb_control_block(struct sk_buff *skb,
  * If no status information has been requested, the skb is freed.
  */
 static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
-                     struct ieee80211_tx_status *status,
-                     bool success)
+                     u32 flags, int ackssi, bool success)
 {
-       struct zd_tx_skb_control_block *cb = (struct zd_tx_skb_control_block *)
-               skb->cb;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+       memset(&info->status, 0, sizeof(info->status));
 
-       ZD_ASSERT(cb->control != NULL);
-       memcpy(&status->control, cb->control, sizeof(status->control));
        if (!success)
-               status->excessive_retries = 1;
-       clear_tx_skb_control_block(skb);
-       ieee80211_tx_status_irqsafe(hw, skb, status);
+               info->status.excessive_retries = 1;
+       info->flags |= flags;
+       info->status.ack_signal = ackssi;
+       ieee80211_tx_status_irqsafe(hw, skb);
 }
 
 /**
@@ -345,15 +289,12 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
 {
        struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue;
        struct sk_buff *skb;
-       struct ieee80211_tx_status status;
 
        skb = skb_dequeue(q);
        if (skb == NULL)
                return;
 
-       memset(&status, 0, sizeof(status));
-
-       tx_status(hw, skb, &status, 0);
+       tx_status(hw, skb, 0, 0, 0);
 }
 
 /**
@@ -368,28 +309,20 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
  */
 void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
 {
-       struct zd_tx_skb_control_block *cb =
-               (struct zd_tx_skb_control_block *)skb->cb;
-       struct ieee80211_hw *hw = cb->hw;
-
-       if (likely(cb->control)) {
-               skb_pull(skb, sizeof(struct zd_ctrlset));
-               if (unlikely(error ||
-                   (cb->control->flags & IEEE80211_TXCTL_NO_ACK)))
-               {
-                       struct ieee80211_tx_status status;
-                       memset(&status, 0, sizeof(status));
-                       tx_status(hw, skb, &status, !error);
-               } else {
-                       struct sk_buff_head *q =
-                               &zd_hw_mac(hw)->ack_wait_queue;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hw *hw = info->driver_data[0];
 
-                       skb_queue_tail(q, skb);
-                       while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
-                               zd_mac_tx_failed(hw);
-               }
+       skb_pull(skb, sizeof(struct zd_ctrlset));
+       if (unlikely(error ||
+           (info->flags & IEEE80211_TX_CTL_NO_ACK))) {
+               tx_status(hw, skb, 0, 0, !error);
        } else {
-               kfree_tx_skb(skb);
+               struct sk_buff_head *q =
+                       &zd_hw_mac(hw)->ack_wait_queue;
+
+               skb_queue_tail(q, skb);
+               while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
+                       zd_mac_tx_failed(hw);
        }
 }
 
@@ -443,8 +376,6 @@ 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)
 {
-       u16 fctl = le16_to_cpu(header->frame_control);
-
        /*
         * CONTROL TODO:
         * - if backoff needed, enable bit 0
@@ -454,7 +385,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
        cs->control = 0;
 
        /* First fragment */
-       if (flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
+       if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
                cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
 
        /* Multicast */
@@ -462,79 +393,104 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
                cs->control |= ZD_CS_MULTICAST;
 
        /* PS-POLL */
-       if ((fctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) ==
-           (IEEE80211_FTYPE_CTL|IEEE80211_STYPE_PSPOLL))
+       if (ieee80211_is_pspoll(header->frame_control))
                cs->control |= ZD_CS_PS_POLL_FRAME;
 
-       if (flags & IEEE80211_TXCTL_USE_RTS_CTS)
+       if (flags & IEEE80211_TX_CTL_USE_RTS_CTS)
                cs->control |= ZD_CS_RTS;
 
-       if (flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+       if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
                cs->control |= ZD_CS_SELF_CTS;
 
        /* FIXME: Management frame? */
 }
 
-void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
+static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
 {
        struct zd_mac *mac = zd_hw_mac(hw);
+       int r;
        u32 tmp, j = 0;
        /* 4 more bytes for tail CRC */
        u32 full_len = beacon->len + 4;
-       zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
-       zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+
+       r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
+       if (r < 0)
+               return r;
+       r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+       if (r < 0)
+               return r;
+
        while (tmp & 0x2) {
-               zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+               r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+               if (r < 0)
+                       return r;
                if ((++j % 100) == 0) {
                        printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
                        if (j >= 500)  {
                                printk(KERN_ERR "Giving up beacon config.\n");
-                               return;
+                               return -ETIMEDOUT;
                        }
                }
                msleep(1);
        }
 
-       zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
-       if (zd_chip_is_zd1211b(&mac->chip))
-               zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
+       r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
+       if (r < 0)
+               return r;
+       if (zd_chip_is_zd1211b(&mac->chip)) {
+               r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
+               if (r < 0)
+                       return r;
+       }
 
-       for (j = 0 ; j < beacon->len; j++)
-               zd_iowrite32(&mac->chip, CR_BCN_FIFO,
+       for (j = 0 ; j < beacon->len; j++) {
+               r = zd_iowrite32(&mac->chip, CR_BCN_FIFO,
                                *((u8 *)(beacon->data + j)));
+               if (r < 0)
+                       return r;
+       }
+
+       for (j = 0; j < 4; j++) {
+               r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
+               if (r < 0)
+                       return r;
+       }
 
-       for (j = 0; j < 4; j++)
-               zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
+       r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
+       if (r < 0)
+               return r;
 
-       zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
        /* 802.11b/g 2.4G CCK 1Mb
         * 802.11a, not yet implemented, uses different values (see GPL vendor
         * driver)
         */
-       zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
+       return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
                        (full_len << 19));
 }
 
 static int fill_ctrlset(struct zd_mac *mac,
-                       struct sk_buff *skb,
-                       struct ieee80211_tx_control *control)
+                       struct sk_buff *skb)
 {
        int r;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        unsigned int frag_len = skb->len + FCS_LEN;
        unsigned int packet_length;
+       struct ieee80211_rate *txrate;
        struct zd_ctrlset *cs = (struct zd_ctrlset *)
                skb_push(skb, sizeof(struct zd_ctrlset));
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
        ZD_ASSERT(frag_len <= 0xffff);
 
-       cs->modulation = control->tx_rate->hw_value;
-       if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
-               cs->modulation = control->tx_rate->hw_value_short;
+       txrate = ieee80211_get_tx_rate(mac->hw, info);
+
+       cs->modulation = txrate->hw_value;
+       if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
+               cs->modulation = txrate->hw_value_short;
 
        cs->tx_length = cpu_to_le16(frag_len);
 
-       cs_set_control(mac, cs, hdr, control->flags);
+       cs_set_control(mac, cs, hdr, info->flags);
 
        packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
        ZD_ASSERT(packet_length <= 0xffff);
@@ -579,24 +535,21 @@ static int fill_ctrlset(struct zd_mac *mac,
  * control block of the skbuff will be initialized. If necessary the incoming
  * mac80211 queues will be stopped.
  */
-static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-                    struct ieee80211_tx_control *control)
+static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct zd_mac *mac = zd_hw_mac(hw);
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        int r;
 
-       r = fill_ctrlset(mac, skb, control);
+       r = fill_ctrlset(mac, skb);
        if (r)
                return r;
 
-       r = init_tx_skb_control_block(skb, hw, control);
-       if (r)
-               return r;
+       info->driver_data[0] = hw;
+
        r = zd_usb_tx(&mac->chip.usb, skb);
-       if (r) {
-               clear_tx_skb_control_block(skb);
+       if (r)
                return r;
-       }
        return 0;
 }
 
@@ -617,13 +570,11 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
                      struct ieee80211_rx_status *stats)
 {
-       u16 fc = le16_to_cpu(rx_hdr->frame_control);
        struct sk_buff *skb;
        struct sk_buff_head *q;
        unsigned long flags;
 
-       if ((fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) !=
-           (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK))
+       if (!ieee80211_is_ack(rx_hdr->frame_control))
                return 0;
 
        q = &zd_hw_mac(hw)->ack_wait_queue;
@@ -634,13 +585,8 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
                tx_hdr = (struct ieee80211_hdr *)skb->data;
                if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
                {
-                       struct ieee80211_tx_status status;
-
-                       memset(&status, 0, sizeof(status));
-                       status.flags = IEEE80211_TX_STATUS_ACK;
-                       status.ack_signal = stats->ssi;
                        __skb_unlink(skb, q);
-                       tx_status(hw, skb, &status, 1);
+                       tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1);
                        goto out;
                }
        }
@@ -656,8 +602,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
        const struct rx_status *status;
        struct sk_buff *skb;
        int bad_frame = 0;
-       u16 fc;
-       bool is_qos, is_4addr, need_padding;
+       __le16 fc;
+       int need_padding;
        int i;
        u8 rate;
 
@@ -691,8 +637,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
 
        stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
        stats.band = IEEE80211_BAND_2GHZ;
-       stats.ssi = status->signal_strength;
-       stats.signal = zd_rx_qual_percent(buffer,
+       stats.signal = status->signal_strength;
+       stats.qual = zd_rx_qual_percent(buffer,
                                          length - sizeof(struct rx_status),
                                          status);
 
@@ -716,13 +662,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
                        && !mac->pass_ctrl)
                return 0;
 
-       fc = le16_to_cpu(*((__le16 *) buffer));
-
-       is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
-                (fc & IEEE80211_STYPE_QOS_DATA);
-       is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
-                  (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
-       need_padding = is_qos ^ is_4addr;
+       fc = *(__le16 *)buffer;
+       need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
 
        skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
        if (skb == NULL)
@@ -751,6 +692,7 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
        case IEEE80211_IF_TYPE_MNTR:
        case IEEE80211_IF_TYPE_MESH_POINT:
        case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS:
                mac->type = conf->type;
                break;
        default:
@@ -765,6 +707,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
 {
        struct zd_mac *mac = zd_hw_mac(hw);
        mac->type = IEEE80211_IF_TYPE_INVALID;
+       zd_set_beacon_interval(&mac->chip, 0);
        zd_write_mac_addr(&mac->chip, NULL);
 }
 
@@ -780,14 +723,20 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
 {
        struct zd_mac *mac = zd_hw_mac(hw);
        int associated;
+       int r;
 
-       if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) {
+       if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
+           mac->type == IEEE80211_IF_TYPE_IBSS) {
                associated = true;
                if (conf->beacon) {
-                       zd_mac_config_beacon(hw, conf->beacon);
-                       kfree_skb(conf->beacon);
-                       zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
+                       r = zd_mac_config_beacon(hw, conf->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(conf->beacon);
                }
        } else
                associated = is_valid_ether_addr(conf->bssid);
@@ -941,6 +890,17 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
        }
 }
 
+static int zd_op_beacon_update(struct ieee80211_hw *hw,
+                              struct sk_buff *skb)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       zd_mac_config_beacon(hw, skb);
+       kfree_skb(skb);
+       zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
+                                       hw->conf.beacon_int);
+       return 0;
+}
+
 static const struct ieee80211_ops zd_ops = {
        .tx                     = zd_op_tx,
        .start                  = zd_op_start,
@@ -951,6 +911,7 @@ static const struct ieee80211_ops zd_ops = {
        .config_interface       = zd_op_config_interface,
        .configure_filter       = zd_op_configure_filter,
        .bss_info_changed       = zd_op_bss_info_changed,
+       .beacon_update          = zd_op_beacon_update,
 };
 
 struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
@@ -982,10 +943,10 @@ 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_HOST_GEN_BEACON_TEMPLATE;
-       hw->max_rssi = 100;
-       hw->max_signal = 100;
+                   IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
+                   IEEE80211_HW_SIGNAL_DB;
 
+       hw->max_signal = 100;
        hw->queues = 1;
        hw->extra_tx_headroom = sizeof(struct zd_ctrlset);