From patchwork Sun Jan 1 11:59:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 638419 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5F0E8C4332F for ; Sun, 1 Jan 2023 12:00:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230336AbjAAMAS (ORCPT ); Sun, 1 Jan 2023 07:00:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37302 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229567AbjAAMAQ (ORCPT ); Sun, 1 Jan 2023 07:00:16 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 848D83887 for ; Sun, 1 Jan 2023 04:00:14 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 1639EB80B28 for ; Sun, 1 Jan 2023 12:00:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6A38BC433EF; Sun, 1 Jan 2023 12:00:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672574411; bh=Opj4eeqoiuuE6+PTA11Al1pDQbsgEQy334HZTacGmCc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bsloiUhNVHifNkppfun5hrfoc4OxloJEArpltfdxFuyHQntgxT467DmLdpUU40n9K ftgsYXEsQulPvHPl1NSApZkbRhbi88AhiUF2iUcTVQaLZCCwQt3aw7gfDvvkMtBs++ FJFtYddrKkQIlEjyao5r1GoBM8NPZpxkaufwyJs6T4hvPxVfsTLPHVbSi2z2uMVeSq 66eh8VRDD7bkOIG4r0a4ehvI12isspJY2eEnyI5ZR/NA2BS/VK4bPGR8B5869iDQCb lpkv4wVdjFaeFvWjyqiyLLWLOw+qkDaL34Oeop0fyNjaSh1okczHf4jg/LxF1KrGUM MLA0UjMYjhJMA== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org Subject: [PATCH 1/3] wifi: mt76: switch to page_pool allocator Date: Sun, 1 Jan 2023 12:59:57 +0100 Message-Id: <3a5bef05c0e70f1e13ff4b9cc3d6a62fca8dc810.1672574310.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org In order to reduce possible memory allocation failures due to memory fragmentation caused by page_frag_cache allocator, switch to page_pool allocator for dma and usb mt76 drivers. Remove per rx-queue page_frag_cache Tested-by: Felix Fietkau Tested-by: Deren Wu Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/Kconfig | 1 + drivers/net/wireless/mediatek/mt76/dma.c | 55 ++++++++++--------- drivers/net/wireless/mediatek/mt76/mac80211.c | 36 ++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 23 +++++++- .../net/wireless/mediatek/mt76/mt7915/mmio.c | 16 ++---- drivers/net/wireless/mediatek/mt76/usb.c | 42 +++++++------- 6 files changed, 112 insertions(+), 61 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index d7f90a0eb21e..18152c16c36f 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config MT76_CORE tristate + select PAGE_POOL config MT76_LEDS bool diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 4fba8059d463..4f5b4068d35e 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -173,7 +173,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev) local_bh_disable(); while ((t = __mt76_get_rxwi(dev)) != NULL) { if (t->ptr) - skb_free_frag(t->ptr); + mt76_put_page_pool_buf(t->ptr, false); kfree(t); } local_bh_enable(); @@ -579,11 +579,11 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, } static int -mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) +mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, + bool allow_direct) { int len = SKB_WITH_OVERHEAD(q->buf_size); - int frames = 0, offset = q->buf_offset; - dma_addr_t addr; + int frames = 0; if (!q->ndesc) return 0; @@ -592,25 +592,28 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) while (q->queued < q->ndesc - 1) { struct mt76_queue_buf qbuf; - void *buf = NULL; + dma_addr_t addr; + int offset; + void *buf; - buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC); + buf = mt76_get_page_pool_buf(q, &offset, q->buf_size); if (!buf) break; - addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE); + addr = dma_map_single(dev->dma_dev, buf + offset, len, + DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(dev->dma_dev, addr))) { - skb_free_frag(buf); + mt76_put_page_pool_buf(buf, allow_direct); break; } - qbuf.addr = addr + offset; - qbuf.len = len - offset; + qbuf.addr = addr + q->buf_offset; + qbuf.len = len - q->buf_offset; qbuf.skip_unmap = false; if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) { dma_unmap_single(dev->dma_dev, addr, len, DMA_FROM_DEVICE); - skb_free_frag(buf); + mt76_put_page_pool_buf(buf, allow_direct); break; } frames++; @@ -654,7 +657,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset) /* WED txfree queue needs ring to be initialized before setup */ q->flags = 0; mt76_dma_queue_reset(dev, q); - mt76_dma_rx_fill(dev, q); + mt76_dma_rx_fill(dev, q, false); q->flags = flags; ret = mtk_wed_device_txfree_ring_setup(wed, q->regs); @@ -702,6 +705,10 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, if (!q->entry) return -ENOMEM; + ret = mt76_create_page_pool(dev, q); + if (ret) + return ret; + ret = mt76_dma_wed_setup(dev, q, false); if (ret) return ret; @@ -715,7 +722,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q, static void mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) { - struct page *page; void *buf; bool more; @@ -729,7 +735,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) if (!buf) break; - skb_free_frag(buf); + mt76_put_page_pool_buf(buf, false); } while (1); if (q->rx_head) { @@ -738,13 +744,6 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q) } spin_unlock_bh(&q->lock); - - if (!q->rx_page.va) - return; - - page = virt_to_page(q->rx_page.va); - __page_frag_cache_drain(page, q->rx_page.pagecnt_bias); - memset(&q->rx_page, 0, sizeof(q->rx_page)); } static void @@ -761,7 +760,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) mt76_dma_rx_cleanup(dev, q); mt76_dma_sync_idx(dev, q); - mt76_dma_rx_fill(dev, q); + mt76_dma_rx_fill(dev, q, false); } static void @@ -778,7 +777,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size); } else { - skb_free_frag(data); + mt76_put_page_pool_buf(data, true); } if (more) @@ -851,6 +850,8 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) goto free_frag; skb_reserve(skb, q->buf_offset); + if (mt76_is_page_from_pp(data)) + skb_mark_for_recycle(skb); *(u32 *)skb->cb = info; @@ -866,10 +867,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) continue; free_frag: - skb_free_frag(data); + mt76_put_page_pool_buf(data, true); } - mt76_dma_rx_fill(dev, q); + mt76_dma_rx_fill(dev, q, true); return done; } @@ -912,7 +913,7 @@ mt76_dma_init(struct mt76_dev *dev, mt76_for_each_q_rx(dev, i) { netif_napi_add(&dev->napi_dev, &dev->napi[i], poll); - mt76_dma_rx_fill(dev, &dev->q_rx[i]); + mt76_dma_rx_fill(dev, &dev->q_rx[i], false); napi_enable(&dev->napi[i]); } @@ -963,6 +964,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev) netif_napi_del(&dev->napi[i]); mt76_dma_rx_cleanup(dev, q); + + page_pool_destroy(q->page_pool); } mt76_free_pending_txwi(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 7fe7f68acc24..9fefb441e4d4 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -4,6 +4,7 @@ */ #include #include +#include #include "mt76.h" #define CHAN2G(_idx, _freq) { \ @@ -556,6 +557,41 @@ void mt76_unregister_phy(struct mt76_phy *phy) } EXPORT_SYMBOL_GPL(mt76_unregister_phy); +int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q) +{ + struct page_pool_params pp_params = { + .order = 0, + .pool_size = 256, + .flags = PP_FLAG_PAGE_FRAG, + .nid = NUMA_NO_NODE, + .dev = dev->dma_dev, + }; + + q->page_pool = page_pool_create(&pp_params); + if (IS_ERR(q->page_pool)) { + int err = PTR_ERR(q->page_pool); + + q->page_pool = NULL; + return err; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_create_page_pool); + +void mt76_put_page_pool_buf(void *buf, bool allow_direct) +{ + struct page *page = virt_to_head_page(buf); + + if (!mt76_is_page_from_pp(buf)) { + skb_free_frag(buf); + return; + } + + page_pool_put_full_page(page->pp, page, allow_direct); +} +EXPORT_SYMBOL_GPL(mt76_put_page_pool_buf); + struct mt76_dev * mt76_alloc_device(struct device *pdev, unsigned int size, const struct ieee80211_ops *ops, diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 4f808b676954..885d39411f68 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -202,7 +202,7 @@ struct mt76_queue { dma_addr_t desc_dma; struct sk_buff *rx_head; - struct page_frag_cache rx_page; + struct page_pool *page_pool; }; struct mt76_mcu_ops { @@ -1401,6 +1401,13 @@ mt76_mcu_skb_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, return mt76_mcu_skb_send_and_get_msg(dev, skb, cmd, wait_resp, NULL); } +static inline bool mt76_is_page_from_pp(void *buf) +{ + struct page *page = virt_to_head_page(buf); + + return (page->pp_magic & ~0x3UL) == PP_SIGNATURE; +} + void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set); s8 mt76_get_rate_power_limits(struct mt76_phy *phy, @@ -1421,6 +1428,20 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked); struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token); int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr, struct mt76_txwi_cache *r, dma_addr_t phys); +int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q); +void mt76_put_page_pool_buf(void *buf, bool allow_direct); + +static inline void * +mt76_get_page_pool_buf(struct mt76_queue *q, u32 *offset, u32 size) +{ + struct page *page; + + page = page_pool_dev_alloc_frag(q->page_pool, offset, size); + if (!page) + return NULL; + + return page_address(page) + *offset; +} static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 7ae5277922f3..30ec490b47b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -594,13 +594,9 @@ static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed) static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) { struct mt7915_dev *dev; - u32 length; int i; dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size + - sizeof(struct skb_shared_info)); - for (i = 0; i < dev->mt76.rx_token_size; i++) { struct mt76_txwi_cache *t; @@ -610,7 +606,7 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) dma_unmap_single(dev->mt76.dma_dev, t->dma_addr, wed->wlan.rx_size, DMA_FROM_DEVICE); - __free_pages(virt_to_page(t->ptr), get_order(length)); + mt76_put_page_pool_buf(t->ptr, false); t->ptr = NULL; mt76_put_rxwi(&dev->mt76, t); @@ -621,13 +617,9 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) { struct mtk_rxbm_desc *desc = wed->rx_buf_ring.desc; struct mt7915_dev *dev; - u32 length; int i; dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size + - sizeof(struct skb_shared_info)); - for (i = 0; i < size; i++) { struct mt76_txwi_cache *t = mt76_get_rxwi(&dev->mt76); dma_addr_t phy_addr; @@ -635,7 +627,7 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) int token; void *ptr; - page = __dev_alloc_pages(GFP_KERNEL, get_order(length)); + page = __dev_alloc_page(GFP_KERNEL); if (!page) goto unmap; @@ -644,7 +636,7 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) wed->wlan.rx_size, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev->mt76.dev, phy_addr))) { - __free_pages(page, get_order(length)); + __free_page(page); goto unmap; } @@ -653,7 +645,7 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size) if (token < 0) { dma_unmap_single(dev->mt76.dma_dev, phy_addr, wed->wlan.rx_size, DMA_TO_DEVICE); - __free_pages(page, get_order(length)); + __free_page(page); goto unmap; } diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 3e281715fcd4..b88959ef38aa 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -319,29 +319,27 @@ mt76u_set_endpoints(struct usb_interface *intf, static int mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb, - int nsgs, gfp_t gfp) + int nsgs) { int i; for (i = 0; i < nsgs; i++) { - struct page *page; void *data; int offset; - data = page_frag_alloc(&q->rx_page, q->buf_size, gfp); + data = mt76_get_page_pool_buf(q, &offset, q->buf_size); if (!data) break; - page = virt_to_head_page(data); - offset = data - page_address(page); - sg_set_page(&urb->sg[i], page, q->buf_size, offset); + sg_set_page(&urb->sg[i], virt_to_head_page(data), q->buf_size, + offset); } if (i < nsgs) { int j; for (j = nsgs; j < urb->num_sgs; j++) - skb_free_frag(sg_virt(&urb->sg[j])); + mt76_put_page_pool_buf(sg_virt(&urb->sg[j]), false); urb->num_sgs = i; } @@ -354,15 +352,16 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb, static int mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, - struct urb *urb, int nsgs, gfp_t gfp) + struct urb *urb, int nsgs) { enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN]; + int offset; if (qid == MT_RXQ_MAIN && dev->usb.sg_en) - return mt76u_fill_rx_sg(dev, q, urb, nsgs, gfp); + return mt76u_fill_rx_sg(dev, q, urb, nsgs); urb->transfer_buffer_length = q->buf_size; - urb->transfer_buffer = page_frag_alloc(&q->rx_page, q->buf_size, gfp); + urb->transfer_buffer = mt76_get_page_pool_buf(q, &offset, q->buf_size); return urb->transfer_buffer ? 0 : -ENOMEM; } @@ -400,7 +399,7 @@ mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue *q, if (err) return err; - return mt76u_refill_rx(dev, q, e->urb, sg_size, GFP_KERNEL); + return mt76u_refill_rx(dev, q, e->urb, sg_size); } static void mt76u_urb_free(struct urb *urb) @@ -408,10 +407,10 @@ static void mt76u_urb_free(struct urb *urb) int i; for (i = 0; i < urb->num_sgs; i++) - skb_free_frag(sg_virt(&urb->sg[i])); + mt76_put_page_pool_buf(sg_virt(&urb->sg[i]), false); if (urb->transfer_buffer) - skb_free_frag(urb->transfer_buffer); + mt76_put_page_pool_buf(urb->transfer_buffer, false); usb_free_urb(urb); } @@ -547,6 +546,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb, len -= data_len; nsgs++; } + + skb_mark_for_recycle(skb); dev->drv->rx_skb(dev, MT_RXQ_MAIN, skb, NULL); return nsgs; @@ -612,7 +613,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) count = mt76u_process_rx_entry(dev, urb, q->buf_size); if (count > 0) { - err = mt76u_refill_rx(dev, q, urb, count, GFP_ATOMIC); + err = mt76u_refill_rx(dev, q, urb, count); if (err < 0) break; } @@ -663,6 +664,10 @@ mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) struct mt76_queue *q = &dev->q_rx[qid]; int i, err; + err = mt76_create_page_pool(dev, q); + if (err) + return err; + spin_lock_init(&q->lock); q->entry = devm_kcalloc(dev->dev, MT_NUM_RX_ENTRIES, sizeof(*q->entry), @@ -691,7 +696,6 @@ EXPORT_SYMBOL_GPL(mt76u_alloc_mcu_queue); static void mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) { - struct page *page; int i; for (i = 0; i < q->ndesc; i++) { @@ -701,13 +705,7 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) mt76u_urb_free(q->entry[i].urb); q->entry[i].urb = NULL; } - - if (!q->rx_page.va) - return; - - page = virt_to_page(q->rx_page.va); - __page_frag_cache_drain(page, q->rx_page.pagecnt_bias); - memset(&q->rx_page, 0, sizeof(q->rx_page)); + page_pool_destroy(q->page_pool); } static void mt76u_free_rx(struct mt76_dev *dev) From patchwork Sun Jan 1 11:59:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 638714 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 63A10C4708E for ; Sun, 1 Jan 2023 12:00:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230374AbjAAMAU (ORCPT ); Sun, 1 Jan 2023 07:00:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229877AbjAAMAR (ORCPT ); Sun, 1 Jan 2023 07:00:17 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7F45C26DF for ; Sun, 1 Jan 2023 04:00:16 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 0A24760DC1 for ; Sun, 1 Jan 2023 12:00:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 180D3C433EF; Sun, 1 Jan 2023 12:00:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672574415; bh=3+jYWPrA54QtaZ4aweVvXqDlAkz42vn8mXF/RN/qKTA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QnBfCfyCllPXB7gSaBUUy/rY57fBZZR8tIF4f6HkcAEHrS+rxTAFpG+Y4zvoofT+U pNt6auDmDPyBL3mRjSuJx/H6aipbwLxO6acrJnFY7H1ElzT5hlGkGXQBB52Y/gmg46 4+fFd+HlrVOa14GeuNy/P97HEm1bNwK/qTA9R4wE546HsQjqBc4vbkJ7EUC18JuJAx E/x8sGL0YzUwCKsDcvT42tYaEk2H4JUqlrd5ocU5qBr56SvGLuVvuQsDHSY1tB/Wz6 n+EZYEdQbn8gBtqqt3n4wfTKX9/YlFMx8p8IgDOl723nUlM/E9Yf+HM/EhwgDmi9xa YIUeXAzE/qr6A== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org Subject: [PATCH 2/3] wifi: mt76: dma: keep rx pages DMA mapped Date: Sun, 1 Jan 2023 12:59:58 +0100 Message-Id: <36edaadfa36577f58611fb4b946acb1a4cd1151a.1672574310.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org For mmio devices rely on page_pool capability to keep rx buffers DMA mapped and just sync rx buffers before accessing them. Tested-by: Felix Fietkau Tested-by: Deren Wu Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/dma.c | 34 +++++++++++-------- drivers/net/wireless/mediatek/mt76/mac80211.c | 8 +++++ .../net/wireless/mediatek/mt76/mt7915/mmio.c | 5 +-- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 4f5b4068d35e..2284ce4fd7cb 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -406,9 +406,14 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, if (!t) return NULL; - dma_unmap_single(dev->dma_dev, t->dma_addr, - SKB_WITH_OVERHEAD(q->buf_size), - DMA_FROM_DEVICE); + if (mt76_is_page_from_pp(t->ptr)) + dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, + SKB_WITH_OVERHEAD(q->buf_size), + page_pool_get_dma_dir(q->page_pool)); + else + dma_unmap_single(dev->dma_dev, t->dma_addr, + SKB_WITH_OVERHEAD(q->buf_size), + DMA_FROM_DEVICE); buf = t->ptr; t->dma_addr = 0; @@ -425,9 +430,14 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx, } else { buf = e->buf; e->buf = NULL; - dma_unmap_single(dev->dma_dev, e->dma_addr[0], - SKB_WITH_OVERHEAD(q->buf_size), - DMA_FROM_DEVICE); + if (mt76_is_page_from_pp(buf)) + dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0], + SKB_WITH_OVERHEAD(q->buf_size), + page_pool_get_dma_dir(q->page_pool)); + else + dma_unmap_single(dev->dma_dev, e->dma_addr[0], + SKB_WITH_OVERHEAD(q->buf_size), + DMA_FROM_DEVICE); } return buf; @@ -591,6 +601,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, spin_lock_bh(&q->lock); while (q->queued < q->ndesc - 1) { + enum dma_data_direction dir; struct mt76_queue_buf qbuf; dma_addr_t addr; int offset; @@ -600,19 +611,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, if (!buf) break; - addr = dma_map_single(dev->dma_dev, buf + offset, len, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(dev->dma_dev, addr))) { - mt76_put_page_pool_buf(buf, allow_direct); - break; - } + addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset; + dir = page_pool_get_dma_dir(q->page_pool); + dma_sync_single_for_device(dev->dma_dev, addr, len, dir); qbuf.addr = addr + q->buf_offset; qbuf.len = len - q->buf_offset; qbuf.skip_unmap = false; if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) { - dma_unmap_single(dev->dma_dev, addr, len, - DMA_FROM_DEVICE); mt76_put_page_pool_buf(buf, allow_direct); break; } diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 9fefb441e4d4..3d6b6f12ffde 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -567,6 +567,14 @@ int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q) .dev = dev->dma_dev, }; + if (mt76_is_mmio(dev)) { + /* rely on page_pool for DMA mapping */ + pp_params.flags |= PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; + pp_params.dma_dir = DMA_FROM_DEVICE; + pp_params.max_len = PAGE_SIZE; + pp_params.offset = 0; + } + q->page_pool = page_pool_create(&pp_params); if (IS_ERR(q->page_pool)) { int err = PTR_ERR(q->page_pool); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 30ec490b47b6..757c2e25c25f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -604,8 +604,9 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) if (!t || !t->ptr) continue; - dma_unmap_single(dev->mt76.dma_dev, t->dma_addr, - wed->wlan.rx_size, DMA_FROM_DEVICE); + if (!mt76_is_page_from_pp(t->ptr)) + dma_unmap_single(dev->mt76.dma_dev, t->dma_addr, + wed->wlan.rx_size, DMA_FROM_DEVICE); mt76_put_page_pool_buf(t->ptr, false); t->ptr = NULL; From patchwork Sun Jan 1 11:59:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 638418 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B8970C4708E for ; Sun, 1 Jan 2023 12:00:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230448AbjAAMAZ (ORCPT ); Sun, 1 Jan 2023 07:00:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37348 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230084AbjAAMAX (ORCPT ); Sun, 1 Jan 2023 07:00:23 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 218ED3897 for ; Sun, 1 Jan 2023 04:00:20 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id AA1DD60DC1 for ; Sun, 1 Jan 2023 12:00:19 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B96DBC433EF; Sun, 1 Jan 2023 12:00:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1672574419; bh=gWpai8ebe8cYhL5pzNuy6ch3p1tItq+L4/MtLLXKYXU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CZq2fSt7Rx7vUklfMN0PgpN8tnRvpVPc5Wp0QWRy7cD99vmDP1HsFKh81ioEqOjZ+ tjkZWPQAS4dE00rwF9J2KfMoPiBmJK/fLEXLUzzoPlXaGSz8Vz5k7ZiAayxRlV2LRq TOXoIQj0e2FQt4SsIa9e2Ysjyz8gI9gbOI8r+AaQ+tLO2wL6hvUC18rycjJdja9F5a NrCflnxzXlenvCL8vR8kiaAqvksRA/0mlgMwmZDK8pTyIRQb1L/zvRXzqOcpmueLps QqV236x+13iTV7aZF0cUOCP8+tAzoPuUsrGEIcPcaokU9DtBvzRGdfg93bZMahS2BE VXISTNN/pWf0Q== From: Lorenzo Bianconi To: nbd@nbd.name Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org Subject: [PATCH 3/3] wifi: mt76: enable page_pool stats Date: Sun, 1 Jan 2023 12:59:59 +0100 Message-Id: <2a1b36dd3b2579f328b403b5741ec8ae84c574e9.1672574310.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Enable page_pool ethtool statistics for mt7915 and mt7921 chipsets. Tested-by: Felix Fietkau Tested-by: Deren Wu Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/Kconfig | 1 + drivers/net/wireless/mediatek/mt76/mac80211.c | 13 ++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7915/main.c | 26 ++++++++++------ .../net/wireless/mediatek/mt76/mt7921/main.c | 31 ++++++++++++++++--- 5 files changed, 58 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index 18152c16c36f..90e958e608aa 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -2,6 +2,7 @@ config MT76_CORE tristate select PAGE_POOL + select PAGE_POOL_STATS config MT76_LEDS bool diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 3d6b6f12ffde..21fa1077c5b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -1729,6 +1729,19 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, } EXPORT_SYMBOL_GPL(mt76_ethtool_worker); +void mt76_ethtool_page_pool_stats(struct mt76_dev *dev, u64 *data, int *index) +{ + struct page_pool_stats stats = {}; + int i; + + mt76_for_each_q_rx(dev, i) + page_pool_get_stats(dev->q_rx[i].page_pool, &stats); + + page_pool_ethtool_stats_get(data, &stats); + *index += page_pool_ethtool_stats_get_count(); +} +EXPORT_SYMBOL_GPL(mt76_ethtool_page_pool_stats); + enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy) { struct ieee80211_hw *hw = phy->hw; diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 885d39411f68..7c3036eea3f8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1310,6 +1310,7 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout); } +void mt76_ethtool_page_pool_stats(struct mt76_dev *dev, u64 *data, int *index); void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, struct mt76_sta_stats *stats); int mt76_skb_adjust_pad(struct sk_buff *skb, int pad); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 0511d6a505b0..9ae10e780d74 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -1280,19 +1280,22 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 sset, u8 *data) { - if (sset == ETH_SS_STATS) - memcpy(data, *mt7915_gstrings_stats, - sizeof(mt7915_gstrings_stats)); + if (sset != ETH_SS_STATS) + return; + + memcpy(data, *mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats)); + data += sizeof(mt7915_gstrings_stats); + page_pool_ethtool_stats_get_strings(data); } static int mt7915_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int sset) { - if (sset == ETH_SS_STATS) - return MT7915_SSTATS_LEN; + if (sset != ETH_SS_STATS) + return 0; - return 0; + return MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count(); } static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) @@ -1320,7 +1323,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, }; struct mib_stats *mib = &phy->mib; /* See mt7915_ampdu_stat_read_phy, etc */ - int i, ei = 0; + int i, ei = 0, stats_size; mutex_lock(&dev->mt76.mutex); @@ -1401,9 +1404,12 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, return; ei += wi.worker_stat_count; - if (ei != MT7915_SSTATS_LEN) - dev_err(dev->mt76.dev, "ei: %d MT7915_SSTATS_LEN: %d", - ei, (int)MT7915_SSTATS_LEN); + + mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei); + + stats_size = MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count(); + if (ei != stats_size) + dev_err(dev->mt76.dev, "ei: %d size: %d", ei, stats_size); } static void diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 76ac5069638f..7d53ddd3bf15 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1135,17 +1135,34 @@ static void mt7921_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 sset, u8 *data) { + struct mt7921_dev *dev = mt7921_hw_dev(hw); + if (sset != ETH_SS_STATS) return; memcpy(data, *mt7921_gstrings_stats, sizeof(mt7921_gstrings_stats)); + + if (mt76_is_sdio(&dev->mt76)) + return; + + data += sizeof(mt7921_gstrings_stats); + page_pool_ethtool_stats_get_strings(data); } static int mt7921_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int sset) { - return sset == ETH_SS_STATS ? ARRAY_SIZE(mt7921_gstrings_stats) : 0; + struct mt7921_dev *dev = mt7921_hw_dev(hw); + + if (sset != ETH_SS_STATS) + return 0; + + if (mt76_is_sdio(&dev->mt76)) + return ARRAY_SIZE(mt7921_gstrings_stats); + + return ARRAY_SIZE(mt7921_gstrings_stats) + + page_pool_ethtool_stats_get_count(); } static void @@ -1165,6 +1182,7 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ethtool_stats *stats, u64 *data) { struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + int stats_size = ARRAY_SIZE(mt7921_gstrings_stats); struct mt7921_phy *phy = mt7921_hw_phy(hw); struct mt7921_dev *dev = phy->dev; struct mib_stats *mib = &phy->mib; @@ -1220,9 +1238,14 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return; ei += wi.worker_stat_count; - if (ei != ARRAY_SIZE(mt7921_gstrings_stats)) - dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %zu", - ei, ARRAY_SIZE(mt7921_gstrings_stats)); + + if (!mt76_is_sdio(&dev->mt76)) { + mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei); + stats_size += page_pool_ethtool_stats_get_count(); + } + + if (ei != stats_size) + dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %d", ei, stats_size); } static u64