Instead of using a preallocated DMA buffer for USB devices, it is sufficient to provide sk_buffs to it and let the USB layer handle the rest. This makes the USB transfers a bit simpler for us. Signed-off-by: Ivo van Doorn <IvDoorn@xxxxxxxxx> --- diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c b/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c index 1ea6696..c7ef5f8 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c @@ -256,32 +256,6 @@ static void rt2x00_eeprom_write(const struct rt2x00_dev *rt2x00dev, /* * TX/RX Descriptor access functions. */ -static inline struct urb* rt2x00_urb(struct data_entry *entry) -{ - return (struct urb*)entry->priv; -} - -static inline void* rt2x00_rxdata_addr(struct data_entry *entry) -{ - return entry->data_addr; -} - -static inline struct data_desc* rt2x00_rxdesc_addr(struct data_entry *entry) -{ - return entry->data_addr + - (rt2x00_urb(entry)->actual_length - entry->ring->desc_size); -} - -static inline void* rt2x00_txdata_addr(struct data_entry *entry) -{ - return entry->data_addr + entry->ring->desc_size; -} - -static inline struct data_desc* rt2x00_txdesc_addr(struct data_entry *entry) -{ - return entry->data_addr; -} - static inline void rt2x00_desc_read(struct data_desc *desc, const u8 word, u32 *value) { @@ -974,7 +948,6 @@ static int rt2500usb_alloc_dma_ring(struct rt2x00_dev *rt2x00dev, { struct data_ring *ring = &rt2x00dev->ring[ring_type]; unsigned int i; - int status; /* * Initialize work structure for deferred work. @@ -994,38 +967,29 @@ static int rt2500usb_alloc_dma_ring(struct rt2x00_dev *rt2x00dev, return -ENOMEM; /* - * Allocate DMA memory for descriptor and buffer. - */ - ring->data_addr = usb_buffer_alloc( - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)), - rt2x00_get_ring_size(ring), GFP_KERNEL, &ring->data_dma); - if (!ring->data_addr) { - kfree(ring->entry); - return -ENOMEM; - } - - /* * Initialize all ring entries to contain valid * addresses. */ - status = 0; for (i = 0; i < ring->stats.limit; i++) { ring->entry[i].flags = 0; ring->entry[i].ring = ring; - ring->entry[i].priv = - (!status) ? usb_alloc_urb(0, GFP_KERNEL) : NULL; + ring->entry[i].priv = usb_alloc_urb(0, GFP_KERNEL); if (!ring->entry[i].priv) - status = -ENOMEM; - ring->entry[i].skb = NULL; - ring->entry[i].data_addr = ring->data_addr - + (i * ring->desc_size) - + (i * ring->data_size); - ring->entry[i].data_dma = ring->data_dma - + (i * ring->desc_size) - + (i * ring->data_size); + return -ENOMEM; + + if (ring_type == RING_RX) { + ring->entry[i].skb = dev_alloc_skb(NET_IP_ALIGN + + ring->data_size + ring->desc_size); + if (!ring->entry[i].skb) + return -ENOMEM; + + skb_reserve(ring->entry[i].skb, NET_IP_ALIGN); + skb_put(ring->entry[i].skb, + ring->data_size + ring->desc_size); + } } - return status; + return 0; } static void rt2500usb_free_ring(struct rt2x00_dev *rt2x00dev, @@ -1035,23 +999,17 @@ static void rt2500usb_free_ring(struct rt2x00_dev *rt2x00dev, unsigned int i; if (!ring->entry) - goto exit; + return; for (i = 0; i < ring->stats.limit; i++) { - usb_kill_urb(rt2x00_urb(&ring->entry[i])); - usb_free_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); + usb_free_urb(ring->entry[i].priv); + if (ring_type == RING_RX) + kfree_skb(ring->entry[i].skb); } kfree(ring->entry); ring->entry = NULL; - -exit: - if (ring->data_addr) - usb_buffer_free( - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)), - rt2x00_get_ring_size(ring), ring->data_addr, - ring->data_dma); - ring->data_addr = NULL; } static int rt2500usb_allocate_dma_rings(struct rt2x00_dev *rt2x00dev) @@ -1092,22 +1050,17 @@ static void rt2500usb_init_rxring(struct rt2x00_dev *rt2x00dev, struct data_ring *ring = &rt2x00dev->ring[ring_type]; struct usb_device *usb_dev = interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); - struct urb *urb; unsigned int i; ring->type = ring_type; for (i = 0; i < ring->stats.limit; i++) { - urb = rt2x00_urb(&ring->entry[i]); - - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = ring->entry[i].data_dma; usb_fill_bulk_urb( - urb, + ring->entry[i].priv, usb_dev, usb_rcvbulkpipe(usb_dev, 1), - ring->entry[i].data_addr, - ring->data_size + ring->desc_size, + ring->entry[i].skb->data, + ring->entry[i].skb->len, rt2500usb_interrupt, &ring->entry[i]); } @@ -1119,18 +1072,12 @@ static void rt2500usb_init_txring(struct rt2x00_dev *rt2x00dev, enum ring_index ring_type) { struct data_ring *ring = &rt2x00dev->ring[ring_type]; - struct urb *urb; unsigned int i; ring->type = ring_type; - for (i = 0; i < ring->stats.limit; i++) { - urb = rt2x00_urb(&ring->entry[i]); - - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = ring->entry[i].data_dma; + for (i = 0; i < ring->stats.limit; i++) CLEAR_FLAGS(&ring->entry[i]); - } rt2x00_ring_index_clear(ring); } @@ -1434,7 +1381,7 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev) ring = &rt2x00dev->ring[RING_RX]; for (i = 0; i < ring->stats.limit; i++) { SET_FLAG(&ring->entry[i], ENTRY_OWNER_NIC); - usb_submit_urb(rt2x00_urb(&ring->entry[i]), GFP_ATOMIC); + usb_submit_urb(ring->entry[i].priv, GFP_ATOMIC); } /* @@ -1488,23 +1435,23 @@ static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev) ring = &rt2x00dev->ring[RING_RX]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_TX]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_ATIM]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_PRIO]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_BEACON]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); } /* @@ -1792,8 +1739,9 @@ static void rt2500usb_rxdone(struct work_struct *work) while (1) { entry = rt2x00_get_data_entry(ring); - rxd = rt2x00_rxdesc_addr(entry); - urb = rt2x00_urb(entry); + rxd = (struct data_desc*) + (entry->skb->data + urb->actual_length - ring->desc_size); + urb = entry->priv; rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); @@ -1827,9 +1775,10 @@ static void rt2500usb_rxdone(struct work_struct *work) break; skb_reserve(skb, NET_IP_ALIGN); + skb_put(skb, ring->data_size + ring->desc_size); - memcpy(skb_put(skb, size), - rt2x00_rxdata_addr(entry), size); + urb->transfer_buffer = skb->data; + urb->transfer_buffer_length = skb->len; rt2x00dev->rx_status.rate = device_signal_to_rate( &rt2x00dev->hwmodes[0], @@ -1841,8 +1790,18 @@ static void rt2500usb_rxdone(struct work_struct *work) rt2x00dev->rx_status.noise = rt2x00_get_link_noise(&rt2x00dev->link); + /* + * Received USB packets have 4 bytes of extra data, + * Trim the skb_buffer to only contain the valid + * frame data (so ignore the device's descriptor). + */ + size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + size -= FCS_LEN; + skb_trim(entry->skb, size); + __ieee80211_rx(rt2x00dev->hw, - skb, &rt2x00dev->rx_status); + entry->skb, &rt2x00dev->rx_status); + entry->skb = skb; /* * Update link statistics @@ -1878,8 +1837,8 @@ static void rt2500usb_txdone(struct work_struct *work) while (!rt2x00_ring_empty(ring)) { entry = rt2x00_get_data_entry_done(ring); - txd = rt2x00_txdesc_addr(entry); - urb = rt2x00_urb(entry); + txd = (struct data_desc *)entry->skb->data; + urb = entry->priv; rt2x00_desc_read(txd, 0, &word); if (GET_FLAG(entry, ENTRY_OWNER_NIC)) @@ -1903,6 +1862,8 @@ static void rt2500usb_txdone(struct work_struct *work) rt2x00_bbp_read(rt2x00dev, 0, (u8*)&entry->tx_status.ack_signal); + skb_pull(entry->skb, ring->desc_size); + /* * If this is not an RTS frame send the tx_status to mac80211, * that method also cleans up the skb structure. When this diff --git a/drivers/net/wireless/mac80211/rt2x00/rt73usb.c b/drivers/net/wireless/mac80211/rt2x00/rt73usb.c index 2285a64..98f6595 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt73usb.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt73usb.c @@ -252,21 +252,6 @@ static void rt2x00_eeprom_write(const struct rt2x00_dev *rt2x00dev, /* * TX/RX Descriptor access functions. */ -static inline struct urb* rt2x00_urb(struct data_entry *entry) -{ - return (struct urb*)entry->priv; -} - -static inline void* rt2x00_data_addr(struct data_entry *entry) -{ - return entry->data_addr + entry->ring->desc_size; -} - -static inline struct data_desc* rt2x00_desc_addr(struct data_entry *entry) -{ - return entry->data_addr; -} - static inline void rt2x00_desc_read(struct data_desc *desc, const u8 word, u32 *value) { @@ -1204,7 +1189,6 @@ static int rt73usb_alloc_dma_ring(struct rt2x00_dev *rt2x00dev, { struct data_ring *ring = &rt2x00dev->ring[ring_type]; unsigned int i; - int status; /* * Initialize work structure for deferred work. @@ -1224,38 +1208,29 @@ static int rt73usb_alloc_dma_ring(struct rt2x00_dev *rt2x00dev, return -ENOMEM; /* - * Allocate DMA memory for descriptor and buffer. - */ - ring->data_addr = usb_buffer_alloc( - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)), - rt2x00_get_ring_size(ring), GFP_KERNEL, &ring->data_dma); - if (!ring->data_addr) { - kfree(ring->entry); - return -ENOMEM; - } - - /* * Initialize all ring entries to contain valid * addresses. */ - status = 0; for (i = 0; i < ring->stats.limit; i++) { ring->entry[i].flags = 0; ring->entry[i].ring = ring; - ring->entry[i].priv = - (!status) ? usb_alloc_urb(0, GFP_KERNEL) : NULL; + ring->entry[i].priv = usb_alloc_urb(0, GFP_KERNEL); if (!ring->entry[i].priv) - status = -ENOMEM; - ring->entry[i].skb = NULL; - ring->entry[i].data_addr = ring->data_addr - + (i * ring->desc_size) - + (i * ring->data_size); - ring->entry[i].data_dma = ring->data_dma - + (i * ring->desc_size) - + (i * ring->data_size); + return -ENOMEM; + + if (ring_type == RING_RX) { + ring->entry[i].skb = dev_alloc_skb(NET_IP_ALIGN + + ring->data_size + ring->desc_size); + if (!ring->entry[i].skb) + return -ENOMEM; + + skb_reserve(ring->entry[i].skb, NET_IP_ALIGN); + skb_put(ring->entry[i].skb, + ring->data_size + ring->desc_size); + } } - return status; + return 0; } static void rt73usb_free_ring(struct rt2x00_dev *rt2x00dev, @@ -1265,23 +1240,17 @@ static void rt73usb_free_ring(struct rt2x00_dev *rt2x00dev, unsigned int i; if (!ring->entry) - goto exit; + return; for (i = 0; i < ring->stats.limit; i++) { - usb_kill_urb(rt2x00_urb(&ring->entry[i])); - usb_free_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); + usb_free_urb(ring->entry[i].priv); + if (ring_type == RING_RX) + kfree_skb(ring->entry[i].skb); } kfree(ring->entry); ring->entry = NULL; - -exit: - if (ring->data_addr) - usb_buffer_free( - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)), - rt2x00_get_ring_size(ring), ring->data_addr, - ring->data_dma); - ring->data_addr = NULL; } static int rt73usb_allocate_dma_rings(struct rt2x00_dev *rt2x00dev) @@ -1330,22 +1299,17 @@ static void rt73usb_init_rxring(struct rt2x00_dev *rt2x00dev, struct data_ring *ring = &rt2x00dev->ring[ring_type]; struct usb_device *usb_dev = interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); - struct urb *urb; unsigned int i; ring->type = ring_type; for (i = 0; i < ring->stats.limit; i++) { - urb = rt2x00_urb(&ring->entry[i]); - - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = ring->entry[i].data_dma; usb_fill_bulk_urb( - urb, + ring->entry[i].priv, usb_dev, usb_rcvbulkpipe(usb_dev, 1), - ring->entry[i].data_addr, - ring->data_size + ring->desc_size, + ring->entry[i].skb->data, + ring->entry[i].skb->len, rt73usb_interrupt, &ring->entry[i]); } @@ -1357,18 +1321,12 @@ static void rt73usb_init_txring(struct rt2x00_dev *rt2x00dev, enum ring_index ring_type) { struct data_ring *ring = &rt2x00dev->ring[ring_type]; - struct urb *urb; unsigned int i; ring->type = ring_type; - for (i = 0; i < ring->stats.limit; i++) { - urb = rt2x00_urb(&ring->entry[i]); - - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = ring->entry[i].data_dma; + for (i = 0; i < ring->stats.limit; i++) CLEAR_FLAGS(&ring->entry[i]); - } rt2x00_ring_index_clear(ring); } @@ -1688,7 +1646,7 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) ring = &rt2x00dev->ring[RING_RX]; for (i = 0; i < ring->stats.limit; i++) { SET_FLAG(&ring->entry[i], ENTRY_OWNER_NIC); - usb_submit_urb(rt2x00_urb(&ring->entry[i]), GFP_ATOMIC); + usb_submit_urb(ring->entry[i].priv, GFP_ATOMIC); } /* @@ -1741,31 +1699,31 @@ static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev) ring = &rt2x00dev->ring[RING_RX]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_AC_VO]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_AC_VI]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_AC_BE]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_AC_BK]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_PRIO]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); ring = &rt2x00dev->ring[RING_BEACON]; for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(rt2x00_urb(&ring->entry[i])); + usb_kill_urb(ring->entry[i].priv); } /* @@ -2064,8 +2022,8 @@ static void rt73usb_rxdone(struct work_struct *work) while (1) { entry = rt2x00_get_data_entry(ring); - rxd = rt2x00_desc_addr(entry); - urb = rt2x00_urb(entry); + rxd = (struct data_desc*)entry->skb->data; + urb = entry->priv; rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); @@ -2095,9 +2053,10 @@ static void rt73usb_rxdone(struct work_struct *work) break; skb_reserve(skb, NET_IP_ALIGN); + skb_put(skb, ring->data_size + ring->desc_size); - memcpy(skb_put(skb, size), - rt2x00_data_addr(entry), size); + urb->transfer_buffer = skb->data; + urb->transfer_buffer_length = skb->len; rt2x00dev->rx_status.rate = device_signal_to_rate( &rt2x00dev->hwmodes[0], @@ -2109,8 +2068,17 @@ static void rt73usb_rxdone(struct work_struct *work) rt2x00dev->rx_status.noise = rt2x00_get_link_noise(&rt2x00dev->link); + /* + * Trim the skb_buffer to only contain the valid + * frame data (so ignore the device's descriptor). + */ + size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + skb_pull(entry->skb, ring->desc_size); + skb_trim(entry->skb, size); + __ieee80211_rx(rt2x00dev->hw, - skb, &rt2x00dev->rx_status); + entry->skb, &rt2x00dev->rx_status); + entry->skb = skb; /* * Update link statistics @@ -2141,8 +2109,8 @@ static void rt73usb_txdone(struct work_struct *work) while (!rt2x00_ring_empty(ring)) { entry = rt2x00_get_data_entry_done(ring); - txd = rt2x00_desc_addr(entry); - urb = rt2x00_urb(entry); + txd = (struct data_desc *)entry->skb->data; + urb = entry->priv; rt2x00_desc_read(txd, 0, &word); if (GET_FLAG(entry, ENTRY_OWNER_NIC)) @@ -2166,6 +2134,8 @@ static void rt73usb_txdone(struct work_struct *work) rt2x00_bbp_read(rt2x00dev, 32, (u8*)&entry->tx_status.ack_signal); + skb_pull(entry->skb, ring->desc_size); + /* * If this is not an RTS frame send the tx_status to mac80211, * that method also cleans up the skb structure. When this - To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html