]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
niu: Create struct niu_page
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Sat, 15 Mar 2025 03:59:41 +0000 (23:59 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Mon, 17 Mar 2025 19:55:40 +0000 (15:55 -0400)
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) <willy@infradead.org>
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/sun/niu.h

index 72177fea1cfb3ec2ab78d7f4ae4d0e702da4c7ad..e3296a8b4bc314c4cb6615d69cd780b72a915247 100644 (file)
 
 #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
index 04c215f91fc08e004c4781feb646d7cd4b1e8f83..c3d9243e7d053861d37548afc3c988cd59b44b26 100644 (file)
@@ -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;