Skip to contentSkip to conversation

rt2x00: Make USB work in interrupt context

PATCH In review Ivo van Doorn 1 participant 1 message Feb 28, 2007 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

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.

---

drivers/net/wireless/mac80211/rt2x00/rt2400pci.c +30 -51
index 18e615c..c50cd80 100644
@@ -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
index 489877c..49b9a51 100644
@@ -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
index faa1953..84f0cfd 100644
@@ -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
index 316bf3a..a94b03e 100644
@@ -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
index a030e90..a8a1df4 100644
@@ -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
index dd32800..2a976c0 100644
@@ -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 */