[linux-yocto] [PATCH 84/87] LSI acp34xx: Major rework of lsi_acp_net.c Ethernet driver
Paul Butler
butler.paul at gmail.com
Mon May 27 09:56:55 PDT 2013
Changes include (but not limited to):
- Removed hard-coded phy code. Driver now uses Linux phy framework.
- Converted driver to register itself as a platform_driver and
activate/deactivate via probe() and remove() calls.
- Broke up allocation of one big buffer into smaller chunks.
- Added netpoll support to support kgdboe.
- Removed hard-coding of IRQ number - now parses DTB for it.
- Removed unnecessary build-time options, converted remaining ones to
menuconfig selectable options.
- More code/comment cleanup.
Signed-off-by: David Mercado <david.mercado at windriver.com>
- checkpatch cleanup
Signed-off-by: Niraj Desai <niraj.desai at windriver.com>
- cherry-pick conflict - merged LSI version
Signed-off-by: Paul Butler <paul.butler at windriver.com>
---
drivers/net/ethernet/Kconfig | 1 +
drivers/net/ethernet/lsi/Kconfig | 23 +-
drivers/net/ethernet/lsi/Makefile | 2 +-
drivers/net/ethernet/lsi/lsi_acp_mdio.c | 239 ---
drivers/net/ethernet/lsi/lsi_acp_net.c | 2517 +++++++++++--------------------
drivers/net/ethernet/lsi/lsi_acp_net.h | 482 ++++++
6 files changed, 1391 insertions(+), 1873 deletions(-)
delete mode 100644 drivers/net/ethernet/lsi/lsi_acp_mdio.c
create mode 100644 drivers/net/ethernet/lsi/lsi_acp_net.h
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 22109fb..65641ba 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -33,6 +33,7 @@ source "drivers/net/ethernet/chelsio/Kconfig"
source "drivers/net/ethernet/cirrus/Kconfig"
source "drivers/net/ethernet/cisco/Kconfig"
source "drivers/net/ethernet/davicom/Kconfig"
+source "drivers/net/ethernet/lsi/Kconfig"
config DNET
tristate "Dave ethernet support (DNET)"
diff --git a/drivers/net/ethernet/lsi/Kconfig b/drivers/net/ethernet/lsi/Kconfig
index 8c9dc08..1c760e5 100644
--- a/drivers/net/ethernet/lsi/Kconfig
+++ b/drivers/net/ethernet/lsi/Kconfig
@@ -1,8 +1,12 @@
config LSI_NET
- bool "Network interface for LSI's APP and AXXIA"
+ bool "LSI ACP34XX Ethernet support"
+ select MII
+ select PHYLIB
help
Network interface driver for LSI's APP and AXXIA series boards.
+if LSI_NET
+
config LSI_NET_NUM_RX_DESC
int "LSI Axxia Network Driver: Number of receive descriptors"
depends on LSI_NET
@@ -30,3 +34,20 @@ config LSI_NET_TX_BUF_SZ
default "32768"
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/Makefile b/drivers/net/ethernet/lsi/Makefile
index 9618c59..2754e5b 100644
--- a/drivers/net/ethernet/lsi/Makefile
+++ b/drivers/net/ethernet/lsi/Makefile
@@ -1,3 +1,3 @@
# Makefile for the LSI FEMAC network interface.
-obj-$(CONFIG_LSI_NET) += lsi_acp_mdio.o lsi_acp_net.o
+obj-$(CONFIG_LSI_NET) += lsi_acp_net.o
diff --git a/drivers/net/ethernet/lsi/lsi_acp_mdio.c b/drivers/net/ethernet/lsi/lsi_acp_mdio.c
deleted file mode 100644
index eaa35fa..0000000
--- a/drivers/net/ethernet/lsi/lsi_acp_mdio.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * drivers/net/ethernet/lsi/lsi_acp_mdio.c
- *
- * Copyright (C) 2010 LSI
- *
- * 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>
-#include <linux/of.h>
-#include <asm/irq.h>
-#include <linux/io.h>
-
-#include <asm/lsi/acp_ncr.h>
-
-/*
- ==============================================================================
- ==============================================================================
- MDIO Access
- ==============================================================================
- ==============================================================================
-*/
-
-#ifndef CONFIG_ACPISS
-
-#define BZ33327_WA
-
-static unsigned long mdio_base;
-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))
-
-/*
- ------------------------------------------------------------------------------
- acp_mdio_read
-*/
-
-int
-acp_mdio_read(unsigned long address, unsigned long offset,
- unsigned short *value)
-{
- unsigned long command = 0;
- unsigned long status;
- unsigned long flags;
-
- spin_lock_irqsave(&mdio_lock, flags);
-#if defined(BZ33327_WA)
- /* Set the mdio_busy (status) bit. */
- status = in_le32(MDIO_STATUS_RD_DATA);
- status |= 0x40000000;
- out_le32(MDIO_STATUS_RD_DATA, status);
-#endif /* BZ33327_WA */
-
- /* Write the command. */
- command |= 0x10000000; /* op_code: read */
- command |= (address & 0x1f) << 16; /* port_addr (target device) */
- command |= (offset & 0x1f) << 21;/* device_addr (target register) */
- out_le32(MDIO_CONTROL_RD_DATA, command);
-
-#if defined(BZ33327_WA)
- /* Wait for the mdio_busy (status) bit to clear. */
- do {
- status = in_le32(MDIO_STATUS_RD_DATA);
- } while (0 != (status & 0x40000000));
-
- /* Wait for the mdio_busy (control) bit to clear. */
- do {
- command = in_le32(MDIO_CONTROL_RD_DATA);
- } while (0 != (command & 0x80000000));
-
- *value = (unsigned short)(command & 0xffff);
-#endif /* BZ33327_WA */
- spin_unlock_irqrestore(&mdio_lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL(acp_mdio_read);
-
-/*
- ------------------------------------------------------------------------------
- acp_mdio_write
-*/
-
-int
-acp_mdio_write(unsigned long address, unsigned long offset,
- unsigned short value)
-{
- unsigned long command = 0;
- unsigned long status;
- unsigned long flags;
-
- spin_lock_irqsave(&mdio_lock, flags);
-
- /* Wait for mdio_busy (control) to be clear. */
- do {
- command = in_le32(MDIO_CONTROL_RD_DATA);
- } while (0 != (command & 0x80000000));
-
-#if defined(BZ33327_WA)
- /* Set the mdio_busy (status) bit. */
- status = in_le32(MDIO_STATUS_RD_DATA);
- status |= 0x40000000;
- out_le32(MDIO_STATUS_RD_DATA, status);
-#endif /* BZ33327_WA */
-
- /* Write the command. */
- command = 0x08000000; /* op_code: write */
- command |= (address & 0x1f) << 16; /* port_addr (target device) */
- command |= (offset & 0x1f) << 21;/* device_addr (target register) */
- command |= (value & 0xffff); /* value */
- out_le32(MDIO_CONTROL_RD_DATA, command);
-
-#if defined(BZ33327_WA)
- /* Wait for the mdio_busy (status) bit to clear. */
- do {
- status = in_le32(MDIO_STATUS_RD_DATA);
- } while (0 != (status & 0x40000000));
-#endif /* BZ33327_WA */
-
- /* Wait for the mdio_busy (control) bit to clear. */
- do {
- command = in_le32(MDIO_CONTROL_RD_DATA);
- } while (0 != (command & 0x80000000));
-
- spin_unlock_irqrestore(&mdio_lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL(acp_mdio_write);
-
-/*
- ------------------------------------------------------------------------------
- acp_mdio_initialize
-*/
-
-static int
-acp_mdio_initialize(void)
-{
- if (is_asic()) {
- out_le32(MDIO_CLK_OFFSET, 0x10);
- out_le32(MDIO_CLK_PERIOD, 0x2c);
- } else {
- out_le32(MDIO_CLK_OFFSET, 0x05);
- out_le32(MDIO_CLK_PERIOD, 0x0c);
- }
-
- return 0;
-}
-
-#endif /* ! CONFIG_ACPISS */
-
-/*
- ==============================================================================
- ==============================================================================
- Interrupts
- ==============================================================================
- ==============================================================================
-*/
-
-/*
- ------------------------------------------------------------------------------
- acp_wrappers_init
-*/
-
-int __init
-acp_wrappers_init(void)
-{
- int rc = -1;
- struct device_node *np = NULL;
- const u32 *field;
- u64 mdio_phys_address;
- u32 mdio_size;
-
- printk(KERN_INFO "Initializing ACP Wrappers.\n");
-
-#ifndef CONFIG_ACPISS
-
- np = of_find_node_by_type(np, "network");
-
- while (np && !of_device_is_compatible(np, "acp-femac"))
- np = of_find_node_by_type(np, "network");
-
- if (np) {
- field = of_get_property(np, "enabled", NULL);
-
- if (!field || (field && (0 == *field))) {
- printk(KERN_WARNING "Networking is Not Enabled.\n");
- goto acp_wrappers_init_done;
- }
-
- field = of_get_property(np, "mdio-reg", NULL);
-
- if (!field) {
- printk(KERN_ERR
- "Couldn't get \"mdio-reg\" property.\n");
- } else {
- mdio_phys_address = of_translate_address(np, field);
- mdio_size = field[1];
- rc = 0;
- }
- }
-
- if (0 != rc) {
- mdio_phys_address = 0x002000409000ULL;
- mdio_size = 0x1000;
- printk(KERN_WARNING
- "** MDIO Address Not Specified in Device Tree.\n");
- }
-
- mdio_base = (unsigned long)ioremap(mdio_phys_address, mdio_size);
- rc = acp_mdio_initialize();
-#endif
-
- if (0 != rc)
- printk(KERN_ERR "MDIO Initiailzation Failed!\n");
-
-acp_wrappers_init_done:
- return 0;
-}
-module_init(acp_wrappers_init);
-
-MODULE_AUTHOR("LSI Corporation");
-MODULE_DESCRIPTION("Timing Test");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.c b/drivers/net/ethernet/lsi/lsi_acp_net.c
index f8a5e66..39671cc 100644
--- a/drivers/net/ethernet/lsi/lsi_acp_net.c
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.c
@@ -1,7 +1,7 @@
/*
* drivers/net/ethernet/lsi/lsi_acp_net.c
*
- * Copyright (C) 2009 LSI
+ * Copyright (C) 2013 LSI
*
* 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
@@ -16,7 +16,24 @@
* 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
+ * USA
+ *
+ * NOTES:
+ *
+ * 1) This driver parses the DTB for driver specific settings. A few of
+ * them can be overriden by setting environment variables in U-boot:
+ *
+ * ethaddr - MAC address of interface, in xx:xx:xx:xx:xx:xx format
+ *
+ * ad_value - PHY advertise value. Can be set to one of these or multiple
+ * can be OR'ed together. If not set, the driver defaults to
+ * the OR'ed quantity of all four (0x1e1).
+ *
+ * 0x101 - 100/Full
+ * 0x81 - 100/Half
+ * 0x41 - 10/Full
+ * 0x21 - 10/Half
+ *
*/
#include <linux/module.h>
@@ -32,7 +49,10 @@
#include <linux/delay.h>
#include <linux/bitops.h>
#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
#include <linux/netdevice.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/skbuff.h>
@@ -46,14 +66,16 @@
#include <asm/dma.h>
#include <asm/lsi/acp_ncr.h>
+#include "lsi_acp_net.h"
+
+#define LSI_DRV_NAME "acp-femac"
+#define LSI_MDIO_NAME "acp-femac-mdio"
+#define LSI_DRV_VERSION "2013-04-30"
-extern int acp_mdio_read(unsigned long,
- unsigned long,
- unsigned short *);
-extern int acp_mdio_write(unsigned long,
- unsigned long,
- unsigned short);
-extern int ubootenv_get(const char *, char *);
+
+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;
@@ -61,718 +83,320 @@ static void *tx_base;
static void *dma_base;
/*
- ======================================================================
- ======================================================================
- Optimizations
- ======================================================================
- ======================================================================
-*/
-
-#define DISABLE_TX_INTERRUPTS
-/*#define PRELOAD_RX_BUFFERS*/
-
-#undef DMA_CACHABLE
-/*#define DMA_CACHABLE*/
-
-/*
=============================================================================
- NAPI Support (new and newer)...
+ MDIO / PHY
=============================================================================
*/
-#define LSINET_NAPI
-#define LSINET_NAPI_WEIGHT 64
-
-/*
- ======================================================================
- ======================================================================
- ======================================================================
- PHY
- ======================================================================
- ======================================================================
- ======================================================================
-*/
-
-#undef PHYLESS
-
-#ifndef PHYLESS
-
-/* -- control -- */
-
-#define PHY_CONTROL 0x00
-
-union phy_control {
- unsigned short raw;
-
- struct {
- unsigned short soft_reset:1;
- unsigned short loop_back:1;
- unsigned short force100:1; /* speedBit0 */
- unsigned short autoneg_enable:1;
- unsigned short power_down:1;
- unsigned short isolate:1;
- unsigned short restart_autoneg:1;
- unsigned short full_duplex:1; /* duplex */
- unsigned short collision_test:1;
- unsigned short unused:7;
- } __packed bits;
-} __packed;
-
-/* -- status -- */
-
-#define PHY_STATUS 0x01
-
-union phy_status {
- unsigned short raw;
-
- struct {
- unsigned short t4_capable:1;
- unsigned short tx_fdx_capable:1;
- unsigned short tx_capable:1;
- unsigned short bt_fdx_capable:1;
- unsigned short tenbt_capable:1;
- unsigned short unused:4;
- unsigned short mf_pream_suppress:1;
- unsigned short autoneg_comp:1; /* autoNegDone */
- unsigned short remote_fault:1; /* remoutFault */
- unsigned short autoneg_capable:1;
- unsigned short link_status:1; /* linkStatus */
- unsigned short jabber_detect:1;
- unsigned short extd_reg_capable:1;
- } __packed bits;
-} __packed;
-
-/* -- id_high -- */
-
-#define PHY_ID_HIGH 0x02
-
-union phy_id_high {
- unsigned short raw;
-
- struct {
- unsigned short id:16;
- } __packed bits;
-} __packed;
-
-/* -- id_low -- */
-
-#define PHY_ID_LOW 0x03
-
-union phy_id_low {
- unsigned short raw;
-
- struct {
- unsigned short id:6;
- unsigned short model:6;
- unsigned short revision:4;
- } __packed bits;
-} __packed;
-
-/* -- autoneg_advertise -- */
-
-#define PHY_AUTONEG_ADVERTISE 0x04
-
-/* -- link_partner_ability -- */
-
-#define PHY_LINK_PARTNER_ABILITY 0x05
-
-/* -- -- */
-
-#define MICREL_PHY_AUXILIARY_CONTROL_STATUS 0x1f
-
-union micrel_phy_auxiliary_control_status {
- unsigned short raw;
-
- struct {
- unsigned short unused:3;
- unsigned short energy:1;
- unsigned short force_link:1;
- unsigned short power_saving:1;
- unsigned short interrupt_level:1;
- unsigned short jabber_enable:1;
- unsigned short autoneg_indication:1;
- unsigned short enable_pause:1;
- unsigned short isolate:1;
- unsigned short op_mode_indication:3;
- unsigned short unused2:2;
- } bits;
-};
-
-/*
- Auto-negotiation Advertisement Values.
-*/
-
-#define PHY_AUTONEG_ADVERTISE_100FULL 0x101
-#define PHY_AUTONEG_ADVERTISE_100 0x081
-#define PHY_AUTONEG_ADVERTISE_10FULL 0x041
-#define PHY_AUTONEG_ADVERTISE_10 0x021
-
-#define UNKNOWN_PHY 0x0
-#define BCM5221_PHY 0x1
-#define MICREL_PHY 0x2
-
-static int phy_read(int, int, unsigned short *);
-static int phy_write(int, int, unsigned short);
-static int phy_speed(int);
-static int phy_duplex(int);
-static int phy_renegotiate(int);
-static int phy_enable(struct net_device *);
-
-#endif /* PHYLESS */
+#define MDIO_CONTROL_RD_DATA ((void *)(pdata->mdio_base + 0x0))
+#define MDIO_STATUS_RD_DATA ((void *)(pdata->mdio_base + 0x4))
+#define MDIO_CLK_OFFSET ((void *)(pdata->mdio_base + 0x8))
+#define MDIO_CLK_PERIOD ((void *)(pdata->mdio_base + 0xc))
/*
- ======================================================================
- ======================================================================
- ======================================================================
+ * ----------------------------------------------------------------------
+ * appnic_mdio_initialize
+ */
- NIC Interface
+static void appnic_mdio_initialize(struct net_device *dev)
+{
+ struct appnic_device *pdata = netdev_priv(dev);
- ======================================================================
- ======================================================================
- ======================================================================
-*/
+ if (is_asic()) {
+ out_le32(MDIO_CLK_OFFSET, 0x10);
+ out_le32(MDIO_CLK_PERIOD, 0x2c);
+ } else {
+ out_le32(MDIO_CLK_OFFSET, 0x05);
+ out_le32(MDIO_CLK_PERIOD, 0x0c);
+ }
-static int enable_rx_tx(struct net_device *);
+ return;
+}
/*
- ======================================================================
- ======================================================================
- ======================================================================
-
- Device Data Structures
-
- ======================================================================
- ======================================================================
- ======================================================================
-*/
-
-
-struct appnic_dma_descriptor {
+ * ----------------------------------------------------------------------
+ * appnic_mii_read
+ *
+ * Returns -EBUSY if unsuccessful, the (short) value otherwise.
+ */
- /* Word 0 */
- unsigned long unused:24;
- /* big endian to little endian */
- unsigned long byte_swapping_on:1;
- unsigned long error:1;
- unsigned long interrupt_on_completion:1;
- unsigned long end_of_packet:1;
- unsigned long start_of_packet:1;
- unsigned long write:1;
- /* 00=Fill|01=Block|10=Scatter */
- unsigned long transfer_type:2;
+static int appnic_mii_read(struct mii_bus *bus, int phy, int reg)
+{
+ struct appnic_device *pdata = (struct appnic_device *)bus->priv;
+ unsigned long flags;
+ unsigned short value;
+ unsigned long command = 0;
+ unsigned long status;
- /* Word 1 */
- unsigned long pdu_length:16;
- unsigned long data_transfer_length:16;
+ spin_lock_irqsave(&pdata->mdio_lock, flags);
- /* Word 2 */
- unsigned long target_memory_address;
+ /* Set the mdio_busy (status) bit. */
+ status = in_le32(MDIO_STATUS_RD_DATA);
+ status |= 0x40000000;
+ out_le32(MDIO_STATUS_RD_DATA, status);
- /* Word 3 */
- unsigned long host_data_memory_pointer;
+ /* Write the command. */
+ command |= 0x10000000; /* op_code: read */
+ command |= (phy & 0x1f) << 16; /* port_addr (target device) */
+ command |= (reg & 0x1f) << 21; /* device_addr (target register) */
+ out_le32(MDIO_CONTROL_RD_DATA, command);
-} __packed;
+ /* Wait for the mdio_busy (status) bit to clear. */
+ do {
+ status = in_le32(MDIO_STATUS_RD_DATA);
+ } while (0 != (status & 0x40000000));
-union appnic_queue_pointer {
+ /* Wait for the mdio_busy (control) bit to clear. */
+ do {
+ command = in_le32(MDIO_CONTROL_RD_DATA);
+ } while (0 != (command & 0x80000000));
- unsigned long raw;
+ value = (unsigned short)(command & 0xffff);
+ spin_unlock_irqrestore(&pdata->mdio_lock, flags);
- struct {
- unsigned long unused:11;
- unsigned long generation_bit:1;
- unsigned long offset:20;
- } __packed bits;
+ return value;
+}
-} __packed;
/*
- =============================================================================
- The Device Struction
- =============================================================================
-*/
-
-struct appnic_device {
-
- /* net_device */
- struct net_device *device;
-
- /* Addresses, Interrupt, and PHY stuff. */
- unsigned long rx_base;
- unsigned long tx_base;
- unsigned long dma_base;
- unsigned long interrupt;
- unsigned long mdio_clock;
- unsigned long phy_address;
- unsigned long ad_value;
- unsigned char mac_addr[6];
-
-#ifdef LSINET_NAPI
- /* napi */
- struct napi_struct napi;
-#endif /* LSINET_ENABLE_NAPI */
-
- /* statistics */
- struct net_device_stats stats;
-
- /*
- * DMA-able memory.
- */
-
- int dma_alloc_size;
- void *dma_alloc;
- dma_addr_t dma_alloc_dma;
- int dma_alloc_offset;
-
- /* tail pointers */
- volatile union appnic_queue_pointer *rx_tail;
- dma_addr_t rx_tail_dma;
- volatile union appnic_queue_pointer *tx_tail;
- dma_addr_t tx_tail_dma;
-
- /* descriptors */
- struct appnic_dma_descriptor *rx_desc;
- dma_addr_t rx_desc_dma;
- unsigned rx_num_desc;
- struct appnic_dma_descriptor *tx_desc;
- dma_addr_t tx_desc_dma;
- unsigned tx_num_desc;
-
- /* buffers */
- unsigned rx_buf_sz;
- unsigned rx_buf_per_desc;
- void *rx_buf;
- dma_addr_t rx_buf_dma;
- unsigned tx_buf_sz;
- unsigned tx_buf_per_desc;
- void *tx_buf;
- dma_addr_t tx_buf_dma;
-
- /*
- * The local pointers
- */
-
- union appnic_queue_pointer rx_tail_copy;
- union appnic_queue_pointer rx_head;
-
- union appnic_queue_pointer tx_tail_copy;
- union appnic_queue_pointer tx_head;
-
- /*
- * Polling Mode?
- */
-
- int polling;
+ * ----------------------------------------------------------------------
+ * appnic_mii_write
+ */
- /*
- * Spin Lock
- */
+static int appnic_mii_write(struct mii_bus *bus, int phy, int reg, u16 val)
+{
+ struct appnic_device *pdata = (struct appnic_device *)bus->priv;
+ unsigned long flags;
+ unsigned long command = 0;
+ unsigned long status;
- spinlock_t lock;
- spinlock_t extra_lock;
-};
+ spin_lock_irqsave(&pdata->mdio_lock, flags);
-#define DESCRIPTOR_GRANULARITY 64
-#define BUFFER_ALIGNMENT 64
+ /* Wait for mdio_busy (control) to be clear. */
+ do {
+ command = in_le32(MDIO_CONTROL_RD_DATA);
+ } while (0 != (command & 0x80000000));
+
+ /* Set the mdio_busy (status) bit. */
+ status = in_le32(MDIO_STATUS_RD_DATA);
+ status |= 0x40000000;
+ out_le32(MDIO_STATUS_RD_DATA, status);
+
+ /* Write the command. */
+ command = 0x08000000; /* op_code: write */
+ command |= (phy & 0x1f) << 16; /* port_addr (target device) */
+ command |= (reg & 0x1f) << 21; /* device_addr (target register) */
+ command |= (val & 0xffff); /* value */
+ out_le32(MDIO_CONTROL_RD_DATA, command);
+
+ /* Wait for the mdio_busy (status) bit to clear. */
+ do {
+ status = in_le32(MDIO_STATUS_RD_DATA);
+ } while (0 != (status & 0x40000000));
-#define ALIGN64B(address) \
- ((((unsigned long) (address) + (64UL - 1UL)) & ~(64UL - 1UL)))
+ /* Wait for the mdio_busy (control) bit to clear. */
+ do {
+ command = in_le32(MDIO_CONTROL_RD_DATA);
+ } while (0 != (command & 0x80000000));
-#define ALIGN64B_OFFSET(address) \
- (ALIGN64B(address) - (unsigned long) (address))
+ spin_unlock_irqrestore(&pdata->mdio_lock, flags);
-#define APPNIC_NAME "appnic"
+ return 0;
+}
/*
- * Overview
- * --------
- *
- * Register offset decoding is as follows:
- *
- * Bit(s) Description
- *
- * 16:15 define the Channel. There is only one; therefore, 00.
- * 14:12 define the MAC within the channel. Only one so 000.
- * 11:10 define the register "space" as follows:
- * 00 = fast ethernet MACmw.l 06000000 ffffffff 3200000
- * 10 = global
- * 11 = interrupt
- * 9: 2 register
- * 1: 0 always 00, 32 bit registers only.
- *
- * Receive registers start at the base address. Transmit registers start
- * at 0x20000 above the base address. DMA start at a completely different
- * base address (in this case 0x8000000 above the base).
+ * ----------------------------------------------------------------------
+ * appnic_handle_link_change
*
-*/
-
-/*
- ======================================================================
- ======================================================================
- ======================================================================
-
- Registers.
-
- ======================================================================
- ======================================================================
- ======================================================================
-*/
-
-/* SMII Status ------------------------------------------------------ */
-
-#define APPNIC_RX_SMII_STATUS (rx_base + 0x10)
-#define APPNIC_RX_SMII_STATUS_SPEED 0x01
-#define APPNIC_RX_SMII_STATUS_DUPLEX 0x02
-#define APPNIC_RX_SMII_STATUS_LINK 0x04
-#define APPNIC_RX_SMII_STATUS_JABBER 0x08
-#define APPNIC_RX_SMII_STATUS_FCD 0x10 /* False Carrier Detect */
-
-#define SMII_SPEED_100(smii_status) \
- (0 != (smii_status & APPNIC_RX_SMII_STATUS_SPEED))
-#define SMII_DUPLEX(smii_status) \
- (0 != (smii_status & APPNIC_RX_SMII_STATUS_DUPLEX))
-#define SMII_LINK(smii_status) \
- (0 != (smii_status & APPNIC_RX_SMII_STATUS_LINK))
-#define SMII_JABBER(smii_status) \
- (0 != (smii_status & APPNIC_RX_SMII_STATUS_JABBER))
-
-/* Receive Configuration -------------------------------------------- */
-
-#define APPNIC_RX_CONF (rx_base + 0x004c)
-#define APPNIC_RX_CONF_ENABLE 0x0001
-/* Pass Any Packet */
-#define APPNIC_RX_CONF_PAP 0x0002
-#define APPNIC_RX_CONF_JUMBO9K 0x0008
-#define APPNIC_RX_CONF_STRIPCRC 0x0010
-/* Accept All MAC Types */
-#define APPNIC_RX_CONF_AMT 0x0020
-/* Accept Flow Control */
-#define APPNIC_RX_CONF_AFC 0x0040
-/* Enable VLAN */
-#define APPNIC_RX_CONF_VLAN 0x0200
-/* RX MAC Speed, 1=100MBS */
-#define APPNIC_RX_CONF_SPEED 0x0800
-/* 1=Duplex Mode */
-#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.
+ * Called periodically when PHY is in polling mode.
*/
-#define APPNIC_RX_CONF_RXFCE 0x4000
-/*
- * Controls the insertion of FC packets
- * by the MAC transmitter.
- */
-#define APPNIC_RX_CONF_TXFCE 0x8000
-
-/* Receive Stat Overflow -------------------------------------------- */
-
-#define APPNIC_RX_STAT_OVERFLOW (rx_base + 0x278)
-
-/* Receive Stat Undersize ------------------------------------------- */
-
-#define APPNIC_RX_STAT_UNDERSIZE (rx_base + 0x280)
-
-/* Receive Stat Oversize -------------------------------------------- */
-
-#define APPNIC_RX_STAT_OVERSIZE (rx_base + 0x2b8)
-
-/* Receive Stat Multicast ------------------------------------------- */
-
-#define APPNIC_RX_STAT_MULTICAST (rx_base + 0x2d0)
-
-/* Receive Stat Packet OK ------------------------------------------- */
-
-#define APPNIC_RX_STAT_PACKET_OK (rx_base + 0x2c0)
-
-/* Receive Stat CRC Error ------------------------------------------- */
-
-#define APPNIC_RX_STAT_CRC_ERROR (rx_base + 0x2c8)
-
-/* Receive Stat Align Error ----------------------------------------- */
-
-#define APPNIC_RX_STAT_ALIGN_ERROR (rx_base + 0x2e8)
-
-/* Receive Ethernet Mode -------------------------------------------- */
-
-#define APPNIC_RX_MODE (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_MAC_0 0x00001
-
-/* Receive Internal Interrupt Control ------------------------------- */
-
-#define APPNIC_RX_INTERNAL_INTERRUPT_CONTROL (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_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_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_TXCONFIG_DTPA_ASSERT 0x8000
-#define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_DISABLE 0x4000
-#define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_WATER_MARK_HIGH 0x3f00
-#define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_WATER_MARK_LOW 0x3f
-
-/* 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)
-
-/* Transmit Extended Configuration ---------------------------------- */
-
-#define APPNIC_TX_EXTENDED_CONF (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
-#define APPNIC_TX_EXTENDED_CONF_LATE_COLLISION_WINDOW_COUNT 0xff
-
-/* Transmit Half Duplex Configuration ------------------------------- */
-
-#define APPNIC_TX_HALF_DUPLEX_CONF (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_ENABLE_SWAP_SA 0x8000
-#define APPNIC_TX_CONF_LINK 0x2000
-#define APPNIC_TX_CONF_DUPLEX 0x1000
-#define APPNIC_TX_CONF_SPEED 0x0800
-#define APPNIC_TX_CONF_XBK_RST_RX_NTX 0x0600
-#define APPNIC_TX_CONF_IFG 0x01f0
-#define APPNIC_TX_CONF_APP_CRC_ENABLE 0x0004
-#define APPNIC_TX_CONF_PAD_ENABLE 0x0002
-#define APPNIC_TX_CONF_ENABLE 0x0001
-
-#define TX_CONF_SET_IFG(tx_configuration, ifg) \
- do { \
- (tx_configuration) &= ~APPNIC_TX_CONF_IFG; \
- (tx_configuration) |= ((ifg & 0x1f) << 4); \
- } while (0);
-
-/* Transmit Time Value Configuration -------------------------------- */
-
-#define APPNIC_TX_TIME_VALUE_CONF (tx_base + 0x5c)
-#define APPNIC_TX_TIME_VALUE_CONF_PAUSE_VALUE 0xffff
-
-/* Transmit Stat Underrun ------------------------------------------- */
-
-#define APPNIC_TX_STAT_UNDERRUN (tx_base + 0x300)
-
-/* Transmit Stat Packet OK ------------------------------------------ */
-
-#define APPNIC_TX_STAT_PACKET_OK (tx_base + 0x318)
-
-/* Transmit Stat Undersize ------------------------------------------ */
-
-#define APPNIC_TX_STAT_UNDERSIZE (tx_base + 0x350)
-
-/* Transmit Status Late Collision ----------------------------------- */
-
-#define APPNIC_TX_STATUS_LATE_COLLISION (tx_base + 0x368)
-
-/* Transmit Status Excessive Collision ------------------------------ */
-
-#define APPNIC_TX_STATUS_EXCESSIVE_COLLISION (tx_base + 0x370)
-
-/* Transmit Stat Collision Above Watermark -------------------------- */
-
-#define APPNIC_TX_STAT_COLLISION_ABOVE_WATERMARK (tx_base + 0x380)
-
-/* Transmit Mode ---------------------------------------------------- */
-
-#define APPNIC_TX_MODE (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_MAC_0 0x1
-
-/* Transmit Interrupt Control --------------------------------------- */
-
-#define APPNIC_TX_INTERRUPT_CONTROL (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_MAC_0 0x1
-
-/* */
-
-#define APPNIC_DMA_PCI_CONTROL (dma_base + 0x00)
-
-/* */
-
-#define APPNIC_DMA_CONTROL (dma_base + 0x08)
-
-/* DMA Interrupt Status --------------------------------------------- */
-
-#define APPNIC_DMA_INTERRUPT_STATUS (dma_base + 0x18)
-#define APPNIC_DMA_INTERRUPT_STATUS_RX 0x2
-#define APPNIC_DMA_INTERRUPT_STATUS_TX 0x1
-#define RX_INTERRUPT(dma_interrupt_status) \
- (0 != (dma_interrupt_status & APPNIC_DMA_INTERRUPT_STATUS_RX))
-#define TX_INTERRUPT(dma_interrupt_status) \
- (0 != (dma_interrupt_status & APPNIC_DMA_INTERRUPT_STATUS_TX))
-
-/* DMA Interrupt Enable --------------------------------------------- */
-
-#define APPNIC_DMA_INTERRUPT_ENABLE (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)
-/* DMA Receive Queue Size ------------------------------------------- */
-
-#define APPNIC_DMA_RX_QUEUE_SIZE (dma_base + 0x34)
-
-/* DMA Transmit Queue Base Address ---------------------------------- */
-
-#define APPNIC_DMA_TX_QUEUE_BASE_ADDRESS (dma_base + 0x38)
-
-/* DMA Transmit Queue Size ------------------------------------------ */
-
-#define APPNIC_DMA_TX_QUEUE_SIZE (dma_base + 0x3c)
-
-/* DMA Recevie Tail Pointer Address --------------------------------- */
-
-#define APPNIC_DMA_RX_TAIL_POINTER_ADDRESS (dma_base + 0x48)
+static void appnic_handle_link_change(struct net_device *dev)
+{
+ struct appnic_device *pdata = netdev_priv(dev);
+ struct phy_device *phydev = pdata->phy_dev;
+ int status_change = 0;
+ unsigned long rx_configuration;
+ unsigned long tx_configuration = 0;
-/* DMA Transmit Tail Pointer Address -------------------------------- */
+ rx_configuration =
+ (APPNIC_RX_CONF_STRIPCRC |
+ APPNIC_RX_CONF_RXFCE |
+ APPNIC_RX_CONF_TXFCE);
+ tx_configuration =
+ (APPNIC_TX_CONF_ENABLE_SWAP_SA |
+ APPNIC_TX_CONF_APP_CRC_ENABLE |
+ APPNIC_TX_CONF_PAD_ENABLE);
-#define APPNIC_DMA_TX_TAIL_POINTER_ADDRESS (dma_base + 0x4c)
+ TX_CONF_SET_IFG(tx_configuration, 0xf);
-/* DMA Receive Head Pointer ----------------------------------------- */
+ if (phydev->link) {
+ if ((pdata->speed != phydev->speed) ||
+ (pdata->duplex != phydev->duplex)) {
-#define APPNIC_DMA_RX_HEAD_POINTER (dma_base + 0x50)
-#define APPNIC_DMA_RX_HEAD_POINTER_GB 0x100000
-#define APPNIC_DMA_RX_HEAD_POINTER_POINTER 0x0fffff
+ if (phydev->duplex) {
+ rx_configuration |= APPNIC_RX_CONF_DUPLEX;
+ tx_configuration |= APPNIC_TX_CONF_DUPLEX;
+ }
+ if (phydev->speed == SPEED_100) {
+ rx_configuration |= APPNIC_RX_CONF_SPEED;
+ tx_configuration |= APPNIC_TX_CONF_SPEED;
+ }
-/* DMA Receive Tail Pointer Local Copy ------------------------------ */
+ rx_configuration |= (APPNIC_RX_CONF_ENABLE |
+ APPNIC_RX_CONF_LINK);
+ tx_configuration |= (APPNIC_TX_CONF_LINK |
+ APPNIC_TX_CONF_ENABLE);
-#define APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY (dma_base + 0x54)
-#define APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY_GB 0x100000
-#define APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY_POINTER 0x0fffff
+ pdata->speed = phydev->speed;
+ pdata->duplex = phydev->duplex;
+ status_change = 1;
+ }
+ }
+ if (phydev->link != pdata->link) {
+ if (!phydev->link) {
+ pdata->speed = 0;
+ pdata->duplex = -1;
+ }
+ pdata->link = phydev->link;
+ status_change = 1;
+ }
-/* DMA Transmit Head Pointer ---------------------------------------- */
+ if (status_change) {
+ if (phydev->link) {
+ netif_carrier_on(dev);
+ netdev_info(dev, "link up (%d/%s)\n",
+ phydev->speed,
+ phydev->duplex == DUPLEX_FULL ?
+ "Full" : "Half");
+ } else {
+ netif_carrier_off(dev);
+ netdev_info(dev, "link down\n");
+ }
-#define APPNIC_DMA_TX_HEAD_POINTER (dma_base + 0x58)
-#define APPNIC_DMA_TX_HEAD_POINTER_GB 0x100000
-#define APPNIC_DMA_TX_HEAD_POINTER_POINTER 0x0fffff
+ if (rx_configuration != read_mac(APPNIC_RX_CONF))
+ write_mac(rx_configuration, APPNIC_RX_CONF);
-/* DMA Transmit Tail Pointer Local Copy ----------------------------- */
+ if (tx_configuration != read_mac(APPNIC_TX_CONF))
+ write_mac(tx_configuration, APPNIC_TX_CONF);
+ }
-#define APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY (dma_base + 0x5c)
-#define APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY_GB 0x100000
-#define APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY_POINTER 0x0fffff
+ return;
+}
/*
- ======================================================================
- ======================================================================
- ======================================================================
+ * ----------------------------------------------------------------------
+ * appnic_mii_probe
+ */
- Access
+static int appnic_mii_probe(struct net_device *dev)
+{
+ struct appnic_device *pdata = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+ int ret;
+
+ /* Find the first phy */
+ phydev = phy_find_first(pdata->mii_bus);
+ if (!phydev) {
+ netdev_err(dev, " no PHY found\n");
+ return -ENODEV;
+ }
- N.B. On the APP, DMA transfers from the NIC MUST USE THE MEMORY
- ALIAS AT 0x60000000!
+ ret = phy_connect_direct(dev, phydev,
+ &appnic_handle_link_change, 0,
+ PHY_INTERFACE_MODE_MII);
- ======================================================================
- ======================================================================
- ======================================================================
-*/
+ if (ret) {
+ netdev_err(dev, "Could not attach to PHY\n");
+ return ret;
+ }
-#define readio(address) in_le32((u32 *) (address))
+ netdev_info(dev,
+ "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+ phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
-#define writeio(value, address) out_le32((u32 *) (address), (value))
+ /* Mask with MAC supported features */
+ phydev->supported &= PHY_BASIC_FEATURES;
+ phydev->advertising = mii_adv_to_ethtool_adv_t(pdata->ad_value);
-static inline void
-readdescriptor(unsigned long address, struct appnic_dma_descriptor *descriptor)
-{
- unsigned long *from = (unsigned long *) address;
- unsigned long *to = (unsigned long *) descriptor;
+ pdata->link = 0;
+ pdata->speed = 0;
+ pdata->duplex = -1;
+ pdata->phy_dev = phydev;
- *to++ = swab32(*from++);
- *to++ = swab32(*from++);
- *to++ = swab32(*from++);
- *to++ = swab32(*from++);
- return;
+ pr_info("%s: PHY initialized successfully", LSI_DRV_NAME);
+ return 0;
}
-static inline void
-writedescriptor(unsigned long address,
- const struct appnic_dma_descriptor *descriptor)
+/*
+ * ----------------------------------------------------------------------
+ * appnic_mii_init
+ */
+
+static int __devinit appnic_mii_init(struct platform_device *pdev,
+ struct net_device *dev)
{
- unsigned long *to = (unsigned long *) address;
- unsigned long *from = (unsigned long *) descriptor;
+ struct appnic_device *pdata = netdev_priv(dev);
+ int i, err = -ENXIO;
- *to++ = swab32(*from++);
- *to++ = swab32(*from++);
- *to++ = swab32(*from++);
- *to++ = swab32(*from++);
- return;
-}
+ pdata->mii_bus = mdiobus_alloc();
+ if (!pdata->mii_bus) {
+ err = -ENOMEM;
+ goto err_out_1;
+ }
-static inline union appnic_queue_pointer
-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;
-}
+ pdata->mii_bus->name = LSI_MDIO_NAME;
+ snprintf(pdata->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pdev->name, pdev->id);
+ pdata->mii_bus->priv = pdata;
+ pdata->mii_bus->read = appnic_mii_read;
+ pdata->mii_bus->write = appnic_mii_write;
+ pdata->mii_bus->irq = pdata->phy_irq;
+ for (i = 0; i < PHY_MAX_ADDR; ++i)
+ pdata->mii_bus->irq[i] = PHY_POLL;
+
+ if (mdiobus_register(pdata->mii_bus)) {
+ pr_warn("%s: Error registering mii bus", LSI_DRV_NAME);
+ goto err_out_free_bus_2;
+ }
-#define SWAB_QUEUE_POINTER(pointer) \
-swab_queue_pointer((const union appnic_queue_pointer *) (pointer))
+ if (appnic_mii_probe(dev) < 0) {
+ pr_warn("%s: Error registering mii bus", LSI_DRV_NAME);
+ goto err_out_unregister_bus_3;
+ }
-#define read_mac(address) readio((address))
-#define write_mac(value, address) writeio((value), (address))
+ return 0;
+err_out_unregister_bus_3:
+ mdiobus_unregister(pdata->mii_bus);
+err_out_free_bus_2:
+ mdiobus_free(pdata->mii_bus);
+err_out_1:
+ return err;
+}
/*
======================================================================
+ NIC Interface
======================================================================
- ======================================================================
+*/
- Module Information
+#define DESCRIPTOR_GRANULARITY 64
+#define BUFFER_ALIGNMENT 64
- ======================================================================
- ======================================================================
- ======================================================================
-*/
+#define ALIGN64B(address) \
+ ((((unsigned long) (address) + (64UL - 1UL)) & ~(64UL - 1UL)))
-MODULE_AUTHOR("John Jacques");
-MODULE_DESCRIPTION("Agere APP3xx ethernet driver");
-MODULE_LICENSE("GPL");
+#define ALIGN64B_OFFSET(address) \
+ (ALIGN64B(address) - (unsigned long) (address))
/*
* ----- Note On Buffer Space -----
*
* Minimum number of descriptors is 64 for the receiver and 64 for the
* transmitter; therefore, 2048 bytes (16 bytes each).
- * This driver uses the following parameters,
- * all of which may be set on the command line if this drivers is used
- * as a module.
+ * This driver uses the following parameters, all of which may be set on
+ * the command line if this drivers is used as a module.
*
* - rx_num_desc : Number of receive descriptors. This must be a multiple
* of 64.
@@ -810,34 +434,14 @@ 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");
-/*
- * Only 1 device is possible...
- */
-
-struct net_device *this_net_device;
-
static unsigned long dropped_by_stack;
static unsigned long out_of_tx_descriptors;
static unsigned long transmit_interrupts;
-#ifdef LSINET_NAPI
static unsigned long receive_interrupts;
-#endif
-
-#define APPNIC_TIMER_PERIOD 5
-#ifndef PHYLESS
-static void appnic_timer_handler(unsigned long);
-static struct timer_list appnic_timer;
-#endif /* PHYLESS */
/*
======================================================================
- ======================================================================
- ======================================================================
-
Utility Functions
-
- ======================================================================
- ======================================================================
======================================================================
*/
@@ -846,7 +450,7 @@ static struct timer_list appnic_timer;
clear_statistics
*/
-static void clear_statistics(struct appnic_device *device)
+static void clear_statistics(struct appnic_device *pdata)
{
int waste;
@@ -854,8 +458,7 @@ static void clear_statistics(struct appnic_device *device)
* Clear memory.
*/
- memset((void *) &(device->stats), 0,
- sizeof(struct net_device_stats));
+ memset((void *) &(pdata->stats), 0, sizeof(struct net_device_stats));
/*
* Clear counters.
@@ -928,60 +531,58 @@ static void clear_statistics(struct appnic_device *device)
* 1) The hardware clears the statistics registers after a read.
*/
-static void get_hw_statistics(struct appnic_device *device)
+static void get_hw_statistics(struct appnic_device *pdata)
{
unsigned long flags;
/* tx_packets */
- device->stats.tx_packets += read_mac(APPNIC_TX_STAT_PACKET_OK);
+ pdata->stats.tx_packets += read_mac(APPNIC_TX_STAT_PACKET_OK);
/* multicast */
- device->stats.multicast += read_mac(APPNIC_RX_STAT_MULTICAST);
+ pdata->stats.multicast += read_mac(APPNIC_RX_STAT_MULTICAST);
/* collision */
- device->stats.collisions += read_mac(APPNIC_TX_STATUS_LATE_COLLISION);
- device->stats.collisions +=
+ pdata->stats.collisions += read_mac(APPNIC_TX_STATUS_LATE_COLLISION);
+ pdata->stats.collisions +=
read_mac(APPNIC_TX_STATUS_EXCESSIVE_COLLISION);
- device->stats.collisions +=
+ pdata->stats.collisions +=
read_mac(APPNIC_TX_STAT_COLLISION_ABOVE_WATERMARK);
/* rx_length_errors */
- device->stats.rx_length_errors += read_mac(APPNIC_RX_STAT_UNDERSIZE);
- device->stats.rx_length_errors += read_mac(APPNIC_RX_STAT_OVERSIZE);
+ 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 */
- device->stats.tx_fifo_errors += read_mac(APPNIC_TX_STAT_UNDERRUN);
+ 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);
- spin_lock_irqsave(&device->lock, flags);
-
- device->stats.rx_errors +=
- (device->stats.rx_length_errors +
- device->stats.rx_crc_errors +
- device->stats.rx_frame_errors +
- device->stats.rx_fifo_errors +
- device->stats.rx_dropped +
- device->stats.rx_over_errors);
+ pdata->stats.rx_errors +=
+ (pdata->stats.rx_length_errors +
+ pdata->stats.rx_crc_errors +
+ pdata->stats.rx_frame_errors +
+ pdata->stats.rx_fifo_errors +
+ pdata->stats.rx_dropped +
+ pdata->stats.rx_over_errors);
- device->stats.rx_dropped = 0;
- device->stats.rx_over_errors = 0;
+ pdata->stats.rx_dropped = 0;
+ pdata->stats.rx_over_errors = 0;
- device->stats.tx_errors +=
- (device->stats.tx_fifo_errors +
- device->stats.tx_aborted_errors);
- device->stats.tx_aborted_errors = 0;
+ pdata->stats.tx_errors += (pdata->stats.tx_fifo_errors +
+ pdata->stats.tx_aborted_errors);
+ pdata->stats.tx_aborted_errors = 0;
- spin_unlock_irqrestore(&device->lock, flags);
+ spin_unlock_irqrestore(&pdata->dev_lock, flags);
/*
* That's all.
@@ -1005,7 +606,6 @@ static int queue_initialized(union appnic_queue_pointer head,
int initialized;
/* Calculate the number of descriptors currently initialized. */
-
if (head.bits.generation_bit == tail.bits.generation_bit) {
/* same generation */
initialized = (head.bits.offset - tail.bits.offset);
@@ -1016,7 +616,7 @@ static int queue_initialized(union appnic_queue_pointer head,
tail.bits.offset);
}
- /* number of descriptors is offset / sizeof(a descriptor) */
+ /* Number of descriptors is offset / sizeof(a descriptor). */
initialized /= sizeof(struct appnic_dma_descriptor);
return initialized;
@@ -1036,7 +636,6 @@ static int queue_uninitialized(union appnic_queue_pointer head,
int allocated;
/* Calculate the number of descriptors currently unused/uninitialized */
-
if (head.bits.generation_bit == tail.bits.generation_bit)
/* Same generation. */
allocated = ((size * sizeof(struct appnic_dma_descriptor)) -
@@ -1045,7 +644,7 @@ static int queue_uninitialized(union appnic_queue_pointer head,
/* Different generation. */
allocated = tail.bits.offset - head.bits.offset;
- /* number of descriptors is offset / sizeof(a descriptor). */
+ /* Number of descriptors is offset / sizeof(a descriptor). */
allocated /= sizeof(struct appnic_dma_descriptor);
/* That's all. */
@@ -1094,106 +693,6 @@ static void queue_decrement(union appnic_queue_pointer *queue,
return;
}
-
-#ifndef PHYLESS
-
-static void appnic_timer_handler(unsigned long __opaque)
-{
- struct net_device *device = (struct net_device *) __opaque;
-
- enable_rx_tx(device);
- appnic_timer.expires = jiffies + (APPNIC_TIMER_PERIOD * HZ);
- add_timer(&appnic_timer);
-}
-
-#endif
-
-/*
- * ----------------------------------------------------------------------
- * enable_rx_tx
- *
- * -- NOTES --
- *
- * 1) Does not change the default values in the extended and
- * half-duplex configuration registers.
- */
-
-static int enable_rx_tx(struct net_device *device)
-{
- int return_code = 1;
- int carrier_state = 0;
- unsigned long rx_configuration;
- unsigned long tx_configuration = 0;
- union phy_status phy_status;
- struct appnic_device *dev = netdev_priv(device);
-
- rx_configuration =
- (APPNIC_RX_CONF_STRIPCRC |
- APPNIC_RX_CONF_RXFCE |
- APPNIC_RX_CONF_TXFCE);
- tx_configuration =
- (APPNIC_TX_CONF_ENABLE_SWAP_SA |
- APPNIC_TX_CONF_APP_CRC_ENABLE |
- APPNIC_TX_CONF_PAD_ENABLE);
-
- TX_CONF_SET_IFG(tx_configuration, 0xf);
-
- /*
- * Setup the receive and transmit configuration registers (using smii
- * status to set speed/duplex and check the link status).
- */
-
- if ((0 == phy_read(dev->phy_address, PHY_STATUS, &phy_status.raw)) &&
- (0 == phy_read(dev->phy_address, PHY_STATUS, &phy_status.raw))) {
-
- if (1 == phy_status.bits.autoneg_comp) {
- if (1 == phy_status.bits.link_status) {
- if (1 == phy_speed(dev->phy_address)) {
- rx_configuration |=
- APPNIC_RX_CONF_SPEED;
- tx_configuration |=
- APPNIC_TX_CONF_SPEED;
- }
-
- if (1 == phy_duplex(dev->phy_address)) {
- rx_configuration |=
- APPNIC_RX_CONF_DUPLEX;
- tx_configuration |=
- APPNIC_TX_CONF_DUPLEX;
- }
-
- rx_configuration |=
- (APPNIC_RX_CONF_ENABLE |
- APPNIC_RX_CONF_LINK);
- tx_configuration |=
- (APPNIC_TX_CONF_LINK |
- APPNIC_TX_CONF_ENABLE);
- return_code = 0;
- carrier_state = 1;
- } else {
- netif_carrier_off(device);
- }
- } else {
- netif_carrier_off(device);
- }
- } else {
- pr_err("acp-femac: phy_read() failed!\n");
- }
-
- if (rx_configuration != read_mac(APPNIC_RX_CONF))
- write_mac(rx_configuration, APPNIC_RX_CONF);
-
- if (tx_configuration != read_mac(APPNIC_TX_CONF))
- write_mac(tx_configuration, APPNIC_TX_CONF);
-
- if (0 != carrier_state)
- netif_carrier_on(device);
- else
- netif_carrier_off(device);
-
- return return_code;
-}
-
/*
* ----------------------------------------------------------------------
* disable_rx_tx
@@ -1204,7 +703,7 @@ static void disable_rx_tx(void)
unsigned long tx_configuration;
unsigned long rx_configuration;
- pr_info("acp-femac: Disabling the interface.\n");
+ pr_info("%s: Disabling the interface.\n", LSI_DRV_NAME);
rx_configuration = read_mac(APPNIC_RX_CONF);
rx_configuration &= ~APPNIC_RX_CONF_ENABLE;
@@ -1219,160 +718,10 @@ static void disable_rx_tx(void)
return;
}
-/*
- ======================================================================
- ======================================================================
- ======================================================================
- PHY interface (BCM5221)
- ======================================================================
- ======================================================================
- ======================================================================
-*/
-
-#ifndef PHYLESS
-
-/*
- * ----------------------------------------------------------------------
- * phy_read
- *
- * Returns -1 if unsuccessful, the (short) value otherwise.
- */
-
-static int
-phy_read(int phy, int reg, unsigned short *value)
-{
- return acp_mdio_read(phy, reg, value);
-}
-
-/*
- * ----------------------------------------------------------------------
- * phy_write
- */
-
-static int
-phy_write(int phy, int reg, unsigned short value)
-{
- return acp_mdio_write(phy, reg, value);
-}
/*
- * ----------------------------------------------------------------------
- * phy_speed
- *
- * Returns the speed (1=100, 0=10) or an error (-1).
- */
-
-static int
-phy_speed(int phy)
-{
- union micrel_phy_auxiliary_control_status aux;
-
- phy_read(phy, MICREL_PHY_AUXILIARY_CONTROL_STATUS, &aux.raw);
-
- switch ((aux.bits.op_mode_indication & 3)) {
- case 2:
- return 1;
- break;
- case 1:
- return 0;
- break;
- default:
- break;
- }
-
- return -1;
-}
-
-/*
- * ----------------------------------------------------------------------
- * phy_duplex
- *
- * Returns duplex status (1=full duplex, 0=half duplex) or an error (-1).
- */
-
-static int
-phy_duplex(int phy)
-{
- union micrel_phy_auxiliary_control_status aux;
-
- phy_read(phy, MICREL_PHY_AUXILIARY_CONTROL_STATUS, &aux.raw);
-
- return (aux.bits.op_mode_indication >> 2) & 0x1;
-}
-
-/*
- * ----------------------------------------------------------------------
- * phy_renegotiate
- */
-
-static int
-phy_renegotiate(int phy)
-{
- union phy_control control;
- union phy_status status;
- int autoneg_retries = 2;
- int autoneg_complete_retries = 8;
-
- pr_info("acp-femac: Initiating Auto Negotiation ");
-
- /* Takes about 2 seconds for autoneg to complete ... */
- do {
- phy_read(phy, PHY_CONTROL, &control.raw);
- control.bits.restart_autoneg = 1;
- phy_write(phy, PHY_CONTROL, control.raw);
-
- do {
- pr_cont(".");
- mdelay(500);
- phy_read(phy, PHY_STATUS, &status.raw);
- } while ((0 < --autoneg_complete_retries) &&
- (0 == status.bits.autoneg_comp));
-
- if (0 != status.bits.autoneg_comp)
- break;
-
- pr_cont(".");
-
- } while (0 < --autoneg_retries);
-
- if (0 == status.bits.autoneg_comp) {
- pr_info("acp-femac: Auto Negotiation Failed\n");
- return -1;
- }
-
- pr_info("acp-femac: Auto Negotiation Succeeded\n");
- return 0;
-}
-
-/*
- * ----------------------------------------------------------------------
- * phy_enable
- */
-
-static int phy_enable(struct net_device *device)
-{
- struct appnic_device *dev = netdev_priv(device);
-
- if (phy_write(dev->phy_address, PHY_AUTONEG_ADVERTISE,
- (unsigned short)dev->ad_value) != 0)
- return -1;
-
- phy_renegotiate(dev->phy_address);
-
- return 0;
-}
-
-#endif /* PHYLESS */
-
-/*
- ======================================================================
======================================================================
- ======================================================================
-
Linux Network Driver Interface
-
- ======================================================================
- ======================================================================
======================================================================
*/
@@ -1381,54 +730,48 @@ static int phy_enable(struct net_device *device)
* handle_transmit_interrupt
*/
-static void handle_transmit_interrupt(struct net_device *device)
+static void handle_transmit_interrupt(struct net_device *dev)
{
- struct appnic_device *dev = netdev_priv(device);
+ struct appnic_device *pdata = netdev_priv(dev);
/*
* The hardware's tail pointer should be one descriptor (or more)
* ahead of software's copy.
*/
- while (0 < queue_initialized(SWAB_QUEUE_POINTER(dev->tx_tail),
- dev->tx_tail_copy, dev->tx_num_desc)) {
- queue_increment(&dev->tx_tail_copy, dev->tx_num_desc);
+ while (0 < queue_initialized(SWAB_QUEUE_POINTER(pdata->tx_tail),
+ pdata->tx_tail_copy, pdata->tx_num_desc)) {
+ queue_increment(&pdata->tx_tail_copy, pdata->tx_num_desc);
}
return;
}
-/* static DECLARE_MUTEX(rpm); */
-
/*
* ----------------------------------------------------------------------
* lsinet_rx_packet
*/
-static void
-lsinet_rx_packet(struct net_device *device)
+static void lsinet_rx_packet(struct net_device *dev)
{
- struct appnic_device *adapter = netdev_priv(device);
+ struct appnic_device *pdata = netdev_priv(dev);
struct appnic_dma_descriptor descriptor;
struct sk_buff *sk_buff;
unsigned bytes_copied = 0;
unsigned error_num = 0;
- int return_code;
unsigned long ok_stat, overflow_stat, crc_stat, align_stat;
- /*
- * TEMP HACK:
- * should use down_interruptible
- */
- spin_lock(&adapter->extra_lock);
- readdescriptor(((unsigned long) adapter->rx_desc +
- adapter->rx_tail_copy.bits.offset), &descriptor);
+ spin_lock(&pdata->extra_lock);
+
+ readdescriptor(((unsigned long)pdata->rx_desc +
+ pdata->rx_tail_copy.bits.offset), &descriptor);
sk_buff = dev_alloc_skb(1600);
- if ((struct sk_buff *) 0 == sk_buff) {
- pr_err("acp-femac: dev_alloc_skb() failed! Dropping packet.\n");
- spin_unlock(&adapter->extra_lock);
+ 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;
}
@@ -1441,45 +784,44 @@ lsinet_rx_packet(struct net_device *device)
* Copy the received packet into the skb.
*/
- while (0 < queue_initialized(SWAB_QUEUE_POINTER(adapter->rx_tail),
- adapter->rx_tail_copy, adapter->rx_num_desc)) {
+ while (0 < queue_initialized(SWAB_QUEUE_POINTER(pdata->rx_tail),
+ pdata->rx_tail_copy, pdata->rx_num_desc)) {
-#ifdef PRELOAD_RX_BUFFERS
+#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 +
- adapter->dma_alloc_offset),
+ memcpy((void *)buffer,
+ (void *)(descriptor.host_data_memory_pointer +
+ pdata->dma_alloc_offset_rx),
descriptor.pdu_length);
}
-#else /* PRELOAD_RX_BUFFERS */
- memcpy((void *) skb_put(sk_buff,
- descriptor.pdu_length),
- (void *) (descriptor.host_data_memory_pointer +
- adapter->dma_alloc_offset),
- descriptor.pdu_length);
-#endif /* PRELOAD_RX_BUFFERS */
+#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 = adapter->rx_buf_per_desc;
- writedescriptor(((unsigned long) adapter->rx_desc +
- adapter->rx_tail_copy.bits.offset),
+ descriptor.data_transfer_length = pdata->rx_buf_per_desc;
+ writedescriptor(((unsigned long)pdata->rx_desc +
+ pdata->rx_tail_copy.bits.offset),
&descriptor);
if (0 != descriptor.error)
error_num = 1;
- queue_increment(&adapter->rx_tail_copy,
- adapter->rx_num_desc);
+ queue_increment(&pdata->rx_tail_copy, pdata->rx_num_desc);
if (0 != descriptor.end_of_packet)
break;
- readdescriptor(((unsigned long) adapter->rx_desc +
- adapter->rx_tail_copy.bits.offset),
+ readdescriptor(((unsigned long)pdata->rx_desc +
+ pdata->rx_tail_copy.bits.offset),
&descriptor);
}
if (0 == descriptor.end_of_packet) {
- pr_err("acp-femac: No end of packet! %lu/%lu/%lu/%lu\n",
- ok_stat, overflow_stat, crc_stat, align_stat);
+ pr_err("%s: No end of packet! %lu/%lu/%lu/%lu\n",
+ LSI_DRV_NAME, ok_stat, overflow_stat,
+ crc_stat, align_stat);
BUG();
dev_kfree_skb(sk_buff);
@@ -1491,30 +833,22 @@ lsinet_rx_packet(struct net_device *device)
0xff, 0xff, 0xff };
unsigned char multicast[] = { 0x01, 0x00 };
- if ((0 == memcmp((const void *) &(ethhdr->h_dest[0]),
- (const void *) &(device->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)))) {
-
- adapter->stats.rx_bytes += bytes_copied;
- ++adapter->stats.rx_packets;
- sk_buff->dev = device;
+ 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)))) {
+
+ pdata->stats.rx_bytes += bytes_copied;
+ ++pdata->stats.rx_packets;
+ sk_buff->dev = dev;
sk_buff->protocol = eth_type_trans(sk_buff,
- device);
-#ifdef LSINET_NAPI
- return_code = netif_receive_skb(sk_buff);
-#else
- return_code = netif_rx(sk_buff);
-#endif
-
- if (NET_RX_DROP == return_code)
+ dev);
+ if (netif_receive_skb(sk_buff) == NET_RX_DROP)
++dropped_by_stack;
} else {
dev_kfree_skb(sk_buff);
@@ -1523,118 +857,108 @@ lsinet_rx_packet(struct net_device *device)
dev_kfree_skb(sk_buff);
if (0 != overflow_stat)
- ++adapter->stats.rx_fifo_errors;
+ ++pdata->stats.rx_fifo_errors;
else if (0 != crc_stat)
- ++adapter->stats.rx_crc_errors;
+ ++pdata->stats.rx_crc_errors;
else if (0 != align_stat)
- ++adapter->stats.rx_frame_errors;
+ ++pdata->stats.rx_frame_errors;
}
}
- /* TEMP */
- spin_unlock(&adapter->extra_lock);
+ spin_unlock(&pdata->extra_lock);
/* That's all. */
return;
}
/*
- * ============================================================================
+ * ----------------------------------------------------------------------
* lsinet_rx_packets
*/
-static int
-lsinet_rx_packets(struct net_device *device, int max)
+static int lsinet_rx_packets(struct net_device *dev, int max)
{
- struct appnic_device *adapter = netdev_priv(device);
+ struct appnic_device *pdata = netdev_priv(dev);
union appnic_queue_pointer queue;
int updated_head_pointer = 0;
int packets = 0;
- queue.raw = adapter->rx_tail_copy.raw;
+ queue.raw = pdata->rx_tail_copy.raw;
/* Receive Packets */
- while (0 < queue_initialized(SWAB_QUEUE_POINTER(adapter->rx_tail),
- queue, adapter->rx_num_desc)) {
+ while (0 < queue_initialized(SWAB_QUEUE_POINTER(pdata->rx_tail),
+ queue, pdata->rx_num_desc)) {
struct appnic_dma_descriptor descriptor;
- readdescriptor(((unsigned long) adapter->rx_desc +
+ readdescriptor(((unsigned long)pdata->rx_desc +
queue.bits.offset),
&descriptor);
if (0 != descriptor.end_of_packet) {
- lsinet_rx_packet(device);
+ lsinet_rx_packet(dev);
++packets;
- queue.raw = adapter->rx_tail_copy.raw;
+ queue.raw = pdata->rx_tail_copy.raw;
if ((-1 != max) && (packets == max))
break;
} else {
- queue_increment(&queue, adapter->rx_num_desc);
+ queue_increment(&queue, pdata->rx_num_desc);
}
}
/* Update the Head Pointer */
- while (1 < queue_uninitialized(adapter->rx_head,
- adapter->rx_tail_copy,
- adapter->rx_num_desc)) {
+ while (1 < queue_uninitialized(pdata->rx_head,
+ pdata->rx_tail_copy,
+ pdata->rx_num_desc)) {
struct appnic_dma_descriptor descriptor;
- readdescriptor(((unsigned long) adapter->rx_desc +
- adapter->rx_head.bits.offset), &descriptor);
- descriptor.data_transfer_length = adapter->rx_buf_per_desc;
+ readdescriptor(((unsigned long)pdata->rx_desc +
+ pdata->rx_head.bits.offset), &descriptor);
+ descriptor.data_transfer_length = pdata->rx_buf_per_desc;
descriptor.write = 1;
descriptor.pdu_length = 0;
descriptor.start_of_packet = 0;
descriptor.end_of_packet = 0;
descriptor.interrupt_on_completion = 1;
- writedescriptor(((unsigned long) adapter->rx_desc +
- adapter->rx_head.bits.offset),
+ writedescriptor(((unsigned long)pdata->rx_desc +
+ pdata->rx_head.bits.offset),
&descriptor);
- queue_increment(&adapter->rx_head, adapter->rx_num_desc);
+ queue_increment(&pdata->rx_head, pdata->rx_num_desc);
updated_head_pointer = 1;
}
if (0 != updated_head_pointer)
- write_mac(adapter->rx_head.raw, APPNIC_DMA_RX_HEAD_POINTER);
+ write_mac(pdata->rx_head.raw, APPNIC_DMA_RX_HEAD_POINTER);
return packets;
}
-#ifdef LSINET_NAPI
-
/*
- * ============================================================================
+ * ----------------------------------------------------------------------
* lsinet_poll
*/
-static int
-lsinet_poll(struct napi_struct *napi, int budget)
+static int lsinet_poll(struct napi_struct *napi, int budget)
{
- struct appnic_device *adapter =
+ struct appnic_device *pdata =
container_of(napi, struct appnic_device, napi);
- struct net_device *device = adapter->device;
+ struct net_device *dev = pdata->device;
union appnic_queue_pointer queue;
- int status;
int cur_budget = budget;
- int done;
unsigned long dma_interrupt_status;
- queue.raw = adapter->rx_tail_copy.raw;
-
- done = 1;
+ 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(device, cur_budget);
+ cur_budget -= lsinet_rx_packets(dev, cur_budget);
if (0 == cur_budget)
break;
@@ -1642,36 +966,18 @@ lsinet_poll(struct napi_struct *napi, int budget)
} while ((RX_INTERRUPT(dma_interrupt_status)) && cur_budget);
- if (done) {
- napi_complete(napi);
- /* re-enable receive interrupts */
- write_mac((APPNIC_DMA_INTERRUPT_ENABLE_RECEIVE |
- APPNIC_DMA_INTERRUPT_ENABLE_TRANSMIT),
- APPNIC_DMA_INTERRUPT_ENABLE);
- }
-
- status = (done ? 0 : 1);
- return status;
-}
-
-#else /* Not using NAPI, define the Rx interrupt handler instead */
-
-/*
- * ----------------------------------------------------------------------
- * handle_receive_interrupt
- */
-
-static void handle_receive_interrupt(struct net_device *device)
-{
- struct appnic_device *dev = netdev_priv(device);
- union appnic_queue_pointer queue;
+ napi_complete(napi);
- queue.raw = dev_->rx_tail_copy.raw;
- lsinet_rx_packets(device, -1);
+ /*
+ * 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;
+ return 0;
}
-#endif /* else not NAPI */
/*
* ----------------------------------------------------------------------
@@ -1680,70 +986,62 @@ static void handle_receive_interrupt(struct net_device *device)
static irqreturn_t appnic_isr(int irq, void *device_id)
{
- struct net_device *device = (struct net_device *) device_id;
- struct appnic_device *dev = netdev_priv(device);
+ struct net_device *dev = (struct net_device *)device_id;
+ struct appnic_device *pdata = netdev_priv(dev);
unsigned long dma_interrupt_status;
unsigned long flags;
/* Acquire the lock */
- spin_lock_irqsave(&dev->lock, flags);
-
+ spin_lock_irqsave(&pdata->dev_lock, flags);
/* Get the status. */
dma_interrupt_status = read_mac(APPNIC_DMA_INTERRUPT_STATUS);
-#ifdef LSINET_NAPI
/* NAPI - don't ack RX interrupt */
write_mac(APPNIC_DMA_INTERRUPT_ENABLE_RECEIVE,
- APPNIC_DMA_INTERRUPT_STATUS);
-#else
- write_mac(0, APPNIC_DMA_INTERRUPT_STATUS);
-#endif
+ APPNIC_DMA_INTERRUPT_STATUS);
/* Handle interrupts */
-
if (TX_INTERRUPT(dma_interrupt_status)) {
/* transmition complete */
++transmit_interrupts;
- handle_transmit_interrupt(device);
+ handle_transmit_interrupt(dev);
}
if (RX_INTERRUPT(dma_interrupt_status)) {
-#ifdef LSINET_NAPI
++receive_interrupts;
- if (napi_schedule_prep(&dev->napi)) {
+ if (napi_schedule_prep(&pdata->napi)) {
/*
* Disable RX interrupts and tell the
* system we've got work
*/
-
write_mac(APPNIC_DMA_INTERRUPT_ENABLE_TRANSMIT,
APPNIC_DMA_INTERRUPT_ENABLE);
- __napi_schedule(&dev->napi);
+ __napi_schedule(&pdata->napi);
} else {
write_mac(APPNIC_DMA_INTERRUPT_ENABLE_TRANSMIT,
APPNIC_DMA_INTERRUPT_ENABLE);
}
-#else
- /* Receive complete */
- handle_receive_interrupt(device);
-#endif
}
- /* release the lock */
- spin_unlock_irqrestore(&dev->lock, flags);
+ /* Release the lock */
+ spin_unlock_irqrestore(&pdata->dev_lock, flags);
return IRQ_HANDLED;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
+
/*
+ * ----------------------------------------------------------------------
+ * appnic_poll_controller
+ *
* Polling receive - used by netconsole and other diagnostic tools
* to allow network i/o with interrupts disabled.
*/
-static void
-appnic_poll_controller(struct net_device *dev)
+
+static void appnic_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
appnic_isr(dev->irq, dev);
@@ -1752,6 +1050,7 @@ appnic_poll_controller(struct net_device *dev)
#endif
+
/*
* ----------------------------------------------------------------------
* appnic_open
@@ -1762,60 +1061,35 @@ appnic_poll_controller(struct net_device *dev)
* increment the module usage count.
*/
-int appnic_open(struct net_device *device)
+static int appnic_open(struct net_device *dev)
{
+ struct appnic_device *pdata = netdev_priv(dev);
int return_code = 0;
- /* Enable the receiver and transmitter. */
- if (0 != enable_rx_tx(device)) {
- pr_err("acp-femac: Unable to enable the appnic interface.\n");
- disable_rx_tx();
- return -EBUSY;
- }
+ /* Bring the PHY up */
+ phy_start(pdata->phy_dev);
-#ifdef LSINET_NAPI
- {
- struct appnic_device *adapter = netdev_priv(device);
- napi_enable(&adapter->napi);
- }
-#endif /* LSINET_NAPI */
+ /* Enable NAPI */
+ napi_enable(&pdata->napi);
- /* Install the interrupt handlers. */
- return_code = request_irq(device->irq, appnic_isr, IRQF_DISABLED,
- APPNIC_NAME, device);
+ /* Install the interrupt handlers */
+ return_code = request_irq(dev->irq, appnic_isr, IRQF_DISABLED,
+ LSI_DRV_NAME, dev);
if (0 != return_code) {
- pr_err("acp-femac: request_irq() failed, returned 0x%x/%d\n",
- return_code, return_code);
+ pr_err("%s: request_irq() failed, returned 0x%x/%d\n",
+ LSI_DRV_NAME, return_code, return_code);
return return_code;
}
- /* enable interrupts */
+ /* Enable interrupts */
write_mac((APPNIC_DMA_INTERRUPT_ENABLE_RECEIVE |
APPNIC_DMA_INTERRUPT_ENABLE_TRANSMIT),
APPNIC_DMA_INTERRUPT_ENABLE);
- {
-#ifndef PHYLESS
- struct appnic_device *dev = netdev_priv(device);
-#endif
-
-#ifndef PHYLESS
-
- init_timer(&appnic_timer);
- appnic_timer.expires = jiffies + (APPNIC_TIMER_PERIOD * HZ);
- appnic_timer.data = (unsigned long) device;
- appnic_timer.function = appnic_timer_handler;
- add_timer(&appnic_timer);
- dev->polling = 1;
-
-#endif /* PHYLESS */
+ /* Let the OS know we are ready to send packets */
+ netif_start_queue(dev);
- }
-
- /* let the OS know we are ready to send packets */
- netif_start_queue(device);
-
- /* that's all */
+ /* That's all */
return 0;
}
@@ -1827,50 +1101,29 @@ int appnic_open(struct net_device *device)
* down; operations performed at open time should be reversed.
*/
-int appnic_stop(struct net_device *device)
+static int appnic_stop(struct net_device *dev)
{
- int return_code = 0;
-
- pr_info("acp-femac: Stopping the interface.\n");
+ struct appnic_device *pdata = netdev_priv(dev);
- /*
- * Indicate to the OS that no more packets should be sent.
- */
+ pr_info("%s: Stopping the interface.\n", LSI_DRV_NAME);
- netif_stop_queue(device);
+ /* Disable all device interrupts */
+ write_mac(0, APPNIC_DMA_INTERRUPT_ENABLE);
+ free_irq(dev->irq, dev);
- /*
- * Stop the receiver and transmitter.
- */
+ /* Indicate to the OS that no more packets should be sent. */
+ netif_stop_queue(dev);
+ napi_disable(&pdata->napi);
+ /* Stop the receiver and transmitter. */
disable_rx_tx();
- /* Disable NAPI. */
-#ifdef LSINET_NAPI
- {
- struct appnic_device *adapter = netdev_priv(device);
- napi_disable(&adapter->napi);
- }
-#endif
-
- /*
- * Free the interrupts.
- */
-
- free_irq(device->irq, device);
-
-#ifndef PHYLESS
-
- del_timer(&appnic_timer);
-
-#endif /* PHYLESS */
-
- /*
- * That's all.
- */
-
- return return_code;
+ /* Bring the PHY down. */
+ if (pdata->phy_dev)
+ phy_stop(pdata->phy_dev);
+ /* That's all. */
+ return 0;
}
/*
@@ -1886,37 +1139,36 @@ int appnic_stop(struct net_device *device)
* 1) This will not get called again by the kernel until it returns.
*/
-int
-appnic_hard_start_xmit(struct sk_buff *skb,
- struct net_device *device)
+static int appnic_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
- struct appnic_device *adapter = netdev_priv(device);
+ struct appnic_device *pdata = netdev_priv(dev);
int length;
int buf_per_desc;
length = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
- buf_per_desc = adapter->tx_buf_sz / adapter->tx_num_desc;
+ buf_per_desc = pdata->tx_buf_sz / pdata->tx_num_desc;
/*
* If enough transmit descriptors are available, copy and transmit.
*/
while (((length / buf_per_desc) + 1) >=
- queue_uninitialized(adapter->tx_head,
- SWAB_QUEUE_POINTER(adapter->tx_tail),
- adapter->tx_num_desc)) {
- handle_transmit_interrupt(device);
+ queue_uninitialized(pdata->tx_head,
+ SWAB_QUEUE_POINTER(pdata->tx_tail),
+ pdata->tx_num_desc)) {
+ handle_transmit_interrupt(dev);
}
if (((length / buf_per_desc) + 1) <
- queue_uninitialized(adapter->tx_head,
- SWAB_QUEUE_POINTER(adapter->tx_tail),
- adapter->tx_num_desc)) {
+ queue_uninitialized(pdata->tx_head,
+ SWAB_QUEUE_POINTER(pdata->tx_tail),
+ pdata->tx_num_desc)) {
int bytes_copied = 0;
struct appnic_dma_descriptor descriptor;
- readdescriptor(((unsigned long) adapter->tx_desc +
- adapter->tx_head.bits.offset), &descriptor);
+ readdescriptor(((unsigned long)pdata->tx_desc +
+ pdata->tx_head.bits.offset), &descriptor);
descriptor.start_of_packet = 1;
while (bytes_copied < length) {
@@ -1926,7 +1178,7 @@ appnic_hard_start_xmit(struct sk_buff *skb,
if ((length - bytes_copied) > buf_per_desc) {
memcpy((void *)
(descriptor.host_data_memory_pointer +
- adapter->dma_alloc_offset),
+ pdata->dma_alloc_offset_tx),
(void *) ((unsigned long) skb->data +
bytes_copied),
buf_per_desc);
@@ -1937,36 +1189,37 @@ appnic_hard_start_xmit(struct sk_buff *skb,
} else {
memcpy((void *)
(descriptor.host_data_memory_pointer +
- adapter->dma_alloc_offset),
+ pdata->dma_alloc_offset_tx),
(void *) ((unsigned long) skb->data +
bytes_copied),
(length - bytes_copied));
descriptor.data_transfer_length =
(length - bytes_copied);
descriptor.end_of_packet = 1;
-#ifdef DISABLE_TX_INTERRUPTS
+#ifdef CONFIG_DISABLE_TX_INTERRUPTS
descriptor.interrupt_on_completion = 0;
-#else /* DISABLE_TX_INTERRUPTS */
+#else
descriptor.interrupt_on_completion = 1;
-#endif /* DISABLE_TX_INTERRUPTS */
+#endif
bytes_copied = length;
}
- adapter->stats.tx_bytes += bytes_copied;
- writedescriptor(((unsigned long) adapter->tx_desc +
- adapter->tx_head.bits.offset), &descriptor);
- queue_increment(&adapter->tx_head,
- adapter->tx_num_desc);
- readdescriptor(((unsigned long) adapter->tx_desc +
- adapter->tx_head.bits.offset), &descriptor);
+ pdata->stats.tx_bytes += bytes_copied;
+ writedescriptor(((unsigned long) pdata->tx_desc +
+ pdata->tx_head.bits.offset), &descriptor);
+ queue_increment(&pdata->tx_head, pdata->tx_num_desc);
+ readdescriptor(((unsigned long)pdata->tx_desc +
+ pdata->tx_head.bits.offset),
+ &descriptor);
descriptor.start_of_packet = 0;
}
- write_mac(adapter->tx_head.raw, APPNIC_DMA_TX_HEAD_POINTER);
- device->trans_start = jiffies;
+ write_mac(pdata->tx_head.raw, APPNIC_DMA_TX_HEAD_POINTER);
+ dev->trans_start = jiffies;
} else {
++out_of_tx_descriptors;
- pr_err("acp-femac: No transmit descriptors available!\n");
+ pr_err("%s: No transmit descriptors available!\n",
+ LSI_DRV_NAME);
}
/* Free the socket buffer */
@@ -1984,21 +1237,21 @@ appnic_hard_start_xmit(struct sk_buff *skb,
* nstat -i is run.
*/
-struct net_device_stats *appnic_get_stats(struct net_device *device)
+static struct net_device_stats *appnic_get_stats(struct net_device *dev)
{
- struct appnic_device *dev = netdev_priv(device);
+ struct appnic_device *pdata = netdev_priv(dev);
/*
* Update the statistics structure.
*/
- get_hw_statistics(dev);
+ get_hw_statistics(pdata);
/*
* That's all.
*/
- return &dev->stats;
+ return &pdata->stats;
}
/*
@@ -2006,17 +1259,16 @@ struct net_device_stats *appnic_get_stats(struct net_device *device)
* appnic_set_mac_address
*/
-static int
-appnic_set_mac_address(struct net_device *device, void *data)
+static int appnic_set_mac_address(struct net_device *dev, void *data)
{
struct sockaddr *address = data;
unsigned long swap_source_address;
- if (netif_running(device))
+ if (netif_running(dev))
return -EBUSY;
- memcpy(device->dev_addr, address->sa_data, 6);
- memcpy(device->perm_addr, address->sa_data, 6);
+ memcpy(dev->dev_addr, address->sa_data, 6);
+ memcpy(dev->perm_addr, address->sa_data, 6);
swap_source_address = ((address->sa_data[4]) << 8) |
address->sa_data[5];
@@ -2027,113 +1279,44 @@ appnic_set_mac_address(struct net_device *device, void *data)
swap_source_address = ((address->sa_data[0]) << 8) |
address->sa_data[1];
write_mac(swap_source_address, APPNIC_SWAP_SOURCE_ADDRESS_0);
- memcpy(device->dev_addr, address->sa_data, device->addr_len);
+ memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
return 0;
}
/*
======================================================================
- ======================================================================
- ======================================================================
-
ETHTOOL Operations
-
- ======================================================================
- ======================================================================
======================================================================
*/
/*
* ----------------------------------------------------------------------
- * appnic_get_settings
+ * appnic_get_drvinfo
*/
-static int
-appnic_get_settings(struct net_device *device, struct ethtool_cmd *command)
+static void appnic_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
{
- struct appnic_device *dev = netdev_priv(device);
- unsigned short ad_value;
- int speed;
- int duplex;
-
- memset(command, 0, sizeof(struct ethtool_cmd));
-
- /* What the hardware supports. */
-
- command->supported = (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full);
-
-#ifndef PHYLESS
-
- /* What is currently advertised. */
-
- if (0 != phy_read(dev->phy_address,
- PHY_AUTONEG_ADVERTISE,
- &ad_value)) {
- pr_err("acp-femac: PHY read failed!\n");
- return -EIO;
- }
-
- switch (ad_value) {
- case 0x1e1:
- command->advertising = (ADVERTISED_100baseT_Full |
- ADVERTISED_100baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_10baseT_Half);
- break;
-
- case 0xe1:
- command->advertising = (ADVERTISED_100baseT_Half |
- ADVERTISED_10baseT_Full |
- ADVERTISED_10baseT_Half);
- break;
-
- case 0x61:
- command->advertising = (ADVERTISED_10baseT_Full |
- ADVERTISED_10baseT_Half);
- break;
-
- case 0x41:
- default:
- command->advertising = (ADVERTISED_10baseT_Half);
- break;
- }
-
- /* The current speed. */
-
- speed = phy_speed(dev->phy_address);
- if (-1 == speed) {
- pr_err("acp-femac: PHY read failed!\n");
- return -EIO;
- } else if (1 == speed) {
- command->speed = SPEED_100;
- } else {
- command->speed = SPEED_10;
- }
-
- /* Is the current link duplex? */
-
+ strcpy(info->driver, LSI_DRV_NAME);
+ strcpy(info->version, LSI_DRV_VERSION);
+}
- duplex = phy_duplex(dev->phy_address);
- if (-1 == duplex) {
- pr_err("acp-femac: PHY read failed!\n");
- return -EIO;
- } else if (1 == duplex) {
- command->duplex = DUPLEX_FULL;
- } else {
- command->duplex = DUPLEX_HALF;
- }
+/*
+ * ----------------------------------------------------------------------
+ * appnic_get_settings
+ */
-#endif /* PHYLESS */
+static int appnic_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct appnic_device *pdata = netdev_priv(dev);
+ struct phy_device *phydev = pdata->phy_dev;
- /* Is autoneg enabled? */
- command->autoneg = AUTONEG_ENABLE;
+ if (!phydev)
+ return -ENODEV;
- /* Return success. */
- return 0;
+ return phy_ethtool_gset(phydev, cmd);
}
/*
@@ -2141,19 +1324,14 @@ appnic_get_settings(struct net_device *device, struct ethtool_cmd *command)
*/
static const struct ethtool_ops appnic_ethtool_ops = {
+ .get_drvinfo = appnic_get_drvinfo,
.get_settings = appnic_get_settings
};
/*
======================================================================
- ======================================================================
- ======================================================================
-
Linux Module Interface.
-
- ======================================================================
- ======================================================================
======================================================================
*/
@@ -2166,6 +1344,7 @@ static const struct net_device_ops appnic_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = appnic_poll_controller,
#endif
+
};
/*
@@ -2173,14 +1352,14 @@ static const struct net_device_ops appnic_netdev_ops = {
* appnic_init
*/
-int
-appnic_init(struct net_device *device)
+int appnic_init(struct net_device *dev)
{
- struct appnic_device *adapter = netdev_priv(device);
+ struct appnic_device *pdata = netdev_priv(dev);
void *dma_offset;
int index;
unsigned long buf;
struct appnic_dma_descriptor descriptor;
+ struct sockaddr address;
/*
* Reset the MAC
@@ -2198,22 +1377,22 @@ appnic_init(struct net_device *device)
*/
if (0 != (rx_num_desc % DESCRIPTOR_GRANULARITY)) {
- pr_warn("acp-femac: rx_num_desc was not a multiple of %d.\n",
- 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);
}
- adapter->rx_num_desc = rx_num_desc;
+ pdata->rx_num_desc = rx_num_desc;
if (0 != (tx_num_desc % DESCRIPTOR_GRANULARITY)) {
- pr_warn("acp-femac: tx_num_desc was not a multiple of %d.\n",
- 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);
}
- adapter->tx_num_desc = tx_num_desc;
+ pdata->tx_num_desc = tx_num_desc;
/*
* up [rt]x_buf_sz. Must be some multiple of 64 bytes
@@ -2221,178 +1400,205 @@ appnic_init(struct net_device *device)
*/
if (0 != (rx_buf_sz % (BUFFER_ALIGNMENT * rx_num_desc))) {
- pr_warn("acp-femac: rx_buf_sz was not a multiple of %d.\n",
- (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));
}
- adapter->rx_buf_sz = rx_buf_sz;
+ pdata->rx_buf_sz = rx_buf_sz;
if (0 != (tx_buf_sz % (BUFFER_ALIGNMENT * tx_num_desc))) {
- pr_warn("acp-femac: tx_buf_sz was not a multiple of %d.\n",
- (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));
}
- adapter->tx_buf_sz = tx_buf_sz;
+ pdata->tx_buf_sz = tx_buf_sz;
/*
- * Allocate dma-able memory
+ * Allocate dma-able memory. Broken into smaller parts to keep
+ * from allocating a single large chunk of memory, but not too
+ * small since mappings obtained from dma_alloc_coherent() have
+ * a minimum size of one page.
*/
- adapter->dma_alloc_size =
+ pdata->dma_alloc_size =
/* The tail pointers (rx and tx) */
(sizeof(union appnic_queue_pointer) * 2) +
/* The RX descriptor ring (and padding to allow
* 64 byte alignment) */
- (sizeof(struct appnic_dma_descriptor) * adapter->rx_num_desc) +
+ (sizeof(struct appnic_dma_descriptor) * pdata->rx_num_desc) +
(DESCRIPTOR_GRANULARITY) +
/* The TX descriptor ring (and padding...) */
- (sizeof(struct appnic_dma_descriptor) * adapter->tx_num_desc) +
- (DESCRIPTOR_GRANULARITY) +
- /* The RX buffer (and padding...) */
- (adapter->rx_buf_sz) + (BUFFER_ALIGNMENT) +
- /* The TX buffer (and padding...) */
- (adapter->tx_buf_sz) + (BUFFER_ALIGNMENT);
+ (sizeof(struct appnic_dma_descriptor) * pdata->tx_num_desc) +
+ (DESCRIPTOR_GRANULARITY);
-#ifdef DMA_CACHABLE
-
- adapter->dma_alloc = kmalloc(adapter->dma_alloc_size, GFP_KERNEL);
+ pdata->dma_alloc_size_rx =
+ /* The RX buffer (and padding...) */
+ (pdata->rx_buf_sz) + (BUFFER_ALIGNMENT);
- if ((void *)0 == adapter->dma_alloc) {
- pr_err("Could not allocate %d bytes of DMA-able memory!\n",
- adapter->dma_alloc_size);
- kfree(adapter);
- return -ENOMEM;
- }
+ pdata->dma_alloc_size_tx =
+ /* The TX buffer (and padding...) */
+ (pdata->tx_buf_sz) + (BUFFER_ALIGNMENT);
- adapter->dma_alloc_dma = virt_to_phys(adapter->dma_alloc);
-#else
/*
* This needs to be set to something sane for
* dma_alloc_coherent()
*/
- device->dev.archdata.dma_ops = &dma_direct_ops;
+ dev->dev.archdata.dma_ops = &dma_direct_ops;
- adapter->dma_alloc = (void *) dma_alloc_coherent(&device->dev,
- adapter->dma_alloc_size,
- &adapter->dma_alloc_dma,
- GFP_KERNEL);
+ pdata->dma_alloc = (void *)dma_alloc_coherent(&dev->dev,
+ pdata->dma_alloc_size,
+ &pdata->dma_alloc_dma,
+ GFP_KERNEL);
- if ((void *) 0 == adapter->dma_alloc) {
- pr_err("Could not allocate %d bytes of DMA-able memory!\n",
- adapter->dma_alloc_size);
- kfree(adapter);
+ if ((void *)0 == pdata->dma_alloc) {
+ pr_err("%s: Could not allocate %d bytes of DMA-able memory!\n",
+ LSI_DRV_NAME, pdata->dma_alloc_size);
+ kfree(pdata);
return -ENOMEM;
}
-#endif
- adapter->dma_alloc_offset = (int)adapter->dma_alloc -
- (int)adapter->dma_alloc_dma;
- dma_offset = adapter->dma_alloc;
+ pdata->dma_alloc_offset = (int)pdata->dma_alloc -
+ (int)pdata->dma_alloc_dma;
+
+ pdata->dma_alloc_rx = (void *)dma_alloc_coherent(&dev->dev,
+ pdata->dma_alloc_size_rx,
+ &pdata->dma_alloc_dma_rx,
+ GFP_KERNEL);
+
+ if ((void *)0 == pdata->dma_alloc_rx) {
+ pr_err("%s: Could not allocate %d bytes of 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;
+ }
+
+ pdata->dma_alloc_offset_rx = (int)pdata->dma_alloc_rx -
+ (int)pdata->dma_alloc_dma_rx;
+
+ pdata->dma_alloc_tx = (void *)dma_alloc_coherent(&dev->dev,
+ pdata->dma_alloc_size_tx,
+ &pdata->dma_alloc_dma_tx,
+ GFP_KERNEL);
+
+ if ((void *)0 == pdata->dma_alloc_tx) {
+ pr_err("%s: Could not allocate %d bytes of 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
*/
- adapter->rx_tail = (union appnic_queue_pointer *)dma_offset;
- adapter->rx_tail_dma = (int)adapter->rx_tail -
- (int)adapter->dma_alloc_offset;
- dma_offset += sizeof(union appnic_queue_pointer);
- memset((void *) adapter->rx_tail, 0,
+ dma_offset = pdata->dma_alloc;
+
+ pdata->rx_tail = (union appnic_queue_pointer *)dma_offset;
+ pdata->rx_tail_dma = (int)pdata->rx_tail - (int)pdata->dma_alloc_offset;
+ memset((void *)pdata->rx_tail, 0,
sizeof(union appnic_queue_pointer));
- adapter->tx_tail = (union appnic_queue_pointer *)dma_offset;
- adapter->tx_tail_dma = (int)adapter->tx_tail -
- (int)adapter->dma_alloc_offset;
dma_offset += sizeof(union appnic_queue_pointer);
- memset((void *)adapter->tx_tail, 0,
- sizeof(union appnic_queue_pointer));
+
+ pdata->tx_tail = (union appnic_queue_pointer *)dma_offset;
+ pdata->tx_tail_dma = (int)pdata->tx_tail - (int)pdata->dma_alloc_offset;
+ memset((void *)pdata->tx_tail, 0, sizeof(union appnic_queue_pointer));
+
+ dma_offset += sizeof(union appnic_queue_pointer);
/*
* Initialize the descriptor pointers
*/
- adapter->rx_desc = (struct appnic_dma_descriptor *)ALIGN64B(dma_offset);
- adapter->rx_desc_dma = (int)adapter->rx_desc -
- (int)adapter->dma_alloc_offset;
- dma_offset += (sizeof(struct appnic_dma_descriptor) *
- adapter->rx_num_desc) + (DESCRIPTOR_GRANULARITY);
- memset((void *)adapter->rx_desc, 0,
- (sizeof(struct appnic_dma_descriptor) * adapter->rx_num_desc));
+ pdata->rx_desc = (struct appnic_dma_descriptor *)ALIGN64B(dma_offset);
+ pdata->rx_desc_dma = (int)pdata->rx_desc - (int)pdata->dma_alloc_offset;
+ memset((void *)pdata->rx_desc, 0,
+ (sizeof(struct appnic_dma_descriptor) * pdata->rx_num_desc));
- adapter->tx_desc = (struct appnic_dma_descriptor *)ALIGN64B(dma_offset);
- adapter->tx_desc_dma = (int)adapter->tx_desc -
- (int)adapter->dma_alloc_offset;
dma_offset += (sizeof(struct appnic_dma_descriptor) *
- adapter->tx_num_desc) + (DESCRIPTOR_GRANULARITY);
- memset((void *)adapter->tx_desc, 0,
- (sizeof(struct appnic_dma_descriptor) * adapter->tx_num_desc));
+ pdata->rx_num_desc) + (DESCRIPTOR_GRANULARITY);
+
+ pdata->tx_desc = (struct appnic_dma_descriptor *)ALIGN64B(dma_offset);
+ pdata->tx_desc_dma = (int)pdata->tx_desc - (int)pdata->dma_alloc_offset;
+ memset((void *)pdata->tx_desc, 0,
+ (sizeof(struct appnic_dma_descriptor) * pdata->tx_num_desc));
/*
* Initialize the buffer pointers
*/
- adapter->rx_buf = (void *)ALIGN64B(dma_offset);
- adapter->rx_buf_dma = (int)adapter->rx_buf -
- (int)adapter->dma_alloc_offset;
- adapter->rx_buf_per_desc = adapter->rx_buf_sz / adapter->rx_num_desc;
+ dma_offset = pdata->dma_alloc_rx;
+
+ pdata->rx_buf = (void *)ALIGN64B(dma_offset);
+ pdata->rx_buf_dma = (int)pdata->rx_buf -
+ (int)pdata->dma_alloc_offset_rx;
+ pdata->rx_buf_per_desc = pdata->rx_buf_sz / pdata->rx_num_desc;
- dma_offset += (adapter->rx_buf_sz) + (BUFFER_ALIGNMENT);
+ dma_offset = pdata->dma_alloc_tx;
- adapter->tx_buf = (void *)ALIGN64B(dma_offset);
- adapter->tx_buf_dma = (int)adapter->tx_buf -
- (int)adapter->dma_alloc_offset;
- adapter->tx_buf_per_desc =
- adapter->tx_buf_sz / adapter->tx_num_desc;
- dma_offset += (adapter->tx_buf_sz) + (BUFFER_ALIGNMENT);
+ pdata->tx_buf = (void *)ALIGN64B(dma_offset);
+ pdata->tx_buf_dma = (int)pdata->tx_buf -
+ (int)pdata->dma_alloc_offset_tx;
+ pdata->tx_buf_per_desc = pdata->tx_buf_sz / pdata->tx_num_desc;
/*
* Initialize the descriptors
*/
- buf = (unsigned long) adapter->rx_buf_dma;
- for (index = 0; index < adapter->rx_num_desc; ++index) {
+ buf = (unsigned long)pdata->rx_buf_dma;
+ for (index = 0; index < pdata->rx_num_desc; ++index) {
memset((void *) &descriptor, 0,
sizeof(struct appnic_dma_descriptor));
descriptor.write = 1;
descriptor.interrupt_on_completion = 1;
descriptor.host_data_memory_pointer = buf;
- descriptor.data_transfer_length = adapter->rx_buf_per_desc;
+ descriptor.data_transfer_length = pdata->rx_buf_per_desc;
- writedescriptor(((unsigned long)adapter->rx_desc + (index *
+ writedescriptor(((unsigned long)pdata->rx_desc + (index *
sizeof(struct appnic_dma_descriptor))),
&descriptor);
- buf += adapter->rx_buf_per_desc;
+ buf += pdata->rx_buf_per_desc;
}
- buf = (unsigned long)adapter->tx_buf_dma;
+ buf = (unsigned long)pdata->tx_buf_dma;
- for (index = 0; index < adapter->tx_num_desc; ++index) {
+ for (index = 0; index < pdata->tx_num_desc; ++index) {
memset((void *) &descriptor, 0,
sizeof(struct appnic_dma_descriptor));
descriptor.write = 1;
descriptor.interrupt_on_completion = 1;
descriptor.host_data_memory_pointer = buf;
- writedescriptor(((unsigned long)adapter->tx_desc + (index *
+ writedescriptor(((unsigned long)pdata->tx_desc + (index *
sizeof(struct appnic_dma_descriptor))),
&descriptor);
- buf += adapter->tx_buf_per_desc;
+ buf += pdata->tx_buf_per_desc;
}
/*
* Initialize the spinlocks.
*/
- spin_lock_init(&adapter->lock);
- spin_lock_init(&adapter->extra_lock);
+ spin_lock_init(&pdata->mdio_lock);
+ spin_lock_init(&pdata->dev_lock);
+ spin_lock_init(&pdata->extra_lock);
/*
* Take MAC out of reset
@@ -2414,19 +1620,15 @@ appnic_init(struct net_device *device)
write_mac(0x1, APPNIC_RX_EXTERNAL_INTERRUPT_CONTROL);
write_mac(0x40010000, APPNIC_DMA_PCI_CONTROL);
write_mac(0x30000, APPNIC_DMA_CONTROL);
- writeio(0x280044, dma_base + 0x60);
- writeio(0xc0, dma_base + 0x64);
+ out_le32(dma_base + 0x60, 0x280044);
+ out_le32(dma_base + 0x64, 0xc0);
/*
* Set the MAC address
*/
- {
- struct sockaddr address;
-
- memcpy(&(address.sa_data[0]), device->dev_addr, 6);
- appnic_set_mac_address(device, &address);
- }
+ memcpy(&(address.sa_data[0]), dev->dev_addr, 6);
+ appnic_set_mac_address(dev, &address);
/*
* Initialize the queue pointers.
@@ -2436,13 +1638,13 @@ appnic_init(struct net_device *device)
* Receiver
*/
- memset((void *) &adapter->rx_tail_copy,
- 0, sizeof(union appnic_queue_pointer));
- memset((void *) &adapter->rx_head,
- 0, sizeof(union appnic_queue_pointer));
+ memset((void *)&pdata->rx_tail_copy, 0,
+ sizeof(union appnic_queue_pointer));
+ memset((void *)&pdata->rx_head, 0,
+ sizeof(union appnic_queue_pointer));
- write_mac(adapter->rx_desc_dma, APPNIC_DMA_RX_QUEUE_BASE_ADDRESS);
- write_mac((adapter->rx_num_desc *
+ write_mac(pdata->rx_desc_dma, APPNIC_DMA_RX_QUEUE_BASE_ADDRESS);
+ write_mac((pdata->rx_num_desc *
sizeof(struct appnic_dma_descriptor)) / 1024,
APPNIC_DMA_RX_QUEUE_SIZE);
@@ -2451,9 +1653,9 @@ appnic_init(struct net_device *device)
* are ready
*/
- adapter->rx_head.bits.offset = (adapter->rx_num_desc - 1) *
+ pdata->rx_head.bits.offset = (pdata->rx_num_desc - 1) *
sizeof(struct appnic_dma_descriptor);
- write_mac(adapter->rx_tail_dma, APPNIC_DMA_RX_TAIL_POINTER_ADDRESS);
+ write_mac(pdata->rx_tail_dma, APPNIC_DMA_RX_TAIL_POINTER_ADDRESS);
/*
* N.B.
@@ -2463,29 +1665,29 @@ appnic_init(struct net_device *device)
* local copy of the tail) based on it.
*/
- adapter->rx_tail->raw =
+ pdata->rx_tail->raw =
read_mac(APPNIC_DMA_RX_TAIL_POINTER_LOCAL_COPY);
- adapter->rx_tail_copy.raw = adapter->rx_tail->raw;
- adapter->rx_head.raw = adapter->rx_tail->raw;
- queue_decrement(&adapter->rx_head, adapter->rx_num_desc);
- adapter->rx_head.bits.generation_bit =
- (0 == adapter->rx_head.bits.generation_bit) ? 1 : 0;
- write_mac(adapter->rx_head.raw, APPNIC_DMA_RX_HEAD_POINTER);
+ pdata->rx_tail_copy.raw = pdata->rx_tail->raw;
+ pdata->rx_head.raw = pdata->rx_tail->raw;
+ queue_decrement(&pdata->rx_head, pdata->rx_num_desc);
+ pdata->rx_head.bits.generation_bit =
+ (0 == pdata->rx_head.bits.generation_bit) ? 1 : 0;
+ write_mac(pdata->rx_head.raw, APPNIC_DMA_RX_HEAD_POINTER);
/*
* Transmitter
*/
- memset((void *) &adapter->tx_tail_copy,
- 0, sizeof(union appnic_queue_pointer));
- memset((void *) &adapter->tx_head,
- 0, sizeof(union appnic_queue_pointer));
+ memset((void *) &pdata->tx_tail_copy, 0,
+ sizeof(union appnic_queue_pointer));
+ memset((void *) &pdata->tx_head, 0,
+ sizeof(union appnic_queue_pointer));
- write_mac(adapter->tx_desc_dma, APPNIC_DMA_TX_QUEUE_BASE_ADDRESS);
- write_mac((adapter->tx_num_desc *
+ write_mac(pdata->tx_desc_dma, APPNIC_DMA_TX_QUEUE_BASE_ADDRESS);
+ write_mac((pdata->tx_num_desc *
sizeof(struct appnic_dma_descriptor)) / 1024,
APPNIC_DMA_TX_QUEUE_SIZE);
- write_mac(adapter->tx_tail_dma, APPNIC_DMA_TX_TAIL_POINTER_ADDRESS);
+ write_mac(pdata->tx_tail_dma, APPNIC_DMA_TX_TAIL_POINTER_ADDRESS);
/*
* N.B.
@@ -2495,44 +1697,36 @@ appnic_init(struct net_device *device)
* local copy of the tail) based on it.
*/
- adapter->tx_tail->raw =
- read_mac(APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY);
- adapter->tx_tail_copy.raw = adapter->tx_tail->raw;
- adapter->tx_head.raw = adapter->tx_tail->raw;
- write_mac(adapter->tx_head.raw, APPNIC_DMA_TX_HEAD_POINTER);
+ 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(adapter);
- /* Initialize the PHY */
-#ifndef PHYLESS
- if (0 != phy_enable(device))
- pr_warn("acp-femac: Failed to initialize the PHY!\n");
-#endif /* PHYLESS */
+ clear_statistics(pdata);
/* Fill in the net_device structure */
- ether_setup(device);
- device->irq = irq_create_mapping(NULL, 33);
- if (NO_IRQ == device) {
- pr_err("acp-femac: irq_create_mapping() failed\n");
+ ether_setup(dev);
+ dev->irq = irq_create_mapping(NULL, pdata->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(device->irq, IRQ_TYPE_LEVEL_HIGH)) {
- pr_err("acp-femac: set_irq_type() failed\n");
+ 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;
}
- device->netdev_ops = &appnic_netdev_ops;
+ dev->netdev_ops = &appnic_netdev_ops;
- SET_ETHTOOL_OPS(device, &appnic_ethtool_ops);
-#ifdef LSINET_NAPI
- memset((void *) &adapter->napi, 0, sizeof(struct napi_struct));
- netif_napi_add(device, &adapter->napi,
+ 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);
- adapter->device = device;
-#endif
+ pdata->device = dev;
/* That's all */
return 0;
@@ -2557,153 +1751,171 @@ appnic_read_proc(char *page, char **start, off_t offset,
/*
* ----------------------------------------------------------------------
- * lsinet_init
+ * appnic_probe_config_dt
*/
-int
-lsinet_init(void)
+#ifdef CONFIG_OF
+static int __devinit appnic_probe_config_dt(struct net_device *dev,
+ struct device_node *np)
{
- int rc = 0;
- struct net_device *device;
- struct device_node *np = NULL;
+ struct appnic_device *pdata = netdev_priv(dev);
const u32 *field;
- struct appnic_device *appnic_device;
- unsigned char uboot_env_string[40];
-
- /* Allocate space for the device. */
-
- device = alloc_etherdev(sizeof(struct appnic_device));
- if ((struct net_device *)0 == device) {
- pr_err("acp-femac: Couldn't allocate net device.\n");
- rc = -ENOMEM;
- goto out;
- }
-
- this_net_device = device; /* For /proc/reads. */
- appnic_device = netdev_priv(device);
+ u64 value64;
+ u32 value32;
+ int length;
- /*
- * Get the physical addresses, interrupt number, etc. from the
- * device tree. If no entry exists (older boot loader...) just
- * use the pre-devicetree method.
- */
+ if (!np)
+ return -ENODEV;
- np = of_find_node_by_type(np, "network");
+ field = of_get_property(np, "reg", NULL);
- while (np && !of_device_is_compatible(np, "acp-femac"))
- np = of_find_node_by_type(np, "network");
+ if (!field) {
+ pr_err("%s: Couldn't get \"reg\" property.", LSI_DRV_NAME);
+ return -EINVAL;
+ }
- if (np) {
- u64 value64;
- u32 value32;
- int length;
+ value64 = of_translate_address(np, field);
+ value32 = field[1];
+ field += 2;
+ rx_base = ioremap(value64, value32);
+ pdata->rx_base = (unsigned long)rx_base;
+ value64 = of_translate_address(np, field);
+ value32 = field[1];
+ field += 2;
+ tx_base = ioremap(value64, value32);
+ pdata->tx_base = (unsigned long)tx_base;
+ value64 = of_translate_address(np, field);
+ value32 = field[1];
+ field += 2;
+ dma_base = ioremap(value64, value32);
+ pdata->dma_base = (unsigned long)dma_base;
+
+ field = of_get_property(np, "interrupts", NULL);
+ if (!field)
+ goto device_tree_failed;
+ else
+ pdata->interrupt = field[0];
- field = of_get_property(np, "enabled", NULL);
+ field = of_get_property(np, "mdio-clock", NULL);
+ if (!field)
+ goto device_tree_failed;
+ else
+ pdata->mdio_clock = field[0];
- if (!field || (field && (0 == *field))) {
- pr_err("acp-femac: Not Enabled\n");
- rc = -EINVAL;
- goto out;
- }
+ field = of_get_property(np, "mdio-reg", NULL);
+ if (!field) {
+ goto device_tree_failed;
+ } else {
+ value64 = of_translate_address(np, field);
+ value32 = field[1];
+ pdata->mdio_base = (unsigned long)ioremap(value64, value32);
+ }
- field = of_get_property(np, "reg", NULL);
+ field = of_get_property(np, "phy-address", NULL);
+ if (!field)
+ goto device_tree_failed;
+ else
+ pdata->phy_address = field[0];
- if (!field) {
- pr_err("acp-femac: Couldn't get \"reg\" property.\n");
- rc = -EINVAL;
- goto out;
- }
+ field = of_get_property(np, "ad-value", NULL);
+ if (!field)
+ goto device_tree_failed;
+ else
+ pdata->ad_value = field[0];
- value64 = of_translate_address(np, field);
- value32 = field[1];
- field += 2;
- rx_base = ioremap(value64, value32);
- appnic_device->rx_base = (unsigned long)rx_base;
- value64 = of_translate_address(np, field);
- value32 = field[1];
- field += 2;
- tx_base = ioremap(value64, value32);
- appnic_device->tx_base = (unsigned long)tx_base;
- value64 = of_translate_address(np, field);
- value32 = field[1];
- field += 2;
- dma_base = ioremap(value64, value32);
- appnic_device->dma_base = (unsigned long)dma_base;
+ field = of_get_property(np, "mac-address", &length);
+ if (!field || 6 != length) {
+ goto device_tree_failed;
+ } else {
+ int i;
+ u8 *value;
- field = of_get_property(np, "interrupts", NULL);
+ value = (u8 *)field;
- if (!field)
- goto device_tree_failed;
- else
- appnic_device->interrupt = field[0];
+ for (i = 0; i < 6; ++i)
+ pdata->mac_addr[i] = value[i];
+ }
- field = of_get_property(np, "mdio-clock", NULL);
+ memcpy(dev->dev_addr, &pdata->mac_addr[0], 6);
+ memcpy(dev->perm_addr, &pdata->mac_addr[0], 6);
- if (!field)
- goto device_tree_failed;
- else
- appnic_device->mdio_clock = field[0];
+ return 0;
- field = of_get_property(np, "phy-address", NULL);
+device_tree_failed:
+ pr_err("%s: Reading Device Tree Failed\n", LSI_DRV_NAME);
+ iounmap(rx_base);
+ iounmap(tx_base);
+ iounmap(dma_base);
+ return -EINVAL;
+}
+#else
+static inline int appnic_probe_config_dt(struct net_device *dev,
+ struct device_node *np)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_OF */
- if (!field)
- goto device_tree_failed;
- else
- appnic_device->phy_address = field[0];
+/*
+ * ----------------------------------------------------------------------
+ * appnic_drv_probe
+ */
- field = of_get_property(np, "ad-value", NULL);
+static int __devinit appnic_drv_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ struct device_node *np = pdev->dev.of_node;
+ struct net_device *dev;
+ struct appnic_device *pdata;
- if (!field)
- goto device_tree_failed;
- else
- appnic_device->ad_value = field[0];
+ pr_info("%s: LSI(R) 10/100 Network Driver - version %s\n",
+ LSI_DRV_NAME, LSI_DRV_VERSION);
- field = of_get_property(np, "mac-address", &length);
+ /* Allocate space for the device. */
- if (!field || 6 != length) {
- goto device_tree_failed;
- } else {
- int i;
- u8 *value;
+ dev = alloc_etherdev(sizeof(struct appnic_device));
+ if (!dev) {
+ pr_err("%s: Couldn't allocate net device.\n", LSI_DRV_NAME);
+ rc = -ENOMEM;
+ goto out;
+ }
- value = (u8 *)field;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ platform_set_drvdata(pdev, dev);
- for (i = 0; i < 6; ++i)
- appnic_device->mac_addr[i] = value[i];
- }
+ pdata = netdev_priv(dev);
- memcpy(device->dev_addr, &appnic_device->mac_addr[0], 6);
- memcpy(device->perm_addr, &appnic_device->mac_addr[0], 6);
+ /*
+ * Get the physical addresses, interrupt number, etc. from the
+ * device tree. If no entry exists (older boot loader...) just
+ * use the pre-devicetree method.
+ */
- goto device_tree_succeeded;
+ rc = appnic_probe_config_dt(dev, np);
-device_tree_failed:
- pr_err("acp-femac: Reading Device Tree Failed\n");
- iounmap(rx_base);
- iounmap(tx_base);
- iounmap(dma_base);
- rc = -EINVAL;
+ if (rc == -EINVAL) {
goto out;
+ } else if (rc == -ENODEV) {
+
+#ifdef CONFIG_MTD_NAND_EP501X_UBOOTENV
- } else {
/*
* 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.
*/
+
unsigned char ethaddr_string[20];
-#ifdef CONFIG_MTD_NAND_EP501X_UBOOTENV
+
if (0 != ubootenv_get("ethaddr", ethaddr_string)) {
- pr_err("acp-femac: Could not read ethernet address!\n");
- return -EBUSY;
- }
+ pr_err("%s: Could not read ethernet address!\n",
+ LSI_DRV_NAME);
+ return -EFAULT;
+ } else {
- {
- char *string;
- int i = 0;
u8 mac_address[6];
-
- string = ethaddr_string;
+ int i = 0;
+ char *string = ethaddr_string;
while ((0 != string) && (6 > i)) {
char *value;
@@ -2714,91 +1926,80 @@ device_tree_failed:
mac_address[i++] = (u8)res;
}
- memcpy(device->dev_addr, mac_address, 6);
- memcpy(device->perm_addr, mac_address, 6);
- device->addr_len = 6;
+ memcpy(dev->dev_addr, mac_address, 6);
+ memcpy(dev->perm_addr, mac_address, 6);
+ dev->addr_len = 6;
- pr_info(
- "acp-femac: Using Static Addresses and Interrupts.\n");
+ pr_info("%s: Using Static Addresses and Interrupts",
+ LSI_DRV_NAME);
rx_base = ioremap(0x002000480000ULL, 0x1000);
- appnic_device->rx_base =
+ pdata->rx_base =
(unsigned long)ioremap(0x002000480000ULL, 0x1000);
tx_base = ioremap(0x002000481000ULL, 0x1000);
- appnic_device->tx_base =
+ pdata->tx_base =
(unsigned long)ioremap(0x002000481000ULL, 0x1000);
- dma_base = ioremap(0x002000482000ULL, 0x1000);
- appnic_device->dma_base =
+ dma_base = ioremap(0x002000482000ULL, 0x1000);
+ pdata->dma_base =
(unsigned long)ioremap(0x002000482000ULL, 0x1000);
- appnic_device->interrupt = 33;
+ pdata->interrupt = 33;
}
#else
/* Neither dtb info nor ubootenv driver found. */
- pr_err("Could not read ethernet address!\n");
+ pr_err("%s: Could not read ethernet address!", LSI_DRV_NAME);
return -EBUSY;
#endif
+
}
-device_tree_succeeded:
#ifdef CONFIG_MTD_NAND_EP501X_UBOOTENV
- /* Override phy_address with u-boot environment variable if set. */
- if (0 == ubootenv_get("phy_address", uboot_env_string)) {
- /*
- * User may have entered phy_address value in u-boot as
- * either a decimal or hex value. Try reading both ways.
- */
- unsigned long res;
- if (kstrtoul(uboot_env_string, 10, &res))
- return -EBUSY;
- appnic_device->phy_address = res;
- if (appnic_device->phy_address == 0) {
+
+ {
+ unsigned char uboot_env_string[20];
+
+ /* Override ad_value with u-boot environment variable if set. */
+ if (0 == ubootenv_get("ad_value", uboot_env_string)) {
+ /*
+ * Assume ad_value is always entered as a hex value,
+ * since u-boot defaults this value as hex.
+ */
unsigned long res;
- ubootenv_get("phy_address", uboot_env_string);
if (kstrtoul(uboot_env_string, 16, &res))
return -EBUSY;
- appnic_device->phy_address = res;
+ pdata->ad_value = res;
}
}
- /* Override ad_value with u-boot environment variable if set. */
- if (0 == ubootenv_get("ad_value", uboot_env_string)) {
- /*
- * Assume ad_value is always entered as a hex value,
- * since u-boot defaults this value as hex.
- */
- unsigned long res;
- if (kstrtoul(uboot_env_string, 16, &res))
- return -EBUSY;
- appnic_device->ad_value = res;
- }
#endif
- /* ad_value should never be 0. Use default if so ... */
- if (appnic_device->ad_value == 0) {
- appnic_device->ad_value = (PHY_AUTONEG_ADVERTISE_100FULL |
- PHY_AUTONEG_ADVERTISE_100 |
- PHY_AUTONEG_ADVERTISE_10FULL |
- PHY_AUTONEG_ADVERTISE_10);
- pr_err("acp-femac: Set ad_value to default of 0x%lx\n",
- appnic_device->ad_value);
+ /* ad_value should never be 0. */
+ if (pdata->ad_value == 0) {
+ pdata->ad_value = 0x1e1;
+ pr_err("%s: Set ad_value to default of 0x%lx\n",
+ LSI_DRV_NAME, pdata->ad_value);
}
- pr_info("acp-femac: ad_value = 0x%lx, phy_address = 0x%lx\n",
- appnic_device->ad_value, appnic_device->phy_address);
-
/* Initialize the device. */
-
- rc = appnic_init(device);
+ rc = appnic_init(dev);
if (0 != rc) {
- pr_err("acp-femac: appnic_init() failed: %d\n", rc);
+ pr_err("%s: appnic_init() failed: %d\n", LSI_DRV_NAME, rc);
rc = -ENODEV;
goto out;
}
- strcpy(this_net_device->name, "eth%d");
-
/* Register the device. */
- rc = register_netdev(this_net_device);
+ rc = register_netdev(dev);
if (0 != rc) {
- pr_err("acp-femac: register_netdev() failed: %d\n", rc);
+ pr_err("%s: register_netdev() failed: %d\n", LSI_DRV_NAME, rc);
+ rc = -ENODEV;
+ goto out;
+ }
+
+ /* Initialize the MDIO interface. */
+ appnic_mdio_initialize(dev);
+
+ /* Initialize the PHY. */
+ rc = appnic_mii_init(pdev, dev);
+ if (rc) {
+ pr_warn("%s: Failed to initialize PHY", LSI_DRV_NAME);
rc = -ENODEV;
goto out;
}
@@ -2811,20 +2012,72 @@ out:
return rc;
}
-module_init(lsinet_init);
-
/*
* ----------------------------------------------------------------------
- * lsinet_exit
+ * appnic_drv_remove
*/
-void __exit
-lsinet_exit(void)
+static int __devexit appnic_drv_remove(struct platform_device *pdev)
{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct appnic_device *pdata;
+
+ pr_info("%s: Stopping driver", LSI_DRV_NAME);
+
remove_proc_entry("driver/appnic", NULL);
- unregister_netdev(this_net_device);
- return;
+ 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);
+ }
+
+ iounmap(rx_base);
+ iounmap(tx_base);
+ iounmap(dma_base);
+
+ return 0;
+}
+
+static const struct of_device_id appnic_dt_ids[] = {
+ { .compatible = "acp-femac", }
+};
+MODULE_DEVICE_TABLE(of, appnic_dt_ids);
+
+static struct platform_driver appnic_driver = {
+ .probe = appnic_drv_probe,
+ .remove = __devexit_p(appnic_drv_remove),
+ .driver = {
+ .name = LSI_DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = NULL,
+ .of_match_table = appnic_dt_ids,
+ },
+};
+
+/* 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_exit(lsinet_exit);
+module_init(appnic_init_module);
+module_exit(appnic_cleanup_module);
diff --git a/drivers/net/ethernet/lsi/lsi_acp_net.h b/drivers/net/ethernet/lsi/lsi_acp_net.h
new file mode 100644
index 0000000..db4bfcf
--- /dev/null
+++ b/drivers/net/ethernet/lsi/lsi_acp_net.h
@@ -0,0 +1,482 @@
+/*
+ * drivers/net/ethernet/lsi/lsi_acp_net.h
+ *
+ * Copyright (C) 2013 LSI
+ *
+ * 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
+ */
+
+#ifndef _LSI_ACP_NET_H
+#define _LSI_ACP_NET_H
+
+#ifdef CONFIG_MTD_NAND_EP501X_UBOOTENV
+extern int ubootenv_get(const char *, char *);
+#endif
+
+/*
+ * This is the maximum number of packets to be received every
+ * NAPI poll
+ */
+#define LSINET_NAPI_WEIGHT 64
+
+/*
+ ======================================================================
+ Device Data Structures
+ ======================================================================
+*/
+
+struct appnic_dma_descriptor {
+
+ /* Word 0 */
+ unsigned long unused:24;
+ /* big endian to little endian */
+ unsigned long byte_swapping_on:1;
+ unsigned long error:1;
+ unsigned long interrupt_on_completion:1;
+ unsigned long end_of_packet:1;
+ unsigned long start_of_packet:1;
+ unsigned long write:1;
+ /* 00=Fill|01=Block|10=Scatter */
+ unsigned long transfer_type:2;
+
+ /* Word 1 */
+ unsigned long pdu_length:16;
+ unsigned long data_transfer_length:16;
+
+ /* Word 2 */
+ unsigned long target_memory_address;
+
+ /* Word 3 */
+ unsigned long host_data_memory_pointer;
+
+} __packed;
+
+union appnic_queue_pointer {
+
+ unsigned long raw;
+
+ struct {
+ unsigned long unused:11;
+ unsigned long generation_bit:1;
+ unsigned long offset:20;
+ } __packed bits;
+
+} __packed;
+
+/*
+ =============================================================================
+ The appnic Device Structure
+ =============================================================================
+*/
+
+struct appnic_device {
+
+ /* net_device */
+ struct net_device *device;
+
+ /* Addresses, Interrupt, and PHY stuff. */
+ unsigned long rx_base;
+ unsigned long tx_base;
+ unsigned long dma_base;
+ unsigned long interrupt;
+ unsigned long mdio_clock;
+ unsigned long mdio_base;
+ unsigned long phy_address;
+ unsigned long ad_value;
+ unsigned char mac_addr[6];
+
+ /* NAPI */
+ struct napi_struct napi;
+
+ /* statistics */
+ struct net_device_stats stats;
+
+ /* DMA-able memory */
+ int dma_alloc_size;
+ int dma_alloc_size_rx;
+ int dma_alloc_size_tx;
+ void *dma_alloc;
+ void *dma_alloc_rx;
+ void *dma_alloc_tx;
+ dma_addr_t dma_alloc_dma;
+ dma_addr_t dma_alloc_dma_rx;
+ dma_addr_t dma_alloc_dma_tx;
+ int dma_alloc_offset;
+ int dma_alloc_offset_rx;
+ int dma_alloc_offset_tx;
+
+ /* tail pointers */
+ volatile union appnic_queue_pointer *rx_tail;
+ dma_addr_t rx_tail_dma;
+ volatile union appnic_queue_pointer *tx_tail;
+ dma_addr_t tx_tail_dma;
+
+ /* descriptors */
+ struct appnic_dma_descriptor *rx_desc;
+ dma_addr_t rx_desc_dma;
+ unsigned rx_num_desc;
+ struct appnic_dma_descriptor *tx_desc;
+ dma_addr_t tx_desc_dma;
+ unsigned tx_num_desc;
+
+ /* buffers */
+ unsigned rx_buf_sz;
+ unsigned rx_buf_per_desc;
+ void *rx_buf;
+ dma_addr_t rx_buf_dma;
+ unsigned tx_buf_sz;
+ unsigned tx_buf_per_desc;
+ void *tx_buf;
+ dma_addr_t tx_buf_dma;
+
+ /* The local pointers */
+ union appnic_queue_pointer rx_tail_copy;
+ union appnic_queue_pointer rx_head;
+ union appnic_queue_pointer tx_tail_copy;
+ union appnic_queue_pointer tx_head;
+
+ /* Spin Lock */
+ spinlock_t mdio_lock;
+ spinlock_t dev_lock;
+ spinlock_t extra_lock;
+
+ /* PHY */
+ struct mii_bus *mii_bus;
+ struct phy_device *phy_dev;
+ int phy_irq[PHY_MAX_ADDR];
+ unsigned int link;
+ unsigned int speed;
+ unsigned int duplex;
+};
+
+/*
+ * Overview
+ * --------
+ *
+ * Register offset decoding is as follows:
+ *
+ * Bit(s) Description
+ *
+ * 16:15 define the Channel. There is only one; therefore, 00.
+ * 14:12 define the MAC within the channel. Only one so 000.
+ * 11:10 define the register "space" as follows:
+ * 00 = fast ethernet MACmw.l 06000000 ffffffff 3200000
+ * 10 = global
+ * 11 = interrupt
+ * 9: 2 register
+ * 1: 0 always 00, 32 bit registers only.
+ *
+ * Receive registers start at the base address. Transmit registers start
+ * at 0x20000 above the base address. DMA start at a completely different
+ * base address (in this case 0x8000000 above the base).
+ *
+*/
+
+/* Receive Configuration -------------------------------------------- */
+
+#define APPNIC_RX_CONF (rx_base + 0x004c)
+#define APPNIC_RX_CONF_ENABLE 0x0001
+/* Pass Any Packet */
+#define APPNIC_RX_CONF_PAP 0x0002
+#define APPNIC_RX_CONF_JUMBO9K 0x0008
+#define APPNIC_RX_CONF_STRIPCRC 0x0010
+/* Accept All MAC Types */
+#define APPNIC_RX_CONF_AMT 0x0020
+/* Accept Flow Control */
+#define APPNIC_RX_CONF_AFC 0x0040
+/* Enable VLAN */
+#define APPNIC_RX_CONF_VLAN 0x0200
+/* RX MAC Speed, 1=100MBS */
+#define APPNIC_RX_CONF_SPEED 0x0800
+/* 1=Duplex Mode */
+#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.
+ */
+#define APPNIC_RX_CONF_RXFCE 0x4000
+/*
+ * Controls the insertion of FC packets
+ * by the MAC transmitter.
+ */
+#define APPNIC_RX_CONF_TXFCE 0x8000
+
+/* Receive Stat Overflow -------------------------------------------- */
+
+#define APPNIC_RX_STAT_OVERFLOW (rx_base + 0x278)
+
+/* Receive Stat Undersize ------------------------------------------- */
+
+#define APPNIC_RX_STAT_UNDERSIZE (rx_base + 0x280)
+
+/* Receive Stat Oversize -------------------------------------------- */
+
+#define APPNIC_RX_STAT_OVERSIZE (rx_base + 0x2b8)
+
+/* Receive Stat Multicast ------------------------------------------- */
+
+#define APPNIC_RX_STAT_MULTICAST (rx_base + 0x2d0)
+
+/* Receive Stat Packet OK ------------------------------------------- */
+
+#define APPNIC_RX_STAT_PACKET_OK (rx_base + 0x2c0)
+
+/* Receive Stat CRC Error ------------------------------------------- */
+
+#define APPNIC_RX_STAT_CRC_ERROR (rx_base + 0x2c8)
+
+/* Receive Stat Align Error ----------------------------------------- */
+
+#define APPNIC_RX_STAT_ALIGN_ERROR (rx_base + 0x2e8)
+
+/* Receive Ethernet Mode -------------------------------------------- */
+
+#define APPNIC_RX_MODE (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_MAC_0 0x00001
+
+/* Receive Internal Interrupt Control ------------------------------- */
+
+#define APPNIC_RX_INTERNAL_INTERRUPT_CONTROL (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_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_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_TXCONFIG_DTPA_ASSERT 0x8000
+#define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_DISABLE 0x4000
+#define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_WATER_MARK_HIGH 0x3f00
+#define APPNIC_TX_WATERMARK_TXCONFIG_DTPA_WATER_MARK_LOW 0x3f
+
+/* 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)
+
+/* Transmit Extended Configuration ---------------------------------- */
+
+#define APPNIC_TX_EXTENDED_CONF (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
+#define APPNIC_TX_EXTENDED_CONF_LATE_COLLISION_WINDOW_COUNT 0xff
+
+/* Transmit Half Duplex Configuration ------------------------------- */
+
+#define APPNIC_TX_HALF_DUPLEX_CONF (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_ENABLE_SWAP_SA 0x8000
+#define APPNIC_TX_CONF_LINK 0x2000
+#define APPNIC_TX_CONF_DUPLEX 0x1000
+#define APPNIC_TX_CONF_SPEED 0x0800
+#define APPNIC_TX_CONF_XBK_RST_RX_NTX 0x0600
+#define APPNIC_TX_CONF_IFG 0x01f0
+#define APPNIC_TX_CONF_APP_CRC_ENABLE 0x0004
+#define APPNIC_TX_CONF_PAD_ENABLE 0x0002
+#define APPNIC_TX_CONF_ENABLE 0x0001
+
+#define TX_CONF_SET_IFG(tx_configuration, ifg) \
+ do { \
+ (tx_configuration) &= ~APPNIC_TX_CONF_IFG; \
+ (tx_configuration) |= ((ifg & 0x1f) << 4); \
+ } while (0);
+
+/* Transmit Time Value Configuration -------------------------------- */
+
+#define APPNIC_TX_TIME_VALUE_CONF (tx_base + 0x5c)
+#define APPNIC_TX_TIME_VALUE_CONF_PAUSE_VALUE 0xffff
+
+/* Transmit Stat Underrun ------------------------------------------- */
+
+#define APPNIC_TX_STAT_UNDERRUN (tx_base + 0x300)
+
+/* Transmit Stat Packet OK ------------------------------------------ */
+
+#define APPNIC_TX_STAT_PACKET_OK (tx_base + 0x318)
+
+/* Transmit Stat Undersize ------------------------------------------ */
+
+#define APPNIC_TX_STAT_UNDERSIZE (tx_base + 0x350)
+
+/* Transmit Status Late Collision ----------------------------------- */
+
+#define APPNIC_TX_STATUS_LATE_COLLISION (tx_base + 0x368)
+
+/* Transmit Status Excessive Collision ------------------------------ */
+
+#define APPNIC_TX_STATUS_EXCESSIVE_COLLISION (tx_base + 0x370)
+
+/* Transmit Stat Collision Above Watermark -------------------------- */
+
+#define APPNIC_TX_STAT_COLLISION_ABOVE_WATERMARK (tx_base + 0x380)
+
+/* Transmit Mode ---------------------------------------------------- */
+
+#define APPNIC_TX_MODE (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_MAC_0 0x1
+
+/* Transmit Interrupt Control --------------------------------------- */
+
+#define APPNIC_TX_INTERRUPT_CONTROL (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_MAC_0 0x1
+
+/* */
+
+#define APPNIC_DMA_PCI_CONTROL (dma_base + 0x00)
+
+/* */
+
+#define APPNIC_DMA_CONTROL (dma_base + 0x08)
+
+/* DMA Interrupt Status --------------------------------------------- */
+
+#define APPNIC_DMA_INTERRUPT_STATUS (dma_base + 0x18)
+#define APPNIC_DMA_INTERRUPT_STATUS_RX 0x2
+#define APPNIC_DMA_INTERRUPT_STATUS_TX 0x1
+#define RX_INTERRUPT(dma_interrupt_status) \
+ (0 != (dma_interrupt_status & APPNIC_DMA_INTERRUPT_STATUS_RX))
+#define TX_INTERRUPT(dma_interrupt_status) \
+ (0 != (dma_interrupt_status & APPNIC_DMA_INTERRUPT_STATUS_TX))
+
+/* DMA Interrupt Enable --------------------------------------------- */
+
+#define APPNIC_DMA_INTERRUPT_ENABLE (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)
+
+/* DMA Receive Queue Size ------------------------------------------- */
+
+#define APPNIC_DMA_RX_QUEUE_SIZE (dma_base + 0x34)
+
+/* DMA Transmit Queue Base Address ---------------------------------- */
+
+#define APPNIC_DMA_TX_QUEUE_BASE_ADDRESS (dma_base + 0x38)
+
+/* DMA Transmit Queue Size ------------------------------------------ */
+
+#define APPNIC_DMA_TX_QUEUE_SIZE (dma_base + 0x3c)
+
+/* DMA Recevie Tail Pointer Address --------------------------------- */
+
+#define APPNIC_DMA_RX_TAIL_POINTER_ADDRESS (dma_base + 0x48)
+
+/* DMA Transmit Tail Pointer Address -------------------------------- */
+
+#define APPNIC_DMA_TX_TAIL_POINTER_ADDRESS (dma_base + 0x4c)
+
+/* DMA Receive Head Pointer ----------------------------------------- */
+
+#define APPNIC_DMA_RX_HEAD_POINTER (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_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_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_GB 0x100000
+#define APPNIC_DMA_TX_TAIL_POINTER_LOCAL_COPY_POINTER 0x0fffff
+
+#define read_mac(address) in_le32((u32 *) (address))
+#define write_mac(value, address) out_le32((u32 *) (address), (value))
+
+static inline void
+readdescriptor(unsigned long address, struct appnic_dma_descriptor *descriptor)
+{
+ unsigned long *from = (unsigned long *) address;
+ unsigned long *to = (unsigned long *) descriptor;
+
+ *to++ = swab32(*from++);
+ *to++ = swab32(*from++);
+ *to++ = swab32(*from++);
+ *to++ = swab32(*from++);
+ return;
+}
+
+static inline void
+writedescriptor(unsigned long address,
+ const struct appnic_dma_descriptor *descriptor)
+{
+ unsigned long *to = (unsigned long *) address;
+ unsigned long *from = (unsigned long *) descriptor;
+
+ *to++ = swab32(*from++);
+ *to++ = swab32(*from++);
+ *to++ = swab32(*from++);
+ *to++ = swab32(*from++);
+ return;
+}
+
+static inline union appnic_queue_pointer
+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;
+}
+
+#define SWAB_QUEUE_POINTER(pointer) \
+swab_queue_pointer((const union appnic_queue_pointer *) (pointer))
+
+#endif /* _LSI_ACP_NET_H */
--
1.8.3
More information about the linux-yocto
mailing list