rt2x00: USB don't need preallocated DMA
PATCH 12/28 rt2x00: USB don't need preallocated DMA
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 <[email protected]>
---
drivers/net/wireless/mac80211/rt2x00/rt2500usb.c +50 -89
@@ -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
drivers/net/wireless/mac80211/rt2x00/rt73usb.c +50 -80
256 lines not on this page · raw message