/* * Atmel MACB Ethernet Controller driver * * Copyright (C) 2004-2006 Atmel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/clk.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/mii.h>#include <linux/mutex.h>#include <linux/dma-mapping.h>#include <linux/ethtool.h>#include <linux/platform_device.h> #include <asm/arch/board.h> #include "macb.h" #define RX_BUFFER_SIZE 128#define RX_RING_SIZE 512#define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE) /* Make the IP header word-aligned (the ethernet header is 14 bytes) */#define RX_OFFSET 2 #define TX_RING_SIZE 128#define DEF_TX_RING_PENDING (TX_RING_SIZE - 1)#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE) #define TX_RING_GAP(bp) \ (TX_RING_SIZE - (bp)->tx_pending)#define TX_BUFFS_AVAIL(bp) \ (((bp)->tx_tail <= (bp)->tx_head) ? \ (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \ (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp))#define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1)) #define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1)) /* minimum number of free TX descriptors before waking up TX process */#define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4) #define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \ | MACB_BIT(ISR_ROVR)) static void __macb_set_hwaddr(struct macb *bp){ u32 bottom; u16 top; bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr)); macb_writel(bp, SA1B, bottom); top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4))); macb_writel(bp, SA1T, top);} static void __init macb_get_hwaddr(struct macb *bp){ u32 bottom; u16 top; u8 addr[6]; bottom = macb_readl(bp, SA1B); top = macb_readl(bp, SA1T); addr[0] = bottom & 0xff; addr[1] = (bottom >> 8) & 0xff; addr[2] = (bottom >> 16) & 0xff; addr[3] = (bottom >> 24) & 0xff; addr[4] = top & 0xff; addr[5] = (top >> 8) & 0xff; if (is_valid_ether_addr(addr)) memcpy(bp->dev->dev_addr, addr, sizeof(addr));} static void macb_enable_mdio(struct macb *bp){ unsigned long flags; u32 reg; spin_lock_irqsave(&bp->lock, flags); reg = macb_readl(bp, NCR); reg |= MACB_BIT(MPE); macb_writel(bp, NCR, reg); macb_writel(bp, IER, MACB_BIT(MFD)); spin_unlock_irqrestore(&bp->lock, flags);} static void macb_disable_mdio(struct macb *bp){ unsigned long flags; u32 reg; spin_lock_irqsave(&bp->lock, flags); reg = macb_readl(bp, NCR); reg &= ~MACB_BIT(MPE); macb_writel(bp, NCR, reg); macb_writel(bp, IDR, MACB_BIT(MFD)); spin_unlock_irqrestore(&bp->lock, flags);} static int macb_mdio_read(struct net_device *dev, int phy_id, int location){ struct macb *bp = netdev_priv(dev); int value; mutex_lock(&bp->mdio_mutex); macb_enable_mdio(bp); macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_READ) | MACB_BF(PHYA, phy_id) | MACB_BF(REGA, location) | MACB_BF(CODE, MACB_MAN_CODE))); wait_for_completion(&bp->mdio_complete); value = MACB_BFEXT(DATA, macb_readl(bp, MAN)); macb_disable_mdio(bp); mutex_unlock(&bp->mdio_mutex); return value;} static void macb_mdio_write(struct net_device *dev, int phy_id, int location, int val){ struct macb *bp = netdev_priv(dev); dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n", phy_id, location, val); mutex_lock(&bp->mdio_mutex); macb_enable_mdio(bp); macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_WRITE) | MACB_BF(PHYA, phy_id) | MACB_BF(REGA, location) | MACB_BF(CODE, MACB_MAN_CODE) | MACB_BF(DATA, val))); wait_for_completion(&bp->mdio_complete); macb_disable_mdio(bp); mutex_unlock(&bp->mdio_mutex);} static int macb_phy_probe(struct macb *bp){ int phy_address; u16 phyid1, phyid2; for (phy_address = 0; phy_address < 32; phy_address++) { phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1); phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2); if (phyid1 != 0xffff && phyid1 != 0x0000 && phyid2 != 0xffff && phyid2 != 0x0000) break; } if (phy_address == 32) return -ENODEV; dev_info(&bp->pdev->dev, "detected PHY at address %d (ID %04x:%04x)\n", phy_address, phyid1, phyid2); bp->mii.phy_id = phy_address; return 0;} static void macb_set_media(struct macb *bp, int media){ u32 reg; spin_lock_irq(&bp->lock); reg = macb_readl(bp, NCFGR); reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL)) reg |= MACB_BIT(SPD); if (media & ADVERTISE_FULL) reg |= MACB_BIT(FD); macb_writel(bp, NCFGR, reg); spin_unlock_irq(&bp->lock);} static void macb_check_media(struct macb *bp, int ok_to_print, int init_media){ struct mii_if_info *mii = &bp->mii; unsigned int old_carrier, new_carrier; int advertise, lpa, media, duplex; /* if forced media, go no further */ if (mii->force_media) return; /* check current and old link status */ old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; new_carrier = (unsigned int) mii_link_ok(mii); /* if carrier state did not change, assume nothing else did */ if (!init_media && old_carrier == new_carrier) return; /* no carrier, nothing much to do */ if (!new_carrier) { netif_carrier_off(mii->dev); printk(KERN_INFO "%s: link down\n", mii->dev->name); return; } /* * we have carrier, see who's on the other end */ netif_carrier_on(mii->dev); /* get MII advertise and LPA values */ if (!init_media && mii->advertising) { advertise = mii->advertising; } else { advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); mii->advertising = advertise; } lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); /* figure out media and duplex from advertise and LPA values */ media = mii_nway_result(lpa & advertise); duplex = (media & ADVERTISE_FULL) ? 1 : 0; if (ok_to_print) printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", mii->dev->name, media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10", duplex ? "full" : "half", lpa); mii->full_duplex = duplex; /* Let the MAC know about the new link state */ macb_set_media(bp, media);} static void macb_update_stats(struct macb *bp){ u32 __iomem *reg = bp->regs + MACB_PFR; u32 *p = &bp->hw_stats.rx_pause_frames; u32 *end = &bp->hw_stats.tx_pause_frames + 1; WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); for(; p < end; p++, reg++) *p += __raw_readl(reg);} static void macb_periodic_task(struct work_struct *work){ struct macb *bp = container_of(work, struct macb, periodic_task.work); macb_update_stats(bp); macb_check_media(bp, 1, 0); schedule_delayed_work(&bp->periodic_task, HZ);} static void macb_tx(struct macb *bp){ unsigned int tail; unsigned int head; u32 status; status = macb_readl(bp, TSR); macb_writel(bp, TSR, status); dev_dbg(&bp->pdev->dev, "macb_tx status = %02lx\n", (unsigned long)status); if (status & MACB_BIT(UND)) { printk(KERN_ERR "%s: TX underrun, resetting buffers\n", bp->dev->name); bp->tx_head = bp->tx_tail = 0; } if (!(status & MACB_BIT(COMP))) /* * This may happen when a buffer becomes complete * between reading the ISR and scanning the * descriptors. Nothing to worry about. */ return; head = bp->tx_head; for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { struct ring_info *rp = &bp->tx_skb[tail]; struct sk_buff *skb = rp->skb; u32 bufstat; BUG_ON(skb == NULL); rmb(); bufstat = bp->tx_ring[tail].ctrl; if (!(bufstat & MACB_BIT(TX_USED))) break; dev_dbg(&bp->pdev->dev, "skb %u (data %p) TX complete\n", tail, skb->data); dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len, DMA_TO_DEVICE); bp->stats.tx_packets++; bp->stats.tx_bytes += skb->len; rp->skb = NULL; dev_kfree_skb_irq(skb); } bp->tx_tail = tail; if (netif_queue_stopped(bp->dev) && TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH) netif_wake_queue(bp->dev);} static int macb_rx_frame(struct macb *bp, unsigned int first_frag, unsigned int last_frag){ unsigned int len; unsigned int frag; unsigned int offset = 0; struct sk_buff *skb; len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl); dev_dbg(&bp->pdev->dev, "macb_rx_frame frags %u - %u (len %u)\n", first_frag, last_frag, len); skb = dev_alloc_skb(len + RX_OFFSET); if (!skb) { bp->stats.rx_dropped++; for (frag = first_frag; ; frag = NEXT_RX(frag)) { bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); if (frag == last_frag) break; } wmb(); return 1; } skb_reserve(skb, RX_OFFSET); skb->dev = bp->dev; skb->ip_summed = CHECKSUM_NONE; skb_put(skb, len); for (frag = first_frag; ; frag = NEXT_RX(frag)) { unsigned int frag_len = RX_BUFFER_SIZE; if (offset + frag_len > len) { BUG_ON(frag != last_frag); frag_len = len - offset; } memcpy(skb->data + offset, bp->rx_buffers + (RX_BUFFER_SIZE * frag), frag_len); offset += RX_BUFFER_SIZE; bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); wmb(); if (frag == last_frag) break; } skb->protocol = eth_type_trans(skb, bp->dev); bp->stats.rx_packets++; bp->stats.rx_bytes += len; bp->dev->last_rx = jiffies; dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n", skb->len, skb->csum); netif_receive_skb(skb); return 0;} /* Mark DMA descriptors from begin up to and not including end as unused */static void discard_partial_frame(struct macb *bp, unsigned int begin, unsigned int end){ unsigned int frag; for (frag = begin; frag != end; frag = NEXT_RX(frag)) bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); wmb(); /* * When this happens, the hardware stats registers for * whatever caused this is updated, so we don't have to record * anything. */} static int macb_rx(struct macb *bp, int budget){ int received = 0; unsigned int tail = bp->rx_tail; int first_frag = -1; for (; budget > 0; tail = NEXT_RX(tail)) { u32 addr, ctrl; rmb(); addr = bp->rx_ring[tail].addr; ctrl = bp->rx_ring[tail].ctrl; if (!(addr & MACB_BIT(RX_USED))) break; if (ctrl & MACB_BIT(RX_SOF)) { if (first_frag != -1) discard_partial_frame(bp, first_frag, tail); first_frag = tail; } if (ctrl & MACB_BIT(RX_EOF)) { int dropped; BUG_ON(first_frag == -1); dropped = macb_rx_frame(bp, first_frag, tail); first_frag = -1; if (!dropped) { received++; budget--; } } } if (first_frag != -1) bp->rx_tail = first_frag; else bp->rx_tail = tail; return received;} static int macb_poll(struct net_device *dev, int *budget){ struct macb *bp = netdev_priv(dev); int orig_budget, work_done, retval = 0; u32 status; status = macb_readl(bp, RSR); macb_writel(bp, RSR, status); if (!status) { /* * This may happen if an interrupt was pending before * this function was called last time, and no packets * have been received since. */ netif_rx_complete(dev); goto out; } dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n", (unsigned long)status, *budget); if (!(status & MACB_BIT(REC))) { dev_warn(&bp->pdev->dev, "No RX buffers complete, status = %02lx\n", (unsigned long)status); netif_rx_complete(dev); goto out; } orig_budget = *budget; if (orig_budget > dev->quota) orig_budget = dev->quota; work_done = macb_rx(bp, orig_budget); if (work_done < orig_budget) { netif_rx_complete(dev); retval = 0; } else { retval = 1; } /* * We've done what we can to clean the buffers. Make sure we * get notified when new packets arrive. */out:Lines 1–500 of 1213. Load more
/* * Atmel MACB Ethernet Controller driver * * Copyright (C) 2004-2006 Atmel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/clk.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/mii.h> #include <linux/mutex.h> #include <linux/dma-mapping.h> #include <linux/ethtool.h> #include <linux/platform_device.h> #include <asm/arch/board.h> #include "macb.h" #define RX_BUFFER_SIZE 128 #define RX_RING_SIZE 512 #define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE) /* Make the IP header word-aligned (the ethernet header is 14 bytes) */ #define RX_OFFSET 2 #define TX_RING_SIZE 128 #define DEF_TX_RING_PENDING (TX_RING_SIZE - 1) #define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE) #define TX_RING_GAP(bp) \ (TX_RING_SIZE - (bp)->tx_pending) #define TX_BUFFS_AVAIL(bp) \ (((bp)->tx_tail <= (bp)->tx_head) ? \ (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \ (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp)) #define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1)) #define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1)) /* minimum number of free TX descriptors before waking up TX process */ #define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4) #define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \ | MACB_BIT(ISR_ROVR)) static void __macb_set_hwaddr(struct macb *bp) { u32 bottom; u16 top; bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr)); macb_writel(bp, SA1B, bottom); top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4))); macb_writel(bp, SA1T, top); } static void __init macb_get_hwaddr(struct macb *bp) { u32 bottom; u16 top; u8 addr[6]; bottom = macb_readl(bp, SA1B); top = macb_readl(bp, SA1T); addr[0] = bottom & 0xff; addr[1] = (bottom >> 8) & 0xff; addr[2] = (bottom >> 16) & 0xff; addr[3] = (bottom >> 24) & 0xff; addr[4] = top & 0xff; addr[5] = (top >> 8) & 0xff; if (is_valid_ether_addr(addr)) memcpy(bp->dev->dev_addr, addr, sizeof(addr)); } static void macb_enable_mdio(struct macb *bp) { unsigned long flags; u32 reg; spin_lock_irqsave(&bp->lock, flags); reg = macb_readl(bp, NCR); reg |= MACB_BIT(MPE); macb_writel(bp, NCR, reg); macb_writel(bp, IER, MACB_BIT(MFD)); spin_unlock_irqrestore(&bp->lock, flags); } static void macb_disable_mdio(struct macb *bp) { unsigned long flags; u32 reg; spin_lock_irqsave(&bp->lock, flags); reg = macb_readl(bp, NCR); reg &= ~MACB_BIT(MPE); macb_writel(bp, NCR, reg); macb_writel(bp, IDR, MACB_BIT(MFD)); spin_unlock_irqrestore(&bp->lock, flags); } static int macb_mdio_read(struct net_device *dev, int phy_id, int location) { struct macb *bp = netdev_priv(dev); int value; mutex_lock(&bp->mdio_mutex); macb_enable_mdio(bp); macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_READ) | MACB_BF(PHYA, phy_id) | MACB_BF(REGA, location) | MACB_BF(CODE, MACB_MAN_CODE))); wait_for_completion(&bp->mdio_complete); value = MACB_BFEXT(DATA, macb_readl(bp, MAN)); macb_disable_mdio(bp); mutex_unlock(&bp->mdio_mutex); return value; } static void macb_mdio_write(struct net_device *dev, int phy_id, int location, int val) { struct macb *bp = netdev_priv(dev); dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n", phy_id, location, val); mutex_lock(&bp->mdio_mutex); macb_enable_mdio(bp); macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_WRITE) | MACB_BF(PHYA, phy_id) | MACB_BF(REGA, location) | MACB_BF(CODE, MACB_MAN_CODE) | MACB_BF(DATA, val))); wait_for_completion(&bp->mdio_complete); macb_disable_mdio(bp); mutex_unlock(&bp->mdio_mutex); } static int macb_phy_probe(struct macb *bp) { int phy_address; u16 phyid1, phyid2; for (phy_address = 0; phy_address < 32; phy_address++) { phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1); phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2); if (phyid1 != 0xffff && phyid1 != 0x0000 && phyid2 != 0xffff && phyid2 != 0x0000) break; } if (phy_address == 32) return -ENODEV; dev_info(&bp->pdev->dev, "detected PHY at address %d (ID %04x:%04x)\n", phy_address, phyid1, phyid2); bp->mii.phy_id = phy_address; return 0; } static void macb_set_media(struct macb *bp, int media) { u32 reg; spin_lock_irq(&bp->lock); reg = macb_readl(bp, NCFGR); reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL)) reg |= MACB_BIT(SPD); if (media & ADVERTISE_FULL) reg |= MACB_BIT(FD); macb_writel(bp, NCFGR, reg); spin_unlock_irq(&bp->lock); } static void macb_check_media(struct macb *bp, int ok_to_print, int init_media) { struct mii_if_info *mii = &bp->mii; unsigned int old_carrier, new_carrier; int advertise, lpa, media, duplex; /* if forced media, go no further */ if (mii->force_media) return; /* check current and old link status */ old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; new_carrier = (unsigned int) mii_link_ok(mii); /* if carrier state did not change, assume nothing else did */ if (!init_media && old_carrier == new_carrier) return; /* no carrier, nothing much to do */ if (!new_carrier) { netif_carrier_off(mii->dev); printk(KERN_INFO "%s: link down\n", mii->dev->name); return; } /* * we have carrier, see who's on the other end */ netif_carrier_on(mii->dev); /* get MII advertise and LPA values */ if (!init_media && mii->advertising) { advertise = mii->advertising; } else { advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); mii->advertising = advertise; } lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); /* figure out media and duplex from advertise and LPA values */ media = mii_nway_result(lpa & advertise); duplex = (media & ADVERTISE_FULL) ? 1 : 0; if (ok_to_print) printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", mii->dev->name, media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10", duplex ? "full" : "half", lpa); mii->full_duplex = duplex; /* Let the MAC know about the new link state */ macb_set_media(bp, media); } static void macb_update_stats(struct macb *bp) { u32 __iomem *reg = bp->regs + MACB_PFR; u32 *p = &bp->hw_stats.rx_pause_frames; u32 *end = &bp->hw_stats.tx_pause_frames + 1; WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); for(; p < end; p++, reg++) *p += __raw_readl(reg); } static void macb_periodic_task(struct work_struct *work) { struct macb *bp = container_of(work, struct macb, periodic_task.work); macb_update_stats(bp); macb_check_media(bp, 1, 0); schedule_delayed_work(&bp->periodic_task, HZ); } static void macb_tx(struct macb *bp) { unsigned int tail; unsigned int head; u32 status; status = macb_readl(bp, TSR); macb_writel(bp, TSR, status); dev_dbg(&bp->pdev->dev, "macb_tx status = %02lx\n", (unsigned long)status); if (status & MACB_BIT(UND)) { printk(KERN_ERR "%s: TX underrun, resetting buffers\n", bp->dev->name); bp->tx_head = bp->tx_tail = 0; } if (!(status & MACB_BIT(COMP))) /* * This may happen when a buffer becomes complete * between reading the ISR and scanning the * descriptors. Nothing to worry about. */ return; head = bp->tx_head; for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { struct ring_info *rp = &bp->tx_skb[tail]; struct sk_buff *skb = rp->skb; u32 bufstat; BUG_ON(skb == NULL); rmb(); bufstat = bp->tx_ring[tail].ctrl; if (!(bufstat & MACB_BIT(TX_USED))) break; dev_dbg(&bp->pdev->dev, "skb %u (data %p) TX complete\n", tail, skb->data); dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len, DMA_TO_DEVICE); bp->stats.tx_packets++; bp->stats.tx_bytes += skb->len; rp->skb = NULL; dev_kfree_skb_irq(skb); } bp->tx_tail = tail; if (netif_queue_stopped(bp->dev) && TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH) netif_wake_queue(bp->dev); } static int macb_rx_frame(struct macb *bp, unsigned int first_frag, unsigned int last_frag) { unsigned int len; unsigned int frag; unsigned int offset = 0; struct sk_buff *skb; len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl); dev_dbg(&bp->pdev->dev, "macb_rx_frame frags %u - %u (len %u)\n", first_frag, last_frag, len); skb = dev_alloc_skb(len + RX_OFFSET); if (!skb) { bp->stats.rx_dropped++; for (frag = first_frag; ; frag = NEXT_RX(frag)) { bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); if (frag == last_frag) break; } wmb(); return 1; } skb_reserve(skb, RX_OFFSET); skb->dev = bp->dev; skb->ip_summed = CHECKSUM_NONE; skb_put(skb, len); for (frag = first_frag; ; frag = NEXT_RX(frag)) { unsigned int frag_len = RX_BUFFER_SIZE; if (offset + frag_len > len) { BUG_ON(frag != last_frag); frag_len = len - offset; } memcpy(skb->data + offset, bp->rx_buffers + (RX_BUFFER_SIZE * frag), frag_len); offset += RX_BUFFER_SIZE; bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); wmb(); if (frag == last_frag) break; } skb->protocol = eth_type_trans(skb, bp->dev); bp->stats.rx_packets++; bp->stats.rx_bytes += len; bp->dev->last_rx = jiffies; dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n", skb->len, skb->csum); netif_receive_skb(skb); return 0; } /* Mark DMA descriptors from begin up to and not including end as unused */ static void discard_partial_frame(struct macb *bp, unsigned int begin, unsigned int end) { unsigned int frag; for (frag = begin; frag != end; frag = NEXT_RX(frag)) bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); wmb(); /* * When this happens, the hardware stats registers for * whatever caused this is updated, so we don't have to record * anything. */ } static int macb_rx(struct macb *bp, int budget) { int received = 0; unsigned int tail = bp->rx_tail; int first_frag = -1; for (; budget > 0; tail = NEXT_RX(tail)) { u32 addr, ctrl; rmb(); addr = bp->rx_ring[tail].addr; ctrl = bp->rx_ring[tail].ctrl; if (!(addr & MACB_BIT(RX_USED))) break; if (ctrl & MACB_BIT(RX_SOF)) { if (first_frag != -1) discard_partial_frame(bp, first_frag, tail); first_frag = tail; } if (ctrl & MACB_BIT(RX_EOF)) { int dropped; BUG_ON(first_frag == -1); dropped = macb_rx_frame(bp, first_frag, tail); first_frag = -1; if (!dropped) { received++; budget--; } } } if (first_frag != -1) bp->rx_tail = first_frag; else bp->rx_tail = tail; return received; } static int macb_poll(struct net_device *dev, int *budget) { struct macb *bp = netdev_priv(dev); int orig_budget, work_done, retval = 0; u32 status; status = macb_readl(bp, RSR); macb_writel(bp, RSR, status); if (!status) { /* * This may happen if an interrupt was pending before * this function was called last time, and no packets * have been received since. */ netif_rx_complete(dev); goto out; } dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n", (unsigned long)status, *budget); if (!(status & MACB_BIT(REC))) { dev_warn(&bp->pdev->dev, "No RX buffers complete, status = %02lx\n", (unsigned long)status); netif_rx_complete(dev); goto out; } orig_budget = *budget; if (orig_budget > dev->quota) orig_budget = dev->quota; work_done = macb_rx(bp, orig_budget); if (work_done < orig_budget) { netif_rx_complete(dev); retval = 0; } else { retval = 1; } /* * We've done what we can to clean the buffers. Make sure we * get notified when new packets arrive. */ out: