* [PATCH] iwl3945: better skb management in rx path
@ 2013-06-28 12:03 Eric Dumazet
2013-06-28 14:38 ` Paul Stewart
0 siblings, 1 reply; 9+ messages in thread
From: Eric Dumazet @ 2013-06-28 12:03 UTC (permalink / raw)
To: John W. Linville; +Cc: Steinar H. Gunderson, linux-wireless, netdev
From: Eric Dumazet <edumazet@google.com>
Steinar reported reallocations of skb->head with IPv6, leading to
a warning in skb_try_coalesce()
It turns out iwl3945 has several problems :
1) skb->truesize is underestimated.
We really consume PAGE_SIZE bytes for a fragment,
not the frame length.
2) 128 bytes of initial headroom is a bit low and forces reallocations.
3) We can avoid consuming a full page for small enough frames.
Reported-by: Steinar H. Gunderson <sesse@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
Note : compiled only, I do not have this hardware.
drivers/net/wireless/iwlegacy/3945.c | 30 +++++++++++++++----------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index c092033..ad7294f 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -483,14 +483,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
- u16 len = le16_to_cpu(rx_hdr->len);
+ u32 len = le16_to_cpu(rx_hdr->len);
struct sk_buff *skb;
__le16 fc = hdr->frame_control;
+ u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order;
/* We received data from the HW, so stop the watchdog */
- if (unlikely
- (len + IL39_RX_FRAME_SIZE >
- PAGE_SIZE << il->hw_params.rx_page_order)) {
+ if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) {
D_DROP("Corruption detected!\n");
return;
}
@@ -506,26 +505,33 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
D_INFO("Woke queues - frame received on passive channel\n");
}
- skb = dev_alloc_skb(128);
+ skb = dev_alloc_skb(256);
if (!skb) {
IL_ERR("dev_alloc_skb failed\n");
return;
}
if (!il3945_mod_params.sw_crypto)
- il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
+ il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt,
le32_to_cpu(rx_end->status), stats);
- skb_add_rx_frag(skb, 0, rxb->page,
- (void *)rx_hdr->payload - (void *)pkt, len,
- len);
-
+ /* If frame is small enough to fit into skb->head, copy it
+ * and do not consume a full page
+ */
+ if (len <= 256) {
+ skb_copy_to_linear_data(skb, rx_hdr->payload, len);
+ skb->tail += len;
+ } else {
+ skb_add_rx_frag(skb, 0, rxb->page,
+ (void *)rx_hdr->payload - (void *)pkt, len,
+ fraglen);
+ il->alloc_rxb_page--;
+ rxb->page = NULL;
+ }
il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
ieee80211_rx(il->hw, skb);
- il->alloc_rxb_page--;
- rxb->page = NULL;
}
#define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] iwl3945: better skb management in rx path
2013-06-28 12:03 [PATCH] iwl3945: better skb management in rx path Eric Dumazet
@ 2013-06-28 14:38 ` Paul Stewart
0 siblings, 0 replies; 9+ messages in thread
From: Paul Stewart @ 2013-06-28 14:38 UTC (permalink / raw)
To: Eric Dumazet
Cc: John W. Linville, Steinar H. Gunderson, linux-wireless, netdev
On Fri, Jun 28, 2013 at 5:03 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> Steinar reported reallocations of skb->head with IPv6, leading to
> a warning in skb_try_coalesce()
>
> It turns out iwl3945 has several problems :
>
> 1) skb->truesize is underestimated.
> We really consume PAGE_SIZE bytes for a fragment,
> not the frame length.
> 2) 128 bytes of initial headroom is a bit low and forces reallocations.
> 3) We can avoid consuming a full page for small enough frames.
>
> Reported-by: Steinar H. Gunderson <sesse@google.com>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
> Note : compiled only, I do not have this hardware.
>
> drivers/net/wireless/iwlegacy/3945.c | 30 +++++++++++++++----------
> 1 file changed, 18 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
> index c092033..ad7294f 100644
> --- a/drivers/net/wireless/iwlegacy/3945.c
> +++ b/drivers/net/wireless/iwlegacy/3945.c
> @@ -483,14 +483,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
> struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
> struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
> struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
> - u16 len = le16_to_cpu(rx_hdr->len);
> + u32 len = le16_to_cpu(rx_hdr->len);
> struct sk_buff *skb;
> __le16 fc = hdr->frame_control;
> + u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order;
>
> /* We received data from the HW, so stop the watchdog */
> - if (unlikely
> - (len + IL39_RX_FRAME_SIZE >
> - PAGE_SIZE << il->hw_params.rx_page_order)) {
> + if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) {
> D_DROP("Corruption detected!\n");
> return;
> }
> @@ -506,26 +505,33 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
> D_INFO("Woke queues - frame received on passive channel\n");
> }
>
> - skb = dev_alloc_skb(128);
> + skb = dev_alloc_skb(256);
> if (!skb) {
> IL_ERR("dev_alloc_skb failed\n");
> return;
> }
>
> if (!il3945_mod_params.sw_crypto)
> - il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
> + il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt,
> le32_to_cpu(rx_end->status), stats);
>
> - skb_add_rx_frag(skb, 0, rxb->page,
> - (void *)rx_hdr->payload - (void *)pkt, len,
> - len);
> -
> + /* If frame is small enough to fit into skb->head, copy it
> + * and do not consume a full page
> + */
> + if (len <= 256) {
Presumably this 256 is related to the "dev_alloc_skb(256)"? It might
be worth making this a constant of some sort so they don't
inadvertently drift apart in the future.
> + skb_copy_to_linear_data(skb, rx_hdr->payload, len);
> + skb->tail += len;
> + } else {
> + skb_add_rx_frag(skb, 0, rxb->page,
> + (void *)rx_hdr->payload - (void *)pkt, len,
> + fraglen);
> + il->alloc_rxb_page--;
> + rxb->page = NULL;
> + }
> il_update_stats(il, false, fc, len);
> memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
>
> ieee80211_rx(il->hw, skb);
> - il->alloc_rxb_page--;
> - rxb->page = NULL;
> }
>
> #define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] iwl3945: better skb management in rx path
@ 2013-06-28 14:38 ` Paul Stewart
0 siblings, 0 replies; 9+ messages in thread
From: Paul Stewart @ 2013-06-28 14:38 UTC (permalink / raw)
To: Eric Dumazet
Cc: John W. Linville, Steinar H. Gunderson, linux-wireless, netdev
On Fri, Jun 28, 2013 at 5:03 AM, Eric Dumazet <eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> From: Eric Dumazet <edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
>
> Steinar reported reallocations of skb->head with IPv6, leading to
> a warning in skb_try_coalesce()
>
> It turns out iwl3945 has several problems :
>
> 1) skb->truesize is underestimated.
> We really consume PAGE_SIZE bytes for a fragment,
> not the frame length.
> 2) 128 bytes of initial headroom is a bit low and forces reallocations.
> 3) We can avoid consuming a full page for small enough frames.
>
> Reported-by: Steinar H. Gunderson <sesse-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Eric Dumazet <edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
> ---
> Note : compiled only, I do not have this hardware.
>
> drivers/net/wireless/iwlegacy/3945.c | 30 +++++++++++++++----------
> 1 file changed, 18 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
> index c092033..ad7294f 100644
> --- a/drivers/net/wireless/iwlegacy/3945.c
> +++ b/drivers/net/wireless/iwlegacy/3945.c
> @@ -483,14 +483,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
> struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
> struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
> struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
> - u16 len = le16_to_cpu(rx_hdr->len);
> + u32 len = le16_to_cpu(rx_hdr->len);
> struct sk_buff *skb;
> __le16 fc = hdr->frame_control;
> + u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order;
>
> /* We received data from the HW, so stop the watchdog */
> - if (unlikely
> - (len + IL39_RX_FRAME_SIZE >
> - PAGE_SIZE << il->hw_params.rx_page_order)) {
> + if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) {
> D_DROP("Corruption detected!\n");
> return;
> }
> @@ -506,26 +505,33 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
> D_INFO("Woke queues - frame received on passive channel\n");
> }
>
> - skb = dev_alloc_skb(128);
> + skb = dev_alloc_skb(256);
> if (!skb) {
> IL_ERR("dev_alloc_skb failed\n");
> return;
> }
>
> if (!il3945_mod_params.sw_crypto)
> - il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
> + il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt,
> le32_to_cpu(rx_end->status), stats);
>
> - skb_add_rx_frag(skb, 0, rxb->page,
> - (void *)rx_hdr->payload - (void *)pkt, len,
> - len);
> -
> + /* If frame is small enough to fit into skb->head, copy it
> + * and do not consume a full page
> + */
> + if (len <= 256) {
Presumably this 256 is related to the "dev_alloc_skb(256)"? It might
be worth making this a constant of some sort so they don't
inadvertently drift apart in the future.
> + skb_copy_to_linear_data(skb, rx_hdr->payload, len);
> + skb->tail += len;
> + } else {
> + skb_add_rx_frag(skb, 0, rxb->page,
> + (void *)rx_hdr->payload - (void *)pkt, len,
> + fraglen);
> + il->alloc_rxb_page--;
> + rxb->page = NULL;
> + }
> il_update_stats(il, false, fc, len);
> memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
>
> ieee80211_rx(il->hw, skb);
> - il->alloc_rxb_page--;
> - rxb->page = NULL;
> }
>
> #define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] iwl3945: better skb management in rx path
@ 2013-06-28 14:50 ` Eric Dumazet
0 siblings, 0 replies; 9+ messages in thread
From: Eric Dumazet @ 2013-06-28 14:50 UTC (permalink / raw)
To: Paul Stewart
Cc: John W. Linville, Steinar H. Gunderson, linux-wireless, netdev
From: Eric Dumazet <edumazet@google.com>
On Fri, 2013-06-28 at 07:38 -0700, Paul Stewart wrote:
> Presumably this 256 is related to the "dev_alloc_skb(256)"? It might
> be worth making this a constant of some sort so they don't
> inadvertently drift apart in the future.
Hi Paul !
Well, I can do that, but the 128 was not a constant to begin with ;)
Thanks
[PATCH v2] iwl3945: better skb management in rx path
Steinar reported reallocations of skb->head with IPv6, leading to
a warning in skb_try_coalesce()
It turns out iwl3945 has several problems :
1) skb->truesize is underestimated.
We really consume PAGE_SIZE bytes for a fragment,
not the frame length.
2) 128 bytes of initial headroom is a bit low and forces reallocations.
3) We can avoid consuming a full page for small enough frames.
Reported-by: Steinar H. Gunderson <sesse@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paul Stewart <pstew@google.com>
---
v2: use a SMALL_PACKET_SIZE macro
drivers/net/wireless/iwlegacy/3945.c | 32 +++++++++++++++----------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index c092033..38e6be6 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -475,6 +475,8 @@ il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header)
}
}
+#define SMALL_PACKET_SIZE 256
+
static void
il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
struct ieee80211_rx_status *stats)
@@ -483,14 +485,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
- u16 len = le16_to_cpu(rx_hdr->len);
+ u32 len = le16_to_cpu(rx_hdr->len);
struct sk_buff *skb;
__le16 fc = hdr->frame_control;
+ u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order;
/* We received data from the HW, so stop the watchdog */
- if (unlikely
- (len + IL39_RX_FRAME_SIZE >
- PAGE_SIZE << il->hw_params.rx_page_order)) {
+ if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) {
D_DROP("Corruption detected!\n");
return;
}
@@ -506,26 +507,33 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
D_INFO("Woke queues - frame received on passive channel\n");
}
- skb = dev_alloc_skb(128);
+ skb = dev_alloc_skb(SMALL_PACKET_SIZE);
if (!skb) {
IL_ERR("dev_alloc_skb failed\n");
return;
}
if (!il3945_mod_params.sw_crypto)
- il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
+ il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt,
le32_to_cpu(rx_end->status), stats);
- skb_add_rx_frag(skb, 0, rxb->page,
- (void *)rx_hdr->payload - (void *)pkt, len,
- len);
-
+ /* If frame is small enough to fit into skb->head, copy it
+ * and do not consume a full page
+ */
+ if (len <= SMALL_PACKET_SIZE) {
+ skb_copy_to_linear_data(skb, rx_hdr->payload, len);
+ skb->tail += len;
+ } else {
+ skb_add_rx_frag(skb, 0, rxb->page,
+ (void *)rx_hdr->payload - (void *)pkt, len,
+ fraglen);
+ il->alloc_rxb_page--;
+ rxb->page = NULL;
+ }
il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
ieee80211_rx(il->hw, skb);
- il->alloc_rxb_page--;
- rxb->page = NULL;
}
#define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] iwl3945: better skb management in rx path
@ 2013-06-28 14:50 ` Eric Dumazet
0 siblings, 0 replies; 9+ messages in thread
From: Eric Dumazet @ 2013-06-28 14:50 UTC (permalink / raw)
To: Paul Stewart
Cc: John W. Linville, Steinar H. Gunderson, linux-wireless, netdev
From: Eric Dumazet <edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
On Fri, 2013-06-28 at 07:38 -0700, Paul Stewart wrote:
> Presumably this 256 is related to the "dev_alloc_skb(256)"? It might
> be worth making this a constant of some sort so they don't
> inadvertently drift apart in the future.
Hi Paul !
Well, I can do that, but the 128 was not a constant to begin with ;)
Thanks
[PATCH v2] iwl3945: better skb management in rx path
Steinar reported reallocations of skb->head with IPv6, leading to
a warning in skb_try_coalesce()
It turns out iwl3945 has several problems :
1) skb->truesize is underestimated.
We really consume PAGE_SIZE bytes for a fragment,
not the frame length.
2) 128 bytes of initial headroom is a bit low and forces reallocations.
3) We can avoid consuming a full page for small enough frames.
Reported-by: Steinar H. Gunderson <sesse-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Eric Dumazet <edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Cc: Paul Stewart <pstew-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
---
v2: use a SMALL_PACKET_SIZE macro
drivers/net/wireless/iwlegacy/3945.c | 32 +++++++++++++++----------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index c092033..38e6be6 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -475,6 +475,8 @@ il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header)
}
}
+#define SMALL_PACKET_SIZE 256
+
static void
il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
struct ieee80211_rx_status *stats)
@@ -483,14 +485,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
- u16 len = le16_to_cpu(rx_hdr->len);
+ u32 len = le16_to_cpu(rx_hdr->len);
struct sk_buff *skb;
__le16 fc = hdr->frame_control;
+ u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order;
/* We received data from the HW, so stop the watchdog */
- if (unlikely
- (len + IL39_RX_FRAME_SIZE >
- PAGE_SIZE << il->hw_params.rx_page_order)) {
+ if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) {
D_DROP("Corruption detected!\n");
return;
}
@@ -506,26 +507,33 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
D_INFO("Woke queues - frame received on passive channel\n");
}
- skb = dev_alloc_skb(128);
+ skb = dev_alloc_skb(SMALL_PACKET_SIZE);
if (!skb) {
IL_ERR("dev_alloc_skb failed\n");
return;
}
if (!il3945_mod_params.sw_crypto)
- il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
+ il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt,
le32_to_cpu(rx_end->status), stats);
- skb_add_rx_frag(skb, 0, rxb->page,
- (void *)rx_hdr->payload - (void *)pkt, len,
- len);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] iwl3945: better skb management in rx path
2013-06-28 14:50 ` Eric Dumazet
(?)
@ 2013-06-28 14:59 ` Eric Dumazet
-1 siblings, 0 replies; 9+ messages in thread
From: Eric Dumazet @ 2013-06-28 14:59 UTC (permalink / raw)
To: Paul Stewart
Cc: John W. Linville, Steinar H. Gunderson, linux-wireless, netdev
On Fri, 2013-06-28 at 07:50 -0700, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> + if (len <= SMALL_PACKET_SIZE) {
> + skb_copy_to_linear_data(skb, rx_hdr->payload, len);
> + skb->tail += len;
> + } else {
Hmm I'll send a v3, we need a regular __skb_put() here
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3] iwl3945: better skb management in rx path
2013-06-28 14:50 ` Eric Dumazet
(?)
(?)
@ 2013-06-28 15:05 ` Eric Dumazet
2013-06-28 23:05 ` Steinar H. Gunderson
2013-07-01 12:15 ` Stanislaw Gruszka
-1 siblings, 2 replies; 9+ messages in thread
From: Eric Dumazet @ 2013-06-28 15:05 UTC (permalink / raw)
To: Paul Stewart
Cc: John W. Linville, Steinar H. Gunderson, linux-wireless, netdev
From: Eric Dumazet <edumazet@google.com>
Steinar reported reallocations of skb->head with IPv6, leading to
a warning in skb_try_coalesce()
It turns out iwl3945 has several problems :
1) skb->truesize is underestimated.
We really consume PAGE_SIZE bytes for a fragment,
not the frame length.
2) 128 bytes of initial headroom is a bit low and forces reallocations.
3) We can avoid consuming a full page for small enough frames.
Reported-by: Steinar H. Gunderson <sesse@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paul Stewart <pstew@google.com>
---
v3: use regular memcpy(skb_put(...),...)
v2: SMALL_PACKET_SIZE define
drivers/net/wireless/iwlegacy/3945.c | 31 +++++++++++++++----------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index c092033..f09e257 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -475,6 +475,8 @@ il3945_is_network_packet(struct il_priv *il, struct ieee80211_hdr *header)
}
}
+#define SMALL_PACKET_SIZE 256
+
static void
il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
struct ieee80211_rx_status *stats)
@@ -483,14 +485,13 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IL_RX_DATA(pkt);
struct il3945_rx_frame_hdr *rx_hdr = IL_RX_HDR(pkt);
struct il3945_rx_frame_end *rx_end = IL_RX_END(pkt);
- u16 len = le16_to_cpu(rx_hdr->len);
+ u32 len = le16_to_cpu(rx_hdr->len);
struct sk_buff *skb;
__le16 fc = hdr->frame_control;
+ u32 fraglen = PAGE_SIZE << il->hw_params.rx_page_order;
/* We received data from the HW, so stop the watchdog */
- if (unlikely
- (len + IL39_RX_FRAME_SIZE >
- PAGE_SIZE << il->hw_params.rx_page_order)) {
+ if (unlikely(len + IL39_RX_FRAME_SIZE > fraglen)) {
D_DROP("Corruption detected!\n");
return;
}
@@ -506,26 +507,32 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
D_INFO("Woke queues - frame received on passive channel\n");
}
- skb = dev_alloc_skb(128);
+ skb = dev_alloc_skb(SMALL_PACKET_SIZE);
if (!skb) {
IL_ERR("dev_alloc_skb failed\n");
return;
}
if (!il3945_mod_params.sw_crypto)
- il_set_decrypted_flag(il, (struct ieee80211_hdr *)rxb_addr(rxb),
+ il_set_decrypted_flag(il, (struct ieee80211_hdr *)pkt,
le32_to_cpu(rx_end->status), stats);
- skb_add_rx_frag(skb, 0, rxb->page,
- (void *)rx_hdr->payload - (void *)pkt, len,
- len);
-
+ /* If frame is small enough to fit into skb->head, copy it
+ * and do not consume a full page
+ */
+ if (len <= SMALL_PACKET_SIZE) {
+ memcpy(skb_put(skb, len), rx_hdr->payload, len);
+ } else {
+ skb_add_rx_frag(skb, 0, rxb->page,
+ (void *)rx_hdr->payload - (void *)pkt, len,
+ fraglen);
+ il->alloc_rxb_page--;
+ rxb->page = NULL;
+ }
il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
ieee80211_rx(il->hw, skb);
- il->alloc_rxb_page--;
- rxb->page = NULL;
}
#define IL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3] iwl3945: better skb management in rx path
2013-06-28 15:05 ` [PATCH v3] " Eric Dumazet
@ 2013-06-28 23:05 ` Steinar H. Gunderson
2013-07-01 12:15 ` Stanislaw Gruszka
1 sibling, 0 replies; 9+ messages in thread
From: Steinar H. Gunderson @ 2013-06-28 23:05 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Paul Stewart, John W. Linville, linux-wireless, netdev
2013/6/28 Eric Dumazet <eric.dumazet@gmail.com>:
> Steinar reported reallocations of skb->head with IPv6, leading to
> a warning in skb_try_coalesce()
>
> It turns out iwl3945 has several problems :
>
> 1) skb->truesize is underestimated.
> We really consume PAGE_SIZE bytes for a fragment,
> not the frame length.
> 2) 128 bytes of initial headroom is a bit low and forces reallocations.
> 3) We can avoid consuming a full page for small enough frames.
I'm running 3.9.8 plus this patch (hand-applied since GMail mangled
it…), and so far, it seems to work fine. Well, network-manager still
doesn't like Cisco's band-select feature, so from time to time I get
network freezes while it's trying to roam from 5 GHz to 2.4 GHz, but
that's hardly iwl3945's fault.
/* Steinar */
--
Software Engineer, Google Switzerland
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] iwl3945: better skb management in rx path
2013-06-28 15:05 ` [PATCH v3] " Eric Dumazet
2013-06-28 23:05 ` Steinar H. Gunderson
@ 2013-07-01 12:15 ` Stanislaw Gruszka
1 sibling, 0 replies; 9+ messages in thread
From: Stanislaw Gruszka @ 2013-07-01 12:15 UTC (permalink / raw)
To: Eric Dumazet
Cc: Paul Stewart, John W. Linville, Steinar H. Gunderson,
linux-wireless, netdev
On Fri, Jun 28, 2013 at 08:05:06AM -0700, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> Steinar reported reallocations of skb->head with IPv6, leading to
> a warning in skb_try_coalesce()
>
> It turns out iwl3945 has several problems :
>
> 1) skb->truesize is underestimated.
> We really consume PAGE_SIZE bytes for a fragment,
> not the frame length.
> 2) 128 bytes of initial headroom is a bit low and forces reallocations.
> 3) We can avoid consuming a full page for small enough frames.
>
> Reported-by: Steinar H. Gunderson <sesse@google.com>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Paul Stewart <pstew@google.com>
Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
FYI, I'll post 4965 version soon.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2013-07-01 12:13 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-28 12:03 [PATCH] iwl3945: better skb management in rx path Eric Dumazet
2013-06-28 14:38 ` Paul Stewart
2013-06-28 14:38 ` Paul Stewart
2013-06-28 14:50 ` Eric Dumazet
2013-06-28 14:50 ` Eric Dumazet
2013-06-28 14:59 ` Eric Dumazet
2013-06-28 15:05 ` [PATCH v3] " Eric Dumazet
2013-06-28 23:05 ` Steinar H. Gunderson
2013-07-01 12:15 ` Stanislaw Gruszka
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.