Commit 0bbaf069 authored by Kumar Gala's avatar Kumar Gala Committed by Jeff Garzik

[PATCH] gianfar: Add support enhanced TSEC features on the MPC 8548

Jeff,

Just incase this got lost in the recent netdev mailing list transition
here is a nicer version of Andy's patch for gianfar.

- kumar

* TCP/IP/UDP checksumming and verification
* VLAN tag insertion/extraction
* Larger multicast hash-table
* Padding to align IP headers

Also added:
* msg lvl support
* Some whitespace cleanup
Signed-off-by: default avatarAndy Fleming <afleming@freescale.com>
Signed-off-by: default avatarKumar Gala <kumar.gala@freescale.com>
parent be83668a
...@@ -22,9 +22,8 @@ ...@@ -22,9 +22,8 @@
* B-V +1.62 * B-V +1.62
* *
* Theory of operation * Theory of operation
* This driver is designed for the Triple-speed Ethernet * This driver is designed for the non-CPM ethernet controllers
* controllers on the Freescale 8540/8560 integrated processors, * on the 85xx and 83xx family of integrated processors
* as well as the Fast Ethernet Controller on the 8540.
* *
* The driver is initialized through platform_device. Structures which * The driver is initialized through platform_device. Structures which
* define the configuration needed by the board are defined in a * define the configuration needed by the board are defined in a
...@@ -83,9 +82,13 @@ ...@@ -83,9 +82,13 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -123,7 +126,7 @@ static int gfar_set_mac_address(struct net_device *dev); ...@@ -123,7 +126,7 @@ static int gfar_set_mac_address(struct net_device *dev);
static int gfar_change_mtu(struct net_device *dev, int new_mtu); static int gfar_change_mtu(struct net_device *dev, int new_mtu);
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void gfar_phy_change(void *data); static void gfar_phy_change(void *data);
...@@ -139,9 +142,12 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); ...@@ -139,9 +142,12 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
#ifdef CONFIG_GFAR_NAPI #ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget); static int gfar_poll(struct net_device *dev, int *budget);
#endif #endif
static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
static void gfar_phy_startup_timer(unsigned long data); static void gfar_phy_startup_timer(unsigned long data);
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
extern struct ethtool_ops gfar_ethtool_ops; extern struct ethtool_ops gfar_ethtool_ops;
...@@ -149,6 +155,13 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc"); ...@@ -149,6 +155,13 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc");
MODULE_DESCRIPTION("Gianfar Ethernet Driver"); MODULE_DESCRIPTION("Gianfar Ethernet Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
int gfar_uses_fcb(struct gfar_private *priv)
{
if (priv->vlan_enable || priv->rx_csum_enable)
return 1;
else
return 0;
}
static int gfar_probe(struct device *device) static int gfar_probe(struct device *device)
{ {
u32 tempval; u32 tempval;
...@@ -159,7 +172,6 @@ static int gfar_probe(struct device *device) ...@@ -159,7 +172,6 @@ static int gfar_probe(struct device *device)
struct resource *r; struct resource *r;
int idx; int idx;
int err = 0; int err = 0;
int dev_ethtool_ops = 0;
einfo = (struct gianfar_platform_data *) pdev->dev.platform_data; einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
...@@ -265,15 +277,69 @@ static int gfar_probe(struct device *device) ...@@ -265,15 +277,69 @@ static int gfar_probe(struct device *device)
dev->mtu = 1500; dev->mtu = 1500;
dev->set_multicast_list = gfar_set_multi; dev->set_multicast_list = gfar_set_multi;
/* Index into the array of possible ethtool dev->ethtool_ops = &gfar_ethtool_ops;
* ops to catch all 4 possibilities */
if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) == 0) if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
dev_ethtool_ops += 1; priv->rx_csum_enable = 1;
dev->features |= NETIF_F_IP_CSUM;
} else
priv->rx_csum_enable = 0;
priv->vlgrp = NULL;
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
dev->vlan_rx_register = gfar_vlan_rx_register;
dev->vlan_rx_kill_vid = gfar_vlan_rx_kill_vid;
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
priv->vlan_enable = 1;
}
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
priv->extended_hash = 1;
priv->hash_width = 9;
priv->hash_regs[0] = &priv->regs->igaddr0;
priv->hash_regs[1] = &priv->regs->igaddr1;
priv->hash_regs[2] = &priv->regs->igaddr2;
priv->hash_regs[3] = &priv->regs->igaddr3;
priv->hash_regs[4] = &priv->regs->igaddr4;
priv->hash_regs[5] = &priv->regs->igaddr5;
priv->hash_regs[6] = &priv->regs->igaddr6;
priv->hash_regs[7] = &priv->regs->igaddr7;
priv->hash_regs[8] = &priv->regs->gaddr0;
priv->hash_regs[9] = &priv->regs->gaddr1;
priv->hash_regs[10] = &priv->regs->gaddr2;
priv->hash_regs[11] = &priv->regs->gaddr3;
priv->hash_regs[12] = &priv->regs->gaddr4;
priv->hash_regs[13] = &priv->regs->gaddr5;
priv->hash_regs[14] = &priv->regs->gaddr6;
priv->hash_regs[15] = &priv->regs->gaddr7;
if((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE) == 0) } else {
dev_ethtool_ops += 2; priv->extended_hash = 0;
priv->hash_width = 8;
priv->hash_regs[0] = &priv->regs->gaddr0;
priv->hash_regs[1] = &priv->regs->gaddr1;
priv->hash_regs[2] = &priv->regs->gaddr2;
priv->hash_regs[3] = &priv->regs->gaddr3;
priv->hash_regs[4] = &priv->regs->gaddr4;
priv->hash_regs[5] = &priv->regs->gaddr5;
priv->hash_regs[6] = &priv->regs->gaddr6;
priv->hash_regs[7] = &priv->regs->gaddr7;
}
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_PADDING)
priv->padding = DEFAULT_PADDING;
else
priv->padding = 0;
dev->hard_header_len += priv->padding;
dev->ethtool_ops = gfar_op_array[dev_ethtool_ops]; if (dev->features & NETIF_F_IP_CSUM)
dev->hard_header_len += GMAC_FCB_LEN;
priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
#ifdef CONFIG_GFAR_BUFSTASH #ifdef CONFIG_GFAR_BUFSTASH
...@@ -289,6 +355,9 @@ static int gfar_probe(struct device *device) ...@@ -289,6 +355,9 @@ static int gfar_probe(struct device *device)
priv->rxcount = DEFAULT_RXCOUNT; priv->rxcount = DEFAULT_RXCOUNT;
priv->rxtime = DEFAULT_RXTIME; priv->rxtime = DEFAULT_RXTIME;
/* Enable most messages by default */
priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
err = register_netdev(dev); err = register_netdev(dev);
if (err) { if (err) {
...@@ -360,6 +429,7 @@ static int init_phy(struct net_device *dev) ...@@ -360,6 +429,7 @@ static int init_phy(struct net_device *dev)
GFP_KERNEL); GFP_KERNEL);
if(NULL == mii_info) { if(NULL == mii_info) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate mii_info\n", printk(KERN_ERR "%s: Could not allocate mii_info\n",
dev->name); dev->name);
return -ENOMEM; return -ENOMEM;
...@@ -410,6 +480,7 @@ static int init_phy(struct net_device *dev) ...@@ -410,6 +480,7 @@ static int init_phy(struct net_device *dev)
curphy = get_phy_info(priv->mii_info); curphy = get_phy_info(priv->mii_info);
if (curphy == NULL) { if (curphy == NULL) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: No PHY found\n", dev->name); printk(KERN_ERR "%s: No PHY found\n", dev->name);
err = -1; err = -1;
goto no_phy; goto no_phy;
...@@ -446,14 +517,14 @@ static void init_registers(struct net_device *dev) ...@@ -446,14 +517,14 @@ static void init_registers(struct net_device *dev)
gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR); gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR);
/* Init hash registers to zero */ /* Init hash registers to zero */
gfar_write(&priv->regs->iaddr0, 0); gfar_write(&priv->regs->igaddr0, 0);
gfar_write(&priv->regs->iaddr1, 0); gfar_write(&priv->regs->igaddr1, 0);
gfar_write(&priv->regs->iaddr2, 0); gfar_write(&priv->regs->igaddr2, 0);
gfar_write(&priv->regs->iaddr3, 0); gfar_write(&priv->regs->igaddr3, 0);
gfar_write(&priv->regs->iaddr4, 0); gfar_write(&priv->regs->igaddr4, 0);
gfar_write(&priv->regs->iaddr5, 0); gfar_write(&priv->regs->igaddr5, 0);
gfar_write(&priv->regs->iaddr6, 0); gfar_write(&priv->regs->igaddr6, 0);
gfar_write(&priv->regs->iaddr7, 0); gfar_write(&priv->regs->igaddr7, 0);
gfar_write(&priv->regs->gaddr0, 0); gfar_write(&priv->regs->gaddr0, 0);
gfar_write(&priv->regs->gaddr1, 0); gfar_write(&priv->regs->gaddr1, 0);
...@@ -464,9 +535,6 @@ static void init_registers(struct net_device *dev) ...@@ -464,9 +535,6 @@ static void init_registers(struct net_device *dev)
gfar_write(&priv->regs->gaddr6, 0); gfar_write(&priv->regs->gaddr6, 0);
gfar_write(&priv->regs->gaddr7, 0); gfar_write(&priv->regs->gaddr7, 0);
/* Zero out rctrl */
gfar_write(&priv->regs->rctrl, 0x00000000);
/* Zero out the rmon mib registers if it has them */ /* Zero out the rmon mib registers if it has them */
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
memset((void *) &(priv->regs->rmon), 0, memset((void *) &(priv->regs->rmon), 0,
...@@ -497,20 +565,14 @@ static void init_registers(struct net_device *dev) ...@@ -497,20 +565,14 @@ static void init_registers(struct net_device *dev)
gfar_write(&priv->regs->tbipa, TBIPA_VALUE); gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
} }
void stop_gfar(struct net_device *dev)
/* Halt the receive and transmit queues */
void gfar_halt(struct net_device *dev)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs; struct gfar *regs = priv->regs;
unsigned long flags;
u32 tempval; u32 tempval;
/* Lock it down */
spin_lock_irqsave(&priv->lock, flags);
/* Tell the kernel the link is down */
priv->mii_info->link = 0;
adjust_link(dev);
/* Mask all interrupts */ /* Mask all interrupts */
gfar_write(&regs->imask, IMASK_INIT_CLEAR); gfar_write(&regs->imask, IMASK_INIT_CLEAR);
...@@ -533,6 +595,22 @@ void stop_gfar(struct net_device *dev) ...@@ -533,6 +595,22 @@ void stop_gfar(struct net_device *dev)
tempval = gfar_read(&regs->maccfg1); tempval = gfar_read(&regs->maccfg1);
tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
gfar_write(&regs->maccfg1, tempval); gfar_write(&regs->maccfg1, tempval);
}
void stop_gfar(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
unsigned long flags;
/* Lock it down */
spin_lock_irqsave(&priv->lock, flags);
/* Tell the kernel the link is down */
priv->mii_info->link = 0;
adjust_link(dev);
gfar_halt(dev);
if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) { if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
/* Clear any pending interrupts */ /* Clear any pending interrupts */
...@@ -566,7 +644,7 @@ void stop_gfar(struct net_device *dev) ...@@ -566,7 +644,7 @@ void stop_gfar(struct net_device *dev)
sizeof(struct txbd8)*priv->tx_ring_size sizeof(struct txbd8)*priv->tx_ring_size
+ sizeof(struct rxbd8)*priv->rx_ring_size, + sizeof(struct rxbd8)*priv->rx_ring_size,
priv->tx_bd_base, priv->tx_bd_base,
gfar_read(&regs->tbase)); gfar_read(&regs->tbase0));
} }
/* If there are any tx skbs or rx skbs still around, free them. /* If there are any tx skbs or rx skbs still around, free them.
...@@ -620,6 +698,34 @@ void free_skb_resources(struct gfar_private *priv) ...@@ -620,6 +698,34 @@ void free_skb_resources(struct gfar_private *priv)
} }
} }
void gfar_start(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
u32 tempval;
/* Enable Rx and Tx in MACCFG1 */
tempval = gfar_read(&regs->maccfg1);
tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
gfar_write(&regs->maccfg1, tempval);
/* Initialize DMACTRL to have WWR and WOP */
tempval = gfar_read(&priv->regs->dmactrl);
tempval |= DMACTRL_INIT_SETTINGS;
gfar_write(&priv->regs->dmactrl, tempval);
/* Clear THLT, so that the DMA starts polling now */
gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
/* Make sure we aren't stopped */
tempval = gfar_read(&priv->regs->dmactrl);
tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
gfar_write(&priv->regs->dmactrl, tempval);
/* Unmask the interrupts we look for */
gfar_write(&regs->imask, IMASK_DEFAULT);
}
/* Bring the controller up and running */ /* Bring the controller up and running */
int startup_gfar(struct net_device *dev) int startup_gfar(struct net_device *dev)
{ {
...@@ -630,8 +736,8 @@ int startup_gfar(struct net_device *dev) ...@@ -630,8 +736,8 @@ int startup_gfar(struct net_device *dev)
int i; int i;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs; struct gfar *regs = priv->regs;
u32 tempval;
int err = 0; int err = 0;
u32 rctrl = 0;
gfar_write(&regs->imask, IMASK_INIT_CLEAR); gfar_write(&regs->imask, IMASK_INIT_CLEAR);
...@@ -642,6 +748,7 @@ int startup_gfar(struct net_device *dev) ...@@ -642,6 +748,7 @@ int startup_gfar(struct net_device *dev)
&addr, GFP_KERNEL); &addr, GFP_KERNEL);
if (vaddr == 0) { if (vaddr == 0) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n",
dev->name); dev->name);
return -ENOMEM; return -ENOMEM;
...@@ -650,13 +757,13 @@ int startup_gfar(struct net_device *dev) ...@@ -650,13 +757,13 @@ int startup_gfar(struct net_device *dev)
priv->tx_bd_base = (struct txbd8 *) vaddr; priv->tx_bd_base = (struct txbd8 *) vaddr;
/* enet DMA only understands physical addresses */ /* enet DMA only understands physical addresses */
gfar_write(&regs->tbase, addr); gfar_write(&regs->tbase0, addr);
/* Start the rx descriptor ring where the tx ring leaves off */ /* Start the rx descriptor ring where the tx ring leaves off */
addr = addr + sizeof (struct txbd8) * priv->tx_ring_size; addr = addr + sizeof (struct txbd8) * priv->tx_ring_size;
vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size; vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size;
priv->rx_bd_base = (struct rxbd8 *) vaddr; priv->rx_bd_base = (struct rxbd8 *) vaddr;
gfar_write(&regs->rbase, addr); gfar_write(&regs->rbase0, addr);
/* Setup the skbuff rings */ /* Setup the skbuff rings */
priv->tx_skbuff = priv->tx_skbuff =
...@@ -664,6 +771,7 @@ int startup_gfar(struct net_device *dev) ...@@ -664,6 +771,7 @@ int startup_gfar(struct net_device *dev)
priv->tx_ring_size, GFP_KERNEL); priv->tx_ring_size, GFP_KERNEL);
if (priv->tx_skbuff == NULL) { if (priv->tx_skbuff == NULL) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
dev->name); dev->name);
err = -ENOMEM; err = -ENOMEM;
...@@ -678,6 +786,7 @@ int startup_gfar(struct net_device *dev) ...@@ -678,6 +786,7 @@ int startup_gfar(struct net_device *dev)
priv->rx_ring_size, GFP_KERNEL); priv->rx_ring_size, GFP_KERNEL);
if (priv->rx_skbuff == NULL) { if (priv->rx_skbuff == NULL) {
if (netif_msg_ifup(priv))
printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
dev->name); dev->name);
err = -ENOMEM; err = -ENOMEM;
...@@ -730,6 +839,7 @@ int startup_gfar(struct net_device *dev) ...@@ -730,6 +839,7 @@ int startup_gfar(struct net_device *dev)
* Transmit, and Receive */ * Transmit, and Receive */
if (request_irq(priv->interruptError, gfar_error, if (request_irq(priv->interruptError, gfar_error,
0, "enet_error", dev) < 0) { 0, "enet_error", dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d\n", printk(KERN_ERR "%s: Can't get IRQ %d\n",
dev->name, priv->interruptError); dev->name, priv->interruptError);
...@@ -739,6 +849,7 @@ int startup_gfar(struct net_device *dev) ...@@ -739,6 +849,7 @@ int startup_gfar(struct net_device *dev)
if (request_irq(priv->interruptTransmit, gfar_transmit, if (request_irq(priv->interruptTransmit, gfar_transmit,
0, "enet_tx", dev) < 0) { 0, "enet_tx", dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d\n", printk(KERN_ERR "%s: Can't get IRQ %d\n",
dev->name, priv->interruptTransmit); dev->name, priv->interruptTransmit);
...@@ -749,6 +860,7 @@ int startup_gfar(struct net_device *dev) ...@@ -749,6 +860,7 @@ int startup_gfar(struct net_device *dev)
if (request_irq(priv->interruptReceive, gfar_receive, if (request_irq(priv->interruptReceive, gfar_receive,
0, "enet_rx", dev) < 0) { 0, "enet_rx", dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n", printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n",
dev->name, priv->interruptReceive); dev->name, priv->interruptReceive);
...@@ -758,6 +870,7 @@ int startup_gfar(struct net_device *dev) ...@@ -758,6 +870,7 @@ int startup_gfar(struct net_device *dev)
} else { } else {
if (request_irq(priv->interruptTransmit, gfar_interrupt, if (request_irq(priv->interruptTransmit, gfar_interrupt,
0, "gfar_interrupt", dev) < 0) { 0, "gfar_interrupt", dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d\n", printk(KERN_ERR "%s: Can't get IRQ %d\n",
dev->name, priv->interruptError); dev->name, priv->interruptError);
...@@ -787,28 +900,22 @@ int startup_gfar(struct net_device *dev) ...@@ -787,28 +900,22 @@ int startup_gfar(struct net_device *dev)
else else
gfar_write(&regs->rxic, 0); gfar_write(&regs->rxic, 0);
init_waitqueue_head(&priv->rxcleanupq); if (priv->rx_csum_enable)
rctrl |= RCTRL_CHECKSUMMING;
/* Enable Rx and Tx in MACCFG1 */ if (priv->extended_hash)
tempval = gfar_read(&regs->maccfg1); rctrl |= RCTRL_EXTHASH;
tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
gfar_write(&regs->maccfg1, tempval);
/* Initialize DMACTRL to have WWR and WOP */ if (priv->vlan_enable)
tempval = gfar_read(&priv->regs->dmactrl); rctrl |= RCTRL_VLAN;
tempval |= DMACTRL_INIT_SETTINGS;
gfar_write(&priv->regs->dmactrl, tempval);
/* Clear THLT, so that the DMA starts polling now */ /* Init rctrl based on our settings */
gfar_write(&regs->tstat, TSTAT_CLEAR_THALT); gfar_write(&priv->regs->rctrl, rctrl);
/* Make sure we aren't stopped */ if (dev->features & NETIF_F_IP_CSUM)
tempval = gfar_read(&priv->regs->dmactrl); gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM);
tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
gfar_write(&priv->regs->dmactrl, tempval);
/* Unmask the interrupts we look for */ gfar_start(dev);
gfar_write(&regs->imask, IMASK_DEFAULT);
return 0; return 0;
...@@ -824,7 +931,7 @@ int startup_gfar(struct net_device *dev) ...@@ -824,7 +931,7 @@ int startup_gfar(struct net_device *dev)
sizeof(struct txbd8)*priv->tx_ring_size sizeof(struct txbd8)*priv->tx_ring_size
+ sizeof(struct rxbd8)*priv->rx_ring_size, + sizeof(struct rxbd8)*priv->rx_ring_size,
priv->tx_bd_base, priv->tx_bd_base,
gfar_read(&regs->tbase)); gfar_read(&regs->tbase0));
if (priv->mii_info->phyinfo->close) if (priv->mii_info->phyinfo->close)
priv->mii_info->phyinfo->close(priv->mii_info); priv->mii_info->phyinfo->close(priv->mii_info);
...@@ -857,11 +964,62 @@ static int gfar_enet_open(struct net_device *dev) ...@@ -857,11 +964,62 @@ static int gfar_enet_open(struct net_device *dev)
return err; return err;
} }
static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
{
struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN);
memset(fcb, 0, GMAC_FCB_LEN);
/* Flag the bd so the controller looks for the FCB */
bdp->status |= TXBD_TOE;
return fcb;
}
static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
{
int len;
/* If we're here, it's a IP packet with a TCP or UDP
* payload. We set it to checksum, using a pseudo-header
* we provide
*/
fcb->ip = 1;
fcb->tup = 1;
fcb->ctu = 1;
fcb->nph = 1;
/* Notify the controller what the protocol is */
if (skb->nh.iph->protocol == IPPROTO_UDP)
fcb->udp = 1;
/* l3os is the distance between the start of the
* frame (skb->data) and the start of the IP hdr.
* l4os is the distance between the start of the
* l3 hdr and the l4 hdr */
fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN);
fcb->l4os = (u16)(skb->h.raw - skb->nh.raw);
len = skb->nh.iph->tot_len - fcb->l4os;
/* Provide the pseudoheader csum */
fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr,
skb->nh.iph->daddr, len,
skb->nh.iph->protocol, 0);
}
void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
{
fcb->vln = 1;
fcb->vlctl = vlan_tx_tag_get(skb);
}
/* This is called by the kernel when a frame is ready for transmission. */ /* This is called by the kernel when a frame is ready for transmission. */
/* It is pointed to by the dev->hard_start_xmit function pointer */ /* It is pointed to by the dev->hard_start_xmit function pointer */
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct txfcb *fcb = NULL;
struct txbd8 *txbdp; struct txbd8 *txbdp;
/* Update transmit stats */ /* Update transmit stats */
...@@ -876,6 +1034,21 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -876,6 +1034,21 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Clear all but the WRAP status flags */ /* Clear all but the WRAP status flags */
txbdp->status &= TXBD_WRAP; txbdp->status &= TXBD_WRAP;
/* Set up checksumming */
if ((dev->features & NETIF_F_IP_CSUM)
&& (CHECKSUM_HW == skb->ip_summed)) {
fcb = gfar_add_fcb(skb, txbdp);
gfar_tx_checksum(skb, fcb);
}
if (priv->vlan_enable &&
unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) {
if (NULL == fcb)
fcb = gfar_add_fcb(skb, txbdp);
gfar_tx_vlan(skb, fcb);
}
/* Set buffer length and pointer */ /* Set buffer length and pointer */
txbdp->length = skb->len; txbdp->length = skb->len;
txbdp->bufPtr = dma_map_single(NULL, skb->data, txbdp->bufPtr = dma_map_single(NULL, skb->data,
...@@ -972,15 +1145,78 @@ int gfar_set_mac_address(struct net_device *dev) ...@@ -972,15 +1145,78 @@ int gfar_set_mac_address(struct net_device *dev)
} }
/* Enables and disables VLAN insertion/extraction */
static void gfar_vlan_rx_register(struct net_device *dev,
struct vlan_group *grp)
{
struct gfar_private *priv = netdev_priv(dev);
unsigned long flags;
u32 tempval;
spin_lock_irqsave(&priv->lock, flags);
priv->vlgrp = grp;
if (grp) {
/* Enable VLAN tag insertion */
tempval = gfar_read(&priv->regs->tctrl);
tempval |= TCTRL_VLINS;
gfar_write(&priv->regs->tctrl, tempval);
/* Enable VLAN tag extraction */
tempval = gfar_read(&priv->regs->rctrl);
tempval |= RCTRL_VLEX;
gfar_write(&priv->regs->rctrl, tempval);
} else {
/* Disable VLAN tag insertion */
tempval = gfar_read(&priv->regs->tctrl);
tempval &= ~TCTRL_VLINS;
gfar_write(&priv->regs->tctrl, tempval);
/* Disable VLAN tag extraction */
tempval = gfar_read(&priv->regs->rctrl);
tempval &= ~RCTRL_VLEX;
gfar_write(&priv->regs->rctrl, tempval);
}
spin_unlock_irqrestore(&priv->lock, flags);
}
static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
{
struct gfar_private *priv = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
if (priv->vlgrp)
priv->vlgrp->vlan_devices[vid] = NULL;
spin_unlock_irqrestore(&priv->lock, flags);
}
static int gfar_change_mtu(struct net_device *dev, int new_mtu) static int gfar_change_mtu(struct net_device *dev, int new_mtu)
{ {
int tempsize, tempval; int tempsize, tempval;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
int oldsize = priv->rx_buffer_size; int oldsize = priv->rx_buffer_size;
int frame_size = new_mtu + 18; int frame_size = new_mtu + ETH_HLEN;
if (priv->vlan_enable)
frame_size += VLAN_ETH_HLEN;
if (gfar_uses_fcb(priv))
frame_size += GMAC_FCB_LEN;
frame_size += priv->padding;
if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) { if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
printk(KERN_ERR "%s: Invalid MTU setting\n", dev->name); if (netif_msg_drv(priv))
printk(KERN_ERR "%s: Invalid MTU setting\n",
dev->name);
return -EINVAL; return -EINVAL;
} }
...@@ -1190,11 +1426,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1190,11 +1426,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
__netif_rx_schedule(dev); __netif_rx_schedule(dev);
} else { } else {
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n", printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n",
dev->name, gfar_read(&priv->regs->ievent), dev->name, gfar_read(&priv->regs->ievent),
gfar_read(&priv->regs->imask)); gfar_read(&priv->regs->imask));
#endif
} }
#else #else
...@@ -1209,15 +1444,43 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1209,15 +1444,43 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
else else
gfar_write(&priv->regs->rxic, 0); gfar_write(&priv->regs->rxic, 0);
/* Just in case we need to wake the ring param changer */
priv->rxclean = 1;
spin_unlock(&priv->lock); spin_unlock(&priv->lock);
#endif #endif
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static inline int gfar_rx_vlan(struct sk_buff *skb,
struct vlan_group *vlgrp, unsigned short vlctl)
{
#ifdef CONFIG_GFAR_NAPI
return vlan_hwaccel_receive_skb(skb, vlgrp, vlctl);
#else
return vlan_hwaccel_rx(skb, vlgrp, vlctl);
#endif
}
static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
{
/* If valid headers were found, and valid sums
* were verified, then we tell the kernel that no
* checksumming is necessary. Otherwise, it is */
if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
}
static inline struct rxfcb *gfar_get_fcb(struct sk_buff *skb)
{
struct rxfcb *fcb = (struct rxfcb *)skb->data;
/* Remove the FCB from the skb */
skb_pull(skb, GMAC_FCB_LEN);
return fcb;
}
/* gfar_process_frame() -- handle one incoming packet if skb /* gfar_process_frame() -- handle one incoming packet if skb
* isn't NULL. */ * isn't NULL. */
...@@ -1225,26 +1488,42 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, ...@@ -1225,26 +1488,42 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
int length) int length)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct rxfcb *fcb = NULL;
if (skb == NULL) { if (skb == NULL) {
#ifdef BRIEF_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_WARNING "%s: Missing skb!!.\n", printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
dev->name);
#endif
priv->stats.rx_dropped++; priv->stats.rx_dropped++;
priv->extra_stats.rx_skbmissing++; priv->extra_stats.rx_skbmissing++;
} else { } else {
int ret;
/* Prep the skb for the packet */ /* Prep the skb for the packet */
skb_put(skb, length); skb_put(skb, length);
/* Grab the FCB if there is one */
if (gfar_uses_fcb(priv))
fcb = gfar_get_fcb(skb);
/* Remove the padded bytes, if there are any */
if (priv->padding)
skb_pull(skb, priv->padding);
if (priv->rx_csum_enable)
gfar_rx_checksum(skb, fcb);
/* Tell the skb what kind of packet this is */ /* Tell the skb what kind of packet this is */
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
/* Send the packet up the stack */ /* Send the packet up the stack */
if (RECEIVE(skb) == NET_RX_DROP) { if (unlikely(priv->vlgrp && fcb->vln))
ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl);
else
ret = RECEIVE(skb);
if (NET_RX_DROP == ret)
priv->extra_stats.kernel_dropped++; priv->extra_stats.kernel_dropped++;
} }
}
return 0; return 0;
} }
...@@ -1253,7 +1532,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, ...@@ -1253,7 +1532,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
* until the budget/quota has been reached. Returns the number * until the budget/quota has been reached. Returns the number
* of frames handled * of frames handled
*/ */
static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
{ {
struct rxbd8 *bdp; struct rxbd8 *bdp;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1355,9 +1634,6 @@ static int gfar_poll(struct net_device *dev, int *budget) ...@@ -1355,9 +1634,6 @@ static int gfar_poll(struct net_device *dev, int *budget)
mk_ic_value(priv->rxcount, priv->rxtime)); mk_ic_value(priv->rxcount, priv->rxtime));
else else
gfar_write(&priv->regs->rxic, 0); gfar_write(&priv->regs->rxic, 0);
/* Signal to the ring size changer that it's safe to go */
priv->rxclean = 1;
} }
return (rx_work_limit < 0) ? 1 : 0; return (rx_work_limit < 0) ? 1 : 0;
...@@ -1393,10 +1669,8 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1393,10 +1669,8 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (events & IEVENT_CRL) if (events & IEVENT_CRL)
priv->stats.tx_aborted_errors++; priv->stats.tx_aborted_errors++;
if (events & IEVENT_XFUN) { if (events & IEVENT_XFUN) {
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_tx_err(priv))
printk(KERN_WARNING "%s: tx underrun. dropped packet\n", printk(KERN_WARNING "%s: tx underrun. dropped packet\n", dev->name);
dev->name);
#endif
priv->stats.tx_dropped++; priv->stats.tx_dropped++;
priv->extra_stats.tx_underrun++; priv->extra_stats.tx_underrun++;
...@@ -1415,36 +1689,30 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1415,36 +1689,30 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
#endif #endif
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name, printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
dev->name,
gfar_read(&priv->regs->rstat)); gfar_read(&priv->regs->rstat));
#endif
} }
if (events & IEVENT_BABR) { if (events & IEVENT_BABR) {
priv->stats.rx_errors++; priv->stats.rx_errors++;
priv->extra_stats.rx_babr++; priv->extra_stats.rx_babr++;
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: babbling error\n", dev->name); printk(KERN_DEBUG "%s: babbling error\n", dev->name);
#endif
} }
if (events & IEVENT_EBERR) { if (events & IEVENT_EBERR) {
priv->extra_stats.eberr++; priv->extra_stats.eberr++;
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: EBERR\n", dev->name); printk(KERN_DEBUG "%s: EBERR\n", dev->name);
#endif
} }
if (events & IEVENT_RXC) { if ((events & IEVENT_RXC) && (netif_msg_rx_err(priv)))
#ifdef VERBOSE_GFAR_ERRORS
printk(KERN_DEBUG "%s: control frame\n", dev->name); printk(KERN_DEBUG "%s: control frame\n", dev->name);
#endif
}
if (events & IEVENT_BABT) { if (events & IEVENT_BABT) {
priv->extra_stats.tx_babt++; priv->extra_stats.tx_babt++;
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: babt error\n", dev->name); printk(KERN_DEBUG "%s: babt error\n", dev->name);
#endif
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -1535,6 +1803,7 @@ static void gfar_phy_startup_timer(unsigned long data) ...@@ -1535,6 +1803,7 @@ static void gfar_phy_startup_timer(unsigned long data)
/* Forcing failed! Give up */ /* Forcing failed! Give up */
if(result) { if(result) {
if (netif_msg_link(priv))
printk(KERN_ERR "%s: Forcing failed!\n", printk(KERN_ERR "%s: Forcing failed!\n",
mii_info->dev->name); mii_info->dev->name);
return; return;
...@@ -1551,6 +1820,7 @@ static void gfar_phy_startup_timer(unsigned long data) ...@@ -1551,6 +1820,7 @@ static void gfar_phy_startup_timer(unsigned long data)
SA_SHIRQ, SA_SHIRQ,
"phy_interrupt", "phy_interrupt",
mii_info->dev) < 0) { mii_info->dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
mii_info->dev->name, mii_info->dev->name,
priv->einfo->interruptPHY); priv->einfo->interruptPHY);
...@@ -1592,6 +1862,7 @@ static void adjust_link(struct net_device *dev) ...@@ -1592,6 +1862,7 @@ static void adjust_link(struct net_device *dev)
tempval &= ~(MACCFG2_FULL_DUPLEX); tempval &= ~(MACCFG2_FULL_DUPLEX);
gfar_write(&regs->maccfg2, tempval); gfar_write(&regs->maccfg2, tempval);
if (netif_msg_link(priv))
printk(KERN_INFO "%s: Half Duplex\n", printk(KERN_INFO "%s: Half Duplex\n",
dev->name); dev->name);
} else { } else {
...@@ -1599,6 +1870,7 @@ static void adjust_link(struct net_device *dev) ...@@ -1599,6 +1870,7 @@ static void adjust_link(struct net_device *dev)
tempval |= MACCFG2_FULL_DUPLEX; tempval |= MACCFG2_FULL_DUPLEX;
gfar_write(&regs->maccfg2, tempval); gfar_write(&regs->maccfg2, tempval);
if (netif_msg_link(priv))
printk(KERN_INFO "%s: Full Duplex\n", printk(KERN_INFO "%s: Full Duplex\n",
dev->name); dev->name);
} }
...@@ -1622,12 +1894,14 @@ static void adjust_link(struct net_device *dev) ...@@ -1622,12 +1894,14 @@ static void adjust_link(struct net_device *dev)
gfar_write(&regs->maccfg2, tempval); gfar_write(&regs->maccfg2, tempval);
break; break;
default: default:
if (netif_msg_link(priv))
printk(KERN_WARNING printk(KERN_WARNING
"%s: Ack! Speed (%d) is not 10/100/1000!\n", "%s: Ack! Speed (%d) is not 10/100/1000!\n",
dev->name, mii_info->speed); dev->name, mii_info->speed);
break; break;
} }
if (netif_msg_link(priv))
printk(KERN_INFO "%s: Speed %dBT\n", dev->name, printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
mii_info->speed); mii_info->speed);
...@@ -1635,6 +1909,7 @@ static void adjust_link(struct net_device *dev) ...@@ -1635,6 +1909,7 @@ static void adjust_link(struct net_device *dev)
} }
if (!priv->oldlink) { if (!priv->oldlink) {
if (netif_msg_link(priv))
printk(KERN_INFO "%s: Link is up\n", dev->name); printk(KERN_INFO "%s: Link is up\n", dev->name);
priv->oldlink = 1; priv->oldlink = 1;
netif_carrier_on(dev); netif_carrier_on(dev);
...@@ -1642,7 +1917,9 @@ static void adjust_link(struct net_device *dev) ...@@ -1642,7 +1917,9 @@ static void adjust_link(struct net_device *dev)
} }
} else { } else {
if (priv->oldlink) { if (priv->oldlink) {
printk(KERN_INFO "%s: Link is down\n", dev->name); if (netif_msg_link(priv))
printk(KERN_INFO "%s: Link is down\n",
dev->name);
priv->oldlink = 0; priv->oldlink = 0;
priv->oldspeed = 0; priv->oldspeed = 0;
priv->oldduplex = -1; priv->oldduplex = -1;
...@@ -1664,6 +1941,7 @@ static void gfar_set_multi(struct net_device *dev) ...@@ -1664,6 +1941,7 @@ static void gfar_set_multi(struct net_device *dev)
u32 tempval; u32 tempval;
if(dev->flags & IFF_PROMISC) { if(dev->flags & IFF_PROMISC) {
if (netif_msg_drv(priv))
printk(KERN_INFO "%s: Entering promiscuous mode.\n", printk(KERN_INFO "%s: Entering promiscuous mode.\n",
dev->name); dev->name);
/* Set RCTRL to PROM */ /* Set RCTRL to PROM */
...@@ -1679,6 +1957,14 @@ static void gfar_set_multi(struct net_device *dev) ...@@ -1679,6 +1957,14 @@ static void gfar_set_multi(struct net_device *dev)
if(dev->flags & IFF_ALLMULTI) { if(dev->flags & IFF_ALLMULTI) {
/* Set the hash to rx all multicast frames */ /* Set the hash to rx all multicast frames */
gfar_write(&regs->igaddr0, 0xffffffff);
gfar_write(&regs->igaddr1, 0xffffffff);
gfar_write(&regs->igaddr2, 0xffffffff);
gfar_write(&regs->igaddr3, 0xffffffff);
gfar_write(&regs->igaddr4, 0xffffffff);
gfar_write(&regs->igaddr5, 0xffffffff);
gfar_write(&regs->igaddr6, 0xffffffff);
gfar_write(&regs->igaddr7, 0xffffffff);
gfar_write(&regs->gaddr0, 0xffffffff); gfar_write(&regs->gaddr0, 0xffffffff);
gfar_write(&regs->gaddr1, 0xffffffff); gfar_write(&regs->gaddr1, 0xffffffff);
gfar_write(&regs->gaddr2, 0xffffffff); gfar_write(&regs->gaddr2, 0xffffffff);
...@@ -1689,6 +1975,14 @@ static void gfar_set_multi(struct net_device *dev) ...@@ -1689,6 +1975,14 @@ static void gfar_set_multi(struct net_device *dev)
gfar_write(&regs->gaddr7, 0xffffffff); gfar_write(&regs->gaddr7, 0xffffffff);
} else { } else {
/* zero out the hash */ /* zero out the hash */
gfar_write(&regs->igaddr0, 0x0);
gfar_write(&regs->igaddr1, 0x0);
gfar_write(&regs->igaddr2, 0x0);
gfar_write(&regs->igaddr3, 0x0);
gfar_write(&regs->igaddr4, 0x0);
gfar_write(&regs->igaddr5, 0x0);
gfar_write(&regs->igaddr6, 0x0);
gfar_write(&regs->igaddr7, 0x0);
gfar_write(&regs->gaddr0, 0x0); gfar_write(&regs->gaddr0, 0x0);
gfar_write(&regs->gaddr1, 0x0); gfar_write(&regs->gaddr1, 0x0);
gfar_write(&regs->gaddr2, 0x0); gfar_write(&regs->gaddr2, 0x0);
...@@ -1727,16 +2021,15 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr) ...@@ -1727,16 +2021,15 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr)
{ {
u32 tempval; u32 tempval;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar *regs = priv->regs;
u32 *hash = &regs->gaddr0;
u32 result = ether_crc(MAC_ADDR_LEN, addr); u32 result = ether_crc(MAC_ADDR_LEN, addr);
u8 whichreg = ((result >> 29) & 0x7); int width = priv->hash_width;
u8 whichbit = ((result >> 24) & 0x1f); u8 whichbit = (result >> (32 - width)) & 0x1f;
u8 whichreg = result >> (32 - width + 5);
u32 value = (1 << (31-whichbit)); u32 value = (1 << (31-whichbit));
tempval = gfar_read(&hash[whichreg]); tempval = gfar_read(priv->hash_regs[whichreg]);
tempval |= value; tempval |= value;
gfar_write(&hash[whichreg], tempval); gfar_write(priv->hash_regs[whichreg], tempval);
return; return;
} }
...@@ -1754,10 +2047,9 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1754,10 +2047,9 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK); gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
/* Hmm... */ /* Hmm... */
#if defined (BRIEF_GFAR_ERRORS) || defined (VERBOSE_GFAR_ERRORS) if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n", printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
dev->name, events, gfar_read(&priv->regs->imask)); dev->name, events, gfar_read(&priv->regs->imask));
#endif
/* Update the error counters */ /* Update the error counters */
if (events & IEVENT_TXE) { if (events & IEVENT_TXE) {
...@@ -1768,19 +2060,17 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1768,19 +2060,17 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
if (events & IEVENT_CRL) if (events & IEVENT_CRL)
priv->stats.tx_aborted_errors++; priv->stats.tx_aborted_errors++;
if (events & IEVENT_XFUN) { if (events & IEVENT_XFUN) {
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_tx_err(priv))
printk(KERN_DEBUG "%s: underrun. packet dropped.\n", printk(KERN_DEBUG "%s: underrun. packet dropped.\n",
dev->name); dev->name);
#endif
priv->stats.tx_dropped++; priv->stats.tx_dropped++;
priv->extra_stats.tx_underrun++; priv->extra_stats.tx_underrun++;
/* Reactivate the Tx Queues */ /* Reactivate the Tx Queues */
gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
} }
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_tx_err(priv))
printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); printk(KERN_DEBUG "%s: Transmit Error\n", dev->name);
#endif
} }
if (events & IEVENT_BSY) { if (events & IEVENT_BSY) {
priv->stats.rx_errors++; priv->stats.rx_errors++;
...@@ -1793,35 +2083,31 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1793,35 +2083,31 @@ static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
#endif #endif
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name, printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
dev->name,
gfar_read(&priv->regs->rstat)); gfar_read(&priv->regs->rstat));
#endif
} }
if (events & IEVENT_BABR) { if (events & IEVENT_BABR) {
priv->stats.rx_errors++; priv->stats.rx_errors++;
priv->extra_stats.rx_babr++; priv->extra_stats.rx_babr++;
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: babbling error\n", dev->name); printk(KERN_DEBUG "%s: babbling error\n", dev->name);
#endif
} }
if (events & IEVENT_EBERR) { if (events & IEVENT_EBERR) {
priv->extra_stats.eberr++; priv->extra_stats.eberr++;
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_err(priv))
printk(KERN_DEBUG "%s: EBERR\n", dev->name); printk(KERN_DEBUG "%s: EBERR\n", dev->name);
#endif
} }
if (events & IEVENT_RXC) if ((events & IEVENT_RXC) && netif_msg_rx_status(priv))
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_rx_status(priv))
printk(KERN_DEBUG "%s: control frame\n", dev->name); printk(KERN_DEBUG "%s: control frame\n", dev->name);
#endif
if (events & IEVENT_BABT) { if (events & IEVENT_BABT) {
priv->extra_stats.tx_babt++; priv->extra_stats.tx_babt++;
#ifdef VERBOSE_GFAR_ERRORS if (netif_msg_tx_err(priv))
printk(KERN_DEBUG "%s: babt error\n", dev->name); printk(KERN_DEBUG "%s: babt error\n", dev->name);
#endif
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -53,6 +53,12 @@ ...@@ -53,6 +53,12 @@
/* The maximum number of packets to be handled in one call of gfar_poll */ /* The maximum number of packets to be handled in one call of gfar_poll */
#define GFAR_DEV_WEIGHT 64 #define GFAR_DEV_WEIGHT 64
/* Length for FCB */
#define GMAC_FCB_LEN 8
/* Default padding amount */
#define DEFAULT_PADDING 2
/* Number of bytes to align the rx bufs to */ /* Number of bytes to align the rx bufs to */
#define RXBUF_ALIGNMENT 64 #define RXBUF_ALIGNMENT 64
...@@ -166,9 +172,28 @@ extern const char gfar_driver_version[]; ...@@ -166,9 +172,28 @@ extern const char gfar_driver_version[];
mk_ic_icft(count) | \ mk_ic_icft(count) | \
mk_ic_ictt(time)) mk_ic_ictt(time))
#define RCTRL_PAL_MASK 0x001f0000
#define RCTRL_VLEX 0x00002000
#define RCTRL_FILREN 0x00001000
#define RCTRL_GHTX 0x00000400
#define RCTRL_IPCSEN 0x00000200
#define RCTRL_TUCSEN 0x00000100
#define RCTRL_PRSDEP_MASK 0x000000c0
#define RCTRL_PRSDEP_INIT 0x000000c0
#define RCTRL_PROM 0x00000008 #define RCTRL_PROM 0x00000008
#define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \
| RCTRL_TUCSEN | RCTRL_PRSDEP_INIT)
#define RCTRL_EXTHASH (RCTRL_GHTX)
#define RCTRL_VLAN (RCTRL_PRSDEP_INIT)
#define RSTAT_CLEAR_RHALT 0x00800000 #define RSTAT_CLEAR_RHALT 0x00800000
#define TCTRL_IPCSEN 0x00004000
#define TCTRL_TUCSEN 0x00002000
#define TCTRL_VLINS 0x00001000
#define TCTRL_INIT_CSUM (TCTRL_TUCSEN | TCTRL_IPCSEN)
#define IEVENT_INIT_CLEAR 0xffffffff #define IEVENT_INIT_CLEAR 0xffffffff
#define IEVENT_BABR 0x80000000 #define IEVENT_BABR 0x80000000
#define IEVENT_RXC 0x40000000 #define IEVENT_RXC 0x40000000
...@@ -187,12 +212,16 @@ extern const char gfar_driver_version[]; ...@@ -187,12 +212,16 @@ extern const char gfar_driver_version[];
#define IEVENT_RXB0 0x00008000 #define IEVENT_RXB0 0x00008000
#define IEVENT_GRSC 0x00000100 #define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080 #define IEVENT_RXF0 0x00000080
#define IEVENT_FIR 0x00000008
#define IEVENT_FIQ 0x00000004
#define IEVENT_DPE 0x00000002
#define IEVENT_PERR 0x00000001
#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0) #define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0)
#define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF) #define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF)
#define IEVENT_ERR_MASK \ #define IEVENT_ERR_MASK \
(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
| IEVENT_CRL | IEVENT_XFUN) | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR)
#define IMASK_INIT_CLEAR 0x00000000 #define IMASK_INIT_CLEAR 0x00000000
#define IMASK_BABR 0x80000000 #define IMASK_BABR 0x80000000
...@@ -212,10 +241,15 @@ extern const char gfar_driver_version[]; ...@@ -212,10 +241,15 @@ extern const char gfar_driver_version[];
#define IMASK_RXB0 0x00008000 #define IMASK_RXB0 0x00008000
#define IMASK_GTSC 0x00000100 #define IMASK_GTSC 0x00000100
#define IMASK_RXFEN0 0x00000080 #define IMASK_RXFEN0 0x00000080
#define IMASK_FIR 0x00000008
#define IMASK_FIQ 0x00000004
#define IMASK_DPE 0x00000002
#define IMASK_PERR 0x00000001
#define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY) #define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY)
#define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \ #define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \
IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \ IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
IMASK_XFUN | IMASK_RXC | IMASK_BABT) IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
| IMASK_PERR)
/* Attribute fields */ /* Attribute fields */
...@@ -254,6 +288,18 @@ extern const char gfar_driver_version[]; ...@@ -254,6 +288,18 @@ extern const char gfar_driver_version[];
#define TXBD_RETRYLIMIT 0x0040 #define TXBD_RETRYLIMIT 0x0040
#define TXBD_RETRYCOUNTMASK 0x003c #define TXBD_RETRYCOUNTMASK 0x003c
#define TXBD_UNDERRUN 0x0002 #define TXBD_UNDERRUN 0x0002
#define TXBD_TOE 0x0002
/* Tx FCB param bits */
#define TXFCB_VLN 0x80
#define TXFCB_IP 0x40
#define TXFCB_IP6 0x20
#define TXFCB_TUP 0x10
#define TXFCB_UDP 0x08
#define TXFCB_CIP 0x04
#define TXFCB_CTU 0x02
#define TXFCB_NPH 0x01
#define TXFCB_DEFAULT (TXFCB_IP|TXFCB_TUP|TXFCB_CTU|TXFCB_NPH)
/* RxBD status field bits */ /* RxBD status field bits */
#define RXBD_EMPTY 0x8000 #define RXBD_EMPTY 0x8000
...@@ -273,6 +319,18 @@ extern const char gfar_driver_version[]; ...@@ -273,6 +319,18 @@ extern const char gfar_driver_version[];
#define RXBD_TRUNCATED 0x0001 #define RXBD_TRUNCATED 0x0001
#define RXBD_STATS 0x01ff #define RXBD_STATS 0x01ff
/* Rx FCB status field bits */
#define RXFCB_VLN 0x8000
#define RXFCB_IP 0x4000
#define RXFCB_IP6 0x2000
#define RXFCB_TUP 0x1000
#define RXFCB_CIP 0x0800
#define RXFCB_CTU 0x0400
#define RXFCB_EIP 0x0200
#define RXFCB_ETU 0x0100
#define RXFCB_PERR_MASK 0x000c
#define RXFCB_PERR_BADL3 0x0008
struct txbd8 struct txbd8
{ {
u16 status; /* Status Fields */ u16 status; /* Status Fields */
...@@ -280,6 +338,22 @@ struct txbd8 ...@@ -280,6 +338,22 @@ struct txbd8
u32 bufPtr; /* Buffer Pointer */ u32 bufPtr; /* Buffer Pointer */
}; };
struct txfcb {
u8 vln:1,
ip:1,
ip6:1,
tup:1,
udp:1,
cip:1,
ctu:1,
nph:1;
u8 reserved;
u8 l4os; /* Level 4 Header Offset */
u8 l3os; /* Level 3 Header Offset */
u16 phcs; /* Pseudo-header Checksum */
u16 vlctl; /* VLAN control word */
};
struct rxbd8 struct rxbd8
{ {
u16 status; /* Status Fields */ u16 status; /* Status Fields */
...@@ -287,6 +361,21 @@ struct rxbd8 ...@@ -287,6 +361,21 @@ struct rxbd8
u32 bufPtr; /* Buffer Pointer */ u32 bufPtr; /* Buffer Pointer */
}; };
struct rxfcb {
u16 vln:1,
ip:1,
ip6:1,
tup:1,
cip:1,
ctu:1,
eip:1,
etu:1;
u8 rq; /* Receive Queue index */
u8 pro; /* Layer 4 Protocol */
u16 reserved;
u16 vlctl; /* VLAN control word */
};
struct rmon_mib struct rmon_mib
{ {
u32 tr64; /* 0x.680 - Transmit and Receive 64-byte Frame Counter */ u32 tr64; /* 0x.680 - Transmit and Receive 64-byte Frame Counter */
...@@ -371,7 +460,8 @@ struct gfar_stats { ...@@ -371,7 +460,8 @@ struct gfar_stats {
struct gfar { struct gfar {
u8 res1[16]; u32 tsec_id; /* 0x.000 - Controller ID register */
u8 res1[12];
u32 ievent; /* 0x.010 - Interrupt Event Register */ u32 ievent; /* 0x.010 - Interrupt Event Register */
u32 imask; /* 0x.014 - Interrupt Mask Register */ u32 imask; /* 0x.014 - Interrupt Mask Register */
u32 edis; /* 0x.018 - Error Disabled Register */ u32 edis; /* 0x.018 - Error Disabled Register */
...@@ -386,36 +476,102 @@ struct gfar { ...@@ -386,36 +476,102 @@ struct gfar {
u8 res4[8]; u8 res4[8];
u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */ u32 fifo_tx_starve; /* 0x.098 - FIFO transmit starve register */
u32 fifo_tx_starve_shutoff; /* 0x.09c - FIFO transmit starve shutoff register */ u32 fifo_tx_starve_shutoff; /* 0x.09c - FIFO transmit starve shutoff register */
u8 res5[96]; u8 res5[4];
u32 fifo_rx_pause; /* 0x.0a4 - FIFO receive pause threshold register */
u32 fifo_rx_alarm; /* 0x.0a8 - FIFO receive alarm threshold register */
u8 res6[84];
u32 tctrl; /* 0x.100 - Transmit Control Register */ u32 tctrl; /* 0x.100 - Transmit Control Register */
u32 tstat; /* 0x.104 - Transmit Status Register */ u32 tstat; /* 0x.104 - Transmit Status Register */
u8 res6[4]; u32 dfvlan; /* 0x.108 - Default VLAN Control word */
u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */ u32 tbdlen; /* 0x.10c - Transmit Buffer Descriptor Data Length Register */
u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */ u32 txic; /* 0x.110 - Transmit Interrupt Coalescing Configuration Register */
u8 res7[16]; u32 tqueue; /* 0x.114 - Transmit queue control register */
u32 ctbptr; /* 0x.124 - Current Transmit Buffer Descriptor Pointer Register */ u8 res7[40];
u8 res8[92]; u32 tr03wt; /* 0x.140 - TxBD Rings 0-3 round-robin weightings */
u32 tbptr; /* 0x.184 - Transmit Buffer Descriptor Pointer Low Register */ u32 tr47wt; /* 0x.144 - TxBD Rings 4-7 round-robin weightings */
u8 res9[124]; u8 res8[52];
u32 tbase; /* 0x.204 - Transmit Descriptor Base Address Register */ u32 tbdbph; /* 0x.17c - Tx data buffer pointer high */
u8 res10[168]; u8 res9a[4];
u32 ostbd; /* 0x.2b0 - Out-of-Sequence Transmit Buffer Descriptor Register */ u32 tbptr0; /* 0x.184 - TxBD Pointer for ring 0 */
u32 ostbdp; /* 0x.2b4 - Out-of-Sequence Transmit Data Buffer Pointer Register */ u8 res9b[4];
u8 res11[72]; u32 tbptr1; /* 0x.18c - TxBD Pointer for ring 1 */
u8 res9c[4];
u32 tbptr2; /* 0x.194 - TxBD Pointer for ring 2 */
u8 res9d[4];
u32 tbptr3; /* 0x.19c - TxBD Pointer for ring 3 */
u8 res9e[4];
u32 tbptr4; /* 0x.1a4 - TxBD Pointer for ring 4 */
u8 res9f[4];
u32 tbptr5; /* 0x.1ac - TxBD Pointer for ring 5 */
u8 res9g[4];
u32 tbptr6; /* 0x.1b4 - TxBD Pointer for ring 6 */
u8 res9h[4];
u32 tbptr7; /* 0x.1bc - TxBD Pointer for ring 7 */
u8 res9[64];
u32 tbaseh; /* 0x.200 - TxBD base address high */
u32 tbase0; /* 0x.204 - TxBD Base Address of ring 0 */
u8 res10a[4];
u32 tbase1; /* 0x.20c - TxBD Base Address of ring 1 */
u8 res10b[4];
u32 tbase2; /* 0x.214 - TxBD Base Address of ring 2 */
u8 res10c[4];
u32 tbase3; /* 0x.21c - TxBD Base Address of ring 3 */
u8 res10d[4];
u32 tbase4; /* 0x.224 - TxBD Base Address of ring 4 */
u8 res10e[4];
u32 tbase5; /* 0x.22c - TxBD Base Address of ring 5 */
u8 res10f[4];
u32 tbase6; /* 0x.234 - TxBD Base Address of ring 6 */
u8 res10g[4];
u32 tbase7; /* 0x.23c - TxBD Base Address of ring 7 */
u8 res10[192];
u32 rctrl; /* 0x.300 - Receive Control Register */ u32 rctrl; /* 0x.300 - Receive Control Register */
u32 rstat; /* 0x.304 - Receive Status Register */ u32 rstat; /* 0x.304 - Receive Status Register */
u8 res12[4]; u8 res12[8];
u32 rbdlen; /* 0x.30c - RxBD Data Length Register */
u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */ u32 rxic; /* 0x.310 - Receive Interrupt Coalescing Configuration Register */
u8 res13[16]; u32 rqueue; /* 0x.314 - Receive queue control register */
u32 crbptr; /* 0x.324 - Current Receive Buffer Descriptor Pointer */ u8 res13[24];
u8 res14[24]; u32 rbifx; /* 0x.330 - Receive bit field extract control register */
u32 rqfar; /* 0x.334 - Receive queue filing table address register */
u32 rqfcr; /* 0x.338 - Receive queue filing table control register */
u32 rqfpr; /* 0x.33c - Receive queue filing table property register */
u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */ u32 mrblr; /* 0x.340 - Maximum Receive Buffer Length Register */
u8 res15[64]; u8 res14[56];
u32 rbptr; /* 0x.384 - Receive Buffer Descriptor Pointer */ u32 rbdbph; /* 0x.37c - Rx data buffer pointer high */
u8 res16[124]; u8 res15a[4];
u32 rbase; /* 0x.404 - Receive Descriptor Base Address */ u32 rbptr0; /* 0x.384 - RxBD pointer for ring 0 */
u8 res17[248]; u8 res15b[4];
u32 rbptr1; /* 0x.38c - RxBD pointer for ring 1 */
u8 res15c[4];
u32 rbptr2; /* 0x.394 - RxBD pointer for ring 2 */
u8 res15d[4];
u32 rbptr3; /* 0x.39c - RxBD pointer for ring 3 */
u8 res15e[4];
u32 rbptr4; /* 0x.3a4 - RxBD pointer for ring 4 */
u8 res15f[4];
u32 rbptr5; /* 0x.3ac - RxBD pointer for ring 5 */
u8 res15g[4];
u32 rbptr6; /* 0x.3b4 - RxBD pointer for ring 6 */
u8 res15h[4];
u32 rbptr7; /* 0x.3bc - RxBD pointer for ring 7 */
u8 res16[64];
u32 rbaseh; /* 0x.400 - RxBD base address high */
u32 rbase0; /* 0x.404 - RxBD base address of ring 0 */
u8 res17a[4];
u32 rbase1; /* 0x.40c - RxBD base address of ring 1 */
u8 res17b[4];
u32 rbase2; /* 0x.414 - RxBD base address of ring 2 */
u8 res17c[4];
u32 rbase3; /* 0x.41c - RxBD base address of ring 3 */
u8 res17d[4];
u32 rbase4; /* 0x.424 - RxBD base address of ring 4 */
u8 res17e[4];
u32 rbase5; /* 0x.42c - RxBD base address of ring 5 */
u8 res17f[4];
u32 rbase6; /* 0x.434 - RxBD base address of ring 6 */
u8 res17g[4];
u32 rbase7; /* 0x.43c - RxBD base address of ring 7 */
u8 res17[192];
u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */ u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */
u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */ u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */
u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */ u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */
...@@ -432,27 +588,61 @@ struct gfar { ...@@ -432,27 +588,61 @@ struct gfar {
u32 ifstat; /* 0x.53c - Interface Status Register */ u32 ifstat; /* 0x.53c - Interface Status Register */
u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */ u32 macstnaddr1; /* 0x.540 - Station Address Part 1 Register */
u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */ u32 macstnaddr2; /* 0x.544 - Station Address Part 2 Register */
u8 res20[312]; u32 mac01addr1; /* 0x.548 - MAC exact match address 1, part 1 */
struct rmon_mib rmon; u32 mac01addr2; /* 0x.54c - MAC exact match address 1, part 2 */
u8 res21[192]; u32 mac02addr1; /* 0x.550 - MAC exact match address 2, part 1 */
u32 iaddr0; /* 0x.800 - Indivdual address register 0 */ u32 mac02addr2; /* 0x.554 - MAC exact match address 2, part 2 */
u32 iaddr1; /* 0x.804 - Indivdual address register 1 */ u32 mac03addr1; /* 0x.558 - MAC exact match address 3, part 1 */
u32 iaddr2; /* 0x.808 - Indivdual address register 2 */ u32 mac03addr2; /* 0x.55c - MAC exact match address 3, part 2 */
u32 iaddr3; /* 0x.80c - Indivdual address register 3 */ u32 mac04addr1; /* 0x.560 - MAC exact match address 4, part 1 */
u32 iaddr4; /* 0x.810 - Indivdual address register 4 */ u32 mac04addr2; /* 0x.564 - MAC exact match address 4, part 2 */
u32 iaddr5; /* 0x.814 - Indivdual address register 5 */ u32 mac05addr1; /* 0x.568 - MAC exact match address 5, part 1 */
u32 iaddr6; /* 0x.818 - Indivdual address register 6 */ u32 mac05addr2; /* 0x.56c - MAC exact match address 5, part 2 */
u32 iaddr7; /* 0x.81c - Indivdual address register 7 */ u32 mac06addr1; /* 0x.570 - MAC exact match address 6, part 1 */
u32 mac06addr2; /* 0x.574 - MAC exact match address 6, part 2 */
u32 mac07addr1; /* 0x.578 - MAC exact match address 7, part 1 */
u32 mac07addr2; /* 0x.57c - MAC exact match address 7, part 2 */
u32 mac08addr1; /* 0x.580 - MAC exact match address 8, part 1 */
u32 mac08addr2; /* 0x.584 - MAC exact match address 8, part 2 */
u32 mac09addr1; /* 0x.588 - MAC exact match address 9, part 1 */
u32 mac09addr2; /* 0x.58c - MAC exact match address 9, part 2 */
u32 mac10addr1; /* 0x.590 - MAC exact match address 10, part 1*/
u32 mac10addr2; /* 0x.594 - MAC exact match address 10, part 2*/
u32 mac11addr1; /* 0x.598 - MAC exact match address 11, part 1*/
u32 mac11addr2; /* 0x.59c - MAC exact match address 11, part 2*/
u32 mac12addr1; /* 0x.5a0 - MAC exact match address 12, part 1*/
u32 mac12addr2; /* 0x.5a4 - MAC exact match address 12, part 2*/
u32 mac13addr1; /* 0x.5a8 - MAC exact match address 13, part 1*/
u32 mac13addr2; /* 0x.5ac - MAC exact match address 13, part 2*/
u32 mac14addr1; /* 0x.5b0 - MAC exact match address 14, part 1*/
u32 mac14addr2; /* 0x.5b4 - MAC exact match address 14, part 2*/
u32 mac15addr1; /* 0x.5b8 - MAC exact match address 15, part 1*/
u32 mac15addr2; /* 0x.5bc - MAC exact match address 15, part 2*/
u8 res20[192];
struct rmon_mib rmon; /* 0x.680-0x.73c */
u32 rrej; /* 0x.740 - Receive filer rejected packet counter */
u8 res21[188];
u32 igaddr0; /* 0x.800 - Indivdual/Group address register 0*/
u32 igaddr1; /* 0x.804 - Indivdual/Group address register 1*/
u32 igaddr2; /* 0x.808 - Indivdual/Group address register 2*/
u32 igaddr3; /* 0x.80c - Indivdual/Group address register 3*/
u32 igaddr4; /* 0x.810 - Indivdual/Group address register 4*/
u32 igaddr5; /* 0x.814 - Indivdual/Group address register 5*/
u32 igaddr6; /* 0x.818 - Indivdual/Group address register 6*/
u32 igaddr7; /* 0x.81c - Indivdual/Group address register 7*/
u8 res22[96]; u8 res22[96];
u32 gaddr0; /* 0x.880 - Global address register 0 */ u32 gaddr0; /* 0x.880 - Group address register 0 */
u32 gaddr1; /* 0x.884 - Global address register 1 */ u32 gaddr1; /* 0x.884 - Group address register 1 */
u32 gaddr2; /* 0x.888 - Global address register 2 */ u32 gaddr2; /* 0x.888 - Group address register 2 */
u32 gaddr3; /* 0x.88c - Global address register 3 */ u32 gaddr3; /* 0x.88c - Group address register 3 */
u32 gaddr4; /* 0x.890 - Global address register 4 */ u32 gaddr4; /* 0x.890 - Group address register 4 */
u32 gaddr5; /* 0x.894 - Global address register 5 */ u32 gaddr5; /* 0x.894 - Group address register 5 */
u32 gaddr6; /* 0x.898 - Global address register 6 */ u32 gaddr6; /* 0x.898 - Group address register 6 */
u32 gaddr7; /* 0x.89c - Global address register 7 */ u32 gaddr7; /* 0x.89c - Group address register 7 */
u8 res23[856]; u8 res23a[352];
u32 fifocfg; /* 0x.a00 - FIFO interface config register */
u8 res23b[252];
u8 res23c[248];
u32 attr; /* 0x.bf8 - Attributes Register */ u32 attr; /* 0x.bf8 - Attributes Register */
u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */ u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */
u8 res24[1024]; u8 res24[1024];
...@@ -496,6 +686,8 @@ struct gfar_private { ...@@ -496,6 +686,8 @@ struct gfar_private {
struct txbd8 *cur_tx; /* Next free ring entry */ struct txbd8 *cur_tx; /* Next free ring entry */
struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ struct txbd8 *dirty_tx; /* The Ring entry to be freed. */
struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */
u32 *hash_regs[16];
int hash_width;
struct gfar *phyregs; struct gfar *phyregs;
struct work_struct tq; struct work_struct tq;
struct timer_list phy_info_timer; struct timer_list phy_info_timer;
...@@ -506,9 +698,12 @@ struct gfar_private { ...@@ -506,9 +698,12 @@ struct gfar_private {
unsigned int rx_stash_size; unsigned int rx_stash_size;
unsigned int tx_ring_size; unsigned int tx_ring_size;
unsigned int rx_ring_size; unsigned int rx_ring_size;
wait_queue_head_t rxcleanupq;
unsigned int rxclean;
unsigned char vlan_enable:1,
rx_csum_enable:1,
extended_hash:1;
unsigned short padding;
struct vlan_group *vlgrp;
/* Info structure initialized by board setup code */ /* Info structure initialized by board setup code */
unsigned int interruptTransmit; unsigned int interruptTransmit;
unsigned int interruptReceive; unsigned int interruptReceive;
...@@ -519,6 +714,8 @@ struct gfar_private { ...@@ -519,6 +714,8 @@ struct gfar_private {
int oldspeed; int oldspeed;
int oldduplex; int oldduplex;
int oldlink; int oldlink;
uint32_t msg_enable;
}; };
extern inline u32 gfar_read(volatile unsigned *addr) extern inline u32 gfar_read(volatile unsigned *addr)
......
...@@ -46,16 +46,18 @@ ...@@ -46,16 +46,18 @@
extern int startup_gfar(struct net_device *dev); extern int startup_gfar(struct net_device *dev);
extern void stop_gfar(struct net_device *dev); extern void stop_gfar(struct net_device *dev);
extern void gfar_receive(int irq, void *dev_id, struct pt_regs *regs); extern void gfar_halt(struct net_device *dev);
extern void gfar_start(struct net_device *dev);
extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
u64 * buf); u64 * buf);
void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals);
int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals);
void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); static void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo);
static char stat_gstrings[][ETH_GSTRING_LEN] = { static char stat_gstrings[][ETH_GSTRING_LEN] = {
"rx-dropped-by-kernel", "rx-dropped-by-kernel",
...@@ -118,57 +120,56 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = { ...@@ -118,57 +120,56 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = {
"tx-fragmented-frames", "tx-fragmented-frames",
}; };
/* Fill in a buffer with the strings which correspond to the
* stats */
static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
{
struct gfar_private *priv = netdev_priv(dev);
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
else
memcpy(buf, stat_gstrings,
GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN);
}
/* Fill in an array of 64-bit statistics from various sources. /* Fill in an array of 64-bit statistics from various sources.
* This array will be appended to the end of the ethtool_stats * This array will be appended to the end of the ethtool_stats
* structure, and returned to user space * structure, and returned to user space
*/ */
void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf)
{ {
int i; int i;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
u32 *rmon = (u32 *) & priv->regs->rmon;
u64 *extra = (u64 *) & priv->extra_stats; u64 *extra = (u64 *) & priv->extra_stats;
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
u32 *rmon = (u32 *) & priv->regs->rmon;
struct gfar_stats *stats = (struct gfar_stats *) buf; struct gfar_stats *stats = (struct gfar_stats *) buf;
for (i = 0; i < GFAR_RMON_LEN; i++) { for (i = 0; i < GFAR_RMON_LEN; i++)
stats->rmon[i] = (u64) (rmon[i]); stats->rmon[i] = (u64) (rmon[i]);
}
for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
stats->extra[i] = extra[i]; stats->extra[i] = extra[i];
} } else
for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++)
buf[i] = extra[i];
} }
/* Returns the number of stats (and their corresponding strings) */ /* Returns the number of stats (and their corresponding strings) */
int gfar_stats_count(struct net_device *dev) static int gfar_stats_count(struct net_device *dev)
{
return GFAR_STATS_LEN;
}
void gfar_gstrings_normon(struct net_device *dev, u32 stringset, u8 * buf)
{
memcpy(buf, stat_gstrings, GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN);
}
void gfar_fill_stats_normon(struct net_device *dev,
struct ethtool_stats *dummy, u64 * buf)
{ {
int i;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
u64 *extra = (u64 *) & priv->extra_stats;
for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
buf[i] = extra[i]; return GFAR_STATS_LEN;
} else
}
int gfar_stats_count_normon(struct net_device *dev)
{
return GFAR_EXTRA_STATS_LEN; return GFAR_EXTRA_STATS_LEN;
} }
/* Fills in the drvinfo structure with some basic info */ /* Fills in the drvinfo structure with some basic info */
void gfar_gdrvinfo(struct net_device *dev, struct static void gfar_gdrvinfo(struct net_device *dev, struct
ethtool_drvinfo *drvinfo) ethtool_drvinfo *drvinfo)
{ {
strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN); strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN);
...@@ -182,7 +183,7 @@ void gfar_gdrvinfo(struct net_device *dev, struct ...@@ -182,7 +183,7 @@ void gfar_gdrvinfo(struct net_device *dev, struct
} }
/* Return the current settings in the ethtool_cmd structure */ /* Return the current settings in the ethtool_cmd structure */
int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
uint gigabit_support = uint gigabit_support =
...@@ -216,13 +217,13 @@ int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -216,13 +217,13 @@ int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
} }
/* Return the length of the register structure */ /* Return the length of the register structure */
int gfar_reglen(struct net_device *dev) static int gfar_reglen(struct net_device *dev)
{ {
return sizeof (struct gfar); return sizeof (struct gfar);
} }
/* Return a dump of the GFAR register space */ /* Return a dump of the GFAR register space */
void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
{ {
int i; int i;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
...@@ -233,13 +234,6 @@ void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regb ...@@ -233,13 +234,6 @@ void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regb
buf[i] = theregs[i]; buf[i] = theregs[i];
} }
/* Fill in a buffer with the strings which correspond to the
* stats */
void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
{
memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
}
/* Convert microseconds to ethernet clock ticks, which changes /* Convert microseconds to ethernet clock ticks, which changes
* depending on what speed the controller is running at */ * depending on what speed the controller is running at */
static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs) static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs)
...@@ -291,10 +285,13 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic ...@@ -291,10 +285,13 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
/* Get the coalescing parameters, and put them in the cvals /* Get the coalescing parameters, and put them in the cvals
* structure. */ * structure. */
int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP;
cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
cvals->rx_max_coalesced_frames = priv->rxcount; cvals->rx_max_coalesced_frames = priv->rxcount;
...@@ -337,10 +334,13 @@ int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) ...@@ -337,10 +334,13 @@ int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
* Both cvals->*_usecs and cvals->*_frames have to be > 0 * Both cvals->*_usecs and cvals->*_frames have to be > 0
* in order for coalescing to be active * in order for coalescing to be active
*/ */
int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP;
/* Set up rx coalescing */ /* Set up rx coalescing */
if ((cvals->rx_coalesce_usecs == 0) || if ((cvals->rx_coalesce_usecs == 0) ||
(cvals->rx_max_coalesced_frames == 0)) (cvals->rx_max_coalesced_frames == 0))
...@@ -379,7 +379,7 @@ int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) ...@@ -379,7 +379,7 @@ int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
/* Fills in rvals with the current ring parameters. Currently, /* Fills in rvals with the current ring parameters. Currently,
* rx, rx_mini, and rx_jumbo rings are the same size, as mini and * rx, rx_mini, and rx_jumbo rings are the same size, as mini and
* jumbo are ignored by the driver */ * jumbo are ignored by the driver */
void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
...@@ -401,9 +401,8 @@ void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) ...@@ -401,9 +401,8 @@ void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
* necessary so that we don't mess things up while we're in * necessary so that we don't mess things up while we're in
* motion. We wait for the ring to be clean before reallocating * motion. We wait for the ring to be clean before reallocating
* the rings. */ * the rings. */
int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
{ {
u32 tempval;
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
int err = 0; int err = 0;
...@@ -425,37 +424,54 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) ...@@ -425,37 +424,54 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
return -EINVAL; return -EINVAL;
} }
/* Stop the controller so we don't rx any more frames */ if (dev->flags & IFF_UP) {
/* But first, make sure we clear the bits */ unsigned long flags;
tempval = gfar_read(&priv->regs->dmactrl);
tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
gfar_write(&priv->regs->dmactrl, tempval);
tempval = gfar_read(&priv->regs->dmactrl); /* Halt TX and RX, and process the frames which
tempval |= (DMACTRL_GRS | DMACTRL_GTS); * have already been received */
gfar_write(&priv->regs->dmactrl, tempval); spin_lock_irqsave(&priv->lock, flags);
gfar_halt(dev);
gfar_clean_rx_ring(dev, priv->rx_ring_size);
spin_unlock_irqrestore(&priv->lock, flags);
while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))) /* Now we take down the rings to rebuild them */
cpu_relax(); stop_gfar(dev);
}
/* Note that rx is not clean right now */ /* Change the size */
priv->rxclean = 0; priv->rx_ring_size = rvals->rx_pending;
priv->tx_ring_size = rvals->tx_pending;
if (dev->flags & IFF_UP) { /* Rebuild the rings with the new size */
/* Tell the driver to process the rest of the frames */ if (dev->flags & IFF_UP)
gfar_receive(0, (void *) dev, NULL); err = startup_gfar(dev);
return err;
}
static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
{
struct gfar_private *priv = netdev_priv(dev);
int err = 0;
/* Now wait for it to be done */ if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
wait_event_interruptible(priv->rxcleanupq, priv->rxclean); return -EOPNOTSUPP;
/* Ok, all packets have been handled. Now we bring it down, if (dev->flags & IFF_UP) {
* change the ring size, and bring it up */ unsigned long flags;
/* Halt TX and RX, and process the frames which
* have already been received */
spin_lock_irqsave(&priv->lock, flags);
gfar_halt(dev);
gfar_clean_rx_ring(dev, priv->rx_ring_size);
spin_unlock_irqrestore(&priv->lock, flags);
/* Now we take down the rings to rebuild them */
stop_gfar(dev); stop_gfar(dev);
} }
priv->rx_ring_size = rvals->rx_pending; priv->rx_csum_enable = data;
priv->tx_ring_size = rvals->tx_pending;
if (dev->flags & IFF_UP) if (dev->flags & IFF_UP)
err = startup_gfar(dev); err = startup_gfar(dev);
...@@ -463,6 +479,61 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) ...@@ -463,6 +479,61 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
return err; return err;
} }
static uint32_t gfar_get_rx_csum(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return 0;
return priv->rx_csum_enable;
}
static int gfar_set_tx_csum(struct net_device *dev, uint32_t data)
{
unsigned long flags;
struct gfar_private *priv = netdev_priv(dev);
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
spin_lock_irqsave(&priv->lock, flags);
gfar_halt(dev);
if (data)
dev->features |= NETIF_F_IP_CSUM;
else
dev->features &= ~NETIF_F_IP_CSUM;
gfar_start(dev);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
static uint32_t gfar_get_tx_csum(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return 0;
return (dev->features & NETIF_F_IP_CSUM) != 0;
}
static uint32_t gfar_get_msglevel(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
return priv->msg_enable;
}
static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
{
struct gfar_private *priv = netdev_priv(dev);
priv->msg_enable = data;
}
struct ethtool_ops gfar_ethtool_ops = { struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings, .get_settings = gfar_gsettings,
.get_drvinfo = gfar_gdrvinfo, .get_drvinfo = gfar_gdrvinfo,
...@@ -476,52 +547,10 @@ struct ethtool_ops gfar_ethtool_ops = { ...@@ -476,52 +547,10 @@ struct ethtool_ops gfar_ethtool_ops = {
.get_strings = gfar_gstrings, .get_strings = gfar_gstrings,
.get_stats_count = gfar_stats_count, .get_stats_count = gfar_stats_count,
.get_ethtool_stats = gfar_fill_stats, .get_ethtool_stats = gfar_fill_stats,
}; .get_rx_csum = gfar_get_rx_csum,
.get_tx_csum = gfar_get_tx_csum,
struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = { .set_rx_csum = gfar_set_rx_csum,
.get_settings = gfar_gsettings, .set_tx_csum = gfar_set_tx_csum,
.get_drvinfo = gfar_gdrvinfo, .get_msglevel = gfar_get_msglevel,
.get_regs_len = gfar_reglen, .set_msglevel = gfar_set_msglevel,
.get_regs = gfar_get_regs,
.get_link = ethtool_op_get_link,
.get_ringparam = gfar_gringparam,
.set_ringparam = gfar_sringparam,
.get_strings = gfar_gstrings_normon,
.get_stats_count = gfar_stats_count_normon,
.get_ethtool_stats = gfar_fill_stats_normon,
};
struct ethtool_ops gfar_nocoalesce_ethtool_ops = {
.get_settings = gfar_gsettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
.get_regs = gfar_get_regs,
.get_link = ethtool_op_get_link,
.get_ringparam = gfar_gringparam,
.set_ringparam = gfar_sringparam,
.get_strings = gfar_gstrings,
.get_stats_count = gfar_stats_count,
.get_ethtool_stats = gfar_fill_stats,
};
struct ethtool_ops gfar_normon_ethtool_ops = {
.get_settings = gfar_gsettings,
.get_drvinfo = gfar_gdrvinfo,
.get_regs_len = gfar_reglen,
.get_regs = gfar_get_regs,
.get_link = ethtool_op_get_link,
.get_coalesce = gfar_gcoalesce,
.set_coalesce = gfar_scoalesce,
.get_ringparam = gfar_gringparam,
.set_ringparam = gfar_sringparam,
.get_strings = gfar_gstrings_normon,
.get_stats_count = gfar_stats_count_normon,
.get_ethtool_stats = gfar_fill_stats_normon,
};
struct ethtool_ops *gfar_op_array[] = {
&gfar_ethtool_ops,
&gfar_normon_ethtool_ops,
&gfar_nocoalesce_ethtool_ops,
&gfar_normon_nocoalesce_ethtool_ops
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment