From c99828ab6f35b961afab0591f991bab60d7df364 Mon Sep 17 00:00:00 2001 From: jianghai Date: Mon, 26 Jun 2023 17:40:07 +0800 Subject: [PATCH] eth: gmac: adapt to support DMA 32-bit in skb --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 28 +++++++++++++++---- include/linux/skbuff.h | 2 ++ net/core/skbuff.c | 27 ++++++++++++++---- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 42132137b..27a377467 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1340,13 +1340,16 @@ static int __stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p { struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; + gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); + if (priv->dma_cap.addr64 <= 32) + gfp |= GFP_DMA32; - buf->page = page_pool_dev_alloc_pages(rx_q->page_pool); + buf->page = page_pool_alloc_pages(rx_q->page_pool,gfp); if (!buf->page) return -ENOMEM; if (priv->sph) { - buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); + buf->sec_page = page_pool_alloc_pages(rx_q->page_pool,gfp); if (!buf->sec_page) return -ENOMEM; @@ -1425,6 +1428,10 @@ static int __stmmac_init_rx_skbuffers(struct stmmac_priv *priv, struct dma_desc struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_rx_skbuffer *buf = &rx_q->skbuf_pool[i]; struct sk_buff *skb = NULL; + gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); + if (priv->dma_cap.addr64 <= 32) + gfp |= GFP_DMA32; + skb = netdev_alloc_skb(priv->dev, stmmac_get_rx_buf_frsize(priv)); if (!skb) return -ENOMEM; @@ -1433,7 +1440,7 @@ static int __stmmac_init_rx_skbuffers(struct stmmac_priv *priv, struct dma_desc return -ENOMEM; if (priv->sph) { - buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); + buf->sec_page = page_pool_alloc_pages(rx_q->page_pool,gfp); if (!buf->sec_page) return -ENOMEM; @@ -3789,6 +3796,10 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) struct stmmac_rx_skbuffer *buf ; struct sk_buff *skb = NULL; #endif + gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); + + if (priv->dma_cap.addr64 <= 32) + gfp |= GFP_DMA32; len = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE) * PAGE_SIZE; @@ -3803,13 +3814,13 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) buf = &rx_q->buf_pool[entry]; if (!buf->page) { - buf->page = page_pool_dev_alloc_pages(rx_q->page_pool); + buf->page = page_pool_alloc_pages(rx_q->page_pool,gfp); if (!buf->page) break; } if (priv->sph && !buf->sec_page) { - buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); + buf->sec_page = page_pool_alloc_pages(rx_q->page_pool,gfp); if (!buf->sec_page) break; @@ -3850,7 +3861,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) DMA_FROM_DEVICE); if (priv->sph && !buf->sec_page) { - buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); + buf->sec_page = page_pool_alloc_pages(rx_q->page_pool,gfp); if (!buf->sec_page) break; @@ -5282,6 +5293,11 @@ int stmmac_dvr_probe(struct device *device, priv->dma_cap.addr64 = 32; } } + if(priv->dma_cap.addr64 <= 32){ + skb_set_alloc_dma32(GFP_DMA32); + } + dev_info(priv->device, "Using %d bits DMA width,skb alloc dma32 flag %x\n", + priv->dma_cap.addr64,skb_get_alloc_dma32()); ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; ndev->watchdog_timeo = msecs_to_jiffies(watchdog); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 3a02503b3..850fd6d6e 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1088,6 +1088,8 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size); struct sk_buff *build_skb_around(struct sk_buff *skb, void *data, unsigned int frag_size); +void skb_set_alloc_dma32(gfp_t gfp_dma32); +gfp_t skb_get_alloc_dma32(void); /** * alloc_skb - allocate a network buffer * @size: size to allocate diff --git a/net/core/skbuff.c b/net/core/skbuff.c index fc36c8edd..f9969f943 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -87,6 +87,21 @@ static struct kmem_cache *skbuff_ext_cache __ro_after_init; #endif int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS; EXPORT_SYMBOL(sysctl_max_skb_frags); +gfp_t skb_gfp_dma32 = 0; + +void skb_set_alloc_dma32(gfp_t gfp_dma32) +{ + if(gfp_dma32 | GFP_DMA32) + skb_gfp_dma32 = __GFP_DMA32; + else + skb_gfp_dma32 = 0; +} +EXPORT_SYMBOL(skb_set_alloc_dma32); +gfp_t skb_get_alloc_dma32(void) +{ + return skb_gfp_dma32; +} +EXPORT_SYMBOL(skb_get_alloc_dma32); /** * skb_panic - private function for out-of-line support @@ -379,7 +394,7 @@ static void *__napi_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) { struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); - return page_frag_alloc(&nc->page, fragsz, gfp_mask); + return page_frag_alloc(&nc->page, fragsz, gfp_mask | skb_gfp_dma32); } void *napi_alloc_frag(unsigned int fragsz) @@ -405,10 +420,10 @@ void *netdev_alloc_frag(unsigned int fragsz) fragsz = SKB_DATA_ALIGN(fragsz); if (in_irq() || irqs_disabled()) { nc = this_cpu_ptr(&netdev_alloc_cache); - data = page_frag_alloc(nc, fragsz, GFP_ATOMIC); + data = page_frag_alloc(nc, fragsz, GFP_ATOMIC | skb_gfp_dma32); } else { local_bh_disable(); - data = __napi_alloc_frag(fragsz, GFP_ATOMIC); + data = __napi_alloc_frag(fragsz, GFP_ATOMIC | skb_gfp_dma32); local_bh_enable(); } return data; @@ -458,12 +473,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len, if (in_irq() || irqs_disabled()) { nc = this_cpu_ptr(&netdev_alloc_cache); - data = page_frag_alloc(nc, len, gfp_mask); + data = page_frag_alloc(nc, len, gfp_mask | skb_gfp_dma32); pfmemalloc = nc->pfmemalloc; } else { local_bh_disable(); nc = this_cpu_ptr(&napi_alloc_cache.page); - data = page_frag_alloc(nc, len, gfp_mask); + data = page_frag_alloc(nc, len, gfp_mask | skb_gfp_dma32); pfmemalloc = nc->pfmemalloc; local_bh_enable(); } @@ -531,7 +546,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len, if (sk_memalloc_socks()) gfp_mask |= __GFP_MEMALLOC; - data = page_frag_alloc(&nc->page, len, gfp_mask); + data = page_frag_alloc(&nc->page, len, gfp_mask | skb_gfp_dma32); if (unlikely(!data)) return NULL;