Search Linux Wireless

[PATCH] rt2x00: Fix TX failure path

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The callback function write_tx_data() can only fail
when our ENTRY_OWNER_DEVICE_DATA flag on a queue entry
failed to determine the entry was not available and
it is in fact still owned by the hardware.
This means that if that function fails the queue
must be stopped in mac80211.

When rt2x00queue_get_queue() returns NULL in the TX
path, it means mac80211 has passed us an invalid queue,
although this should be impossible, it shouldn't hurt
if we send mac80211 a signal to stop the queue either.

Both issues can simply be resolved by removing their
manual failure handler and making them use the failure path
provided in rt2x00mac_tx().

Signed-off-by: Ivo van Doorn <IvDoorn@xxxxxxxxx>
---
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 48636b0..4c03957 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -132,8 +132,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		ERROR(rt2x00dev,
 		      "Attempt to send packet over invalid queue %d.\n"
 		      "Please file bug report to %s.\n", qid, DRV_PROJECT);
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
+		goto exit_fail;
 	}
 
 	/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index d7752db..b8de9d2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -386,7 +386,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
 	u8 rate_idx, rate_flags;
 
 	if (unlikely(rt2x00queue_full(queue)))
-		return -EINVAL;
+		return -ENOBUFS;
 
 	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
 		ERROR(queue->rt2x00dev,
@@ -415,7 +415,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
 	tx_info = IEEE80211_SKB_CB(skb);
 	rate_idx = tx_info->control.rates[0].idx;
 	rate_flags = tx_info->control.rates[0].flags;
-	skbdesc = get_skb_frame_desc(entry->skb);
+	skbdesc = get_skb_frame_desc(skb);
 	memset(skbdesc, 0, sizeof(*skbdesc));
 	skbdesc->entry = entry;
 	skbdesc->tx_rate_idx = rate_idx;
@@ -427,20 +427,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
 	 * the frame so we can provide it to the driver seperately.
 	 */
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
-	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
+	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags))
 		rt2x00crypto_tx_remove_iv(skb, iv_len);
-	}
 
 	/*
 	 * It could be possible that the queue was corrupted and this
-	 * call failed. Just drop the frame, we cannot rollback and pass
-	 * the frame to mac80211 because the skb->cb has now been tainted.
+	 * call failed. Since we always return NETDEV_TX_OK to mac80211,
+	 * this frame will simply be dropped.
 	 */
 	if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) {
 		clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-		dev_kfree_skb_any(entry->skb);
 		entry->skb = NULL;
-		return 0;
+		return -EIO;
 	}
 
 	if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
--
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

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux