rt2x00: Fix access permissions on debugfs files
[safe/jmp/linux-2.6] / drivers / net / wireless / rt2x00 / rt2x00queue.c
index 49d3bb8..3b27f6a 100644 (file)
@@ -45,10 +45,11 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
        frame_size = entry->queue->data_size + entry->queue->desc_size;
 
        /*
-        * Reserve a few bytes extra headroom to allow drivers some moving
-        * space (e.g. for alignment), while keeping the skb aligned.
+        * The payload should be aligned to a 4-byte boundary,
+        * this means we need at least 3 bytes for moving the frame
+        * into the correct offset.
         */
-       reserved_size = 8;
+       reserved_size = 4;
 
        /*
         * Allocate skbuffer.
@@ -107,26 +108,19 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
 
 void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
 {
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-
-       if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) {
-               dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
-                                DMA_FROM_DEVICE);
-       }
-
-       if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
-               dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
-                                DMA_TO_DEVICE);
-       }
+       if (!skb)
+               return;
 
+       rt2x00queue_unmap_skb(rt2x00dev, skb);
        dev_kfree_skb_any(skb);
 }
 
-void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
-                                     struct txentry_desc *txdesc)
+static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
+                                            struct txentry_desc *txdesc)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
        struct ieee80211_rate *rate =
            ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
@@ -207,6 +201,31 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
        }
 
        /*
+        * Hardware should insert sequence counter.
+        * FIXME: We insert a software sequence counter first for
+        * hardware that doesn't support hardware sequence counting.
+        *
+        * This is wrong because beacons are not getting sequence
+        * numbers assigned properly.
+        *
+        * A secondary problem exists for drivers that cannot toggle
+        * sequence counting per-frame, since those will override the
+        * sequence counter given by mac80211.
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+               spin_lock(&intf->lock);
+
+               if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
+                       intf->seqno += 0x10;
+               hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+               hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
+
+               spin_unlock(&intf->lock);
+
+               __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
+       }
+
+       /*
         * PLCP setup
         * Length calculation depends on OFDM/CCK rate.
         */
@@ -247,10 +266,9 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
                        txdesc->signal |= 0x08;
        }
 }
-EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor);
 
-void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
-                                    struct txentry_desc *txdesc)
+static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
+                                           struct txentry_desc *txdesc)
 {
        struct data_queue *queue = entry->queue;
        struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
@@ -280,7 +298,6 @@ void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
            !test_bit(ENTRY_TXD_BURST, &txdesc->flags))
                rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid);
 }
-EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor);
 
 int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
 {
@@ -330,6 +347,60 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
        return 0;
 }
 
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+                             struct ieee80211_vif *vif)
+{
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+       struct skb_frame_desc *skbdesc;
+       struct txentry_desc txdesc;
+       __le32 desc[16];
+
+       if (unlikely(!intf->beacon))
+               return -ENOBUFS;
+
+       intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
+       if (!intf->beacon->skb)
+               return -ENOMEM;
+
+       /*
+        * Copy all TX descriptor information into txdesc,
+        * after that we are free to use the skb->cb array
+        * for our information.
+        */
+       rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
+
+       /*
+        * For the descriptor we use a local array from where the
+        * driver can move it to the correct location required for
+        * the hardware.
+        */
+       memset(desc, 0, sizeof(desc));
+
+       /*
+        * Fill in skb descriptor
+        */
+       skbdesc = get_skb_frame_desc(intf->beacon->skb);
+       memset(skbdesc, 0, sizeof(*skbdesc));
+       skbdesc->desc = desc;
+       skbdesc->desc_len = intf->beacon->queue->desc_size;
+       skbdesc->entry = intf->beacon;
+
+       /*
+        * Write TX descriptor into reserved room in front of the beacon.
+        */
+       rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
+
+       /*
+        * Send beacon to hardware.
+        * Also enable beacon generation, which might have been disabled
+        * by the driver during the config_beacon() callback function.
+        */
+       rt2x00dev->ops->lib->write_beacon(intf->beacon);
+       rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
+
+       return 0;
+}
+
 struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
                                         const enum data_queue_qid queue)
 {
@@ -421,9 +492,12 @@ void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev)
        if (!rt2x00dev->ops->lib->init_rxentry)
                return;
 
-       for (i = 0; i < queue->limit; i++)
+       for (i = 0; i < queue->limit; i++) {
+               queue->entries[i].flags = 0;
+
                rt2x00dev->ops->lib->init_rxentry(rt2x00dev,
                                                  &queue->entries[i]);
+       }
 }
 
 void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev)
@@ -437,9 +511,12 @@ void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev)
                if (!rt2x00dev->ops->lib->init_txentry)
                        continue;
 
-               for (i = 0; i < queue->limit; i++)
+               for (i = 0; i < queue->limit; i++) {
+                       queue->entries[i].flags = 0;
+
                        rt2x00dev->ops->lib->init_txentry(rt2x00dev,
                                                          &queue->entries[i]);
+               }
        }
 }
 
@@ -509,16 +586,11 @@ static int rt2x00queue_alloc_rxskbs(struct rt2x00_dev *rt2x00dev,
        for (i = 0; i < queue->limit; i++) {
                skb = rt2x00queue_alloc_rxskb(rt2x00dev, &queue->entries[i]);
                if (!skb)
-                       goto exit;
+                       return -ENOMEM;
                queue->entries[i].skb = skb;
        }
 
        return 0;
-
-exit:
-       rt2x00queue_free_skbs(rt2x00dev, queue);
-
-       return -ENOMEM;
 }
 
 int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)