@@ -247,10 +247,10 @@ void rt2x00lib_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb_orig);
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
- unsigned int header_length, i;
+ unsigned int i;
u8 rate_idx, rate_flags, retry_rates;
u8 skbdesc_flags = skbdesc->flags;
bool success;
@@ -261,36 +261,6 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00queue_unmap_skb(entry);
/*
- * Remove the extra tx headroom from the skb.
- */
- skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom);
-
- /*
- * Signal that the TX descriptor is no longer in the skb.
- */
- skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
-
- /*
- * Determine the length of 802.11 header.
- */
- header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
-
- /*
- * Remove L2 padding which was added during
- */
- if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
- rt2x00queue_remove_l2pad(entry->skb, header_length);
-
- /*
- * If the IV/EIV data was stripped from the frame before it was
- * passed to the hardware, we should now reinsert it again because
- * mac80211 will expect the same data to be present it the
- * frame as it was passed to us.
- */
- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
- rt2x00crypto_tx_insert_iv(entry->skb, header_length);
-
- /*
* Send frame to debugfs immediately, after this call is completed
* we are going to overwrite the skb->cb array.
*/
@@ -380,14 +350,17 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* send the status report back.
*/
if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
- ieee80211_tx_status(rt2x00dev->hw, entry->skb);
+ ieee80211_tx_status(rt2x00dev->hw, entry->skb_orig);
else
- dev_kfree_skb_any(entry->skb);
+ dev_kfree_skb_any(entry->skb_orig);
+
+ dev_kfree_skb_any(entry->skb);
/*
* Make this entry available for reuse.
*/
entry->skb = NULL;
+ entry->skb_orig = NULL;
entry->flags = 0;
rt2x00dev->ops->lib->clear_entry(entry);
@@ -497,7 +497,14 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
* after that we are free to use the skb->cb array
* for our information.
*/
- entry->skb = skb;
+ entry->skb_orig = skb;
+ entry->skb = skb_copy(entry->skb_orig, GFP_KERNEL);
+ if (!entry->skb) {
+ ERROR(queue->rt2x00dev,
+ "Failed to allocated copy of the frame.\n");
+ return -ENOMEM;
+ }
+
rt2x00queue_create_tx_descriptor(entry, &txdesc);
/*
@@ -550,7 +557,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
*/
if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- entry->skb = NULL;
+ dev_kfree_skb_any(entry->skb);
+ entry->skb_orig = NULL;
return -EIO;
}
@@ -355,6 +355,7 @@ enum queue_entry_flags {
* @queue: The data queue (&struct data_queue) to which this entry belongs.
* @skb: The buffer which is currently being transmitted (for TX queue),
* or used to directly recieve data in (for RX queue).
+ * @skb_orig: The buffer that we received from mac80211 (for TX; unused for RX).
* @entry_idx: The entry index number.
* @priv_data: Private data belonging to this queue entry. The pointer
* points to data specific to a particular driver and queue type.
@@ -366,6 +367,8 @@ struct queue_entry {
struct sk_buff *skb;
+ struct sk_buff *skb_orig;
+
unsigned int entry_idx;
void *priv_data;