#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"
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;
}
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,
rp->rx_dropped++;
while (1) {
- struct page *page, **link;
+ struct niu_page *page, **link;
u64 addr, val;
u32 rcr_size;
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++;
}
num_rcr = 0;
while (1) {
- struct page *page, **link;
+ struct niu_page *page, **link;
u32 rcr_size, append_size;
u64 addr, val, off;
} 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))
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;
}
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;
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