diff options
author | Zhu Yi <yi.zhu@intel.com> | 2010-03-29 05:35:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-03-31 14:39:34 -0400 |
commit | e3cf8b3f7b9eefbe1d39b160726d6e5c2cbb4c5d (patch) | |
tree | c59a6fcb8d0bcd88d848785a3dbe3978d1568274 /net/wireless/util.c | |
parent | e58b1253f1e850b4469964d7b92cf230196223c0 (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/util.c')
-rw-r--r-- | net/wireless/util.c | 24 |
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; |