diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00pci.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00pci.c | 104 |
1 files changed, 76 insertions, 28 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 04663eb3195..804a9980055 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -23,11 +23,6 @@ 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,37 +97,42 @@ 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; @@ -138,7 +144,7 @@ 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; @@ -163,6 +169,17 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) 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. */ rt2x00lib_rxdone(entry, skb, &desc); @@ -177,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. */ |