]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/rt2x00/rt2x00pci.c
Merge git://git.infradead.org/~dedekind/ubi-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / rt2x00 / rt2x00pci.c
index 2780df00623c4f9392e40087868326fbd8bb7522..804a9980055d6a73c105575a879976b9ad7645f3 100644 (file)
        Abstract: rt2x00 generic pci device routines.
  */
 
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00pci"
-
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -43,9 +38,9 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
                            struct ieee80211_tx_control *control)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct data_ring *ring =
-           rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-       struct data_entry *entry = rt2x00_get_data_entry(ring);
+       struct skb_desc *desc;
+       struct data_ring *ring;
+       struct data_entry *entry;
 
        /*
         * Just in case mac80211 doesn't set this correctly,
@@ -53,14 +48,22 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
         * initialization.
         */
        control->queue = IEEE80211_TX_QUEUE_BEACON;
+       ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+       entry = rt2x00_get_data_entry(ring);
 
        /*
-        * Update the beacon entry.
+        * Fill in skb descriptor
         */
+       desc = get_skb_desc(skb);
+       desc->desc_len = ring->desc_size;
+       desc->data_len = skb->len;
+       desc->desc = entry->priv;
+       desc->data = skb->data;
+       desc->ring = ring;
+       desc->entry = entry;
+
        memcpy(entry->data_addr, skb->data, skb->len);
-       rt2x00lib_write_tx_desc(rt2x00dev, entry->priv,
-                               (struct ieee80211_hdr *)skb->data,
-                               skb->len, control);
+       rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
 
        /*
         * Enable beacon generation.
@@ -78,15 +81,13 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
                            struct data_ring *ring, struct sk_buff *skb,
                            struct ieee80211_tx_control *control)
 {
-       struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
        struct data_entry *entry = rt2x00_get_data_entry(ring);
-       struct data_desc *txd = entry->priv;
+       __le32 *txd = entry->priv;
+       struct skb_desc *desc;
        u32 word;
 
-       if (rt2x00_ring_full(ring)) {
-               ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+       if (rt2x00_ring_full(ring))
                return -EINVAL;
-       }
 
        rt2x00_desc_read(txd, 0, &word);
 
@@ -96,35 +97,43 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
                      "Arrived at non-free entry in the non-full queue %d.\n"
                      "Please file bug report to %s.\n",
                      control->queue, DRV_PROJECT);
-               ieee80211_stop_queue(rt2x00dev->hw, control->queue);
                return -EINVAL;
        }
 
-       entry->skb = skb;
-       memcpy(&entry->tx_status.control, control, sizeof(*control));
+       /*
+        * Fill in skb descriptor
+        */
+       desc = get_skb_desc(skb);
+       desc->desc_len = ring->desc_size;
+       desc->data_len = skb->len;
+       desc->desc = entry->priv;
+       desc->data = skb->data;
+       desc->ring = ring;
+       desc->entry = entry;
+
        memcpy(entry->data_addr, skb->data, skb->len);
-       rt2x00lib_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
-                               skb->len, control);
+       rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
 
        rt2x00_ring_index_inc(ring);
 
-       if (rt2x00_ring_full(ring))
-               ieee80211_stop_queue(rt2x00dev->hw, control->queue);
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
 
 /*
- * RX data handlers.
+ * TX/RX data handlers.
  */
 void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
 {
        struct data_ring *ring = rt2x00dev->rx;
        struct data_entry *entry;
-       struct data_desc *rxd;
        struct sk_buff *skb;
+       struct ieee80211_hdr *hdr;
+       struct skb_desc *skbdesc;
        struct rxdata_entry_desc desc;
+       int header_size;
+       __le32 *rxd;
+       int align;
        u32 word;
 
        while (1) {
@@ -135,20 +144,40 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
                if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
                        break;
 
-               memset(&desc, 0x00, sizeof(desc));
+               memset(&desc, 0, sizeof(desc));
                rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
 
+               hdr = (struct ieee80211_hdr *)entry->data_addr;
+               header_size =
+                   ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+
+               /*
+                * The data behind the ieee80211 header must be
+                * aligned on a 4 byte boundary.
+                */
+               align = header_size % 4;
+
                /*
                 * Allocate the sk_buffer, initialize it and copy
                 * all data into it.
                 */
-               skb = dev_alloc_skb(desc.size + NET_IP_ALIGN);
+               skb = dev_alloc_skb(desc.size + align);
                if (!skb)
                        return;
 
-               skb_reserve(skb, NET_IP_ALIGN);
-               skb_put(skb, desc.size);
-               memcpy(skb->data, entry->data_addr, desc.size);
+               skb_reserve(skb, align);
+               memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
+
+               /*
+                * Fill in skb descriptor
+                */
+               skbdesc = get_skb_desc(skb);
+               skbdesc->desc_len = entry->ring->desc_size;
+               skbdesc->data_len = skb->len;
+               skbdesc->desc = entry->priv;
+               skbdesc->data = skb->data;
+               skbdesc->ring = ring;
+               skbdesc->entry = entry;
 
                /*
                 * Send the frame to rt2x00lib for further processing.
@@ -165,6 +194,37 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
 
+void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
+                     const int tx_status, const int retry)
+{
+       u32 word;
+
+       rt2x00lib_txdone(entry, tx_status, retry);
+
+       /*
+        * Make this entry available for reuse.
+        */
+       entry->flags = 0;
+
+       rt2x00_desc_read(entry->priv, 0, &word);
+       rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0);
+       rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0);
+       rt2x00_desc_write(entry->priv, 0, word);
+
+       rt2x00_ring_index_done_inc(entry->ring);
+
+       /*
+        * If the data ring was full before the txdone handler
+        * we must make sure the packet queue in the mac80211 stack
+        * is reenabled when the txdone handler has finished.
+        */
+       if (!rt2x00_ring_full(entry->ring))
+               ieee80211_wake_queue(rt2x00dev->hw,
+                                    entry->tx_status.control.queue);
+
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
+
 /*
  * Device initialization handlers.
  */