aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2010-03-29 05:35:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-03-31 14:39:34 -0400
commite3cf8b3f7b9eefbe1d39b160726d6e5c2cbb4c5d (patch)
treec59a6fcb8d0bcd88d848785a3dbe3978d1568274 /net/wireless
parente58b1253f1e850b4469964d7b92cf230196223c0 (diff)
mac80211: support paged rx SKBs
Mac80211 drivers can now pass paged SKBs to mac80211 via ieee80211_rx{_irqsafe}. The implementation currently use skb_linearize() in a few places i.e. management frame handling, software decryption, defragmentation and A-MSDU process. We will optimize them one by one later. Signed-off-by: Zhu Yi <yi.zhu@intel.com> Cc: Kalle Valo <kalle.valo@iki.fi> Cc: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/util.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index be2ab8c59e3a..7acb81b9675d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -330,11 +330,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
330 if (iftype == NL80211_IFTYPE_MESH_POINT) { 330 if (iftype == NL80211_IFTYPE_MESH_POINT) {
331 struct ieee80211s_hdr *meshdr = 331 struct ieee80211s_hdr *meshdr =
332 (struct ieee80211s_hdr *) (skb->data + hdrlen); 332 (struct ieee80211s_hdr *) (skb->data + hdrlen);
333 hdrlen += ieee80211_get_mesh_hdrlen(meshdr); 333 /* make sure meshdr->flags is on the linear part */
334 if (!pskb_may_pull(skb, hdrlen + 1))
335 return -1;
334 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { 336 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
335 memcpy(dst, meshdr->eaddr1, ETH_ALEN); 337 skb_copy_bits(skb, hdrlen +
336 memcpy(src, meshdr->eaddr2, ETH_ALEN); 338 offsetof(struct ieee80211s_hdr, eaddr1),
339 dst, ETH_ALEN);
340 skb_copy_bits(skb, hdrlen +
341 offsetof(struct ieee80211s_hdr, eaddr2),
342 src, ETH_ALEN);
337 } 343 }
344 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
338 } 345 }
339 break; 346 break;
340 case cpu_to_le16(IEEE80211_FCTL_FROMDS): 347 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
@@ -346,9 +353,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
346 if (iftype == NL80211_IFTYPE_MESH_POINT) { 353 if (iftype == NL80211_IFTYPE_MESH_POINT) {
347 struct ieee80211s_hdr *meshdr = 354 struct ieee80211s_hdr *meshdr =
348 (struct ieee80211s_hdr *) (skb->data + hdrlen); 355 (struct ieee80211s_hdr *) (skb->data + hdrlen);
349 hdrlen += ieee80211_get_mesh_hdrlen(meshdr); 356 /* make sure meshdr->flags is on the linear part */
357 if (!pskb_may_pull(skb, hdrlen + 1))
358 return -1;
350 if (meshdr->flags & MESH_FLAGS_AE_A4) 359 if (meshdr->flags & MESH_FLAGS_AE_A4)
351 memcpy(src, meshdr->eaddr1, ETH_ALEN); 360 skb_copy_bits(skb, hdrlen +
361 offsetof(struct ieee80211s_hdr, eaddr1),
362 src, ETH_ALEN);
363 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
352 } 364 }
353 break; 365 break;
354 case cpu_to_le16(0): 366 case cpu_to_le16(0):
@@ -357,7 +369,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
357 break; 369 break;
358 } 370 }
359 371
360 if (unlikely(skb->len - hdrlen < 8)) 372 if (!pskb_may_pull(skb, hdrlen + 8))
361 return -1; 373 return -1;
362 374
363 payload = skb->data + hdrlen; 375 payload = skb->data + hdrlen;