[linux-yocto] [PATCH 18/39] LSI FEMAC Ethernet Driver
Bruce Ashfield
bruce.ashfield at windriver.com
Sat Apr 12 21:02:18 PDT 2014
On 2014-04-11, 5:13 PM, Charlie Paul wrote:
> From: David Mercado <david.mercado at windriver.com>
>
> Integrated feedback and suggestions to make driver easier to upstream.
The problem with a commit like this .. is that no one has any idea
what the suggestions and feedback were when they read the patch.
A break down of what was changed should also be in the patch.
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 | 245 ++++-----
> drivers/net/ethernet/lsi/lsi_acp_net.c | 877 +++++++++++++++----------------
> drivers/net/ethernet/lsi/lsi_acp_net.h | 273 +++++++---
> 4 files changed, 740 insertions(+), 670 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..6427ae0 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,49 @@
> #include <linux/skbuff.h>
> #include <linux/platform_device.h>
>
> -/*
> - ==============================================================================
> - ==============================================================================
> - MDIO Access
> - ==============================================================================
> - ==============================================================================
> -*/
> +#define BZ33327_WA
>
> -#ifndef CONFIG_ACPISS
> +/* MDIO Access */
>
> -#define BZ33327_WA
> +struct lsi_mdio_priv {
> + unsigned long base;
> +};
>
> -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,73 +70,74 @@ 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.
> - */
> + /* 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
> - device_type) */
> + * device_type)
> + */
> command |= (address & 0x1f) << 16; /* port_addr (target
> - device) */
> + * device)
> + */
> command |= (offset & 0xffff); /* addr_or_data (target
> - register) */
> - WRITE(MDIO_CONTROL_RD_DATA, command);
> + * register)
> + */
> + 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));
>
> - /*
> - * Step 2: Read the value.
> - */
> + /* Step 2: Read the value. */
>
> /* 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) */
> + * device_type)
> + */
> command |= (address & 0x1f) << 16; /* port_addr (target
> - device) */
> - WRITE(MDIO_CONTROL_RD_DATA, command);
> + * device)
> + */
> + 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);
> @@ -147,14 +147,11 @@ 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,80 +161,81 @@ 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.
> - */
> + /* 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
> - device_type) */
> + * device_type)
> + */
> command |= (address & 0x1f) << 16; /* port_addr (target
> - device) */
> + * device)
> + */
> command |= (offset & 0xffff); /* addr_or_data (target
> - register) */
> - WRITE(MDIO_CONTROL_RD_DATA, command);
> + * register)
> + */
> + 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));
>
> - /*
> - * Step 2: Write the value.
> - */
> + /* Step 2: Write the value. */
>
> /* 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
> - device_type) */
> + * device_type)
> + */
> command |= (address & 0x1f) << 16; /* port_addr (target
> - device) */
> + * 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);
> @@ -246,39 +244,23 @@ 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 +268,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 +285,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 8924b19..78b7e79 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,45 +71,25 @@
> #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"
>
> -/* 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
> *
> @@ -177,12 +147,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;
> @@ -279,34 +247,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);
> @@ -381,9 +321,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))
>
> @@ -426,120 +364,135 @@ 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
> + * ======================================================================
> + */
>
> /* ----------------------------------------------------------------------
> - * clear_statistics
> + * mac_addr_valid
> + *
> + * If mac address is multicast, broadcast, or matches our mac address,
> + * it's a valid address. Otherwise, it's not.
> */
>
> -static void clear_statistics(struct appnic_device *pdata)
> +static bool mac_addr_valid(struct net_device *dev, u8 *mac_addr)
> {
> - int waste;
> -
> - /* Clear memory. */
> + bool is_valid = false;
>
> - memset((void *) &(pdata->stats), 0, sizeof(struct net_device_stats));
> + 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;
>
> - /* Clear counters. */
> + return is_valid;
> +}
>
> - 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 */
> +/* ----------------------------------------------------------------------
> + * clear_statistics
> + *
> + * NOTE: The hardware clears the statistics registers after a read.
> + */
>
> - /* multicast */
> +static void clear_statistics(struct appnic_device *pdata)
> +{
> + /* Clear memory. */
>
> - waste = read_mac(APPNIC_RX_STAT_MULTICAST);
> + memset((void *) &(pdata->stats), 0, sizeof(struct net_device_stats));
>
> - /* collisions will be the sum of the three following. */
> + /* Clear counters by reading them. */
>
> - 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);
> + /* stats.rx_packets */
> + read_mac(APPNIC_RX_STAT_PACKET_OK);
>
> - /* rx_length_errors will be the sum of the two following. */
> + /* stats.tx_packets */
> + read_mac(APPNIC_TX_STAT_PACKET_OK);
>
> - waste = read_mac(APPNIC_RX_STAT_UNDERSIZE);
> - waste = read_mac(APPNIC_RX_STAT_OVERSIZE);
> + /* 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.
> + */
>
> - /* rx_over_errors (out of descriptors?) maintained by the driver. */
> - /* rx_crc_errors */
> + /* stats.multicast */
> + read_mac(APPNIC_RX_STAT_MULTICAST);
>
> - waste = read_mac(APPNIC_RX_STAT_CRC_ERROR);
> + /* 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);
>
> - /* rx_frame_errors */
> + /* stats.rx_length_errors - The sum of the following driver stats. */
> + read_mac(APPNIC_RX_STAT_UNDERSIZE);
> + read_mac(APPNIC_RX_STAT_OVERSIZE);
>
> - waste = read_mac(APPNIC_RX_STAT_ALIGN_ERROR);
> + /* stats.rx_over_errors - Not maintained by this driver. */
>
> - /* rx_fifo_errors */
> + /* stats.rx_crc_errors */
> + read_mac(APPNIC_RX_STAT_CRC_ERROR);
>
> - waste = read_mac(APPNIC_RX_STAT_OVERFLOW);
> + /* stats.rx_frame_errors */
> + read_mac(APPNIC_RX_STAT_ALIGN_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_fifo_errors */
> + read_mac(APPNIC_RX_STAT_OVERFLOW);
>
> - waste = read_mac(APPNIC_TX_STAT_UNDERRUN);
> + /* 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.
> + */
>
> - /* tx_heartbeat_errors */
> - /* tx_window_errors */
> + /* stats.tx_fifo_errors */
> + read_mac(APPNIC_TX_STAT_UNDERRUN);
>
> - /* rx_compressed will not be maintained. */
> - /* tx_compressed will not be maintained. */
> + /* 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.
> + */
>
> - /* That's all. */
> return;
> }
>
> /* ----------------------------------------------------------------------
> * 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);
>
> /* Lock this section out so the statistics maintained by the driver
> * don't get clobbered.
> */
> +
> spin_lock_irqsave(&pdata->dev_lock, flags);
>
> pdata->stats.rx_errors +=
> @@ -559,7 +512,6 @@ static void get_hw_statistics(struct appnic_device *pdata)
>
> spin_unlock_irqrestore(&pdata->dev_lock, flags);
>
> - /* That's all. */
> return;
> }
>
> @@ -665,13 +617,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);
> @@ -681,7 +632,6 @@ static void disable_rx_tx(void)
>
> write_mac(tx_configuration, APPNIC_TX_CONF);
>
> - /* That's all. */
> return;
> }
>
> @@ -698,14 +648,17 @@ 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;
> @@ -724,18 +677,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;
> }
>
> @@ -746,25 +697,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 +
> @@ -778,6 +722,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) {
> @@ -789,29 +734,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, ðhdr->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);
> }
> @@ -819,17 +750,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;
> }
>
> @@ -840,34 +768,38 @@ 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)) {
> + /* Receive Packets */
> +
> + 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. */
> + /* Update the Head Pointer */
> +
> while (1 < queue_uninitialized(pdata->rx_head,
> pdata->rx_tail_copy,
> pdata->rx_num_desc)) {
> @@ -904,36 +836,38 @@ 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;
> }
>
> /* ----------------------------------------------------------------------
> @@ -953,23 +887,23 @@ static irqreturn_t appnic_isr(int irq, void *device_id)
> /* Get the status. */
> dma_interrupt_status = read_mac(APPNIC_DMA_INTERRUPT_STATUS);
>
> - /* NAPI - don't ack RX interrupt. */
> + /* NAPI - don't ack RX interrupt */
> write_mac(APPNIC_DMA_INTERRUPT_ENABLE_RECEIVE,
> APPNIC_DMA_INTERRUPT_STATUS);
>
> /* 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)) {
>
> /* Disable RX interrupts and tell the
> - * system we've got work.
> + * system we've got work
> */
> write_mac(APPNIC_DMA_INTERRUPT_ENABLE_TRANSMIT,
> APPNIC_DMA_INTERRUPT_ENABLE);
> @@ -980,7 +914,7 @@ static irqreturn_t appnic_isr(int irq, void *device_id)
> }
> }
>
> - /* Release the lock. */
> + /* Release the lock */
> spin_unlock_irqrestore(&pdata->dev_lock, flags);
>
> return IRQ_HANDLED;
> @@ -1068,7 +1002,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)
> @@ -1096,22 +1030,24 @@ 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;
>
> /* 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;
> @@ -1145,11 +1081,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;
> }
>
> @@ -1163,22 +1100,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;
> }
>
> /* ----------------------------------------------------------------------
> @@ -1197,8 +1134,6 @@ static struct net_device_stats *appnic_get_stats(struct net_device *dev)
>
> get_hw_statistics(pdata);
>
> - /* That's all. */
> -
> return &pdata->stats;
> }
>
> @@ -1208,14 +1143,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];
> @@ -1232,9 +1171,102 @@ 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;
> + }
> +}
>
> /* ----------------------------------------------------------------------
> * appnic_get_drvinfo
> @@ -1245,6 +1277,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));
> }
>
> /* ----------------------------------------------------------------------
> @@ -1263,17 +1297,21 @@ static int appnic_get_settings(struct net_device *dev,
> return phy_ethtool_gset(phydev, cmd);
> }
>
> -/* Fill in the struture... */
> +/* Fill in the struture... */
> +
> 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,
> @@ -1300,33 +1338,33 @@ 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. */
> +
> write_mac(0x80000000, APPNIC_DMA_PCI_CONTROL);
>
> /* Allocate memory and initialize the descriptors. */
>
> - /* fixup num_[rt]x_desc */
> + /* fixup num_[rt]x_desc. */
> +
> 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;
> @@ -1334,20 +1372,21 @@ int appnic_init(struct net_device *dev)
> /* up [rt]x_buf_sz. Must be some multiple of 64 bytes
> * per descriptor.
> */
> +
> 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;
> @@ -1357,6 +1396,7 @@ int appnic_init(struct net_device *dev)
> * small since mappings obtained from dma_alloc_coherent() have
> * a minimum size of one page.
> */
> +
> pdata->dma_alloc_size =
> /* The tail pointers (rx and tx) */
> (sizeof(union appnic_queue_pointer) * 2) +
> @@ -1377,81 +1417,16 @@ int appnic_init(struct net_device *dev)
> /* The TX buffer (and padding...) */
> (pdata->tx_buf_sz) + (BUFFER_ALIGNMENT);
>
> - /* This needs to be set to something sane for
> - * dma_alloc_coherent().
> - */
> -
> -#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;
> - }
> + /* Allocate the 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;
> + 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_tx = (int)pdata->dma_alloc_tx -
> - (int)pdata->dma_alloc_dma_tx;
> -
> /* Initialize the tail pointers. */
> +
> dma_offset = pdata->dma_alloc;
>
> pdata->rx_tail = (union appnic_queue_pointer *)dma_offset;
> @@ -1466,8 +1441,8 @@ 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. */
> +
> pdata->rx_desc = (struct appnic_dma_descriptor *)ALIGN64B(dma_offset);
> pdata->rx_desc_dma = (int)pdata->rx_desc - (int)pdata->dma_alloc_offset;
> dma_offset += (sizeof(struct appnic_dma_descriptor) *
> @@ -1483,6 +1458,7 @@ int appnic_init(struct net_device *dev)
> (sizeof(struct appnic_dma_descriptor) * pdata->tx_num_desc));
>
> /* Initialize the buffer pointers. */
> +
> dma_offset = pdata->dma_alloc_rx;
>
> pdata->rx_buf = (void *)ALIGN64B(dma_offset);
> @@ -1498,6 +1474,7 @@ int appnic_init(struct net_device *dev)
> pdata->tx_buf_per_desc = pdata->tx_buf_sz / pdata->tx_num_desc;
>
> /* Initialize the descriptors. */
> +
> buf = (unsigned long)pdata->rx_buf_dma;
> for (index = 0; index < pdata->rx_num_desc; ++index) {
> memset((void *) &descriptor, 0,
> @@ -1531,16 +1508,18 @@ int appnic_init(struct net_device *dev)
> }
>
> /* Initialize the spinlocks. */
> +
> spin_lock_init(&pdata->dev_lock);
> - spin_lock_init(&pdata->extra_lock);
>
> /* Take MAC out of reset. */
> +
> write_mac(0x0, APPNIC_RX_SOFT_RESET);
> write_mac(0x1, APPNIC_RX_MODE);
> write_mac(0x0, APPNIC_TX_SOFT_RESET);
> write_mac(0x1, APPNIC_TX_MODE);
>
> /* Set the watermark. */
> +
> ncr_read(NCP_REGION_ID(0x16, 0xff), 0x10, 4, &node_cfg);
>
> if (0 == (0x80000000 & node_cfg))
> @@ -1557,24 +1536,27 @@ 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]);
> + /* Set the MAC address. */
> + 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. */
>
> - /* Receiver */
> + /* Receiver. */
> +
> memset((void *)&pdata->rx_tail_copy, 0,
> sizeof(union appnic_queue_pointer));
> memset((void *)&pdata->rx_head, 0,
> @@ -1588,6 +1570,7 @@ int appnic_init(struct net_device *dev)
> /* Indicate that all of the receive descriptors
> * are ready.
> */
> +
> pdata->rx_head.bits.offset = (pdata->rx_num_desc - 1) *
> sizeof(struct appnic_dma_descriptor);
> write_mac(pdata->rx_tail_dma, APPNIC_DMA_RX_TAIL_POINTER_ADDRESS);
> @@ -1598,6 +1581,7 @@ int appnic_init(struct net_device *dev)
> * tail pointer must be read and the head pointer (and
> * local copy of the tail) based on it.
> */
> +
> pdata->rx_tail->raw =
> read_mac(APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY);
> pdata->rx_tail_copy.raw = pdata->rx_tail->raw;
> @@ -1607,7 +1591,8 @@ int appnic_init(struct net_device *dev)
> (0 == pdata->rx_head.bits.generation_bit) ? 1 : 0;
> write_mac(pdata->rx_head.raw, APPNIC_DMA_RX_HEAD_POINTER);
>
> - /* Transmitter */
> + /* Transmitter. */
> +
> memset((void *) &pdata->tx_tail_copy, 0,
> sizeof(union appnic_queue_pointer));
> memset((void *) &pdata->tx_head, 0,
> @@ -1625,41 +1610,43 @@ int appnic_init(struct net_device *dev)
> * tail pointer must be read and the head pointer (and
> * local copy of the tail) based on it.
> */
> +
> pdata->tx_tail->raw = read_mac(APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY);
> pdata->tx_tail_copy.raw = pdata->tx_tail->raw;
> pdata->tx_head.raw = pdata->tx_tail->raw;
> write_mac(pdata->tx_head.raw, APPNIC_DMA_TX_HEAD_POINTER);
>
> - /* Clear statistics */
> + /* Clear statistics. */
> +
> clear_statistics(pdata);
>
> - /* Fill in the net_device structure */
> + /* 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;
> +
> +err_irq_setup:
> +err_set_mac_addr:
> + femac_free_mem_buffers(dev);
> +err_mem_buffers:
> +err_param:
> + return rc;
> }
>
> /* ----------------------------------------------------------------------
> @@ -1672,9 +1659,11 @@ static int 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
> @@ -1683,44 +1672,44 @@ static int 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;
> @@ -1768,9 +1757,8 @@ static int appnic_probe_config_dt(struct net_device *dev,
> pdata->phy_link_speed = 0;
> pdata->phy_link_duplex = 0;
> } else {
> - pr_err(
> - "Invalid phy-link value \"%s\" in DTS. Defaulting to \"auto\".\n",
> - macspeed);
> + pr_err("Invalid phy-link value \"%s\" in DTS. Defaulting to \"auto\".\n",
> + macspeed);
> pdata->phy_link_auto = 1;
> }
> } else {
> @@ -1778,32 +1766,25 @@ static int 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
> @@ -1834,7 +1815,7 @@ static int 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);
> @@ -1850,12 +1831,12 @@ static int 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.
> */
> @@ -1865,14 +1846,14 @@ static int 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, ":");
> @@ -1881,29 +1862,23 @@ static int 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
> @@ -1918,8 +1893,10 @@ static int 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;
> }
> }
> @@ -1931,7 +1908,7 @@ static int 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. */
> @@ -1939,7 +1916,7 @@ static int 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. */
> @@ -1947,9 +1924,17 @@ static int 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;
> }
> -out:
> +
> + return 0;
> +
> +err_mii_init:
> + unregister_netdev(dev);
> +err_nodev:
> +err_inval:
> + free_netdev(dev);
> +err_alloc_etherdev:
> return rc;
> }
>
> @@ -1960,35 +1945,29 @@ out:
> static int 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;
> @@ -1998,7 +1977,6 @@ static const struct of_device_id appnic_dt_ids[] = {
> { .compatible = "lsi,acp-femac", },
> { .compatible = "acp-femac", },
> { /* end of list */ },
> -
> };
> MODULE_DEVICE_TABLE(of, appnic_dt_ids);
>
> @@ -2013,17 +1991,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 238af6e..c1f4311 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
> @@ -29,21 +29,21 @@ extern int ubootenv_get(const char *, char *);
> extern int acp_mdio_read(unsigned long, unsigned long, unsigned short *, int);
> extern int acp_mdio_write(unsigned long, unsigned long, unsigned short, int);
>
> -/*
> - * This is the maximum number of packets to be received every
> +/* This is the maximum number of packets to be received every
> * NAPI poll
> */
> #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;
> @@ -96,7 +96,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;
> @@ -109,11 +109,7 @@ union appnic_queue_pointer {
>
> } __packed;
>
> -/*
> - =============================================================================
> - The appnic Device Structure
> - =============================================================================
> -*/
> +/* The appnic Device Structure */
>
> struct appnic_device {
>
> @@ -121,9 +117,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;
> @@ -138,8 +137,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;
> @@ -187,7 +190,6 @@ struct appnic_device {
>
> /* Spin Lock */
> spinlock_t dev_lock;
> - spinlock_t extra_lock;
>
> /* PHY */
> struct mii_bus *mii_bus;
> @@ -198,8 +200,11 @@ struct appnic_device {
> unsigned int duplex;
> };
>
> -/*
> - * Overview
> +/* GPREG FEMAC HPROT Register --------------------------------------- */
> +
> +#define GPREG_HPROT_FEMAC ((unsigned long)pdata->gpreg_base + 0x78)
> +
> +/* Overview
> * --------
> *
> * Register offset decoding is as follows:
> @@ -223,7 +228,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
> @@ -241,75 +246,76 @@ struct appnic_device {
> #define APPNIC_RX_CONF_DUPLEX 0x1000
> /* 1=Enable */
> #define APPNIC_RX_CONF_LINK 0x2000
> -/*
> - * Determines the action taken when the FE MAC
> - * receives an FC packet in FD mode.
> +/* Determines the action taken when the FE MAC
> + * 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
> @@ -317,13 +323,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
> @@ -331,12 +337,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
> @@ -351,68 +357,70 @@ struct appnic_device {
> do { \
> (tx_configuration) &= ~APPNIC_TX_CONF_IFG; \
> (tx_configuration) |= ((ifg & 0x1f) << 4); \
> - } while (0);
> + } while (0)
>
> /* 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) \
> @@ -422,55 +430,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
>
> @@ -497,11 +509,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))
> @@ -535,15 +554,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