Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / wireless / rt2x00 / rt2x00mac.c
index 87e280a..b02dbc8 100644 (file)
 
 static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
                                struct data_queue *queue,
-                               struct sk_buff *frag_skb,
-                               struct ieee80211_tx_control *control)
+                               struct sk_buff *frag_skb)
 {
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb);
        struct skb_frame_desc *skbdesc;
+       struct ieee80211_tx_info *rts_info;
        struct sk_buff *skb;
        int size;
 
-       if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+       if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
                size = sizeof(struct ieee80211_cts);
        else
                size = sizeof(struct ieee80211_rts);
@@ -52,13 +53,33 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
        skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom);
        skb_put(skb, size);
 
-       if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
-               ieee80211_ctstoself_get(rt2x00dev->hw, control->vif,
-                                       frag_skb->data, frag_skb->len, control,
+       /*
+        * Copy TX information over from original frame to
+        * RTS/CTS frame. Note that we set the no encryption flag
+        * since we don't want this frame to be encrypted.
+        * RTS frames should be acked, while CTS-to-self frames
+        * should not. The ready for TX flag is cleared to prevent
+        * it being automatically send when the descriptor is
+        * written to the hardware.
+        */
+       memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
+       rts_info = IEEE80211_SKB_CB(skb);
+       rts_info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
+       rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
+       rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
+
+       if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+               rts_info->flags |= IEEE80211_TX_CTL_NO_ACK;
+       else
+               rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
+
+       if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+               ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
+                                       frag_skb->data, size, tx_info,
                                        (struct ieee80211_cts *)(skb->data));
        else
-               ieee80211_rts_get(rt2x00dev->hw, control->vif,
-                                 frag_skb->data, frag_skb->len, control,
+               ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif,
+                                 frag_skb->data, size, tx_info,
                                  (struct ieee80211_rts *)(skb->data));
 
        /*
@@ -68,7 +89,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
        memset(skbdesc, 0, sizeof(*skbdesc));
        skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
 
-       if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
+       if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) {
                WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
                return NETDEV_TX_BUSY;
        }
@@ -76,13 +97,13 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
        return NETDEV_TX_OK;
 }
 
-int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-                struct ieee80211_tx_control *control)
+int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
+       enum data_queue_qid qid = skb_get_queue_mapping(skb);
        struct data_queue *queue;
-       struct skb_frame_desc *skbdesc;
        u16 frame_control;
 
        /*
@@ -100,16 +121,15 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
        /*
         * Determine which queue to put packet on.
         */
-       if (control->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM &&
+       if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
            test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
-               queue = rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
+               queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM);
        else
-               queue = rt2x00queue_get_queue(rt2x00dev, control->queue);
+               queue = rt2x00queue_get_queue(rt2x00dev, qid);
        if (unlikely(!queue)) {
                ERROR(rt2x00dev,
                      "Attempt to send packet over invalid queue %d.\n"
-                     "Please file bug report to %s.\n",
-                     control->queue, DRV_PROJECT);
+                     "Please file bug report to %s.\n", qid, DRV_PROJECT);
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
@@ -119,38 +139,37 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
         * create and queue that frame first. But make sure we have
         * at least enough entries available to send this CTS/RTS
         * frame as well as the data frame.
+        * Note that when the driver has set the set_rts_threshold()
+        * callback function it doesn't need software generation of
+        * neither RTS or CTS-to-self frames and handles everything
+        * inside the hardware.
         */
        frame_control = le16_to_cpu(ieee80211hdr->frame_control);
        if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
-           (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
-                              IEEE80211_TXCTL_USE_CTS_PROTECT))) {
+           (tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS |
+                              IEEE80211_TX_CTL_USE_CTS_PROTECT)) &&
+           !rt2x00dev->ops->hw->set_rts_threshold) {
                if (rt2x00queue_available(queue) <= 1) {
-                       ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+                       ieee80211_stop_queue(rt2x00dev->hw, qid);
                        return NETDEV_TX_BUSY;
                }
 
-               if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb, control)) {
-                       ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+               if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) {
+                       ieee80211_stop_queue(rt2x00dev->hw, qid);
                        return NETDEV_TX_BUSY;
                }
        }
 
-       /*
-        * Initialize skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-
-       if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
-               ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+       if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) {
+               ieee80211_stop_queue(rt2x00dev->hw, qid);
                return NETDEV_TX_BUSY;
        }
 
        if (rt2x00queue_full(queue))
-               ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+               ieee80211_stop_queue(rt2x00dev->hw, qid);
 
        if (rt2x00dev->ops->lib->kick_tx_queue)
-               rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
+               rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, qid);
 
        return NETDEV_TX_OK;
 }
@@ -183,8 +202,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        struct rt2x00_intf *intf = vif_to_intf(conf->vif);
-       struct data_queue *queue =
-           rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
+       struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
        struct queue_entry *entry = NULL;
        unsigned int i;
 
@@ -197,13 +215,12 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
                return -ENODEV;
 
        /*
-        * When we don't support mixed interfaces (a combination
-        * of sta and ap virtual interfaces) then we can only
-        * add this interface when the rival interface count is 0.
+        * We don't support mixed combinations of sta and ap virtual
+        * interfaces. We can only add this interface when the rival
+        * interface count is 0.
         */
-       if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) &&
-           ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
-            (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count)))
+       if ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
+           (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count))
                return -ENOBUFS;
 
        /*
@@ -378,9 +395,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
        if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon)
                return 0;
 
-       status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
-                                                  conf->beacon,
-                                                  conf->beacon_control);
+       status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon);
        if (status)
                dev_kfree_skb(conf->beacon);
 
@@ -454,10 +469,10 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
        struct rt2x00_dev *rt2x00dev = hw->priv;
        unsigned int i;
 
-       for (i = 0; i < hw->queues; i++) {
-               stats->data[i].len = rt2x00dev->tx[i].length;
-               stats->data[i].limit = rt2x00dev->tx[i].limit;
-               stats->data[i].count = rt2x00dev->tx[i].count;
+       for (i = 0; i < rt2x00dev->ops->tx_queues; i++) {
+               stats[i].len = rt2x00dev->tx[i].length;
+               stats[i].limit = rt2x00dev->tx[i].limit;
+               stats[i].count = rt2x00dev->tx[i].count;
        }
 
        return 0;
@@ -515,7 +530,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
 
-int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue_idx,
+int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
                      const struct ieee80211_tx_queue_params *params)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;