diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 81 | 
1 files changed, 38 insertions, 43 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9915a09141e..5b6b789cad3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -177,55 +177,45 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length)  void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)  { -	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); -	unsigned int frame_length = skb->len; +	unsigned int payload_length = skb->len - header_length;  	unsigned int header_align = ALIGN_SIZE(skb, 0);  	unsigned int payload_align = ALIGN_SIZE(skb, header_length); -	unsigned int l2pad = 4 - (payload_align - header_align); +	unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0; -	if (header_align == payload_align) { -		/* -		 * Both header and payload must be moved the same -		 * amount of bytes to align them properly. This means -		 * we don't use the L2 padding but just move the entire -		 * frame. -		 */ -		rt2x00queue_align_frame(skb); -	} else if (!payload_align) { -		/* -		 * Simple L2 padding, only the header needs to be moved, -		 * the payload is already properly aligned. -		 */ -		skb_push(skb, header_align); -		memmove(skb->data, skb->data + header_align, frame_length); -		skbdesc->flags |= SKBDESC_L2_PADDED; -	} else { -		/* -		 * -		 * Complicated L2 padding, both header and payload need -		 * to be moved. By default we only move to the start -		 * of the buffer, so our header alignment needs to be -		 * increased if there is not enough room for the header -		 * to be moved. -		 */ -		if (payload_align > header_align) -			header_align += 4; +	/* +	 * Adjust the header alignment if the payload needs to be moved more +	 * than the header. +	 */ +	if (payload_align > header_align) +		header_align += 4; + +	/* There is nothing to do if no alignment is needed */ +	if (!header_align) +		return; + +	/* Reserve the amount of space needed in front of the frame */ +	skb_push(skb, header_align); + +	/* +	 * Move the header. +	 */ +	memmove(skb->data, skb->data + header_align, header_length); -		skb_push(skb, header_align); -		memmove(skb->data, skb->data + header_align, header_length); +	/* Move the payload, if present and if required */ +	if (payload_length && payload_align)  		memmove(skb->data + header_length + l2pad,  			skb->data + header_length + l2pad + payload_align, -			frame_length - header_length); -		skbdesc->flags |= SKBDESC_L2_PADDED; -	} +			payload_length); + +	/* Trim the skb to the correct size */ +	skb_trim(skb, header_length + l2pad + payload_length);  }  void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)  { -	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); -	unsigned int l2pad = 4 - (header_length & 3); +	unsigned int l2pad = L2PAD_SIZE(header_length); -	if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED)) +	if (!l2pad)  		return;  	memmove(skb->data + l2pad, skb->data, header_length); @@ -346,7 +336,9 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,  	 * Header and alignment information.  	 */  	txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); -	txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); +	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) && +	    (entry->skb->len > txdesc->header_length)) +		txdesc->l2pad = L2PAD_SIZE(txdesc->header_length);  	/*  	 * Check whether this frame is to be acked. @@ -387,10 +379,13 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,  	/*  	 * Beacons and probe responses require the tsf timestamp -	 * to be inserted into the frame. +	 * to be inserted into the frame, except for a frame that has been injected +	 * through a monitor interface. This latter is needed for testing a +	 * monitor interface.  	 */ -	if (ieee80211_is_beacon(hdr->frame_control) || -	    ieee80211_is_probe_resp(hdr->frame_control)) +	if ((ieee80211_is_beacon(hdr->frame_control) || +	    ieee80211_is_probe_resp(hdr->frame_control)) && +	    (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED)))  		__set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags);  	/* @@ -502,7 +497,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	/*  	 * When hardware encryption is supported, and this frame  	 * is to be encrypted, we should strip the IV/EIV data from -	 * the frame so we can provide it to the driver seperately. +	 * the frame so we can provide it to the driver separately.  	 */  	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&  	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {  |