diff mbox

mwifiex: add __GFP_REPEAT to skb allocation call

Message ID 1459256320.6473.160.camel@edumazet-glaptop3.roam.corp.google.com (mailing list archive)
State Not Applicable
Delegated to: Kalle Valo
Headers show

Commit Message

Eric Dumazet March 29, 2016, 12:58 p.m. UTC
On Tue, 2016-03-29 at 17:27 +0800, Wei-Ning Huang wrote:
> Adding some chromium devs to the thread.
> 
> In, http://lxr.free-electrons.com/source/mm/page_alloc.c#L3152
> 
> The default mm retry allocation when 'order <=
> PAGE_ALLOC_COSTLY_ORDER' of gfp_mask contains __GFP_REPEAT.
> PAGE_ALLOC_COSTLY_ORDER is defined to be 3. On systems with page size
> = 4K, this means memory compaction and retry is only done when the
> size of allocation is <= 32K
> In mwifiex, the allocation size is 64K.



>  When we have system with
> memory fragmentation and allocation failed, there will be no retry.
> This is why we need to add __GFP_REPEAT here to allow the system to
> perform memory compaction and retry allocation.
> 
> Maybe Amit@marvell can comment on if this is a good fix on this issue.
> I'm also aware that marvell is the progress of implementing
> scatter/gatter for mwifiex, which can also fix the issue.

Before SG is implemented, you really need to copy incoming frames into
smallest chunks (to get lowest skb->truesize) and leave the 64KB
allocated stuff forever in the driver.

__GFP_REPEAT wont really solve the issue.

It seems the problem comes from the fact that the drivers calls
dev_kfree_skb_any() after calling mwifiex_deaggr_sdio_pkt(), instead of
recycling this very precious 64KB skb once memory gets fragmented.

Another problem is that mwifiex_deaggr_sdio_pkt() uses
mwifiex_alloc_dma_align_buf() with GFP_KERNEL | GFP_DMA

Really GFP_DMA makes no sense here, since the skb is going to be
processed by the stack, which has no such requirement.

Please use normal skb allocations there.





--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Amitkumar Karwar April 5, 2016, 5:48 a.m. UTC | #1
Hi Eric,

Thanks for the comments.

> From: Eric Dumazet [mailto:eric.dumazet@gmail.com]

> Sent: Tuesday, March 29, 2016 6:29 PM

> To: Wei-Ning Huang

> Cc: Kalle Valo; Linux Wireless; LKML; Amitkumar Karwar; Nishant

> Sarmukadam; Sameer Nanda; netdev@vger.kernel.org; Sonny Rao; Douglas

> Anderson

> Subject: Re: [PATCH] mwifiex: add __GFP_REPEAT to skb allocation call

> 

> On Tue, 2016-03-29 at 17:27 +0800, Wei-Ning Huang wrote:

> > Adding some chromium devs to the thread.

> >

> > In, http://lxr.free-electrons.com/source/mm/page_alloc.c#L3152

> >

> > The default mm retry allocation when 'order <=

> > PAGE_ALLOC_COSTLY_ORDER' of gfp_mask contains __GFP_REPEAT.

> > PAGE_ALLOC_COSTLY_ORDER is defined to be 3. On systems with page size

> > = 4K, this means memory compaction and retry is only done when the

> > size of allocation is <= 32K In mwifiex, the allocation size is 64K.

> 

> 

> 

> >  When we have system with

> > memory fragmentation and allocation failed, there will be no retry.

> > This is why we need to add __GFP_REPEAT here to allow the system to

> > perform memory compaction and retry allocation.

> >

> > Maybe Amit@marvell can comment on if this is a good fix on this issue.

> > I'm also aware that marvell is the progress of implementing

> > scatter/gatter for mwifiex, which can also fix the issue.

> 

> Before SG is implemented, you really need to copy incoming frames into

> smallest chunks (to get lowest skb->truesize) and leave the 64KB

> allocated stuff forever in the driver.


We do have a 64KB pre-allocated buffer for receiving Rx data in our driver.

> 

> __GFP_REPEAT wont really solve the issue.

> 

> It seems the problem comes from the fact that the drivers calls

> dev_kfree_skb_any() after calling mwifiex_deaggr_sdio_pkt(), instead of

> recycling this very precious 64KB skb once memory gets fragmented.


Our one time allocated 64k buffer read from firmware contains multiple data chunks. We have a feature called single port aggregation in which firmware attaches an aggregated buffer to single port. So sometimes a single data chunk can exceed 32k. dev_kfree_skb_any() is called to free those data chunks.

> 

> Another problem is that mwifiex_deaggr_sdio_pkt() uses

> mwifiex_alloc_dma_align_buf() with GFP_KERNEL | GFP_DMA

> 

> Really GFP_DMA makes no sense here, since the skb is going to be

> processed by the stack, which has no such requirement.

> 

> Please use normal skb allocations there.


Sure. I will submit a patch for this.

Regards,
Amitkumar
David Laight April 5, 2016, 4:05 p.m. UTC | #2
RnJvbTogQW1pdGt1bWFyIEthcndhcg0KPiBTZW50OiAwNSBBcHJpbCAyMDE2IDA2OjQ4DQouLi4N
Cj4gT3VyIG9uZSB0aW1lIGFsbG9jYXRlZCA2NGsgYnVmZmVyIHJlYWQgZnJvbSBmaXJtd2FyZSBj
b250YWlucyBtdWx0aXBsZSBkYXRhIGNodW5rcy4gV2UgaGF2ZSBhIGZlYXR1cmUNCj4gY2FsbGVk
IHNpbmdsZSBwb3J0IGFnZ3JlZ2F0aW9uIGluIHdoaWNoIGZpcm13YXJlIGF0dGFjaGVzIGFuIGFn
Z3JlZ2F0ZWQgYnVmZmVyIHRvIHNpbmdsZSBwb3J0LiBTbw0KPiBzb21ldGltZXMgYSBzaW5nbGUg
ZGF0YSBjaHVuayBjYW4gZXhjZWVkIDMyay4gZGV2X2tmcmVlX3NrYl9hbnkoKSBpcyBjYWxsZWQg
dG8gZnJlZSB0aG9zZSBkYXRhIGNodW5rcy4NCg0KQWggeWVzLCB3aGljaCBwYXJ0aWN1bGFyIHBy
b2JsZW0gZG9lcyBhZ2dyZWdhdGluZyBkYXRhIGludG8gYSBzaW5nbGUgYnVmZmVyIHNvbHZlPw0K
DQoJRGF2aWQNCg0K
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index b2c839a..8404db5 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -1123,8 +1123,8 @@  static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter,
 				    __func__, pkt_len, blk_size);
 			break;
 		}
-		skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len,
-							 GFP_KERNEL | GFP_DMA);
+		skb_deaggr = __netdev_alloc_skb_ip_align(NULL, pkt_len,
+							 GFP_KERNEL);
 		if (!skb_deaggr)
 			break;
 		skb_put(skb_deaggr, pkt_len);