[linux-yocto] [PATCH 17/28] LSI FEMAC Ethernet: Updated for upstream submittal

Bruce Ashfield bruce.ashfield at windriver.com
Fri May 2 13:18:09 PDT 2014


On 14-05-02 03:16 PM, Charlie Paul wrote:
> From: David Mercado <david.mercado at windriver.com>
>
> Integrated feedback and suggestions to make driver easier to upstream.

If you recall my comment on this sort of commit message before. We really
should say what we changed. Reading this, we have no idea what the
feedback was, and what actually changed in the files.

Bruce

>
> Signed-off-by: David Mercado <david.mercado at windriver.com>
> ---
>   drivers/net/ethernet/lsi/Kconfig        |   15 -
>   drivers/net/ethernet/lsi/lsi_acp_mdio.c |  201 +++----
>   drivers/net/ethernet/lsi/lsi_acp_net.c  |  871 ++++++++++++++-----------------
>   drivers/net/ethernet/lsi/lsi_acp_net.h  |  261 ++++++---
>   4 files changed, 693 insertions(+), 655 deletions(-)
>
> diff --git a/drivers/net/ethernet/lsi/Kconfig b/drivers/net/ethernet/lsi/Kconfig
> index 1c760e5..a78867d 100644
> --- a/drivers/net/ethernet/lsi/Kconfig
> +++ b/drivers/net/ethernet/lsi/Kconfig
> @@ -35,19 +35,4 @@ config LSI_NET_TX_BUF_SZ
>   	help
>   	  The size of the transmit buffer.
>
> -config DISABLE_TX_INTERRUPTS
> -	bool "NIC driver: Disable Tx interrupts"
> -	depends on LSI_NET
> -	default y
> -	help
> -	  If set to "yes", disables Transmit interrupts
> -
> -config PRELOAD_RX_BUFFERS
> -	bool "NIC driver: Preload Rx buffers"
> -	depends on LSI_NET
> -	default n
> -	help
> -	  If set to "yes", enables preloading of Rx buffer prior to
> -	  copying into device
> -
>   endif # LSI_NET
> diff --git a/drivers/net/ethernet/lsi/lsi_acp_mdio.c b/drivers/net/ethernet/lsi/lsi_acp_mdio.c
> index 07643fc..aab609d 100644
> --- a/drivers/net/ethernet/lsi/lsi_acp_mdio.c
> +++ b/drivers/net/ethernet/lsi/lsi_acp_mdio.c
> @@ -1,21 +1,13 @@
>   /*
>    * drivers/net/ethernet/lsi/lsi_acp_mdio.c
>    *
> - * Copyright (C) 2010 LSI
> + * Copyright (C) 2013 LSI Corporation.
>    *
>    * This program is free software; you can redistribute it and/or modify
>    * it under the terms of the GNU General Public License as published by
>    * the Free Software Foundation; either version 2 of the License, or
>    * (at your option) any later version.
>    *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
>    */
>
>   #include <linux/module.h>
> @@ -27,42 +19,53 @@
>   #include <linux/skbuff.h>
>   #include <linux/platform_device.h>
>
> +#define BZ33327_WA
> +
>   /*
> -  ==============================================================================
> -  ==============================================================================
> -  MDIO Access
> -  ==============================================================================
> -  ==============================================================================
> -*/
> + * MDIO Access
> + */
>
> -#ifndef CONFIG_ACPISS
> +struct lsi_mdio_priv {
> +	unsigned long base;
> +};
>
> -#define BZ33327_WA
> -
> -static unsigned long mdio_base;
> +static struct lsi_mdio_priv *mdio_priv;
>   static DEFINE_SPINLOCK(mdio_lock);
>
> -#define MDIO_CONTROL_RD_DATA ((void *)(mdio_base + 0x0))
> -#define MDIO_STATUS_RD_DATA  ((void *)(mdio_base + 0x4))
> -#define MDIO_CLK_OFFSET      ((void *)(mdio_base + 0x8))
> -#define MDIO_CLK_PERIOD      ((void *)(mdio_base + 0xc))
> +#define MDIO_CONTROL_RD_DATA ((void *)(mdio_priv->base + 0x0))
> +#define MDIO_STATUS_RD_DATA  ((void *)(mdio_priv->base + 0x4))
> +#define MDIO_CLK_OFFSET      ((void *)(mdio_priv->base + 0x8))
> +#define MDIO_CLK_PERIOD      ((void *)(mdio_priv->base + 0xc))
>
>   #ifdef CONFIG_ARM
> -#define READ(a) readl((a))
> -#define WRITE(a, v) writel((v), (a))
> +static u32 read_reg(u32 *addr)
> +{
> +	return readl((void __iomem *)addr);
> +}
> +
> +static void write_reg(u32 *addr, u32 value)
> +{
> +	writel(value, (void __iomem *)addr);
> +}
>   #else
> -#define READ(a) in_le32((a))
> -#define WRITE(a, v) out_le32((a), (v))
> +static u32 read_reg(u32 *addr)
> +{
> +	return in_le32((unsigned *)addr);
> +}
> +
> +static void write_reg(u32 *addr, u32 value)
> +{
> +	out_le32((unsigned *)addr, (int)value);
> +}
>   #endif
>
>   /*
> -  ------------------------------------------------------------------------------
> -  acp_mdio_read
> -*/
> + * acp_mdio_read
> + */
>
>   int
>   acp_mdio_read(unsigned long address, unsigned long offset,
> -	      unsigned short *value, int clause45)
> +	      unsigned short *value, int clause_45)
>   {
>   	unsigned long command = 0;
>   	unsigned long status;
> @@ -71,24 +74,24 @@ acp_mdio_read(unsigned long address, unsigned long offset,
>   	spin_lock_irqsave(&mdio_lock, flags);
>   #if defined(BZ33327_WA)
>   	/* Set the mdio_busy (status) bit. */
> -	status = READ(MDIO_STATUS_RD_DATA);
> +	status = read_reg(MDIO_STATUS_RD_DATA);
>   	status |= 0x40000000;
> -	WRITE(MDIO_STATUS_RD_DATA, status);
> +	write_reg(MDIO_STATUS_RD_DATA, status);
>   #endif /* BZ33327_WA */
>
> -	if (clause45 == 0) {
> +	if (clause_45 == 0) {
>   		/* Write the command. */
>   		command = 0x10000000;              /* op_code: read */
>   		command |= (address & 0x1f) << 16; /* port_addr (tgt device) */
>   		command |= (offset & 0x1f) << 21;  /* device_addr (tgt reg) */
> -		WRITE(MDIO_CONTROL_RD_DATA, command);
> +		write_reg(MDIO_CONTROL_RD_DATA, command);
>   	} else {
>   		/*
>   		 * Step 1: Write the address.
>   		 */
>
>   		/* Write the address */
> -		command = 0x20000000;                    /* clause_45 = 1 */
> +		command = 0x20000000;                    /* Clause 45 = 1 */
>   		command |= 0x00000000;                   /* op_code: 0 */
>   		command |= 0x04000000;                   /* interface_sel = 1 */
>   		command |= ((offset & 0x1f000000) >> 3); /* device_addr (target
> @@ -97,16 +100,16 @@ acp_mdio_read(unsigned long address, unsigned long offset,
>   							    device) */
>   		command |= (offset & 0xffff);            /* addr_or_data (target
>   							    register) */
> -		WRITE(MDIO_CONTROL_RD_DATA, command);
> +		write_reg(MDIO_CONTROL_RD_DATA, command);
>
>   		/* Wait for the mdio_busy (status) bit to clear. */
>   		do {
> -			status = READ(MDIO_STATUS_RD_DATA);
> +			status = read_reg(MDIO_STATUS_RD_DATA);
>   		} while (0 != (status & 0x40000000));
>
>   		/* Wait for the mdio_busy (control) bit to clear. */
>   		do {
> -			command = READ(MDIO_CONTROL_RD_DATA);
> +			command = read_reg(MDIO_CONTROL_RD_DATA);
>   		} while (0 != (command & 0x80000000));
>
>   		/*
> @@ -114,30 +117,30 @@ acp_mdio_read(unsigned long address, unsigned long offset,
>   		 */
>
>   		/* Set the mdio_busy (status) bit. */
> -		status = READ(MDIO_STATUS_RD_DATA);
> +		status = read_reg(MDIO_STATUS_RD_DATA);
>   		status |= 0x40000000;
> -		WRITE(MDIO_STATUS_RD_DATA, status);
> +		write_reg(MDIO_STATUS_RD_DATA, status);
>
> -		command = 0x20000000;                    /* clause_45 = 1 */
> +		command = 0x20000000;                    /* Clause 45 = 1 */
>   		command |= 0x10000000;                   /* op_code: read */
>   		command |= 0x04000000;                   /* interface_sel = 1 */
>   		command |= ((offset & 0x1f000000) >> 3); /* device_addr (target
>   							    device_type) */
>   		command |= (address & 0x1f) << 16;       /* port_addr (target
>   							    device) */
> -		WRITE(MDIO_CONTROL_RD_DATA, command);
> +		write_reg(MDIO_CONTROL_RD_DATA, command);
>   	}
>
>   #if defined(BZ33327_WA)
>   	/* Wait for the mdio_busy (status) bit to clear. */
>   	do {
> -		status = READ(MDIO_STATUS_RD_DATA);
> +		status = read_reg(MDIO_STATUS_RD_DATA);
>   	} while (0 != (status & 0x40000000));
>   #endif				/* BZ33327_WA */
>
>   	/* Wait for the mdio_busy (control) bit to clear. */
>   	do {
> -		command = READ(MDIO_CONTROL_RD_DATA);
> +		command = read_reg(MDIO_CONTROL_RD_DATA);
>   	} while (0 != (command & 0x80000000));
>
>   	*value = (unsigned short)(command & 0xffff);
> @@ -148,13 +151,12 @@ acp_mdio_read(unsigned long address, unsigned long offset,
>   EXPORT_SYMBOL(acp_mdio_read);
>
>   /*
> -  ------------------------------------------------------------------------------
> -  acp_mdio_write
> -*/
> + * acp_mdio_write
> + */
>
>   int
>   acp_mdio_write(unsigned long address, unsigned long offset,
> -	       unsigned short value, int clause45)
> +	       unsigned short value, int clause_45)
>   {
>   	unsigned long command = 0;
>   	unsigned long status;
> @@ -164,30 +166,30 @@ acp_mdio_write(unsigned long address, unsigned long offset,
>
>   	/* Wait for mdio_busy (control) to be clear. */
>   	do {
> -		command = READ(MDIO_CONTROL_RD_DATA);
> +		command = read_reg(MDIO_CONTROL_RD_DATA);
>   	} while (0 != (command & 0x80000000));
>
>   #if defined(BZ33327_WA)
>   	/* Set the mdio_busy (status) bit. */
> -	status = READ(MDIO_STATUS_RD_DATA);
> +	status = read_reg(MDIO_STATUS_RD_DATA);
>   	status |= 0x40000000;
> -	WRITE(MDIO_STATUS_RD_DATA, status);
> +	write_reg(MDIO_STATUS_RD_DATA, status);
>   #endif /* BZ33327_WA */
>
> -	if (clause45 == 0) {
> +	if (clause_45 == 0) {
>   		/* Write the command. */
>   		command = 0x08000000;              /* op_code: write */
>   		command |= (address & 0x1f) << 16; /* port_addr (tgt device) */
>   		command |= (offset & 0x1f) << 21;  /* device_addr (tgt reg) */
>   		command |= (value & 0xffff);       /* value */
> -		WRITE(MDIO_CONTROL_RD_DATA, command);
> +		write_reg(MDIO_CONTROL_RD_DATA, command);
>   	} else {
>   		/*
>   		 * Step 1: Write the address.
>   		 */
>
>   		/* Write the address */
> -		command = 0x20000000;                    /* clause_45 = 1 */
> +		command = 0x20000000;                    /* Clause 45 = 1 */
>   		command |= 0x00000000;                   /* op_code: 0 */
>   		command |= 0x04000000;                   /* interface_sel = 1 */
>   		command |= ((offset & 0x1f000000) >> 3); /* device_addr (target
> @@ -196,16 +198,16 @@ acp_mdio_write(unsigned long address, unsigned long offset,
>   							    device) */
>   		command |= (offset & 0xffff);            /* addr_or_data (target
>   							    register) */
> -		WRITE(MDIO_CONTROL_RD_DATA, command);
> +		write_reg(MDIO_CONTROL_RD_DATA, command);
>
>   		/* Wait for the mdio_busy (status) bit to clear. */
>   		do {
> -			status = READ(MDIO_STATUS_RD_DATA);
> +			status = read_reg(MDIO_STATUS_RD_DATA);
>   		} while (0 != (status & 0x40000000));
>
>   		/* Wait for the mdio_busy (control) bit to clear. */
>   		do {
> -			command = READ(MDIO_CONTROL_RD_DATA);
> +			command = read_reg(MDIO_CONTROL_RD_DATA);
>   		} while (0 != (command & 0x80000000));
>
>   		/*
> @@ -213,11 +215,11 @@ acp_mdio_write(unsigned long address, unsigned long offset,
>   		 */
>
>   		/* Set the mdio_busy (status) bit. */
> -		status = READ(MDIO_STATUS_RD_DATA);
> +		status = read_reg(MDIO_STATUS_RD_DATA);
>   		status |= 0x40000000;
> -		WRITE(MDIO_STATUS_RD_DATA, status);
> +		write_reg(MDIO_STATUS_RD_DATA, status);
>
> -		command = 0x20000000;                    /* clause_45 = 1 */
> +		command = 0x20000000;                    /* Clause 45 = 1 */
>   		command |= 0x08000000;                   /* op_code: write */
>   		command |= 0x04000000;                   /* interface_sel = 1 */
>   		command |= ((offset & 0x1f000000) >> 3); /* device_addr (target
> @@ -225,19 +227,19 @@ acp_mdio_write(unsigned long address, unsigned long offset,
>   		command |= (address & 0x1f) << 16;       /* port_addr (target
>   							    device) */
>   		command |= (value & 0xffff);             /* addr_or_data=value*/
> -		WRITE(MDIO_CONTROL_RD_DATA, command);
> +		write_reg(MDIO_CONTROL_RD_DATA, command);
>   	}
>
>   #if defined(BZ33327_WA)
>   	/* Wait for the mdio_busy (status) bit to clear. */
>   	do {
> -		status = READ(MDIO_STATUS_RD_DATA);
> +		status = read_reg(MDIO_STATUS_RD_DATA);
>   	} while (0 != (status & 0x40000000));
>   #endif	/* BZ33327_WA */
>
>   	/* Wait for the mdio_busy (control) bit to clear. */
>   	do {
> -		command = READ(MDIO_CONTROL_RD_DATA);
> +		command = read_reg(MDIO_CONTROL_RD_DATA);
>   	} while (0 != (command & 0x80000000));
>
>   	spin_unlock_irqrestore(&mdio_lock, flags);
> @@ -247,38 +249,26 @@ acp_mdio_write(unsigned long address, unsigned long offset,
>   EXPORT_SYMBOL(acp_mdio_write);
>
>   /*
> -  ------------------------------------------------------------------------------
> -  acp_mdio_initialize
> -*/
> + * acp_mdio_initialize
> + */
>
> -static int
> +static void
>   acp_mdio_initialize(void)
>   {
>   #ifdef CONFIG_ARM
> -	WRITE(MDIO_CLK_OFFSET, 0x1c);
> -	WRITE(MDIO_CLK_PERIOD, 0xf0);
> +	/* LSI AXM (ARM) Platforms. */
> +	write_reg(MDIO_CLK_OFFSET, 0x1c);
> +	write_reg(MDIO_CLK_PERIOD, 0xf0);
>   #else
> -	WRITE(MDIO_CLK_OFFSET, 0x10);
> -	WRITE(MDIO_CLK_PERIOD, 0x2c);
> +	/* LSI ACP (PPC) Platforms. */
> +	write_reg(MDIO_CLK_OFFSET, 0x10);
> +	write_reg(MDIO_CLK_PERIOD, 0x2c);
>   #endif
> -
> -	return 0;
>   }
>
> -#endif /* ! CONFIG_ACPISS */
> -
>   /*
> -  ==============================================================================
> -  ==============================================================================
> -  Linux Stuff
> -  ==============================================================================
> -  ==============================================================================
> -*/
> -
> -/*
> -  ------------------------------------------------------------------------------
> -  acp_wrappers_init
> -*/
> + * acp_wrappers_init
> + */
>
>   int __init
>   acp_mdio_init(void)
> @@ -286,12 +276,16 @@ acp_mdio_init(void)
>   	int rc = -ENODEV;
>   	struct device_node *np = NULL;
>   	const u32 *field;
> +	void __iomem *map;
>   	u64 mdio_address;
>   	u32 mdio_size;
>
> -	pr_info("Initializing Axxia Wrappers.\n");
> +	pr_info("MDIO: Initializing Axxia Wrappers.\n");
> +
> +	mdio_priv = kzalloc(sizeof(struct lsi_mdio_priv), GFP_KERNEL);
> +	if (!mdio_priv)
> +		return -ENOMEM;
>
> -#ifndef CONFIG_ACPISS
>   	np = of_find_node_by_type(np, "network");
>
>   	while (np &&
> @@ -299,22 +293,37 @@ acp_mdio_init(void)
>   	       !of_device_is_compatible(np, "acp-femac"))
>   		np = of_find_node_by_type(np, "network");
>
> -	if (!np)
> +	if (!np) {
> +		pr_warn("MDIO: No compatible devices found.\n");
> +		rc = -EINVAL;
>   		goto error;
> +	}
>
>   	field = of_get_property(np, "mdio-reg", NULL);
>
> -	if (!field)
> +	if (!field) {
> +		pr_crit("MDIO: Unable to read mdio-reg property!\n");
> +		rc = -EINVAL;
>   		goto error;
> +	}
>
>   	mdio_address = of_translate_address(np, field);
> +	if (mdio_address == OF_BAD_ADDR) {
> +		pr_crit("MDIO: of_translate_address failed!\n");
> +		rc = -EINVAL;
> +		goto error;
> +	}
> +
>   	mdio_size = field[1];
> -	mdio_base = (unsigned long)ioremap(mdio_address, mdio_size);
> -	rc = acp_mdio_initialize();
> -#else
> -	rc = 0;
> -#endif
> +	map = ioremap(mdio_address, mdio_size);
> +	if (!map) {
> +		pr_crit("MDIO: Unable to ioremap!\n");
> +		rc = -ENOMEM;
> +		goto error;
> +	}
> +	mdio_priv->base = (unsigned long)map;
>
> +	acp_mdio_initialize();
>   error:
>   	return rc;
>   }
> diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.c b/drivers/net/ethernet/lsi/lsi_acp_net.c
> index 5684779..5589619 100644
> --- a/drivers/net/ethernet/lsi/lsi_acp_net.c
> +++ b/drivers/net/ethernet/lsi/lsi_acp_net.c
> @@ -1,23 +1,13 @@
>   /*
>    * drivers/net/ethernet/lsi/lsi_acp_net.c
>    *
> - * Copyright (C) 2013 LSI
> + * Copyright (C) 2013 LSI Corporation.
>    *
>    * This program is free software; you can redistribute it and/or modify
>    * it under the terms of the GNU General Public License as published by
>    * the Free Software Foundation; either version 2 of the License, or
>    * (at your option) any later version.
>    *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
> - * USA
> - *
>    * NOTES:
>    *
>    * 1) This driver is used by both ACP (PPC) and AXM (ARM) platforms.
> @@ -81,48 +71,28 @@
>   #include <linux/of.h>
>   #include <linux/of_address.h>
>   #include <linux/of_irq.h>
> +#include <linux/of_net.h>
>   #include <linux/dma-mapping.h>
>   #include <linux/uaccess.h>
>   #include <linux/io.h>
>
>   #include <asm/dma.h>
>
> -#ifdef CONFIG_AXXIA
> -#include <mach/ncr.h>
> -#else
>   #include "../../../misc/lsi-ncr.h"
> -#endif
>
>   #include "lsi_acp_net.h"
>
>   extern int acp_mdio_read(unsigned long, unsigned long, unsigned short *, int);
>   extern int acp_mdio_write(unsigned long, unsigned long, unsigned short, int);
>
> -/* Define to disable full duplex mode on Amarillo boards */
> -#undef AMARILLO_WA
> -/*#define AMARILLO_WA*/
> -
>   #define LSI_DRV_NAME           "acp-femac"
>   #define LSI_MDIO_NAME          "acp-femac-mdio"
> -#define LSI_DRV_VERSION        "2013-09-10"
> +#define LSI_DRV_VERSION        "2014-01-09"
>
>   MODULE_AUTHOR("John Jacques");
>   MODULE_DESCRIPTION("LSI ACP-FEMAC Ethernet driver");
>   MODULE_LICENSE("GPL");
>
> -/* Base Addresses of the RX, TX, and DMA Registers. */
> -static void *rx_base;
> -static void *tx_base;
> -static void *dma_base;
> -#ifdef CONFIG_ARM
> -static void *gpreg_base;
> -#define GPREG_BASE 0x002010094000ULL
> -#endif
> -
> -/* BCM5221 registers */
> -#define PHY_BCM_TEST_REG	0x1f
> -#define PHY_AUXILIARY_MODE3	0x1d
> -
>   /*
>    * ----------------------------------------------------------------------
>    * appnic_mii_read
> @@ -183,12 +153,10 @@ static void appnic_handle_link_change(struct net_device *dev)
>   	if (phydev->link) {
>   		if ((pdata->speed != phydev->speed) ||
>   		    (pdata->duplex != phydev->duplex)) {
> -#ifndef AMARILLO_WA
>   			if (phydev->duplex) {
>   				rx_configuration |= APPNIC_RX_CONF_DUPLEX;
>   				tx_configuration |= APPNIC_TX_CONF_DUPLEX;
>   			}
> -#endif
>   			if (phydev->speed == SPEED_100) {
>   				rx_configuration |= APPNIC_RX_CONF_SPEED;
>   				tx_configuration |= APPNIC_TX_CONF_SPEED;
> @@ -287,34 +255,6 @@ skip_first:
>   		return ret;
>   	}
>
> -#ifdef AMARILLO_WA
> -	/*
> -	 * For the Amarillo, without the auto-negotiate ecn.
> -	 */
> -	{
> -		u16 val;
> -		int rc;
> -
> -		/* Enable access to shadow register @ 0x1d */
> -		rc = acp_mdio_read(phydev->addr, PHY_BCM_TEST_REG, &val, 0);
> -		val |= 0x80;
> -		rc |= acp_mdio_write(phydev->addr, PHY_BCM_TEST_REG, val, 0);
> -
> -		/* Set RX FIFO size to 0x7 */
> -		rc |= acp_mdio_read(phydev->addr, PHY_AUXILIARY_MODE3, &val, 0);
> -		val &= 0xf;
> -		val |= 0x7;
> -		rc |= acp_mdio_write(phydev->addr, PHY_AUXILIARY_MODE3, val, 0);
> -
> -		/* Disable access to shadow register @ 0x1d */
> -		rc |= acp_mdio_read(phydev->addr, PHY_BCM_TEST_REG, &val, 0);
> -		val &= ~0x80;
> -		rc |= acp_mdio_write(phydev->addr, PHY_BCM_TEST_REG, val, 0);
> -
> -		if (0 != rc)
> -			return -EIO;
> -	}
> -#endif
>   	netdev_info(dev,
>   		    "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
>   		    phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
> @@ -391,9 +331,7 @@ err_out_1:
>   #define DESCRIPTOR_GRANULARITY 64
>   #define BUFFER_ALIGNMENT 64
>
> -#define ALIGN64B(address) \
> -	((((unsigned long) (address) + (64UL - 1UL)) & ~(64UL - 1UL)))
> -
> +#define ALIGN64B(address) (PTR_ALIGN((address), BUFFER_ALIGNMENT))
>   #define ALIGN64B_OFFSET(address) \
>   	(ALIGN64B(address) - (unsigned long) (address))
>
> @@ -441,26 +379,44 @@ int tx_buf_sz = CONFIG_LSI_NET_TX_BUF_SZ;
>   module_param(tx_buf_sz, int, 0);
>   MODULE_PARM_DESC(tx_buf_sz, "Appnic : Receive buffer size");
>
> -static unsigned long dropped_by_stack;
> -static unsigned long out_of_tx_descriptors;
> -static unsigned long transmit_interrupts;
> -static unsigned long receive_interrupts;
> +/*
> + * ======================================================================
> + * Utility Functions
> + * ======================================================================
> + */
>
>   /*
> -  ======================================================================
> -  Utility Functions
> -  ======================================================================
> -*/
> + * ----------------------------------------------------------------------
> + * mac_addr_valid
> + *
> + * If mac address is multicast, broadcast, or matches our mac address,
> + * it's a valid address. Otherwise, it's not.
> + */
> +
> +static bool mac_addr_valid(struct net_device *dev, u8 *mac_addr)
> +{
> +	bool is_valid = false;
> +
> +	if (is_multicast_ether_addr(mac_addr))
> +		is_valid = true;
> +	else if (is_broadcast_ether_addr(mac_addr))
> +		is_valid = true;
> +	else if (compare_ether_addr(mac_addr, &dev->dev_addr[0]) == 0)
> +		is_valid = true;
> +
> +	return is_valid;
> +}
> +
>
>   /*
> -  ----------------------------------------------------------------------
> -  clear_statistics
> -*/
> + * ----------------------------------------------------------------------
> + * clear_statistics
> + *
> + * NOTE: The hardware clears the statistics registers after a read.
> + */
>
>   static void clear_statistics(struct appnic_device *pdata)
>   {
> -	int waste;
> -
>   	/*
>   	 * Clear memory.
>   	 */
> @@ -468,62 +424,61 @@ static void clear_statistics(struct appnic_device *pdata)
>   	memset((void *) &(pdata->stats), 0, sizeof(struct net_device_stats));
>
>   	/*
> -	 * Clear counters.
> +	 * Clear counters by reading them.
>   	 */
>
> -	waste = read_mac(APPNIC_RX_STAT_PACKET_OK); /* rx_packets */
> -	waste = read_mac(APPNIC_TX_STAT_PACKET_OK); /* tx_packets */
> -
> -	/* rx_bytes kept by driver. */
> -	/* tx_bytes kept by driver. */
> -	/* rx_errors will be the sum of the rx errors available. */
> -	/* tx_errors will be the sum of the tx errors available. */
> -	/* rx_dropped (unable to allocate skb) will be maintained by driver */
> -	/* tx_dropped (unable to allocate skb) will be maintained by driver */
> -
> -	/* multicast */
> -
> -	waste = read_mac(APPNIC_RX_STAT_MULTICAST);
> -
> -	/* collisions will be the sum of the three following. */
> -
> -	waste = read_mac(APPNIC_TX_STATUS_LATE_COLLISION);
> -	waste = read_mac(APPNIC_TX_STATUS_EXCESSIVE_COLLISION);
> -	waste = read_mac(APPNIC_TX_STAT_COLLISION_ABOVE_WATERMARK);
> -
> -	/* rx_length_errors will be the sum of the two following. */
> +	/* stats.rx_packets */
> +	read_mac(APPNIC_RX_STAT_PACKET_OK);
>
> -	waste = read_mac(APPNIC_RX_STAT_UNDERSIZE);
> -	waste = read_mac(APPNIC_RX_STAT_OVERSIZE);
> +	/* stats.tx_packets */
> +	read_mac(APPNIC_TX_STAT_PACKET_OK);
>
> -	/* rx_over_errors (out of descriptors?) maintained by the driver. */
> -	/* rx_crc_errors */
> +	/*
> +	 * stats.rx_bytes - Updated by this driver.
> +	 * stats.tx_bytes - Updated by this driver.
> +	 * stats.rx_errors - The sum of all RX errors available.
> +	 * stats.tx_errors - The sum of all TX errors available.
> +	 * stats.rx_dropped (unable to allocate skb) - Updated by the stack.
> +	 * stats.tx_dropped (unable to allocate skb) - Updated by the stack.
> +	 */
>
> -	waste = read_mac(APPNIC_RX_STAT_CRC_ERROR);
> +	/* stats.multicast */
> +	read_mac(APPNIC_RX_STAT_MULTICAST);
>
> -	/* rx_frame_errors */
> +	/* stats.collisions - The sum of the following driver stats. */
> +	read_mac(APPNIC_TX_STATUS_LATE_COLLISION);
> +	read_mac(APPNIC_TX_STATUS_EXCESSIVE_COLLISION);
> +	read_mac(APPNIC_TX_STAT_COLLISION_ABOVE_WATERMARK);
>
> -	waste = read_mac(APPNIC_RX_STAT_ALIGN_ERROR);
> +	/* stats.rx_length_errors - The sum of the following driver stats. */
> +	read_mac(APPNIC_RX_STAT_UNDERSIZE);
> +	read_mac(APPNIC_RX_STAT_OVERSIZE);
>
> -	/* rx_fifo_errors */
> +	/* stats.rx_over_errors - Not maintained by this driver. */
>
> -	waste = read_mac(APPNIC_RX_STAT_OVERFLOW);
> +	/* stats.rx_crc_errors */
> +	read_mac(APPNIC_RX_STAT_CRC_ERROR);
>
> -	/* rx_missed will not be maintained. */
> -	/* tx_aborted_errors will be maintained by the driver. */
> -	/* tx_carrier_errors will not be maintained. */
> -	/* tx_fifo_errors */
> +	/* stats.rx_frame_errors */
> +	read_mac(APPNIC_RX_STAT_ALIGN_ERROR);
>
> -	waste = read_mac(APPNIC_TX_STAT_UNDERRUN);
> +	/* stats.rx_fifo_errors */
> +	read_mac(APPNIC_RX_STAT_OVERFLOW);
>
> -	/* tx_heartbeat_errors */
> -	/* tx_window_errors */
> +	/*
> +	 * stats.rx_missed - Not maintained by this driver.
> +	 * stats.tx_aborted_errors - Not maintained by this driver.
> +	 * stats.tx_carrier_errors - Not maintained by this driver.
> +	 */
>
> -	/* rx_compressed will not be maintained. */
> -	/* tx_compressed will not be maintained. */
> +	/* stats.tx_fifo_errors */
> +	read_mac(APPNIC_TX_STAT_UNDERRUN);
>
>   	/*
> -	 * That's all.
> +	 * stats.tx_heartbeat_errors - Not maintained by this driver.
> +	 * stats.tx_window_errors - Not mainteaned by this driver.
> +	 * stats.rx_compressed - Not maintained by this driver.
> +	 * stats.tx_compressed - Not maintained by this driver.
>   	 */
>
>   	return;
> @@ -533,38 +488,31 @@ static void clear_statistics(struct appnic_device *pdata)
>    * ----------------------------------------------------------------------
>    * get_hw_statistics
>    *
> - *  -- NOTES --
> - *
> - *  1) The hardware clears the statistics registers after a read.
> + * NOTE: The hardware clears the statistics registers after a read.
>    */
>
>   static void get_hw_statistics(struct appnic_device *pdata)
>   {
>   	unsigned long flags;
>
> -	/* tx_packets */
> -
> +	/* stats.tx_packets */
>   	pdata->stats.tx_packets += read_mac(APPNIC_TX_STAT_PACKET_OK);
>
> -	/* multicast */
> -
> +	/* stats.multicast */
>   	pdata->stats.multicast += read_mac(APPNIC_RX_STAT_MULTICAST);
>
> -	/* collision */
> -
> +	/* stats.collision */
>   	pdata->stats.collisions += read_mac(APPNIC_TX_STATUS_LATE_COLLISION);
>   	pdata->stats.collisions +=
>   		read_mac(APPNIC_TX_STATUS_EXCESSIVE_COLLISION);
>   	pdata->stats.collisions +=
>   	read_mac(APPNIC_TX_STAT_COLLISION_ABOVE_WATERMARK);
>
> -	/* rx_length_errors */
> -
> +	/* stats.rx_length_errors */
>   	pdata->stats.rx_length_errors += read_mac(APPNIC_RX_STAT_UNDERSIZE);
>   	pdata->stats.rx_length_errors += read_mac(APPNIC_RX_STAT_OVERSIZE);
>
> -	/* tx_fifo_errors */
> -
> +	/* stats.tx_fifo_errors */
>   	pdata->stats.tx_fifo_errors += read_mac(APPNIC_TX_STAT_UNDERRUN);
>
>   	/*
> @@ -591,10 +539,6 @@ static void get_hw_statistics(struct appnic_device *pdata)
>
>   	spin_unlock_irqrestore(&pdata->dev_lock, flags);
>
> -	/*
> -	 * That's all.
> -	 */
> -
>   	return;
>   }
>
> @@ -705,13 +649,12 @@ static void queue_decrement(union appnic_queue_pointer *queue,
>    * disable_rx_tx
>    */
>
> -static void disable_rx_tx(void)
> +static void disable_rx_tx(struct net_device *dev)
>   {
> +	struct appnic_device *pdata = netdev_priv(dev);
>   	unsigned long tx_configuration;
>   	unsigned long rx_configuration;
>
> -	pr_info("%s: Disabling the interface.\n", LSI_DRV_NAME);
> -
>   	rx_configuration = read_mac(APPNIC_RX_CONF);
>   	rx_configuration &= ~APPNIC_RX_CONF_ENABLE;
>   	write_mac(rx_configuration, APPNIC_RX_CONF);
> @@ -721,7 +664,6 @@ static void disable_rx_tx(void)
>
>   	write_mac(tx_configuration, APPNIC_TX_CONF);
>
> -	/* That's all. */
>   	return;
>   }
>
> @@ -740,15 +682,18 @@ static void disable_rx_tx(void)
>   static void handle_transmit_interrupt(struct net_device *dev)
>   {
>   	struct appnic_device *pdata = netdev_priv(dev);
> +	union appnic_queue_pointer queue;
>
>   	/*
>   	 * The hardware's tail pointer should be one descriptor (or more)
>   	 * ahead of software's copy.
>   	 */
>
> -	while (0 < queue_initialized(SWAB_QUEUE_POINTER(pdata->tx_tail),
> -				     pdata->tx_tail_copy, pdata->tx_num_desc)) {
> +	queue = swab_queue_pointer(pdata->tx_tail);
> +	while (0 < queue_initialized(queue, pdata->tx_tail_copy,
> +				     pdata->tx_num_desc)) {
>   		queue_increment(&pdata->tx_tail_copy, pdata->tx_num_desc);
> +		queue = swab_queue_pointer(pdata->tx_tail);
>   	}
>
>   	return;
> @@ -768,18 +713,16 @@ static void lsinet_rx_packet(struct net_device *dev)
>   	unsigned error_num = 0;
>   	unsigned long ok_stat = 0, overflow_stat = 0;
>   	unsigned long crc_stat = 0, align_stat = 0;
> -
> -	spin_lock(&pdata->extra_lock);
> +	union appnic_queue_pointer queue;
>
>   	readdescriptor(((unsigned long)pdata->rx_desc +
>   			pdata->rx_tail_copy.bits.offset), &descriptor);
>
> -	sk_buff = dev_alloc_skb(1600);
> +	sk_buff = dev_alloc_skb(LSINET_MAX_MTU);
>
>   	if ((struct sk_buff *)0 == sk_buff) {
>   		pr_err("%s: dev_alloc_skb() failed! Dropping packet.\n",
>   		       LSI_DRV_NAME);
> -		spin_unlock(&pdata->extra_lock);
>   		return;
>   	}
>
> @@ -792,25 +735,18 @@ static void lsinet_rx_packet(struct net_device *dev)
>   	 * Copy the received packet into the skb.
>   	 */
>
> -	while (0 < queue_initialized(SWAB_QUEUE_POINTER(pdata->rx_tail),
> -				pdata->rx_tail_copy, pdata->rx_num_desc)) {
> +	queue = swab_queue_pointer(pdata->rx_tail);
> +	while (0 < queue_initialized(queue, pdata->rx_tail_copy,
> +				     pdata->rx_num_desc)) {
>
> -#ifdef CONFIG_PRELOAD_RX_BUFFERS
>   		{
>   			unsigned char *buffer;
>   			buffer = skb_put(sk_buff, descriptor.pdu_length);
> -			memcmp(buffer, buffer, descriptor.pdu_length);
>   			memcpy((void *)buffer,
>   			       (void *)(descriptor.host_data_memory_pointer +
>   				 pdata->dma_alloc_offset_rx),
>   			       descriptor.pdu_length);
>   		}
> -#else
> -		memcpy((void *)skb_put(sk_buff, descriptor.pdu_length),
> -		       (void *)(descriptor.host_data_memory_pointer +
> -				pdata->dma_alloc_offset_rx),
> -		       descriptor.pdu_length);
> -#endif
>   		bytes_copied += descriptor.pdu_length;
>   		descriptor.data_transfer_length = pdata->rx_buf_per_desc;
>   		writedescriptor(((unsigned long)pdata->rx_desc +
> @@ -824,6 +760,7 @@ static void lsinet_rx_packet(struct net_device *dev)
>   		readdescriptor(((unsigned long)pdata->rx_desc +
>   					pdata->rx_tail_copy.bits.offset),
>   			       &descriptor);
> +		queue = swab_queue_pointer(pdata->rx_tail);
>   	}
>
>   	if (0 == descriptor.end_of_packet) {
> @@ -835,29 +772,15 @@ static void lsinet_rx_packet(struct net_device *dev)
>
>   	} else {
>   		if (0 == error_num) {
> -			struct ethhdr *ethhdr =
> -				(struct ethhdr *) sk_buff->data;
> -			unsigned char broadcast[] = { 0xff, 0xff, 0xff,
> -						      0xff, 0xff, 0xff };
> -			unsigned char multicast[] = { 0x01, 0x00 };
> -
> -			if ((0 == memcmp((const void *)&(ethhdr->h_dest[0]),
> -					 (const void *)&(dev->dev_addr[0]),
> -					 sizeof(ethhdr->h_dest))) ||
> -			    (0 == memcmp((const void *)&(ethhdr->h_dest[0]),
> -					 (const void *) &(broadcast[0]),
> -					 sizeof(ethhdr->h_dest))) ||
> -			    (0 == memcmp((const void *)&(ethhdr->h_dest[0]),
> -					 (const void *) &(multicast[0]),
> -					 sizeof(multicast)))) {
> -
> +			struct ethhdr *ethhdr = (struct ethhdr *) sk_buff->data;
> +			if (mac_addr_valid(dev, &ethhdr->h_dest[0])) {
>   				pdata->stats.rx_bytes += bytes_copied;
> -				++pdata->stats.rx_packets;
> +				pdata->stats.rx_packets++;
>   				sk_buff->dev = dev;
>   				sk_buff->protocol = eth_type_trans(sk_buff,
>   								   dev);
>   				if (netif_receive_skb(sk_buff) == NET_RX_DROP)
> -					++dropped_by_stack;
> +					pdata->dropped_by_stack++;
>   			} else {
>   				dev_kfree_skb(sk_buff);
>   			}
> @@ -865,17 +788,14 @@ static void lsinet_rx_packet(struct net_device *dev)
>   			dev_kfree_skb(sk_buff);
>
>   			if (0 != overflow_stat)
> -				++pdata->stats.rx_fifo_errors;
> +				pdata->stats.rx_fifo_errors++;
>   			else if (0 != crc_stat)
> -				++pdata->stats.rx_crc_errors;
> +				pdata->stats.rx_crc_errors++;
>   			else if (0 != align_stat)
> -				++pdata->stats.rx_frame_errors;
> +				pdata->stats.rx_frame_errors++;
>   		}
>   	}
>
> -	spin_unlock(&pdata->extra_lock);
> -
> -	/* That's all. */
>   	return;
>   }
>
> @@ -887,32 +807,34 @@ static void lsinet_rx_packet(struct net_device *dev)
>   static int lsinet_rx_packets(struct net_device *dev, int max)
>   {
>   	struct appnic_device *pdata = netdev_priv(dev);
> -	union appnic_queue_pointer queue;
> +	union appnic_queue_pointer orig_queue, new_queue;
>   	int updated_head_pointer = 0;
>   	int packets = 0;
>
> -	queue.raw = pdata->rx_tail_copy.raw;
> +	new_queue.raw = pdata->rx_tail_copy.raw;
>
>   	/* Receive Packets */
>
> -	while (0 < queue_initialized(SWAB_QUEUE_POINTER(pdata->rx_tail),
> -				     queue, pdata->rx_num_desc)) {
> +	orig_queue = swab_queue_pointer(pdata->rx_tail);
> +	while (0 < queue_initialized(orig_queue, new_queue,
> +				     pdata->rx_num_desc)) {
>   		struct appnic_dma_descriptor descriptor;
>
>   		readdescriptor(((unsigned long)pdata->rx_desc +
> -				  queue.bits.offset),
> +				  new_queue.bits.offset),
>   				&descriptor);
>
>   		if (0 != descriptor.end_of_packet) {
>   			lsinet_rx_packet(dev);
> -			++packets;
> -			queue.raw = pdata->rx_tail_copy.raw;
> +			packets++;
> +			new_queue.raw = pdata->rx_tail_copy.raw;
>
>   			if ((-1 != max) && (packets == max))
>   				break;
>   		} else {
> -			queue_increment(&queue, pdata->rx_num_desc);
> +			queue_increment(&new_queue, pdata->rx_num_desc);
>   		}
> +		orig_queue = swab_queue_pointer(pdata->rx_tail);
>   	}
>
>   	/* Update the Head Pointer */
> @@ -954,37 +876,39 @@ static int lsinet_poll(struct napi_struct *napi, int budget)
>   	struct appnic_device *pdata =
>   		container_of(napi, struct appnic_device, napi);
>   	struct net_device *dev = pdata->device;
> -	union appnic_queue_pointer queue;
>
> -	int cur_budget = budget;
> +	int work_done = 0;
>   	unsigned long dma_interrupt_status;
>
> -	queue.raw = pdata->rx_tail_copy.raw;
> -
>   	do {
>   		/* Acknowledge the RX interrupt. */
>   		write_mac(~APPNIC_DMA_INTERRUPT_ENABLE_RECEIVE,
>   			   APPNIC_DMA_INTERRUPT_STATUS);
>
> -		cur_budget -= lsinet_rx_packets(dev, cur_budget);
> -		if (0 == cur_budget)
> +		/* Get Rx packets. */
> +		work_done += lsinet_rx_packets(dev, budget - work_done);
> +
> +		/* We've hit the budget limit. */
> +		if (work_done == budget)
>   			break;
>
>   		dma_interrupt_status = read_mac(APPNIC_DMA_INTERRUPT_STATUS);
>
> -	} while ((RX_INTERRUPT(dma_interrupt_status)) && cur_budget);
> +	} while (RX_INTERRUPT(dma_interrupt_status));
>
> -	napi_complete(napi);
> +	if (work_done < budget) {
> +		napi_complete(napi);
>
> -	/*
> -	 * Re-enable receive interrupts (and preserve
> -	 * the already enabled TX interrupt).
> -	 */
> -	write_mac((APPNIC_DMA_INTERRUPT_ENABLE_RECEIVE |
> -		   APPNIC_DMA_INTERRUPT_ENABLE_TRANSMIT),
> -		  APPNIC_DMA_INTERRUPT_ENABLE);
> +		/*
> +		 * Re-enable receive interrupts (and preserve
> +		 * the already enabled TX interrupt).
> +		 */
> +		write_mac((APPNIC_DMA_INTERRUPT_ENABLE_RECEIVE |
> +			   APPNIC_DMA_INTERRUPT_ENABLE_TRANSMIT),
> +			  APPNIC_DMA_INTERRUPT_ENABLE);
> +	}
>
> -	return 0;
> +	return work_done;
>   }
>
>   /*
> @@ -1012,12 +936,12 @@ static irqreturn_t appnic_isr(int irq, void *device_id)
>   	/* Handle interrupts */
>   	if (TX_INTERRUPT(dma_interrupt_status)) {
>   		/* transmition complete */
> -		++transmit_interrupts;
> +		pdata->transmit_interrupts++;
>   		handle_transmit_interrupt(dev);
>   	}
>
>   	if (RX_INTERRUPT(dma_interrupt_status)) {
> -		++receive_interrupts;
> +		pdata->receive_interrupts++;
>   		if (napi_schedule_prep(&pdata->napi)) {
>
>   			/*
> @@ -1124,7 +1048,7 @@ static int appnic_stop(struct net_device *dev)
>   	napi_disable(&pdata->napi);
>
>   	/* Stop the receiver and transmitter. */
> -	disable_rx_tx();
> +	disable_rx_tx(dev);
>
>   	/* Bring the PHY down. */
>   	if (pdata->phy_dev)
> @@ -1153,6 +1077,7 @@ static int appnic_hard_start_xmit(struct sk_buff *skb,
>   	struct appnic_device *pdata = netdev_priv(dev);
>   	int length;
>   	int buf_per_desc;
> +	union appnic_queue_pointer queue;
>
>   	length = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
>   	buf_per_desc = pdata->tx_buf_sz / pdata->tx_num_desc;
> @@ -1161,16 +1086,17 @@ static int appnic_hard_start_xmit(struct sk_buff *skb,
>   	 * If enough transmit descriptors are available, copy and transmit.
>   	 */
>
> +	queue = swab_queue_pointer(pdata->tx_tail);
>   	while (((length / buf_per_desc) + 1) >=
>   		queue_uninitialized(pdata->tx_head,
> -				    SWAB_QUEUE_POINTER(pdata->tx_tail),
> +				    queue,
>   				    pdata->tx_num_desc)) {
>   		handle_transmit_interrupt(dev);
> +		queue = swab_queue_pointer(pdata->tx_tail);
>   	}
>
>   	if (((length / buf_per_desc) + 1) <
> -		queue_uninitialized(pdata->tx_head,
> -				    SWAB_QUEUE_POINTER(pdata->tx_tail),
> +		queue_uninitialized(pdata->tx_head, queue,
>   				    pdata->tx_num_desc)) {
>   		int bytes_copied = 0;
>   		struct appnic_dma_descriptor descriptor;
> @@ -1204,11 +1130,12 @@ static int appnic_hard_start_xmit(struct sk_buff *skb,
>   				descriptor.data_transfer_length =
>   				 (length - bytes_copied);
>   				descriptor.end_of_packet = 1;
> -#ifdef CONFIG_DISABLE_TX_INTERRUPTS
> +				/*
> +				 * Leave TX interrupts disabled. We work
> +				 * the same with or w/o them. Set to "1"
> +				 * if we ever want to enable them though.
> +				 */
>   				descriptor.interrupt_on_completion = 0;
> -#else
> -				descriptor.interrupt_on_completion = 1;
> -#endif
>   				bytes_copied = length;
>   			}
>
> @@ -1222,22 +1149,22 @@ static int appnic_hard_start_xmit(struct sk_buff *skb,
>   			descriptor.start_of_packet = 0;
>   		}
>
> -#ifdef CONFIG_ARM
> -		/* ARM Data sync barrier */
> -		asm volatile ("mcr p15,0,%0,c7,c10,4" : : "r" (0));
> -#endif
> +		/* Data sync barrier */
> +		rmb();
> +
>   		write_mac(pdata->tx_head.raw, APPNIC_DMA_TX_HEAD_POINTER);
>   		dev->trans_start = jiffies;
>   	} else {
> -		++out_of_tx_descriptors;
> +		pdata->out_of_tx_descriptors++;
>   		pr_err("%s: No transmit descriptors available!\n",
>   		       LSI_DRV_NAME);
> +		return NETDEV_TX_BUSY;
>   	}
>
>   	/* Free the socket buffer */
>   	dev_kfree_skb(skb);
>
> -	return 0;
> +	return NETDEV_TX_OK;
>   }
>
>   /*
> @@ -1259,10 +1186,6 @@ static struct net_device_stats *appnic_get_stats(struct net_device *dev)
>
>   	get_hw_statistics(pdata);
>
> -	/*
> -	 * That's all.
> -	 */
> -
>   	return &pdata->stats;
>   }
>
> @@ -1273,14 +1196,18 @@ static struct net_device_stats *appnic_get_stats(struct net_device *dev)
>
>   static int appnic_set_mac_address(struct net_device *dev, void *data)
>   {
> +	struct appnic_device *pdata = netdev_priv(dev);
>   	struct sockaddr *address = data;
>   	unsigned long swap_source_address;
>
>   	if (netif_running(dev))
>   		return -EBUSY;
>
> -	memcpy(dev->dev_addr, address->sa_data, 6);
> -	memcpy(dev->perm_addr, address->sa_data, 6);
> +	if (!is_valid_ether_addr(address->sa_data))
> +		return -EADDRNOTAVAIL;
> +
> +	memcpy(dev->dev_addr, address->sa_data, ETH_ALEN);
> +	memcpy(dev->perm_addr, address->sa_data, ETH_ALEN);
>
>   	swap_source_address = ((address->sa_data[4]) << 8) |
>   			       address->sa_data[5];
> @@ -1297,10 +1224,106 @@ static int appnic_set_mac_address(struct net_device *dev, void *data)
>   }
>
>   /*
> -  ======================================================================
> -  ETHTOOL Operations
> -  ======================================================================
> -*/
> + * ======================================================================
> + * ETHTOOL Operations
> + * ======================================================================
> + */
> +
> +enum {NETDEV_STATS, APPNIC_STATS};
> +
> +struct appnic_stats {
> +	char stat_string[ETH_GSTRING_LEN];
> +	int sizeof_stat;
> +	int stat_offset;
> +};
> +
> +#define APPNIC_STAT(str, m) { \
> +		.stat_string = str, \
> +		.sizeof_stat = sizeof(((struct appnic_device *)0)->m), \
> +		.stat_offset = offsetof(struct appnic_device, m) }
> +
> +static const struct appnic_stats appnic_gstrings_stats[] = {
> +	APPNIC_STAT("rx_packets", stats.rx_packets),
> +	APPNIC_STAT("tx_packets", stats.tx_packets),
> +	APPNIC_STAT("rx_bytes", stats.rx_bytes),
> +	APPNIC_STAT("tx_bytes", stats.tx_bytes),
> +	APPNIC_STAT("rx_errors", stats.rx_errors),
> +	APPNIC_STAT("tx_errors", stats.tx_errors),
> +	APPNIC_STAT("rx_dropped", stats.rx_dropped),
> +	APPNIC_STAT("tx_dropped", stats.tx_dropped),
> +	APPNIC_STAT("multicast", stats.multicast),
> +	APPNIC_STAT("collisions", stats.collisions),
> +	APPNIC_STAT("rx_length_errors", stats.rx_length_errors),
> +	APPNIC_STAT("rx_crc_errors", stats.rx_crc_errors),
> +	APPNIC_STAT("rx_frame_errors", stats.rx_frame_errors),
> +	APPNIC_STAT("rx_fifo_errors", stats.rx_fifo_errors),
> +	APPNIC_STAT("tx_fifo_errors", stats.tx_fifo_errors),
> +
> +	APPNIC_STAT("dropped_by_stack", dropped_by_stack),
> +	APPNIC_STAT("out_of_tx_descriptors", out_of_tx_descriptors),
> +	APPNIC_STAT("transmit_interrupts", transmit_interrupts),
> +	APPNIC_STAT("receive_interrupts", receive_interrupts),
> +};
> +#define APPNIC_GLOBAL_STATS_LEN  ARRAY_SIZE(appnic_gstrings_stats)
> +#define APPNIC_STATS_LEN (APPNIC_GLOBAL_STATS_LEN)
> +
> +/*
> + * ----------------------------------------------------------------------
> + * appnic_get_ethtool_stats
> + */
> +
> +static void appnic_get_ethtool_stats(struct net_device *dev,
> +				     struct ethtool_stats *stats,
> +				     u64 *data)
> +{
> +	struct appnic_device *pdata = netdev_priv(dev);
> +	int i;
> +	char *p = NULL;
> +
> +	get_hw_statistics(pdata);
> +	for (i = 0; i < APPNIC_GLOBAL_STATS_LEN; i++) {
> +		p = (char *) pdata + appnic_gstrings_stats[i].stat_offset;
> +		data[i] = (appnic_gstrings_stats[i].sizeof_stat ==
> +			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
> +	}
> +}
> +
> +/*
> + * ----------------------------------------------------------------------
> + * appnic_get_strings
> + */
> +
> +static void appnic_get_strings(struct net_device *netdev, u32 stringset,
> +			       u8 *data)
> +{
> +	u8 *p = data;
> +	int i;
> +
> +	switch (stringset) {
> +	case ETH_SS_STATS:
> +		for (i = 0; i < APPNIC_GLOBAL_STATS_LEN; i++) {
> +			memcpy(p, appnic_gstrings_stats[i].stat_string,
> +			       ETH_GSTRING_LEN);
> +			p += ETH_GSTRING_LEN;
> +		}
> +		break;
> +	}
> +}
> +
> +/*
> + * ----------------------------------------------------------------------
> + * appnic_get_sset_count
> + */
> +
> +static int appnic_get_sset_count(struct net_device *netdev, int sset)
> +{
> +	switch (sset) {
> +	case ETH_SS_STATS:
> +		return APPNIC_STATS_LEN;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
>
>   /*
>    * ----------------------------------------------------------------------
> @@ -1312,6 +1335,8 @@ static void appnic_get_drvinfo(struct net_device *dev,
>   {
>   	strcpy(info->driver, LSI_DRV_NAME);
>   	strcpy(info->version, LSI_DRV_VERSION);
> +	strlcpy(info->bus_info, dev_name(dev->dev.parent),
> +		sizeof(info->bus_info));
>   }
>
>   /*
> @@ -1336,16 +1361,19 @@ static int appnic_get_settings(struct net_device *dev,
>    */
>
>   static const struct ethtool_ops appnic_ethtool_ops = {
> -	.get_drvinfo = appnic_get_drvinfo,
> -	.get_settings = appnic_get_settings
> +	.get_drvinfo		= appnic_get_drvinfo,
> +	.get_settings		= appnic_get_settings,
> +	.get_ethtool_stats	= appnic_get_ethtool_stats,
> +	.get_strings		= appnic_get_strings,
> +	.get_sset_count		= appnic_get_sset_count,
>   };
>
>
>   /*
> -  ======================================================================
> -  Linux Module Interface.
> -  ======================================================================
> -*/
> + * ======================================================================
> + * Linux Module Interface.
> + * ======================================================================
> + */
>
>   static const struct net_device_ops appnic_netdev_ops = {
>   	.ndo_open = appnic_open,
> @@ -1373,13 +1401,10 @@ int appnic_init(struct net_device *dev)
>   	struct appnic_dma_descriptor descriptor;
>   	struct sockaddr address;
>   	unsigned long node_cfg;
> +	int rc = 0;
>
> -#ifdef CONFIG_ARM
>   	/* Set FEMAC to uncached */
> -	gpreg_base = ioremap(GPREG_BASE, 0x1000);
> -	writel(0x0, gpreg_base+0x78);
> -#endif
> -
> +	femac_uncache(pdata);
>
>   	/*
>   	 * Reset the MAC
> @@ -1397,19 +1422,19 @@ int appnic_init(struct net_device *dev)
>   	 */
>
>   	if (0 != (rx_num_desc % DESCRIPTOR_GRANULARITY)) {
> -		pr_warn("%s: rx_num_desc was not a multiple of %d.\n",
> -			LSI_DRV_NAME, DESCRIPTOR_GRANULARITY);
> -		rx_num_desc += DESCRIPTOR_GRANULARITY -
> -				(rx_num_desc % DESCRIPTOR_GRANULARITY);
> +		pr_err("%s: rx_num_desc was not a multiple of %d.\n",
> +		       LSI_DRV_NAME, DESCRIPTOR_GRANULARITY);
> +		rc = -EINVAL;
> +		goto err_param;
>   	}
>
>   	pdata->rx_num_desc = rx_num_desc;
>
>   	if (0 != (tx_num_desc % DESCRIPTOR_GRANULARITY)) {
> -		pr_warn("%s: tx_num_desc was not a multiple of %d.\n",
> -			LSI_DRV_NAME, DESCRIPTOR_GRANULARITY);
> -		tx_num_desc += DESCRIPTOR_GRANULARITY -
> -			(tx_num_desc % DESCRIPTOR_GRANULARITY);
> +		pr_err("%s: tx_num_desc was not a multiple of %d.\n",
> +		       LSI_DRV_NAME, DESCRIPTOR_GRANULARITY);
> +		rc = -EINVAL;
> +		goto err_param;
>   	}
>
>   	pdata->tx_num_desc = tx_num_desc;
> @@ -1420,19 +1445,19 @@ int appnic_init(struct net_device *dev)
>   	 */
>
>   	if (0 != (rx_buf_sz % (BUFFER_ALIGNMENT * rx_num_desc))) {
> -		pr_warn("%s: rx_buf_sz was not a multiple of %d.\n",
> -			LSI_DRV_NAME, (BUFFER_ALIGNMENT * rx_num_desc));
> -		rx_buf_sz += (BUFFER_ALIGNMENT * rx_num_desc) -
> -				(rx_buf_sz % (BUFFER_ALIGNMENT * rx_num_desc));
> +		pr_err("%s: rx_buf_sz was not a multiple of %d.\n",
> +		       LSI_DRV_NAME, (BUFFER_ALIGNMENT * rx_num_desc));
> +		rc = -EINVAL;
> +		goto err_param;
>   	}
>
>   	pdata->rx_buf_sz = rx_buf_sz;
>
>   	if (0 != (tx_buf_sz % (BUFFER_ALIGNMENT * tx_num_desc))) {
> -		pr_warn("%s: tx_buf_sz was not a multiple of %d.\n",
> -			LSI_DRV_NAME, (BUFFER_ALIGNMENT * tx_num_desc));
> -		tx_buf_sz += (BUFFER_ALIGNMENT * tx_num_desc) -
> -			(tx_buf_sz % (BUFFER_ALIGNMENT * tx_num_desc));
> +		pr_err("%s: tx_buf_sz was not a multiple of %d.\n",
> +		       LSI_DRV_NAME, (BUFFER_ALIGNMENT * tx_num_desc));
> +		rc = -EINVAL;
> +		goto err_param;
>   	}
>
>   	pdata->tx_buf_sz = tx_buf_sz;
> @@ -1464,80 +1489,15 @@ int appnic_init(struct net_device *dev)
>   		(pdata->tx_buf_sz) + (BUFFER_ALIGNMENT);
>
>   	/*
> -	 * This needs to be set to something sane for
> -	 * dma_alloc_coherent()
> +	 * Allocate the buffers.
>   	 */
>
> -#if defined(CONFIG_ARM)
> -	pdata->dma_alloc = (void *)
> -		dma_alloc_coherent(NULL,
> -				   pdata->dma_alloc_size,
> -				   &pdata->dma_alloc_dma,
> -				   GFP_KERNEL);
> -#else
> -	dev->dev.archdata.dma_ops = &dma_direct_ops;
> -
> -	pdata->dma_alloc = (void *)
> -		dma_alloc_coherent(&dev->dev,
> -				   pdata->dma_alloc_size,
> -				   &pdata->dma_alloc_dma,
> -				   GFP_KERNEL);
> -#endif
> -
> -	if ((void *)0 == pdata->dma_alloc) {
> -		pr_err("%s: Can't allocate %d bytes of DMA-able memory!\n",
> -		       LSI_DRV_NAME, pdata->dma_alloc_size);
> -		kfree(pdata);
> -		return -ENOMEM;
> -	}
> -
> -	pdata->dma_alloc_offset = (int)pdata->dma_alloc -
> -					(int)pdata->dma_alloc_dma;
> -
> -#ifdef CONFIG_ARM
> -	pdata->dma_alloc_rx = (void *)dma_alloc_coherent(NULL,
> -#else
> -	pdata->dma_alloc_rx = (void *)dma_alloc_coherent(&dev->dev,
> -#endif
> -						    pdata->dma_alloc_size_rx,
> -						    &pdata->dma_alloc_dma_rx,
> -						    GFP_KERNEL);
> -
> -	if ((void *)0 == pdata->dma_alloc_rx) {
> -		pr_err("%s: Can't allocate %d bytes of RX DMA-able memory!\n",
> -		       LSI_DRV_NAME, pdata->dma_alloc_size_rx);
> -		dma_free_coherent(&dev->dev, pdata->dma_alloc_size,
> -				  pdata->dma_alloc, pdata->dma_alloc_dma);
> -		kfree(pdata);
> -		return -ENOMEM;
> +	rc = femac_alloc_mem_buffers(dev);
> +	if (rc != 0) {
> +		pr_err("%s: Can't allocate DMA-able memory!\n", LSI_DRV_NAME);
> +		goto err_mem_buffers;
>   	}
>
> -	pdata->dma_alloc_offset_rx = (int)pdata->dma_alloc_rx -
> -					(int)pdata->dma_alloc_dma_rx;
> -
> -#ifdef CONFIG_ARM
> -	pdata->dma_alloc_tx = (void *)dma_alloc_coherent(NULL,
> -#else
> -	pdata->dma_alloc_tx = (void *)dma_alloc_coherent(&dev->dev,
> -#endif
> -						    pdata->dma_alloc_size_tx,
> -						    &pdata->dma_alloc_dma_tx,
> -						    GFP_KERNEL);
> -
> -	if ((void *)0 == pdata->dma_alloc_tx) {
> -		pr_err("%s: Can't allocate %d bytes of TX DMA-able memory!\n",
> -		       LSI_DRV_NAME, pdata->dma_alloc_size_tx);
> -		dma_free_coherent(&dev->dev, pdata->dma_alloc_size,
> -				  pdata->dma_alloc, pdata->dma_alloc_dma);
> -		dma_free_coherent(&dev->dev, pdata->dma_alloc_size_rx,
> -				  pdata->dma_alloc_rx, pdata->dma_alloc_dma_rx);
> -		kfree(pdata);
> -		return -ENOMEM;
> -	}
> -
> -	pdata->dma_alloc_offset_tx = (int)pdata->dma_alloc_tx -
> -					(int)pdata->dma_alloc_dma_tx;
> -
>   	/*
>   	 * Initialize the tail pointers
>   	 */
> @@ -1556,7 +1516,6 @@ int appnic_init(struct net_device *dev)
>   	dma_offset += sizeof(union appnic_queue_pointer);
>   	memset((void *)pdata->tx_tail, 0, sizeof(union appnic_queue_pointer));
>
> -
>   	/*
>   	 * Initialize the descriptor pointers
>   	 */
> @@ -1634,7 +1593,6 @@ int appnic_init(struct net_device *dev)
>   	 */
>
>   	spin_lock_init(&pdata->dev_lock);
> -	spin_lock_init(&pdata->extra_lock);
>
>   	/*
>   	 * Take MAC out of reset
> @@ -1665,22 +1623,24 @@ int appnic_init(struct net_device *dev)
>   	write_mac(0x40010000, APPNIC_DMA_PCI_CONTROL);
>   	write_mac(0x30000, APPNIC_DMA_CONTROL);
>   #ifdef CONFIG_ARM
> -	writel(0x280044, dma_base + 0x60);
> -	writel(0xc0, dma_base + 0x64);
> +	writel(0x280044, (unsigned long)pdata->dma_base + 0x60);
> +	writel(0xc0, (unsigned long)pdata->dma_base + 0x64);
>   #else
> -	out_le32(dma_base + 0x60, 0x280044);
> -	out_le32(dma_base + 0x64, 0xc0);
> +	out_le32((unsigned *)pdata->dma_base + 0x60, 0x280044);
> +	out_le32((unsigned *)pdata->dma_base + 0x64, 0xc0);
>   #endif
>
>   	/*
>   	 * Set the MAC address
>   	 */
> -	pr_info("%s: MAC %02x:%02x:%02x:%02x:%02x:%02x\n", LSI_DRV_NAME,
> -		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
> -		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
> +	pr_info("%s: MAC %pM\n", LSI_DRV_NAME, dev->dev_addr);
>
> -	memcpy(&(address.sa_data[0]), dev->dev_addr, 6);
> -	appnic_set_mac_address(dev, &address);
> +	memcpy(&(address.sa_data[0]), dev->dev_addr, ETH_ALEN);
> +	rc = appnic_set_mac_address(dev, &address);
> +	if (rc != 0) {
> +		pr_err("%s: Unable to set MAC address!\n", LSI_DRV_NAME);
> +		goto err_set_mac_addr;
> +	}
>
>   	/*
>   	 * Initialize the queue pointers.
> @@ -1761,48 +1721,30 @@ int appnic_init(struct net_device *dev)
>   	/* Fill in the net_device structure */
>
>   	ether_setup(dev);
> -#ifdef CONFIG_ARM
> -	dev->irq = pdata->dma_interrupt;
> -#else
> -	dev->irq = irq_create_mapping(NULL, pdata->dma_interrupt);
> -	if (NO_IRQ == dev->irq) {
> -		pr_err("%s: irq_create_mapping() failed\n", LSI_DRV_NAME);
> -		return -EBUSY;
> -	}
>
> -	if (0 != irq_set_irq_type(dev->irq, IRQ_TYPE_LEVEL_HIGH)) {
> -		pr_err("%s: set_irq_type() failed\n", LSI_DRV_NAME);
> -		return -EBUSY;
> +	/* Setup IRQ */
> +	rc = femac_irq_setup(dev);
> +	if (rc != 0) {
> +		pr_err("%s: IRQ setup failed!\n", LSI_DRV_NAME);
> +		goto err_irq_setup;
>   	}
> -#endif
>
>   	dev->netdev_ops = &appnic_netdev_ops;
> +	dev->ethtool_ops = &appnic_ethtool_ops;
>
> -	SET_ETHTOOL_OPS(dev, &appnic_ethtool_ops);
>   	memset((void *) &pdata->napi, 0, sizeof(struct napi_struct));
>   	netif_napi_add(dev, &pdata->napi,
>   		       lsinet_poll, LSINET_NAPI_WEIGHT);
>   	pdata->device = dev;
>
> -	/* That's all */
>   	return 0;
> -}
> -
> -/*
> - * ----------------------------------------------------------------------
> - * appnic_read_proc
> - */
> -
> -static int
> -appnic_read_proc(char *page, char **start, off_t offset,
> -		 int count, int *eof, void *data)
> -{
> -	int length;
> -
> -	length = sprintf(page, "-- appnic.c -- Profiling is disabled\n");
>
> -	/* That's all */
> -	return length;
> +err_irq_setup:
> +err_set_mac_addr:
> +	femac_free_mem_buffers(dev);
> +err_mem_buffers:
> +err_param:
> +	return rc;
>   }
>
>   /*
> @@ -1816,9 +1758,11 @@ static int __devinit appnic_probe_config_dt(struct net_device *dev,
>   {
>   	struct appnic_device *pdata = netdev_priv(dev);
>   	const u32 *field;
> +	const char *mac;
>   	const char *macspeed;
> -	int length;
> -#ifndef CONFIG_ARM
> +#ifdef CONFIG_ARM
> +	struct device_node *gp_node;
> +#else
>   	u64 value64;
>   	u32 value32;
>   #endif
> @@ -1827,44 +1771,44 @@ static int __devinit appnic_probe_config_dt(struct net_device *dev,
>   		return -ENODEV;
>
>   #ifdef CONFIG_ARM
> -	rx_base = of_iomap(np, 0);
> -	tx_base = of_iomap(np, 1);
> -	dma_base = of_iomap(np, 2);
> +	gp_node = of_find_compatible_node(NULL, NULL, "lsi,gpreg");
> +	if (!gp_node) {
> +		pr_err("%s: DTS is missing mode 'gpreg'\n", LSI_DRV_NAME);
> +		return -ENODEV;
> +	}
> +	pdata->gpreg_base = of_iomap(gp_node, 0);
> +
> +	pdata->rx_base = of_iomap(np, 0);
> +	pdata->tx_base = of_iomap(np, 1);
> +	pdata->dma_base = of_iomap(np, 2);
> +
> +	pdata->tx_interrupt = irq_of_parse_and_map(np, 0);
> +	pdata->rx_interrupt = irq_of_parse_and_map(np, 1);
> +	pdata->dma_interrupt = irq_of_parse_and_map(np, 2);
>   #else
>   	field = of_get_property(np, "enabled", NULL);
>
>   	if (!field || (field && (0 == *field)))
> -		return -EINVAL;
> +		goto device_tree_failed;
>
>   	field = of_get_property(np, "reg", NULL);
>
> -	if (!field) {
> -		pr_err("%s: Couldn't get \"reg\" property.", LSI_DRV_NAME);
> -		return -EINVAL;
> -	}
> +	if (!field)
> +		goto device_tree_failed;
>
>   	value64 = of_translate_address(np, field);
>   	value32 = field[1];
>   	field += 2;
> -	rx_base = ioremap(value64, value32);
> +	pdata->rx_base = ioremap(value64, value32);
>   	value64 = of_translate_address(np, field);
>   	value32 = field[1];
>   	field += 2;
> -	tx_base = ioremap(value64, value32);
> +	pdata->tx_base = ioremap(value64, value32);
>   	value64 = of_translate_address(np, field);
>   	value32 = field[1];
>   	field += 2;
> -	dma_base = ioremap(value64, value32);
> -#endif
> -	pdata->rx_base = (unsigned long)rx_base;
> -	pdata->tx_base = (unsigned long)tx_base;
> -	pdata->dma_base = (unsigned long)dma_base;
> +	pdata->dma_base = ioremap(value64, value32);
>
> -#ifdef CONFIG_ARM
> -	pdata->tx_interrupt = irq_of_parse_and_map(np, 0);
> -	pdata->rx_interrupt = irq_of_parse_and_map(np, 1);
> -	pdata->dma_interrupt = irq_of_parse_and_map(np, 2);
> -#else
>   	field = of_get_property(np, "interrupts", NULL);
>   	if (!field)
>   		goto device_tree_failed;
> @@ -1922,32 +1866,25 @@ static int __devinit appnic_probe_config_dt(struct net_device *dev,
>   		pdata->phy_link_auto = 1;
>   	}
>
> -	field = of_get_property(np, "mac-address", &length);
> -	if (!field || 6 != length) {
> +	mac = of_get_mac_address(np);
> +	if (!mac)
>   		goto device_tree_failed;
> -	} else {
> -		int i;
> -		u8 *value;
> -
> -		value = (u8 *)field;
>
> -		for (i = 0; i < 6; ++i)
> -			pdata->mac_addr[i] = value[i];
> -	}
> -
> -	memcpy(dev->dev_addr, &pdata->mac_addr[0], 6);
> -	memcpy(dev->perm_addr, &pdata->mac_addr[0], 6);
> +	memcpy(&pdata->mac_addr[0], mac, ETH_ALEN);
> +	memcpy(dev->dev_addr, mac, ETH_ALEN);
> +	memcpy(dev->perm_addr, mac, ETH_ALEN);
>
>   	return 0;
>
>   device_tree_failed:
>   	pr_err("%s: Reading Device Tree Failed\n", LSI_DRV_NAME);
> -	iounmap(rx_base);
> -	iounmap(tx_base);
> -	iounmap(dma_base);
>   #ifdef CONFIG_ARM
> -	iounmap(gpreg_base);
> +	iounmap(pdata->gpreg_base);
>   #endif
> +	iounmap(pdata->rx_base);
> +	iounmap(pdata->tx_base);
> +	iounmap(pdata->dma_base);
> +
>   	return -EINVAL;
>   }
>   #else
> @@ -1979,7 +1916,7 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
>   	if (!dev) {
>   		pr_err("%s: Couldn't allocate net device.\n", LSI_DRV_NAME);
>   		rc = -ENOMEM;
> -		goto out;
> +		goto err_alloc_etherdev;
>   	}
>
>   	SET_NETDEV_DEV(dev, &pdev->dev);
> @@ -1996,13 +1933,13 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
>   	rc = appnic_probe_config_dt(dev, np);
>
>   	if (rc == -EINVAL) {
> -		goto out;
> -	} else if (rc == -ENODEV) {
> +		goto err_inval;
> +	} else if (rc == -EINVAL) {
>
>   #ifdef CONFIG_MTD_NAND_EP501X_UBOOTENV
>
>   		/*
> -		 * Attempt to get device settings from the DTB failed, so
> +		 * The attempt to get device settings from the DTB failed, so
>   		 * try to grab the ethernet MAC from the u-boot environment
>   		 * and use hard-coded values for device base addresses.
>   		 */
> @@ -2012,14 +1949,14 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
>   		if (0 != ubootenv_get("ethaddr", ethaddr_string)) {
>   			pr_err("%s: Could not read ethernet address!\n",
>   			       LSI_DRV_NAME);
> -			return -EFAULT;
> +			rc = -EINVAL;
> +			goto err_inval;
>   		} else {
> -
> -			u8 mac_address[6];
> +			u8 mac_address[ETH_ALEN];
>   			int i = 0;
>   			char *string = ethaddr_string;
>
> -			while ((0 != string) && (6 > i)) {
> +			while ((0 != string) && (ETH_ALEN > i)) {
>   				char *value;
>   				unsigned long res;
>   				value = strsep(&string, ":");
> @@ -2028,29 +1965,23 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
>   				mac_address[i++] = (u8)res;
>   			}
>
> -			memcpy(dev->dev_addr, mac_address, 6);
> -			memcpy(dev->perm_addr, mac_address, 6);
> -			dev->addr_len = 6;
> +			memcpy(dev->dev_addr, mac_address, ETH_ALEN);
> +			memcpy(dev->perm_addr, mac_address, ETH_ALEN);
> +			dev->addr_len = ETH_ALEN;
>
>   			pr_info("%s: Using Static Addresses and Interrupts",
>   				LSI_DRV_NAME);
> -			rx_base = ioremap(0x002000480000ULL, 0x1000);
> -			pdata->rx_base =
> -			 (unsigned long)ioremap(0x002000480000ULL, 0x1000);
> -			tx_base = ioremap(0x002000481000ULL, 0x1000);
> -			pdata->tx_base =
> -			(unsigned long)ioremap(0x002000481000ULL, 0x1000);
> -			dma_base = ioremap(0x002000482000ULL, 0x1000);
> -			pdata->dma_base =
> -			 (unsigned long)ioremap(0x002000482000ULL, 0x1000);
> +			pdata->rx_base = ioremap(0x002000480000ULL, 0x1000);
> +			pdata->tx_base = ioremap(0x002000481000ULL, 0x1000);
> +			pdata->dma_base = ioremap(0x002000482000ULL, 0x1000);
>   			pdata->dma_interrupt = 33;
>   		}
>   #else
>   		/* Neither dtb info nor ubootenv driver found. */
>   		pr_err("%s: Could not read ethernet address!", LSI_DRV_NAME);
> -		return -EBUSY;
> +		rc = -EINVAL;
> +		goto err_inval;
>   #endif
> -
>   	}
>
>   #ifdef CONFIG_MTD_NAND_EP501X_UBOOTENV
> @@ -2065,8 +1996,10 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
>   			 * since u-boot defaults this value as hex.
>   			 */
>   			unsigned long res;
> -			if (kstrtoul(uboot_env_string, 16, &res))
> -				return -EBUSY;
> +			if (kstrtoul(uboot_env_string, 16, &res)) {
> +				rc = -EINVAL;
> +				goto err_inval;
> +			}
>   			pdata->ad_value = res;
>   		}
>   	}
> @@ -2078,7 +2011,7 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
>   	if (0 != rc) {
>   		pr_err("%s: appnic_init() failed: %d\n", LSI_DRV_NAME, rc);
>   		rc = -ENODEV;
> -		goto out;
> +		goto err_nodev;
>   	}
>
>   	/* Register the device. */
> @@ -2086,7 +2019,7 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
>   	if (0 != rc) {
>   		pr_err("%s: register_netdev() failed: %d\n", LSI_DRV_NAME, rc);
>   		rc = -ENODEV;
> -		goto out;
> +		goto err_nodev;
>   	}
>
>   	/* Initialize the PHY. */
> @@ -2094,14 +2027,17 @@ static int __devinit appnic_drv_probe(struct platform_device *pdev)
>   	if (rc) {
>   		pr_warn("%s: Failed to initialize PHY", LSI_DRV_NAME);
>   		rc = -ENODEV;
> -		goto out;
> +		goto err_mii_init;
>   	}
>
> -	/* Create the /proc entry. */
> -	create_proc_read_entry("driver/appnic", 0, NULL,
> -				appnic_read_proc, NULL);
> +	return 0;
>
> -out:
> +err_mii_init:
> +	unregister_netdev(dev);
> +err_nodev:
> +err_inval:
> +	free_netdev(dev);
> +err_alloc_etherdev:
>   	return rc;
>   }
>
> @@ -2113,35 +2049,29 @@ out:
>   static int __devexit appnic_drv_remove(struct platform_device *pdev)
>   {
>   	struct net_device *dev = platform_get_drvdata(pdev);
> -	struct appnic_device *pdata;
> +	struct appnic_device *pdata = NULL;
>
>   	pr_info("%s: Stopping driver", LSI_DRV_NAME);
>
> -	remove_proc_entry("driver/appnic", NULL);
> -
> -	if (dev) {
> -		pdata = netdev_priv(dev);
> -		if (pdata->phy_dev)
> -			phy_disconnect(pdata->phy_dev);
> -		mdiobus_unregister(pdata->mii_bus);
> -		mdiobus_free(pdata->mii_bus);
> -		platform_set_drvdata(pdev, NULL);
> -		unregister_netdev(dev);
> -		free_irq(dev->irq, dev);
> -		dma_free_coherent(&dev->dev, pdata->dma_alloc_size,
> -				  pdata->dma_alloc, pdata->dma_alloc_dma);
> -		dma_free_coherent(&dev->dev, pdata->dma_alloc_size_rx,
> -				  pdata->dma_alloc_rx, pdata->dma_alloc_dma_rx);
> -		dma_free_coherent(&dev->dev, pdata->dma_alloc_size_tx,
> -				  pdata->dma_alloc_tx, pdata->dma_alloc_dma_tx);
> -		free_netdev(dev);
> -	}
> +	BUG_ON(!dev);
> +	pdata = netdev_priv(dev);
> +	BUG_ON(!pdata);
> +	BUG_ON(!pdata->phy_dev);
> +	phy_disconnect(pdata->phy_dev);
> +	pdata->phy_dev = NULL;
> +	mdiobus_unregister(pdata->mii_bus);
> +	mdiobus_free(pdata->mii_bus);
> +	platform_set_drvdata(pdev, NULL);
> +	unregister_netdev(dev);
> +	free_irq(dev->irq, dev);
> +	femac_free_mem_buffers(dev);
> +	free_netdev(dev);
>
> -	iounmap(rx_base);
> -	iounmap(tx_base);
> -	iounmap(dma_base);
> +	iounmap(pdata->rx_base);
> +	iounmap(pdata->tx_base);
> +	iounmap(pdata->dma_base);
>   #ifdef CONFIG_ARM
> -	iounmap(gpreg_base);
> +	iounmap(pdata->gpreg_base);
>   #endif
>
>   	return 0;
> @@ -2163,17 +2093,4 @@ static struct platform_driver appnic_driver = {
>   	},
>   };
>
> -/* Entry point for loading the module */
> -static int __init appnic_init_module(void)
> -{
> -	return platform_driver_register(&appnic_driver);
> -}
> -
> -/* Entry point for unloading the module */
> -static void __exit appnic_cleanup_module(void)
> -{
> -	platform_driver_unregister(&appnic_driver);
> -}
> -
> -module_init(appnic_init_module);
> -module_exit(appnic_cleanup_module);
> +module_platform_driver(appnic_driver);
> diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.h b/drivers/net/ethernet/lsi/lsi_acp_net.h
> index 7b6f2b3..00e02f6 100644
> --- a/drivers/net/ethernet/lsi/lsi_acp_net.h
> +++ b/drivers/net/ethernet/lsi/lsi_acp_net.h
> @@ -1,7 +1,7 @@
>   /*
>    * drivers/net/ethernet/lsi/lsi_acp_net.h
>    *
> - * Copyright (C) 2013 LSI
> + * Copyright (C) 2013 LSI Corporation.
>    *
>    * This program is free software; you can redistribute it and/or modify
>    * it under the terms of the GNU General Public License as published by
> @@ -33,14 +33,18 @@ extern int ubootenv_get(const char *, char *);
>   #define LSINET_NAPI_WEIGHT	64
>
>   /*
> -  ======================================================================
> -  Device Data Structures
> -  ======================================================================
> -*/
> + * This is the maximum number of bytes that serve to hold
> + * incoming Rx data.
> + */
> +#define LSINET_MAX_MTU		(ETH_DATA_LEN + 100) /* MTU + padding */
> +
> +/*
> + * Device Data Structures
> + */
>
>   struct appnic_dma_descriptor {
>
> -#ifdef CONFIG_ARM
> +#ifdef __LITTLE_ENDIAN
>   	/* Word 0 */
>   	/* 00=Fill|01=Block|10=Scatter */
>   	unsigned long transfer_type:2;
> @@ -93,7 +97,7 @@ union appnic_queue_pointer {
>   	unsigned long raw;
>
>   	struct {
> -#ifdef CONFIG_ARM
> +#ifdef __LITTLE_ENDIAN
>   		unsigned long offset:20;
>   		unsigned long generation_bit:1;
>   		unsigned long unused:11;
> @@ -107,10 +111,8 @@ union appnic_queue_pointer {
>   } __packed;
>
>   /*
> -  =============================================================================
> -  The appnic Device Structure
> -  =============================================================================
> -*/
> + * The appnic Device Structure
> + */
>
>   struct appnic_device {
>
> @@ -118,9 +120,12 @@ struct appnic_device {
>   	struct net_device *device;
>
>   	/* Addresses, Interrupt, and PHY stuff. */
> -	unsigned long rx_base;
> -	unsigned long tx_base;
> -	unsigned long dma_base;
> +	void __iomem *rx_base;
> +	void __iomem *tx_base;
> +	void __iomem *dma_base;
> +#ifdef CONFIG_ARM
> +	void __iomem *gpreg_base;
> +#endif
>   	unsigned long tx_interrupt;
>   	unsigned long rx_interrupt;
>   	unsigned long dma_interrupt;
> @@ -135,8 +140,12 @@ struct appnic_device {
>   	/* NAPI */
>   	struct napi_struct napi;
>
> -	/* statistics */
> +	/* Statistics */
>   	struct net_device_stats stats;
> +	unsigned long dropped_by_stack;
> +	unsigned long out_of_tx_descriptors;
> +	unsigned long transmit_interrupts;
> +	unsigned long receive_interrupts;
>
>   	/* DMA-able memory */
>   	int dma_alloc_size;
> @@ -184,7 +193,6 @@ struct appnic_device {
>
>   	/* Spin Lock */
>   	spinlock_t dev_lock;
> -	spinlock_t extra_lock;
>
>   	/* PHY */
>   	struct mii_bus *mii_bus;
> @@ -195,6 +203,10 @@ struct appnic_device {
>   	unsigned int duplex;
>   };
>
> +/* GPREG FEMAC HPROT Register --------------------------------------- */
> +
> +#define GPREG_HPROT_FEMAC	((unsigned long)pdata->gpreg_base + 0x78)
> +
>   /*
>    * Overview
>    * --------
> @@ -220,7 +232,7 @@ struct appnic_device {
>
>   /* Receive Configuration -------------------------------------------- */
>
> -#define APPNIC_RX_CONF		(rx_base + 0x004c)
> +#define APPNIC_RX_CONF		((unsigned long)pdata->rx_base + 0x004c)
>   #define APPNIC_RX_CONF_ENABLE   0x0001
>   /* Pass Any Packet */
>   #define APPNIC_RX_CONF_PAP	0x0002
> @@ -240,73 +252,75 @@ struct appnic_device {
>   #define APPNIC_RX_CONF_LINK	0x2000
>   /*
>    * Determines the action taken when the FE MAC
> - * receives an FC packet in FD mode.
> + * receives an Flow Control packet in FD mode.
>    */
>   #define APPNIC_RX_CONF_RXFCE    0x4000
>   /*
> - * Controls the insertion of FC packets
> + * Controls the insertion of Flow Control packets
>    * by the MAC transmitter.
>    */
>   #define APPNIC_RX_CONF_TXFCE    0x8000
>
>   /* Receive Stat Overflow -------------------------------------------- */
>
> -#define APPNIC_RX_STAT_OVERFLOW (rx_base + 0x278)
> +#define APPNIC_RX_STAT_OVERFLOW ((unsigned long)pdata->rx_base + 0x278)
>
>   /* Receive Stat Undersize ------------------------------------------- */
>
> -#define APPNIC_RX_STAT_UNDERSIZE (rx_base + 0x280)
> +#define APPNIC_RX_STAT_UNDERSIZE ((unsigned long)pdata->rx_base + 0x280)
>
>   /* Receive Stat Oversize -------------------------------------------- */
>
> -#define APPNIC_RX_STAT_OVERSIZE (rx_base + 0x2b8)
> +#define APPNIC_RX_STAT_OVERSIZE ((unsigned long)pdata->rx_base + 0x2b8)
>
>   /* Receive Stat Multicast ------------------------------------------- */
>
> -#define APPNIC_RX_STAT_MULTICAST (rx_base + 0x2d0)
> +#define APPNIC_RX_STAT_MULTICAST ((unsigned long)pdata->rx_base + 0x2d0)
>
>   /* Receive Stat Packet OK ------------------------------------------- */
>
> -#define APPNIC_RX_STAT_PACKET_OK (rx_base + 0x2c0)
> +#define APPNIC_RX_STAT_PACKET_OK ((unsigned long)pdata->rx_base + 0x2c0)
>
>   /* Receive Stat CRC Error ------------------------------------------- */
>
> -#define APPNIC_RX_STAT_CRC_ERROR (rx_base + 0x2c8)
> +#define APPNIC_RX_STAT_CRC_ERROR ((unsigned long)pdata->rx_base + 0x2c8)
>
>   /* Receive Stat Align Error ----------------------------------------- */
>
> -#define APPNIC_RX_STAT_ALIGN_ERROR (rx_base + 0x2e8)
> +#define APPNIC_RX_STAT_ALIGN_ERROR ((unsigned long)pdata->rx_base + 0x2e8)
>
>   /* Receive Ethernet Mode -------------------------------------------- */
>
> -#define APPNIC_RX_MODE (rx_base + 0x0800)
> +#define APPNIC_RX_MODE ((unsigned long)pdata->rx_base + 0x0800)
>   #define APPNIC_RX_MODE_ETHERNET_MODE_ENABLE 0x00001
>
>   /* Receive Soft Reset ----------------------------------------------- */
>
> -#define APPNIC_RX_SOFT_RESET (rx_base + 0x0808)
> +#define APPNIC_RX_SOFT_RESET ((unsigned long)pdata->rx_base + 0x0808)
>   #define APPNIC_RX_SOFT_RESET_MAC_0 0x00001
>
>   /* Receive Internal Interrupt Control ------------------------------- */
>
> -#define APPNIC_RX_INTERNAL_INTERRUPT_CONTROL (rx_base + 0xc00)
> +#define APPNIC_RX_INTERNAL_INTERRUPT_CONTROL \
> +	((unsigned long)pdata->rx_base + 0xc00)
>   #define APPNIC_RX_INTERNAL_INTERRUPT_CONTROL_MAC_0 0x1
>
>   /* Receive External Interrupt Control ------------------------------- */
>
> -#define APPNIC_RX_EXTERNAL_INTERRUPT_CONTROL (rx_base + 0xc04)
> +#define APPNIC_RX_EXTERNAL_INTERRUPT_CONTROL \
> +	((unsigned long)pdata->rx_base + 0xc04)
>   #define APPNIC_RX_EXTERNAL_INTERRUPT_CONTROL_MAC_0_HIGH_LOW 0x10
>   #define APPNIC_RX_EXTERNAL_INTERRUPT_CONTROL_MAC_0 0x1
>
>   /* Receive Interrupt Status ----------------------------------------- */
>
> -#define APPNIC_RX_INTERRUPT_STATUS (rx_base + 0xc20)
> +#define APPNIC_RX_INTERRUPT_STATUS ((unsigned long)pdata->rx_base + 0xc20)
>   #define APPNIC_RX_INTERRUPT_EXTERNAL_STATUS_MAC_0 0x10
>   #define APPNIC_RX_INTERRUPT_INTERNAL_STATUS_MAC_0 0x1
>
>   /* Transmit Watermark ----------------------------------------------- */
>
> -#define APPNIC_TX_WATERMARK (tx_base + 0x18)
> +#define APPNIC_TX_WATERMARK ((unsigned long)pdata->tx_base + 0x18)
>   #define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_ASSERT 0x8000
>   #define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_DISABLE 0x4000
>   #define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_WATER_MARK_HIGH 0x3f00
> @@ -314,13 +328,13 @@ struct appnic_device {
>
>   /* Swap Source Address Registers ------------------------------------ */
>
> -#define APPNIC_SWAP_SOURCE_ADDRESS_2 (tx_base + 0x20)
> -#define APPNIC_SWAP_SOURCE_ADDRESS_1 (tx_base + 0x24)
> -#define APPNIC_SWAP_SOURCE_ADDRESS_0 (tx_base + 0x28)
> +#define APPNIC_SWAP_SOURCE_ADDRESS_2 ((unsigned long)pdata->tx_base + 0x20)
> +#define APPNIC_SWAP_SOURCE_ADDRESS_1 ((unsigned long)pdata->tx_base + 0x24)
> +#define APPNIC_SWAP_SOURCE_ADDRESS_0 ((unsigned long)pdata->tx_base + 0x28)
>
>   /* Transmit Extended Configuration ---------------------------------- */
>
> -#define APPNIC_TX_EXTENDED_CONF (tx_base + 0x30)
> +#define APPNIC_TX_EXTENDED_CONF ((unsigned long)pdata->tx_base + 0x30)
>   #define APPNIC_TX_EXTENDED_CONF_TRANSMIT_COLLISION_WATERMARK_LEVEL 0xf000
>   #define APPNIC_TX_EXTENDED_CONF_EXCESSIVE_DEFFERED_PACKET_DROP 0x200
>   #define APPNIC_TX_EXTENDED_CONF_JUMBO9K 0x100
> @@ -328,12 +342,12 @@ struct appnic_device {
>
>   /* Transmit Half Duplex Configuration ------------------------------- */
>
> -#define APPNIC_TX_HALF_DUPLEX_CONF (tx_base + 0x34)
> +#define APPNIC_TX_HALF_DUPLEX_CONF ((unsigned long)pdata->tx_base + 0x34)
>   #define APPNIC_TX_HALF_DUPLEX_CONF_RANDOM_SEED_VALUE 0xff
>
>   /* Transmit Configuration ------------------------------------------- */
>
> -#define APPNIC_TX_CONF			(tx_base + 0x0050)
> +#define APPNIC_TX_CONF	((unsigned long)pdata->tx_base + 0x0050)
>   #define APPNIC_TX_CONF_ENABLE_SWAP_SA	0x8000
>   #define APPNIC_TX_CONF_LINK		0x2000
>   #define APPNIC_TX_CONF_DUPLEX		0x1000
> @@ -352,64 +366,66 @@ struct appnic_device {
>
>   /* Transmit Time Value Configuration -------------------------------- */
>
> -#define APPNIC_TX_TIME_VALUE_CONF (tx_base + 0x5c)
> +#define APPNIC_TX_TIME_VALUE_CONF ((unsigned long)pdata->tx_base + 0x5c)
>   #define APPNIC_TX_TIME_VALUE_CONF_PAUSE_VALUE 0xffff
>
>   /* Transmit Stat Underrun ------------------------------------------- */
>
> -#define APPNIC_TX_STAT_UNDERRUN (tx_base + 0x300)
> +#define APPNIC_TX_STAT_UNDERRUN ((unsigned long)pdata->tx_base + 0x300)
>
>   /* Transmit Stat Packet OK ------------------------------------------ */
>
> -#define APPNIC_TX_STAT_PACKET_OK (tx_base + 0x318)
> +#define APPNIC_TX_STAT_PACKET_OK ((unsigned long)pdata->tx_base + 0x318)
>
>   /* Transmit Stat Undersize ------------------------------------------ */
>
> -#define APPNIC_TX_STAT_UNDERSIZE (tx_base + 0x350)
> +#define APPNIC_TX_STAT_UNDERSIZE ((unsigned long)pdata->tx_base + 0x350)
>
>   /* Transmit Status Late Collision ----------------------------------- */
>
> -#define APPNIC_TX_STATUS_LATE_COLLISION (tx_base + 0x368)
> +#define APPNIC_TX_STATUS_LATE_COLLISION ((unsigned long)pdata->tx_base + 0x368)
>
>   /* Transmit Status Excessive Collision ------------------------------ */
>
> -#define APPNIC_TX_STATUS_EXCESSIVE_COLLISION (tx_base + 0x370)
> +#define APPNIC_TX_STATUS_EXCESSIVE_COLLISION \
> +	((unsigned long)pdata->tx_base + 0x370)
>
>   /* Transmit Stat Collision Above Watermark -------------------------- */
>
> -#define APPNIC_TX_STAT_COLLISION_ABOVE_WATERMARK (tx_base + 0x380)
> +#define APPNIC_TX_STAT_COLLISION_ABOVE_WATERMARK \
> +	((unsigned long)pdata->tx_base + 0x380)
>
>   /* Transmit Mode ---------------------------------------------------- */
>
> -#define APPNIC_TX_MODE (tx_base + 0x800)
> +#define APPNIC_TX_MODE ((unsigned long)pdata->tx_base + 0x800)
>   #define APPNIC_TX_MODE_ETHERNET_MODE_ENABLE 0x1
>
>   /* Transmit Soft Reset ---------------------------------------------- */
>
> -#define APPNIC_TX_SOFT_RESET (tx_base + 0x808)
> +#define APPNIC_TX_SOFT_RESET ((unsigned long)pdata->tx_base + 0x808)
>   #define APPNIC_TX_SOFT_RESET_MAC_0 0x1
>
>   /* Transmit Interrupt Control --------------------------------------- */
>
> -#define APPNIC_TX_INTERRUPT_CONTROL (tx_base + 0xc00)
> +#define APPNIC_TX_INTERRUPT_CONTROL ((unsigned long)pdata->tx_base + 0xc00)
>   #define APPNIC_TX_INTERRUPT_CONTROL_MAC_0 0x1
>
>   /* Transmit Interrupt Status ---------------------------------------- */
>
> -#define APPNIC_TX_INTERRUPT_STATUS (tx_base + 0xc20)
> +#define APPNIC_TX_INTERRUPT_STATUS ((unsigned long)pdata->tx_base + 0xc20)
>   #define APPNIC_TX_INTERRUPT_STATUS_MAC_0 0x1
>
>   /* */
>
> -#define APPNIC_DMA_PCI_CONTROL (dma_base + 0x00)
> +#define APPNIC_DMA_PCI_CONTROL ((unsigned long)pdata->dma_base + 0x00)
>
>   /* */
>
> -#define APPNIC_DMA_CONTROL (dma_base + 0x08)
> +#define APPNIC_DMA_CONTROL ((unsigned long)pdata->dma_base + 0x08)
>
>   /* DMA Interrupt Status --------------------------------------------- */
>
> -#define APPNIC_DMA_INTERRUPT_STATUS (dma_base + 0x18)
> +#define APPNIC_DMA_INTERRUPT_STATUS ((unsigned long)pdata->dma_base + 0x18)
>   #define APPNIC_DMA_INTERRUPT_STATUS_RX 0x2
>   #define APPNIC_DMA_INTERRUPT_STATUS_TX 0x1
>   #define RX_INTERRUPT(dma_interrupt_status) \
> @@ -419,55 +435,59 @@ struct appnic_device {
>
>   /* DMA Interrupt Enable --------------------------------------------- */
>
> -#define APPNIC_DMA_INTERRUPT_ENABLE (dma_base + 0x1c)
> +#define APPNIC_DMA_INTERRUPT_ENABLE ((unsigned long)pdata->dma_base + 0x1c)
>   #define APPNIC_DMA_INTERRUPT_ENABLE_RECEIVE 0x2
>   #define APPNIC_DMA_INTERRUPT_ENABLE_TRANSMIT 0x1
>
>   /* DMA Receive Queue Base Address ----------------------------------- */
>
> -#define APPNIC_DMA_RX_QUEUE_BASE_ADDRESS (dma_base + 0x30)
> +#define APPNIC_DMA_RX_QUEUE_BASE_ADDRESS ((unsigned long)pdata->dma_base + 0x30)
>
>   /* DMA Receive Queue Size ------------------------------------------- */
>
> -#define APPNIC_DMA_RX_QUEUE_SIZE (dma_base + 0x34)
> +#define APPNIC_DMA_RX_QUEUE_SIZE ((unsigned long)pdata->dma_base + 0x34)
>
>   /* DMA Transmit Queue Base Address ---------------------------------- */
>
> -#define APPNIC_DMA_TX_QUEUE_BASE_ADDRESS (dma_base + 0x38)
> +#define APPNIC_DMA_TX_QUEUE_BASE_ADDRESS ((unsigned long)pdata->dma_base + 0x38)
>
>   /* DMA Transmit Queue Size ------------------------------------------ */
>
> -#define APPNIC_DMA_TX_QUEUE_SIZE (dma_base + 0x3c)
> +#define APPNIC_DMA_TX_QUEUE_SIZE ((unsigned long)pdata->dma_base + 0x3c)
>
>   /* DMA Recevie Tail Pointer Address --------------------------------- */
>
> -#define APPNIC_DMA_RX_TAIL_POINTER_ADDRESS (dma_base + 0x48)
> +#define APPNIC_DMA_RX_TAIL_POINTER_ADDRESS \
> +	((unsigned long)pdata->dma_base + 0x48)
>
>   /* DMA Transmit Tail Pointer Address -------------------------------- */
>
> -#define APPNIC_DMA_TX_TAIL_POINTER_ADDRESS (dma_base + 0x4c)
> +#define APPNIC_DMA_TX_TAIL_POINTER_ADDRESS \
> +	((unsigned long)pdata->dma_base + 0x4c)
>
>   /* DMA Receive Head Pointer ----------------------------------------- */
>
> -#define APPNIC_DMA_RX_HEAD_POINTER			(dma_base + 0x50)
> +#define APPNIC_DMA_RX_HEAD_POINTER	((unsigned long)pdata->dma_base + 0x50)
>   #define APPNIC_DMA_RX_HEAD_POINTER_GB			0x100000
>   #define APPNIC_DMA_RX_HEAD_POINTER_POINTER		0x0fffff
>
>   /* DMA Receive Tail Pointer Local Copy ------------------------------ */
>
> -#define APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY		(dma_base + 0x54)
> +#define APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY	\
> +	((unsigned long)pdata->dma_base + 0x54)
>   #define APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY_GB	0x100000
>   #define APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY_POINTER	0x0fffff
>
>   /* DMA Transmit Head Pointer ---------------------------------------- */
>
> -#define APPNIC_DMA_TX_HEAD_POINTER			(dma_base + 0x58)
> +#define APPNIC_DMA_TX_HEAD_POINTER	((unsigned long)pdata->dma_base + 0x58)
>   #define APPNIC_DMA_TX_HEAD_POINTER_GB			0x100000
>   #define APPNIC_DMA_TX_HEAD_POINTER_POINTER		0x0fffff
>
>   /* DMA Transmit Tail Pointer Local Copy ----------------------------- */
>
> -#define APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY		(dma_base + 0x5c)
> +#define APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY	\
> +	((unsigned long)pdata->dma_base + 0x5c)
>   #define APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY_GB	0x100000
>   #define APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY_POINTER	0x0fffff
>
> @@ -494,11 +514,18 @@ writedescriptor(unsigned long address,
>   }
>
>   static inline union appnic_queue_pointer
> -swab_queue_pointer(const union appnic_queue_pointer *old_queue)
> +_swab_queue_pointer(const union appnic_queue_pointer *old_queue)
>   {
>   	return *old_queue;
>   }
>
> +static inline void
> +femac_uncache(struct appnic_device *pdata)
> +{
> +	/* Set FEMAC to uncached */
> +	writel(0x0, GPREG_HPROT_FEMAC);
> +}
> +
>   #else
>
>   #define read_mac(address)         in_le32((u32 *) (address))
> @@ -532,15 +559,115 @@ writedescriptor(unsigned long address,
>   }
>
>   static inline union appnic_queue_pointer
> -swab_queue_pointer(const union appnic_queue_pointer *old_queue)
> +_swab_queue_pointer(const union appnic_queue_pointer *old_queue)
>   {
>   	union appnic_queue_pointer new_queue;
>   	new_queue.raw = swab32(old_queue->raw);
>   	return new_queue;
>   }
> +
> +static inline void
> +femac_uncache(struct appnic_device *pdata) {}
> +
>   #endif /* ifdef CONFIG_ARM */
>
> -#define SWAB_QUEUE_POINTER(pointer) \
> -swab_queue_pointer((const union appnic_queue_pointer *) (pointer))
> +static int
> +femac_irq_setup(struct net_device *dev)
> +{
> +	struct appnic_device *pdata = netdev_priv(dev);
> +
> +#ifdef CONFIG_ARM
> +	dev->irq = pdata->dma_interrupt;
> +#else
> +	dev->irq = irq_create_mapping(NULL, pdata->dma_interrupt);
> +	if (NO_IRQ == dev->irq)
> +		return -EINVAL;
> +
> +	if (0 != irq_set_irq_type(dev->irq, IRQ_TYPE_LEVEL_HIGH))
> +		return -EINVAL;
> +#endif
> +	return 0;
> +}
> +
> +static inline int
> +femac_alloc_mem_buffers(struct net_device *dev)
> +{
> +	struct appnic_device *pdata = netdev_priv(dev);
> +	struct device *device = NULL;
> +	int rc;
> +
> +#ifndef CONFIG_ARM
> +	dev->dev.archdata.dma_ops = &dma_direct_ops;
> +	device = &dev->dev;
> +#endif
> +
> +	pdata->dma_alloc = (void *)dma_alloc_coherent(device,
> +						      pdata->dma_alloc_size,
> +						      &pdata->dma_alloc_dma,
> +						      GFP_KERNEL);
> +	if (pdata->dma_alloc == (void *)0) {
> +		rc = -ENOMEM;
> +		goto err_dma_alloc;
> +	}
> +
> +	pdata->dma_alloc_offset = (int)pdata->dma_alloc -
> +					(int)pdata->dma_alloc_dma;
> +
> +	pdata->dma_alloc_rx = (void *)dma_alloc_coherent(device,
> +						      pdata->dma_alloc_size_rx,
> +						      &pdata->dma_alloc_dma_rx,
> +						      GFP_KERNEL);
> +	if (pdata->dma_alloc_rx == (void *)0) {
> +		rc = -ENOMEM;
> +		goto err_dma_alloc_rx;
> +	}
> +
> +	pdata->dma_alloc_offset_rx = (int)pdata->dma_alloc_rx -
> +					(int)pdata->dma_alloc_dma_rx;
> +
> +	pdata->dma_alloc_tx = (void *)dma_alloc_coherent(device,
> +						      pdata->dma_alloc_size_tx,
> +						      &pdata->dma_alloc_dma_tx,
> +						      GFP_KERNEL);
> +
> +	if (pdata->dma_alloc_tx == (void *)0) {
> +		rc = -ENOMEM;
> +		goto err_dma_alloc_tx;
> +	}
> +
> +	pdata->dma_alloc_offset_tx = (int)pdata->dma_alloc_tx -
> +					(int)pdata->dma_alloc_dma_tx;
> +
> +	return 0;
> +
> +err_dma_alloc_tx:
> +	dma_free_coherent(device, pdata->dma_alloc_size_rx,
> +			  pdata->dma_alloc_rx, pdata->dma_alloc_dma_rx);
> +err_dma_alloc_rx:
> +	dma_free_coherent(device, pdata->dma_alloc_size,
> +			  pdata->dma_alloc, pdata->dma_alloc_dma);
> +err_dma_alloc:
> +	return rc;
> +}
> +
> +static inline void
> +femac_free_mem_buffers(struct net_device *dev)
> +{
> +	struct appnic_device *pdata = netdev_priv(dev);
> +	struct device *device = NULL;
> +
> +#ifndef CONFIG_ARM
> +	device = &dev->dev;
> +#endif
> +	dma_free_coherent(device, pdata->dma_alloc_size,
> +			  pdata->dma_alloc, pdata->dma_alloc_dma);
> +	dma_free_coherent(device, pdata->dma_alloc_size_rx,
> +			  pdata->dma_alloc_rx, pdata->dma_alloc_dma_rx);
> +	dma_free_coherent(device, pdata->dma_alloc_size_tx,
> +			  pdata->dma_alloc_tx, pdata->dma_alloc_dma_tx);
> +}
> +
> +#define swab_queue_pointer(pointer) \
> +	_swab_queue_pointer((const union appnic_queue_pointer *) (pointer))
>
>   #endif /* _LSI_ACP_NET_H */
>



More information about the linux-yocto mailing list