rt2x00: Make USB work in interrupt context
PATCH 17/28 rt2x00: Make USB work in interrupt context
USB devices will no longer schedule their interrupt tasks to a later time. Instead the interrupt handlers will be called immediately when an interrupt is being raised.
For PCI devices this is only done for beacondone handling, (although the other interrupts are also under consideration...). Also the interrupt handlers should make use of rt2x00lib for the statistics updating.
Signed-off-by Ivo van Doorn <[email protected]>
---
drivers/net/wireless/mac80211/rt2x00/rt2400pci.c +30 -51
@@ -824,7 +824,7 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,* Initialization functions. */ static int rt2400pci_alloc_dma_ring (struct rt2x00_dev *rt2x00dev, -enum ring_index ring_type,void (*handler)(struct work_struct *), +enum ring_index ring_type,work_func_t handler,const u16 max_entries,const u16 data_size,const u16 desc_size) {struct data_ring *ring = &rt2x00dev->ring[ring_type];
@@ -908,8 +908,7 @@ static int rt2400pci_allocate_dma_rings(struct rt2x00_dev *rt2x00dev) rt2400pci_txdone, TX_ENTRIES, DATA_FRAME_SIZE, TXD_DESC_SIZE) || rt2400pci_alloc_dma_ring(rt2x00dev, RING_BEACON, - rt2400pci_beacondone, BEACON_ENTRIES, MGMT_FRAME_SIZE, - TXD_DESC_SIZE)) { + NULL, BEACON_ENTRIES, MGMT_FRAME_SIZE, TXD_DESC_SIZE)) {return -ENOMEM ; }
@@ -1624,11 +1623,9 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)/* * Interrupt functions. */ -static void rt2400pci_beacondone (struct work_struct *work) +static void rt2400pci_beacondone (struct rt2x00_dev *rt2x00dev) { -struct data_ring *ring = - container_of(work, struct data_ring, irq_work); -struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; +struct data_ring *ring = &rt2x00dev->ring[RING_BEACON ];struct data_entry *entry =rt2x00_get_data_entry (ring);struct sk_buff *skb;
@@ -1637,7 +1634,8 @@ static void rt2400pci_beacondone(struct work_struct *work)if (!skb)return ; -rt2400pci_beacon_update (rt2x00dev->hw, skb, &entry->tx_status.control); + rt2x00dev->hw_ops->beacon_update (rt2x00dev->hw, skb, + &entry->tx_status.control);dev_kfree_skb_any (skb); }
@@ -1652,11 +1650,13 @@ static void rt2400pci_rxdone(struct work_struct *work)struct data_desc *rxd;u32 word0;u32 word2; +int signal; +int rssi;u16 size;while (1 ) { entry =rt2x00_get_data_entry (ring); - rxd =rt2x00_desc_addr (entry); + rxd = entry->priv;rt2x00_desc_read (rxd,0 , &word0);rt2x00_desc_read (rxd,2 , &word2);
@@ -1669,29 +1669,25 @@ static void rt2400pci_rxdone(struct work_struct *work)* TODO: Don't we need to keep statistics * updated about events like CRC and physical errors? */ -if (!rt2x00_get_field32 (word0,RXD_W0_CRC ) && - !rt2x00_get_field32 (word0,RXD_W0_PHYSICAL_ERROR )) { - skb =dev_alloc_skb (size +NET_IP_ALIGN ); -if (!skb) -break ; +if (rt2x00_get_field32 (word0,RXD_W0_CRC ) || +rt2x00_get_field32 (word0,RXD_W0_PHYSICAL_ERROR )) + goto skip_entry; -skb_reserve (skb,NET_IP_ALIGN ); + skb =dev_alloc_skb (size +NET_IP_ALIGN ); +if (!skb) +break ; -memcpy (skb_put (skb, size),rt2x00_data_addr (entry), - size); +skb_reserve (skb,NET_IP_ALIGN ); - rt2x00dev->rx_status.rate =device_signal_to_rate ( - &rt2x00dev->hwmodes[0 ], -rt2x00_get_field32 (word2,RXD_W2_SIGNAL ), -0 ); +memcpy (skb_put (skb, size), entry->data_addr, size); - rt2x00dev->rx_status.ssi = -rt2x00_get_field32 (word2,RXD_W2_RSSI ); + signal =rt2x00_get_field32 (word2,RXD_W2_SIGNAL ); + rssi =rt2x00_get_field32 (word2,RXD_W2_RSSI ); +rt2x00lib_update_rx_stats (rt2x00dev, signal, rssi,0 ); -__ieee80211_rx (rt2x00dev->hw, - skb, &rt2x00dev->rx_status); - } +__ieee80211_rx (rt2x00dev->hw, skb, &rt2x00dev->rx_status); +skip_entry:rt2x00_set_field32 (&word0,RXD_W0_OWNER_NIC ,1 );rt2x00_desc_write (rxd,0 , word0);rt2x00_ring_index_inc (ring);
@@ -1712,46 +1708,29 @@ static void rt2400pci_txdone(struct work_struct *work)struct data_desc *txd;u32 word;int tx_status; +int retry;int ack; -int rts;while (!rt2x00_ring_empty (ring)) { entry =rt2x00_get_data_entry_done (ring); - txd =rt2x00_desc_addr (entry); + txd = entry->priv;rt2x00_desc_read (txd,0 , &word);if (rt2x00_get_field32 (word,TXD_W0_OWNER_NIC ) || !rt2x00_get_field32 (word,TXD_W0_VALID ))break ; - entry->tx_status.flags =0 ; - entry->tx_status.queue_length = ring->stats.limit; - entry->tx_status.queue_number = entry->tx_status.control.queue; - -/* -* The TXD_W0_RESULT field will only be set when -* we had requested an ACK. So we have received an -* ACK response when ACK was requested and status -* was succesfull. -*/ ack =rt2x00_get_field32 (word,TXD_W0_ACK ); - rts =GET_FLAG (entry,ENTRY_RTS_CTS_FRAME ); tx_status =rt2x00_get_field32 (word,TXD_W0_RESULT ); -rt2x00_update_tx_stats (rt2x00dev, &entry->tx_status, tx_status, - ack, rts); - -rt2x00_bbp_read (rt2x00dev,32 , - (u8 *)&entry->tx_status.ack_signal); - - entry->tx_status.retry_count =rt2x00_get_field32 ( - word,TXD_W0_RETRY_COUNT ); + retry =rt2x00_get_field32 (word,TXD_W0_RETRY_COUNT ); +rt2x00lib_update_tx_stats (entry, tx_status, ack, retry);/* * If this is not an RTS frame send the tx_status to mac80211, * that method also cleans up the skb structure. When this * is a RTS frame, that it is our job to clean this structure up. */ -if (!rts) +if (!GET_FLAG (entry,ENTRY_RTS_CTS_FRAME ))ieee80211_tx_status (rt2x00dev->hw, entry->skb, &entry->tx_status);else
@@ -1759,9 +1738,10 @@ static void rt2400pci_txdone(struct work_struct *work)rt2x00_set_field32 (&word,TXD_W0_VALID ,0 );rt2x00_desc_write (txd,0 , word); -CLEAR_FLAG (entry,ENTRY_RTS_CTS_FRAME ); entry->skb =NULL ; +CLEAR_FLAG (entry,ENTRY_RTS_CTS_FRAME ); +rt2x00_ring_index_done_inc (ring); }
@@ -1814,8 +1794,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)* 1 - Beacon timer expired interrupt. */ if (rt2x00_get_field32 (reg,CSR7_TBCN_EXPIRE )) -queue_work (rt2x00dev->workqueue, - &rt2x00dev->ring[RING_BEACON ].irq_work); +rt2400pci_beacondone (rt2x00dev);/* * 2 - Rx ring done interrupt.
drivers/net/wireless/mac80211/rt2x00/rt2400pci.h +0 -1
@@ -956,7 +956,6 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev);/* * Interrupt functions. */ -static void rt2400pci_beacondone (struct work_struct *work);static void rt2400pci_rxdone (struct work_struct *work);static void rt2400pci_txdone (struct work_struct *work);static irqreturn_t rt2400pci_interrupt (int irq,void *dev_instance);
drivers/net/wireless/mac80211/rt2x00/rt2500pci.c +44 -64
187 lines not on this page · raw message
drivers/net/wireless/mac80211/rt2x00/rt2500pci.h +0 -1
@@ -1223,7 +1223,6 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev);/* * Interrupt functions. */ -static void rt2500pci_beacondone (struct work_struct *work);static void rt2500pci_rxdone (struct work_struct *work);static void rt2500pci_txdone (struct work_struct *work);static irqreturn_t rt2500pci_interrupt (int irq,void *dev_instance);
drivers/net/wireless/mac80211/rt2x00/rt2500usb.c +112 -181
399 lines not on this page · raw message
drivers/net/wireless/mac80211/rt2x00/rt2500usb.h +3 -6
@@ -716,8 +716,6 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,*/ static void rt2500usb_enable_led (struct rt2x00_dev *rt2x00dev);static void rt2500usb_disable_led (struct rt2x00_dev *rt2x00dev); -static void rt2500usb_activity_led (struct rt2x00_dev *rt2x00dev, -char activity);/* * Radio control functions.
@@ -728,9 +726,8 @@ static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev);/* * Interrupt functions. */ -static void rt2500usb_beacondone (struct work_struct *work); -static void rt2500usb_rxdone (struct work_struct *work); -static void rt2500usb_txdone (struct work_struct *work); -static void rt2500usb_interrupt (struct urb *urb); +static void rt2500usb_interrupt_beacondone (struct urb *urb); +static void rt2500usb_interrupt_rxdone (struct urb *urb); +static void rt2500usb_interrupt_txdone (struct urb *urb);#endif /* RT2500USB_H */
drivers/net/wireless/mac80211/rt2x00/rt61pci.c +41 -39
153 lines not on this page · raw message
drivers/net/wireless/mac80211/rt2x00/rt61pci.h +0 -1
@@ -1385,7 +1385,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev);/* * Interrupt functions. */ -static void rt61pci_beacondone (struct work_struct *work);static void rt61pci_rxdone (struct work_struct *work);static void rt61pci_txdone (struct work_struct *work);static irqreturn_t rt61pci_interrupt (int irq,void *dev_instance);
drivers/net/wireless/mac80211/rt2x00/rt73usb.c +114 -161
375 lines not on this page · raw message
drivers/net/wireless/mac80211/rt2x00/rt73usb.h +3 -4
@@ -969,9 +969,8 @@ static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev);/* * Interrupt functions. */ -static void rt73usb_beacondone (struct work_struct *work); -static void rt73usb_rxdone (struct work_struct *work); -static void rt73usb_txdone (struct work_struct *work); -static void rt73usb_interrupt (struct urb *urb); +static void rt73usb_interrupt_beacondone (struct urb *urb); +static void rt73usb_interrupt_rxdone (struct urb *urb); +static void rt73usb_interrupt_txdone (struct urb *urb);#endif /* RT73USB_H */