aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00crypto.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2009-04-26 10:08:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-06 15:14:49 -0400
commit9f1661718c7fcf82e25c6aed20b729ee372d9d65 (patch)
tree099a3305c948f306f46e2cf2f0d24a8ef069f011 /drivers/net/wireless/rt2x00/rt2x00crypto.c
parent9eb4e21e289beba9cfe34f24920eee83c144e62f (diff)
rt2x00: Add support for L2 padding during TX/RX
Some hardware require L2 padding between header and payload because both must be aligned to a 4-byte boundary. This hardware also is easier during the RX path since we no longer need to move the entire payload but rather only the header to remove the padding (mac80211 only wants the payload to be 4-byte aligned). Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00crypto.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c68
1 files changed, 42 insertions, 26 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index ae31581372c0..57ab42cfed34 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -65,7 +65,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
65 __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags); 65 __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
66 66
67 txdesc->key_idx = hw_key->hw_key_idx; 67 txdesc->key_idx = hw_key->hw_key_idx;
68 txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb); 68 txdesc->iv_offset = txdesc->header_length;
69 txdesc->iv_len = hw_key->iv_len; 69 txdesc->iv_len = hw_key->iv_len;
70 70
71 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) 71 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
@@ -132,17 +132,16 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
132 skb_pull(skb, txdesc->iv_len); 132 skb_pull(skb, txdesc->iv_len);
133 133
134 /* IV/EIV data has officially be stripped */ 134 /* IV/EIV data has officially be stripped */
135 skbdesc->flags |= FRAME_DESC_IV_STRIPPED; 135 skbdesc->flags |= SKBDESC_IV_STRIPPED;
136} 136}
137 137
138void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) 138void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
139{ 139{
140 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 140 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
141 unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
142 const unsigned int iv_len = 141 const unsigned int iv_len =
143 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4); 142 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
144 143
145 if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED)) 144 if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
146 return; 145 return;
147 146
148 skb_push(skb, iv_len); 147 skb_push(skb, iv_len);
@@ -154,14 +153,15 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
154 memcpy(skb->data + header_length, skbdesc->iv, iv_len); 153 memcpy(skb->data + header_length, skbdesc->iv, iv_len);
155 154
156 /* IV/EIV data has returned into the frame */ 155 /* IV/EIV data has returned into the frame */
157 skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED; 156 skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
158} 157}
159 158
160void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, 159void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
161 unsigned int header_length, 160 unsigned int header_length,
162 struct rxdone_entry_desc *rxdesc) 161 struct rxdone_entry_desc *rxdesc)
163{ 162{
164 unsigned int payload_len = rxdesc->size - header_length; 163 unsigned int payload_len = rxdesc->size - header_length;
164 unsigned int align = ALIGN_SIZE(skb, header_length);
165 unsigned int iv_len; 165 unsigned int iv_len;
166 unsigned int icv_len; 166 unsigned int icv_len;
167 unsigned int transfer = 0; 167 unsigned int transfer = 0;
@@ -191,32 +191,48 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
191 } 191 }
192 192
193 /* 193 /*
194 * Make room for new data, note that we increase both 194 * Make room for new data. There are 2 possibilities
195 * headsize and tailsize when required. The tailsize is 195 * either the alignment is already present between
196 * only needed when ICV data needs to be inserted and 196 * the 802.11 header and payload. In that case we
197 * the padding is smaller than the ICV data. 197 * we have to move the header less then the iv_len
198 * When alignment requirements is greater than the 198 * since we can use the already available l2pad bytes
199 * ICV data we must trim the skb to the correct size 199 * for the iv data.
200 * because we need to remove the extra bytes. 200 * When the alignment must be added manually we must
201 * move the header more then iv_len since we must
202 * make room for the payload move as well.
201 */ 203 */
202 skb_push(skb, iv_len + align); 204 if (l2pad) {
203 if (align < icv_len) 205 skb_push(skb, iv_len - align);
204 skb_put(skb, icv_len - align); 206 skb_put(skb, icv_len);
205 else if (align > icv_len)
206 skb_trim(skb, rxdesc->size + iv_len + icv_len);
207 207
208 /* Move ieee80211 header */ 208 /* Move ieee80211 header */
209 memmove(skb->data + transfer, 209 memmove(skb->data + transfer,
210 skb->data + transfer + iv_len + align, 210 skb->data + transfer + (iv_len - align),
211 header_length); 211 header_length);
212 transfer += header_length; 212 transfer += header_length;
213 } else {
214 skb_push(skb, iv_len + align);
215 if (align < icv_len)
216 skb_put(skb, icv_len - align);
217 else if (align > icv_len)
218 skb_trim(skb, rxdesc->size + iv_len + icv_len);
219
220 /* Move ieee80211 header */
221 memmove(skb->data + transfer,
222 skb->data + transfer + iv_len + align,
223 header_length);
224 transfer += header_length;
225 }
213 226
214 /* Copy IV/EIV data */ 227 /* Copy IV/EIV data */
215 memcpy(skb->data + transfer, rxdesc->iv, iv_len); 228 memcpy(skb->data + transfer, rxdesc->iv, iv_len);
216 transfer += iv_len; 229 transfer += iv_len;
217 230
218 /* Move payload */ 231 /*
219 if (align) { 232 * Move payload for alignment purposes. Note that
233 * this is only needed when no l2 padding is present.
234 */
235 if (!l2pad) {
220 memmove(skb->data + transfer, 236 memmove(skb->data + transfer,
221 skb->data + transfer + align, 237 skb->data + transfer + align,
222 payload_len); 238 payload_len);