From 77e80bb33fd627434c2450cb5cc88e5ddfc93ca8 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Fri, 14 Mar 2025 23:59:41 -0400 Subject: [PATCH] niu: Create struct niu_page The map_page() call returns a u64, so using page->private or page->index to store the result from that will truncate it on 32-bit systems. Additionally, the next pointer is stored in page->mapping and we're trying to remove references to page->mapping. So define a driver-private struct which overlays struct page and lets us store the 64-bit result of map_page. Gets rid of the niu_next_page() macro; we can use the much more natural page->next instead. Signed-off-by: Matthew Wilcox (Oracle) --- drivers/net/ethernet/sun/niu.c | 93 +++++++++++++--------------------- drivers/net/ethernet/sun/niu.h | 18 ++++++- 2 files changed, 53 insertions(+), 58 deletions(-) diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 72177fea1cfb3..e3296a8b4bc31 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -35,25 +35,6 @@ #include "niu.h" -/* This driver wants to store a link to a "next page" within the - * page struct itself by overloading the content of the "mapping" - * member. This is not expected by the page API, but does currently - * work. However, the randstruct plugin gets very bothered by this - * case because "mapping" (struct address_space) is randomized, so - * casts to/from it trigger warnings. Hide this by way of a union, - * to create a typed alias of "mapping", since that's how it is - * actually being used here. - */ -union niu_page { - struct page page; - struct { - unsigned long __flags; /* unused alias of "flags" */ - struct list_head __lru; /* unused alias of "lru" */ - struct page *next; /* alias of "mapping" */ - }; -}; -#define niu_next_page(p) container_of(p, union niu_page, page)->next - #define DRV_MODULE_NAME "niu" #define DRV_MODULE_VERSION "1.1" #define DRV_MODULE_RELDATE "Apr 22, 2010" @@ -3294,16 +3275,16 @@ static unsigned int niu_hash_rxaddr(struct rx_ring_info *rp, u64 a) return a & (MAX_RBR_RING_SIZE - 1); } -static struct page *niu_find_rxpage(struct rx_ring_info *rp, u64 addr, - struct page ***link) +static struct niu_page *niu_find_rxpage(struct rx_ring_info *rp, u64 addr, + struct niu_page ***link) { unsigned int h = niu_hash_rxaddr(rp, addr); - struct page *p, **pp; + struct niu_page *p, **pp; addr &= PAGE_MASK; pp = &rp->rxhash[h]; - for (; (p = *pp) != NULL; pp = &niu_next_page(p)) { - if (p->private == addr) { + for (; (p = *pp) != NULL; pp = &p->next) { + if (p->dma_addr == addr) { *link = pp; goto found; } @@ -3314,13 +3295,15 @@ found: return p; } -static void niu_hash_page(struct rx_ring_info *rp, struct page *page, u64 base) +static void niu_hash_page(struct rx_ring_info *rp, struct page *page, + u64 base) { + struct niu_page *niu_page = (struct niu_page *)page; unsigned int h = niu_hash_rxaddr(rp, base); - page->private = base; - niu_next_page(page) = rp->rxhash[h]; - rp->rxhash[h] = page; + niu_page->dma_addr = base; + niu_page->next = rp->rxhash[h]; + rp->rxhash[h] = niu_page; } static int niu_rbr_add_page(struct niu *np, struct rx_ring_info *rp, @@ -3387,7 +3370,7 @@ static int niu_rx_pkt_ignore(struct niu *np, struct rx_ring_info *rp) rp->rx_dropped++; while (1) { - struct page *page, **link; + struct niu_page *page, **link; u64 addr, val; u32 rcr_size; @@ -3400,13 +3383,13 @@ static int niu_rx_pkt_ignore(struct niu *np, struct rx_ring_info *rp) rcr_size = rp->rbr_sizes[(val & RCR_ENTRY_PKTBUFSZ) >> RCR_ENTRY_PKTBUFSZ_SHIFT]; - if ((page->private + PAGE_SIZE) - rcr_size == addr) { - *link = niu_next_page(page); - np->ops->unmap_page(np->device, page->private, + if ((page->dma_addr + PAGE_SIZE) - rcr_size == addr) { + *link = page->next; + np->ops->unmap_page(np->device, page->dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); - page->private = 0; - niu_next_page(page) = NULL; - __free_page(page); + page->dma_addr = 0; + page->next = NULL; + __free_page(&page->page); rp->rbr_refill_pending++; } @@ -3434,7 +3417,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, num_rcr = 0; while (1) { - struct page *page, **link; + struct niu_page *page, **link; u32 rcr_size, append_size; u64 addr, val, off; @@ -3468,16 +3451,16 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, } else if (!(val & RCR_ENTRY_MULTI)) append_size = append_size - skb->len; - niu_rx_skb_append(skb, page, off, append_size, rcr_size); - if ((page->private + rp->rbr_block_size) - rcr_size == addr) { - *link = niu_next_page(page); - np->ops->unmap_page(np->device, page->private, + niu_rx_skb_append(skb, &page->page, off, append_size, rcr_size); + if ((page->dma_addr + rp->rbr_block_size) - rcr_size == addr) { + *link = page->next; + np->ops->unmap_page(np->device, page->dma_addr, PAGE_SIZE, DMA_FROM_DEVICE); - page->private = 0; - niu_next_page(page) = NULL; + page->dma_addr = 0; + page->next = NULL; rp->rbr_refill_pending++; } else - get_page(page); + get_page(&page->page); index = NEXT_RCR(rp, index); if (!(val & RCR_ENTRY_MULTI)) @@ -3533,19 +3516,18 @@ static void niu_rbr_free(struct niu *np, struct rx_ring_info *rp) int i; for (i = 0; i < MAX_RBR_RING_SIZE; i++) { - struct page *page; + struct niu_page *page; page = rp->rxhash[i]; while (page) { - struct page *next = niu_next_page(page); - u64 base = page->private; + struct niu_page *next = page->next; - np->ops->unmap_page(np->device, base, PAGE_SIZE, - DMA_FROM_DEVICE); - page->private = 0; - niu_next_page(page) = NULL; + np->ops->unmap_page(np->device, page->dma_addr, + PAGE_SIZE, DMA_FROM_DEVICE); + page->dma_addr = 0; + page->next = NULL; - __free_page(page); + __free_page(&page->page); page = next; } @@ -6457,12 +6439,12 @@ static void niu_reset_buffers(struct niu *np) struct rx_ring_info *rp = &np->rx_rings[i]; for (j = 0, k = 0; j < MAX_RBR_RING_SIZE; j++) { - struct page *page; + struct niu_page *page; page = rp->rxhash[j]; while (page) { - struct page *next = niu_next_page(page); - u64 base = page->private; + struct niu_page *next = page->next; + u64 base = page->dma_addr; base = base >> RBR_DESCR_ADDR_SHIFT; rp->rbr[k++] = cpu_to_le32(base); page = next; @@ -10201,9 +10183,6 @@ static int __init niu_init(void) BUILD_BUG_ON(PAGE_SIZE < 4 * 1024); - BUILD_BUG_ON(offsetof(struct page, mapping) != - offsetof(union niu_page, next)); - niu_debug = netif_msg_init(debug, NIU_MSG_DEFAULT); #ifdef CONFIG_SPARC64 diff --git a/drivers/net/ethernet/sun/niu.h b/drivers/net/ethernet/sun/niu.h index 04c215f91fc08..c3d9243e7d053 100644 --- a/drivers/net/ethernet/sun/niu.h +++ b/drivers/net/ethernet/sun/niu.h @@ -2904,6 +2904,22 @@ struct rxdma_mailbox { #define RX_SKB_ALLOC_SIZE 128 + NET_IP_ALIGN +/* + * Overlays struct page + */ +struct niu_page { + union { + struct { + unsigned long flags; + struct niu_page *next; + unsigned long pad[2]; /* lru.prev & mapping */ + u64 dma_addr; /* index (& private on 32b) */ + }; + struct page page; + }; +}; +static_assert(sizeof(struct niu_page) <= sizeof(struct page)); + struct rx_ring_info { struct niu *np; int rx_channel; @@ -2917,7 +2933,7 @@ struct rx_ring_info { unsigned int rbr_refill_pending; unsigned int rbr_kick_thresh; unsigned int rbr_table_size; - struct page **rxhash; + struct niu_page **rxhash; struct rxdma_mailbox *mbox; __le64 *rcr; __le32 *rbr; -- 2.50.1