summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/staging/octeon
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/staging/octeon')
-rw-r--r--kernel/drivers/staging/octeon/Makefile2
-rw-r--r--kernel/drivers/staging/octeon/ethernet-defines.h67
-rw-r--r--kernel/drivers/staging/octeon/ethernet-mdio.c48
-rw-r--r--kernel/drivers/staging/octeon/ethernet-mdio.h26
-rw-r--r--kernel/drivers/staging/octeon/ethernet-mem.c30
-rw-r--r--kernel/drivers/staging/octeon/ethernet-mem.h23
-rw-r--r--kernel/drivers/staging/octeon/ethernet-rgmii.c313
-rw-r--r--kernel/drivers/staging/octeon/ethernet-rx.c181
-rw-r--r--kernel/drivers/staging/octeon/ethernet-rx.h24
-rw-r--r--kernel/drivers/staging/octeon/ethernet-sgmii.c112
-rw-r--r--kernel/drivers/staging/octeon/ethernet-spi.c237
-rw-r--r--kernel/drivers/staging/octeon/ethernet-tx.c65
-rw-r--r--kernel/drivers/staging/octeon/ethernet-tx.h23
-rw-r--r--kernel/drivers/staging/octeon/ethernet-util.h45
-rw-r--r--kernel/drivers/staging/octeon/ethernet-xaui.c144
-rw-r--r--kernel/drivers/staging/octeon/ethernet.c159
-rw-r--r--kernel/drivers/staging/octeon/octeon-ethernet.h57
17 files changed, 502 insertions, 1054 deletions
diff --git a/kernel/drivers/staging/octeon/Makefile b/kernel/drivers/staging/octeon/Makefile
index 9012dee0c..8ca17210d 100644
--- a/kernel/drivers/staging/octeon/Makefile
+++ b/kernel/drivers/staging/octeon/Makefile
@@ -19,5 +19,3 @@ octeon-ethernet-y += ethernet-rx.o
octeon-ethernet-y += ethernet-sgmii.o
octeon-ethernet-y += ethernet-spi.o
octeon-ethernet-y += ethernet-tx.o
-octeon-ethernet-y += ethernet-xaui.o
-
diff --git a/kernel/drivers/staging/octeon/ethernet-defines.h b/kernel/drivers/staging/octeon/ethernet-defines.h
index 2a98a2153..13e4cee1f 100644
--- a/kernel/drivers/staging/octeon/ethernet-defines.h
+++ b/kernel/drivers/staging/octeon/ethernet-defines.h
@@ -1,46 +1,15 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
/*
* A few defines are used to control the operation of this driver:
- * CONFIG_CAVIUM_RESERVE32
- * This kernel config options controls the amount of memory configured
- * in a wired TLB entry for all processes to share. If this is set, the
- * driver will use this memory instead of kernel memory for pools. This
- * allows 32bit userspace application to access the buffers, but also
- * requires all received packets to be copied.
- * USE_SKBUFFS_IN_HW
- * Tells the driver to populate the packet buffers with kernel skbuffs.
- * This allows the driver to receive packets without copying them. It also
- * means that 32bit userspace can't access the packet buffers.
- * USE_HW_TCPUDP_CHECKSUM
- * Controls if the Octeon TCP/UDP checksum engine is used for packet
- * output. If this is zero, the kernel will perform the checksum in
- * software.
* USE_ASYNC_IOBDMA
* Use asynchronous IO access to hardware. This uses Octeon's asynchronous
* IOBDMAs to issue IO accesses without stalling. Set this to zero
@@ -57,46 +26,20 @@
#include <asm/octeon/cvmx-config.h>
-
-#define OCTEON_ETHERNET_VERSION "1.9"
-
-#ifndef CONFIG_CAVIUM_RESERVE32
-#define CONFIG_CAVIUM_RESERVE32 0
-#endif
-
-#define USE_SKBUFFS_IN_HW 1
#ifdef CONFIG_NETFILTER
#define REUSE_SKBUFFS_WITHOUT_FREE 0
#else
#define REUSE_SKBUFFS_WITHOUT_FREE 1
#endif
-#define USE_HW_TCPUDP_CHECKSUM 1
-
-/* Enable Random Early Dropping under load */
-#define USE_RED 1
#define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0)
-/*
- * Allow SW based preamble removal at 10Mbps to workaround PHYs giving
- * us bad preambles.
- */
-#define USE_10MBPS_PREAMBLE_WORKAROUND 1
-/*
- * Use this to have all FPA frees also tell the L2 not to write data
- * to memory.
- */
-#define DONT_WRITEBACK(x) (x)
-/* Use this to not have FPA frees control L2 */
-/*#define DONT_WRITEBACK(x) 0 */
-
/* Maximum number of SKBs to try to free per xmit packet. */
#define MAX_OUT_QUEUE_DEPTH 1000
-#define FAU_TOTAL_TX_TO_CLEAN (CVMX_FAU_REG_END - sizeof(uint32_t))
-#define FAU_NUM_PACKET_BUFFERS_TO_FREE (FAU_TOTAL_TX_TO_CLEAN - sizeof(uint32_t))
+#define FAU_TOTAL_TX_TO_CLEAN (CVMX_FAU_REG_END - sizeof(u32))
+#define FAU_NUM_PACKET_BUFFERS_TO_FREE (FAU_TOTAL_TX_TO_CLEAN - sizeof(u32))
#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS+1)
-
#endif /* __ETHERNET_DEFINES_H__ */
diff --git a/kernel/drivers/staging/octeon/ethernet-mdio.c b/kernel/drivers/staging/octeon/ethernet-mdio.c
index 40dab11e5..fd9b3d899 100644
--- a/kernel/drivers/staging/octeon/ethernet-mdio.c
+++ b/kernel/drivers/staging/octeon/ethernet-mdio.c
@@ -1,35 +1,19 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
+
#include <linux/kernel.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/ratelimit.h>
#include <linux/of_mdio.h>
-
+#include <generated/utsrelease.h>
#include <net/dst.h>
#include <asm/octeon/octeon.h>
@@ -39,15 +23,14 @@
#include "ethernet-mdio.h"
#include "ethernet-util.h"
-#include <asm/octeon/cvmx-helper-board.h>
-
+#include <asm/octeon/cvmx-gmxx-defs.h>
#include <asm/octeon/cvmx-smix-defs.h>
static void cvm_oct_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- strlcpy(info->driver, "cavium-ethernet", sizeof(info->driver));
- strlcpy(info->version, OCTEON_ETHERNET_VERSION, sizeof(info->version));
+ strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+ strlcpy(info->version, UTS_RELEASE, sizeof(info->version));
strlcpy(info->bus_info, "Builtin", sizeof(info->bus_info));
}
@@ -116,14 +99,14 @@ int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return phy_mii_ioctl(priv->phydev, rq, cmd);
}
-static void cvm_oct_note_carrier(struct octeon_ethernet *priv,
- cvmx_helper_link_info_t li)
+void cvm_oct_note_carrier(struct octeon_ethernet *priv,
+ cvmx_helper_link_info_t li)
{
if (li.s.link_up) {
- pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d\n",
+ pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d, queue %d\n",
netdev_name(priv->netdev), li.s.speed,
(li.s.full_duplex) ? "Full" : "Half",
- priv->port);
+ priv->port, priv->queue);
} else {
pr_notice_ratelimited("%s: Link down\n",
netdev_name(priv->netdev));
@@ -150,7 +133,14 @@ void cvm_oct_adjust_link(struct net_device *dev)
int cvm_oct_common_stop(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
+ int interface = INTERFACE(priv->port);
cvmx_helper_link_info_t link_info;
+ union cvmx_gmxx_prtx_cfg gmx_cfg;
+ int index = INDEX(priv->port);
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ gmx_cfg.s.en = 0;
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
priv->poll = NULL;
diff --git a/kernel/drivers/staging/octeon/ethernet-mdio.h b/kernel/drivers/staging/octeon/ethernet-mdio.h
index 6191b0850..5ed8483fc 100644
--- a/kernel/drivers/staging/octeon/ethernet-mdio.h
+++ b/kernel/drivers/staging/octeon/ethernet-mdio.h
@@ -1,29 +1,13 @@
-/*********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-*********************************************************************/
+ */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@ -41,7 +25,7 @@
extern const struct ethtool_ops cvm_oct_ethtool_ops;
-extern void octeon_mdiobus_force_mod_depencency(void);
+void octeon_mdiobus_force_mod_depencency(void);
int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
int cvm_oct_phy_setup_device(struct net_device *dev);
diff --git a/kernel/drivers/staging/octeon/ethernet-mem.c b/kernel/drivers/staging/octeon/ethernet-mem.c
index 964da860f..5a5cdb3cd 100644
--- a/kernel/drivers/staging/octeon/ethernet-mem.c
+++ b/kernel/drivers/staging/octeon/ethernet-mem.c
@@ -1,29 +1,13 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2010 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
+
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
@@ -54,7 +38,7 @@ static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements)
break;
skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f));
*(struct sk_buff **)(skb->data - sizeof(void *)) = skb;
- cvmx_fpa_free(skb->data, pool, DONT_WRITEBACK(size / 128));
+ cvmx_fpa_free(skb->data, pool, size / 128);
freed--;
}
return elements - freed;
@@ -160,7 +144,7 @@ int cvm_oct_mem_fill_fpa(int pool, int size, int elements)
{
int freed;
- if (USE_SKBUFFS_IN_HW && pool == CVMX_FPA_PACKET_POOL)
+ if (pool == CVMX_FPA_PACKET_POOL)
freed = cvm_oct_fill_hw_skbuff(pool, size, elements);
else
freed = cvm_oct_fill_hw_memory(pool, size, elements);
@@ -169,7 +153,7 @@ int cvm_oct_mem_fill_fpa(int pool, int size, int elements)
void cvm_oct_mem_empty_fpa(int pool, int size, int elements)
{
- if (USE_SKBUFFS_IN_HW && pool == CVMX_FPA_PACKET_POOL)
+ if (pool == CVMX_FPA_PACKET_POOL)
cvm_oct_free_hw_skbuff(pool, size, elements);
else
cvm_oct_free_hw_memory(pool, size, elements);
diff --git a/kernel/drivers/staging/octeon/ethernet-mem.h b/kernel/drivers/staging/octeon/ethernet-mem.h
index 713f2edc8..62d07c426 100644
--- a/kernel/drivers/staging/octeon/ethernet-mem.h
+++ b/kernel/drivers/staging/octeon/ethernet-mem.h
@@ -1,29 +1,12 @@
-/*********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-********************************************************************/
+ */
int cvm_oct_mem_fill_fpa(int pool, int size, int elements);
void cvm_oct_mem_empty_fpa(int pool, int size, int elements);
diff --git a/kernel/drivers/staging/octeon/ethernet-rgmii.c b/kernel/drivers/staging/octeon/ethernet-rgmii.c
index e36f9bc69..613344b88 100644
--- a/kernel/drivers/staging/octeon/ethernet-rgmii.c
+++ b/kernel/drivers/staging/octeon/ethernet-rgmii.c
@@ -1,29 +1,13 @@
-/*********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
+
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/interrupt.h>
@@ -48,6 +32,37 @@ static DEFINE_SPINLOCK(global_register_lock);
static int number_rgmii_ports;
+static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable)
+{
+ union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
+ union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
+ union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ /* Set preamble checking. */
+ gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index,
+ interface));
+ gmxx_rxx_frm_ctl.s.pre_chk = enable;
+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
+ gmxx_rxx_frm_ctl.u64);
+
+ /* Set FCS stripping. */
+ ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
+ if (enable)
+ ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
+ else
+ ipd_sub_port_fcs.s.port_bit &=
+ 0xffffffffull ^ (1ull << priv->port);
+ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
+
+ /* Clear any error bits. */
+ gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index,
+ interface));
+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
+ gmxx_rxx_int_reg.u64);
+}
+
static void cvm_oct_rgmii_poll(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
@@ -68,14 +83,7 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
link_info = cvmx_helper_link_get(priv->port);
if (link_info.u64 == priv->link_info) {
-
- /*
- * If the 10Mbps preamble workaround is supported and we're
- * at 10Mbps we may need to do some special checking.
- */
- if (USE_10MBPS_PREAMBLE_WORKAROUND &&
- (link_info.s.speed == 10)) {
-
+ if (link_info.s.speed == 10) {
/*
* Read the GMXX_RXX_INT_REG[PCTERR] bit and
* see if we are getting preamble errors.
@@ -88,7 +96,6 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
(index, interface));
if (gmxx_rxx_int_reg.s.pcterr) {
-
/*
* We are getting preamble errors at
* 10Mbps. Most likely the PHY is
@@ -97,30 +104,7 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
* packets we need to disable preamble
* checking and do it in software.
*/
- union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
- union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
-
- /* Disable preamble checking */
- gmxx_rxx_frm_ctl.u64 =
- cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
- (index, interface));
- gmxx_rxx_frm_ctl.s.pre_chk = 0;
- cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL
- (index, interface),
- gmxx_rxx_frm_ctl.u64);
-
- /* Disable FCS stripping */
- ipd_sub_port_fcs.u64 =
- cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
- ipd_sub_port_fcs.s.port_bit &=
- 0xffffffffull ^ (1ull << priv->port);
- cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS,
- ipd_sub_port_fcs.u64);
-
- /* Clear any error bits */
- cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
- (index, interface),
- gmxx_rxx_int_reg.u64);
+ cvm_oct_set_hw_preamble(priv, false);
printk_ratelimited("%s: Using 10Mbps with software preamble removal\n",
dev->name);
}
@@ -133,34 +117,13 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
return;
}
- /* If the 10Mbps preamble workaround is allowed we need to on
- preamble checking, FCS stripping, and clear error bits on
- every speed change. If errors occur during 10Mbps operation
- the above code will change this stuff */
- if (USE_10MBPS_PREAMBLE_WORKAROUND) {
-
- union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
- union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
- union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
- int interface = INTERFACE(priv->port);
- int index = INDEX(priv->port);
-
- /* Enable preamble checking */
- gmxx_rxx_frm_ctl.u64 =
- cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
- gmxx_rxx_frm_ctl.s.pre_chk = 1;
- cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
- gmxx_rxx_frm_ctl.u64);
- /* Enable FCS stripping */
- ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
- ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
- cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
- /* Clear any error bits */
- gmxx_rxx_int_reg.u64 =
- cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
- cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
- gmxx_rxx_int_reg.u64);
- }
+ /* Since the 10Mbps preamble workaround is allowed we need to enable
+ * preamble checking, FCS stripping, and clear error bits on
+ * every speed change. If errors occur during 10Mbps operation
+ * the above code will change this stuff
+ */
+ cvm_oct_set_hw_preamble(priv, true);
+
if (priv->phydev == NULL) {
link_info = cvmx_helper_link_autoconf(priv->port);
priv->link_info = link_info.u64;
@@ -176,172 +139,75 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
if (link_info.s.link_up) {
if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
- if (priv->queue != -1)
- printk_ratelimited("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ?
- "Full" : "Half",
- priv->port, priv->queue);
- else
- printk_ratelimited("%s: %u Mbps %s duplex, port %2d, POW\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ?
- "Full" : "Half",
- priv->port);
- } else {
- if (netif_carrier_ok(dev))
- netif_carrier_off(dev);
- printk_ratelimited("%s: Link down\n", dev->name);
+ } else if (netif_carrier_ok(dev)) {
+ netif_carrier_off(dev);
}
+ cvm_oct_note_carrier(priv, link_info);
}
}
-static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
+static int cmv_oct_rgmii_gmx_interrupt(int interface)
{
- union cvmx_npi_rsl_int_blocks rsl_int_blocks;
int index;
- irqreturn_t return_status = IRQ_NONE;
+ int count = 0;
- rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
-
- /* Check and see if this interrupt was caused by the GMX0 block */
- if (rsl_int_blocks.s.gmx0) {
-
- int interface = 0;
- /* Loop through every port of this interface */
- for (index = 0;
- index < cvmx_helper_ports_on_interface(interface);
- index++) {
+ /* Loop through every port of this interface */
+ for (index = 0;
+ index < cvmx_helper_ports_on_interface(interface);
+ index++) {
+ union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
- /* Read the GMX interrupt status bits */
- union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
-
- gmx_rx_int_reg.u64 =
- cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
+ /* Read the GMX interrupt status bits */
+ gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
(index, interface));
- gmx_rx_int_reg.u64 &=
- cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
+ gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
(index, interface));
- /* Poll the port if inband status changed */
- if (gmx_rx_int_reg.s.phy_dupx
- || gmx_rx_int_reg.s.phy_link
- || gmx_rx_int_reg.s.phy_spd) {
- struct net_device *dev =
+ /* Poll the port if inband status changed */
+ if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link ||
+ gmx_rx_int_reg.s.phy_spd) {
+ struct net_device *dev =
cvm_oct_device[cvmx_helper_get_ipd_port
(interface, index)];
- struct octeon_ethernet *priv = netdev_priv(dev);
-
- if (dev &&
- !atomic_read(&cvm_oct_poll_queue_stopping))
- queue_work(cvm_oct_poll_queue,
- &priv->port_work);
-
- gmx_rx_int_reg.u64 = 0;
- gmx_rx_int_reg.s.phy_dupx = 1;
- gmx_rx_int_reg.s.phy_link = 1;
- gmx_rx_int_reg.s.phy_spd = 1;
- cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
- (index, interface),
- gmx_rx_int_reg.u64);
- return_status = IRQ_HANDLED;
- }
+ struct octeon_ethernet *priv = netdev_priv(dev);
+
+ if (dev && !atomic_read(&cvm_oct_poll_queue_stopping))
+ queue_work(cvm_oct_poll_queue,
+ &priv->port_work);
+
+ gmx_rx_int_reg.u64 = 0;
+ gmx_rx_int_reg.s.phy_dupx = 1;
+ gmx_rx_int_reg.s.phy_link = 1;
+ gmx_rx_int_reg.s.phy_spd = 1;
+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
+ gmx_rx_int_reg.u64);
+ count++;
}
}
+ return count;
+}
- /* Check and see if this interrupt was caused by the GMX1 block */
- if (rsl_int_blocks.s.gmx1) {
+static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
+{
+ union cvmx_npi_rsl_int_blocks rsl_int_blocks;
+ int count = 0;
- int interface = 1;
- /* Loop through every port of this interface */
- for (index = 0;
- index < cvmx_helper_ports_on_interface(interface);
- index++) {
+ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
- /* Read the GMX interrupt status bits */
- union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
+ /* Check and see if this interrupt was caused by the GMX0 block */
+ if (rsl_int_blocks.s.gmx0)
+ count += cmv_oct_rgmii_gmx_interrupt(0);
- gmx_rx_int_reg.u64 =
- cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
- (index, interface));
- gmx_rx_int_reg.u64 &=
- cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
- (index, interface));
- /* Poll the port if inband status changed */
- if (gmx_rx_int_reg.s.phy_dupx
- || gmx_rx_int_reg.s.phy_link
- || gmx_rx_int_reg.s.phy_spd) {
+ /* Check and see if this interrupt was caused by the GMX1 block */
+ if (rsl_int_blocks.s.gmx1)
+ count += cmv_oct_rgmii_gmx_interrupt(1);
- struct net_device *dev =
- cvm_oct_device[cvmx_helper_get_ipd_port
- (interface, index)];
- struct octeon_ethernet *priv = netdev_priv(dev);
-
- if (dev &&
- !atomic_read(&cvm_oct_poll_queue_stopping))
- queue_work(cvm_oct_poll_queue,
- &priv->port_work);
-
- gmx_rx_int_reg.u64 = 0;
- gmx_rx_int_reg.s.phy_dupx = 1;
- gmx_rx_int_reg.s.phy_link = 1;
- gmx_rx_int_reg.s.phy_spd = 1;
- cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
- (index, interface),
- gmx_rx_int_reg.u64);
- return_status = IRQ_HANDLED;
- }
- }
- }
- return return_status;
+ return count ? IRQ_HANDLED : IRQ_NONE;
}
int cvm_oct_rgmii_open(struct net_device *dev)
{
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- struct octeon_ethernet *priv = netdev_priv(dev);
- int interface = INTERFACE(priv->port);
- int index = INDEX(priv->port);
- cvmx_helper_link_info_t link_info;
- int rv;
-
- rv = cvm_oct_phy_setup_device(dev);
- if (rv)
- return rv;
-
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- gmx_cfg.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-
- if (!octeon_is_simulation()) {
- if (priv->phydev) {
- int r = phy_read_status(priv->phydev);
-
- if (r == 0 && priv->phydev->link == 0)
- netif_carrier_off(dev);
- cvm_oct_adjust_link(dev);
- } else {
- link_info = cvmx_helper_link_get(priv->port);
- if (!link_info.s.link_up)
- netif_carrier_off(dev);
- priv->poll = cvm_oct_rgmii_poll;
- }
- }
-
- return 0;
-}
-
-int cvm_oct_rgmii_stop(struct net_device *dev)
-{
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- struct octeon_ethernet *priv = netdev_priv(dev);
- int interface = INTERFACE(priv->port);
- int index = INDEX(priv->port);
-
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- gmx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
- return cvm_oct_common_stop(dev);
+ return cvm_oct_common_open(dev, cvm_oct_rgmii_poll);
}
static void cvm_oct_rgmii_immediate_poll(struct work_struct *work)
@@ -357,7 +223,6 @@ int cvm_oct_rgmii_init(struct net_device *dev)
int r;
cvm_oct_common_init(dev);
- dev->netdev_ops->ndo_stop(dev);
INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll);
/*
* Due to GMX errata in CN3XXX series chips, it is necessary
diff --git a/kernel/drivers/staging/octeon/ethernet-rx.c b/kernel/drivers/staging/octeon/ethernet-rx.c
index 22667dbb1..6aed3cf6c 100644
--- a/kernel/drivers/staging/octeon/ethernet-rx.c
+++ b/kernel/drivers/staging/octeon/ethernet-rx.c
@@ -1,29 +1,13 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2010 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cache.h>
@@ -65,6 +49,8 @@ static struct napi_struct cvm_oct_napi;
/**
* cvm_oct_do_interrupt - interrupt handler.
+ * @cpl: Interrupt number. Unused
+ * @dev_id: Cookie to identify the device. Unused
*
* The interrupt occurs whenever the POW has packets in our group.
*
@@ -86,18 +72,22 @@ static irqreturn_t cvm_oct_do_interrupt(int cpl, void *dev_id)
*/
static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
{
- if ((work->word2.snoip.err_code == 10) && (work->len <= 64)) {
+ int port;
+
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
+ port = work->word0.pip.cn68xx.pknd;
+ else
+ port = work->word1.cn38xx.ipprt;
+
+ if ((work->word2.snoip.err_code == 10) && (work->word1.len <= 64)) {
/*
* Ignore length errors on min size packets. Some
* equipment incorrectly pads packets to 64+4FCS
* instead of 60+4FCS. Note these packets still get
* counted as frame errors.
*/
- } else
- if (USE_10MBPS_PREAMBLE_WORKAROUND
- && ((work->word2.snoip.err_code == 5)
- || (work->word2.snoip.err_code == 7))) {
-
+ } else if (work->word2.snoip.err_code == 5 ||
+ work->word2.snoip.err_code == 7) {
/*
* We received a packet with either an alignment error
* or a FCS error. This may be signalling that we are
@@ -106,19 +96,19 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
* packet to determine if we can remove a non spec
* preamble and generate a correct packet.
*/
- int interface = cvmx_helper_get_interface_num(work->ipprt);
- int index = cvmx_helper_get_interface_index_num(work->ipprt);
+ int interface = cvmx_helper_get_interface_num(port);
+ int index = cvmx_helper_get_interface_index_num(port);
union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
gmxx_rxx_frm_ctl.u64 =
cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
if (gmxx_rxx_frm_ctl.s.pre_chk == 0) {
- uint8_t *ptr =
+ u8 *ptr =
cvmx_phys_to_ptr(work->packet_ptr.s.addr);
int i = 0;
- while (i < work->len - 1) {
+ while (i < work->word1.len - 1) {
if (*ptr != 0x55)
break;
ptr++;
@@ -128,18 +118,18 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
if (*ptr == 0xd5) {
/*
printk_ratelimited("Port %d received 0xd5 preamble\n",
- work->ipprt);
+ port);
*/
work->packet_ptr.s.addr += i + 1;
- work->len -= i + 5;
+ work->word1.len -= i + 5;
} else if ((*ptr & 0xf) == 0xd) {
/*
printk_ratelimited("Port %d received 0x?d preamble\n",
- work->ipprt);
+ port);
*/
work->packet_ptr.s.addr += i;
- work->len -= i + 4;
- for (i = 0; i < work->len; i++) {
+ work->word1.len -= i + 4;
+ for (i = 0; i < work->word1.len; i++) {
*ptr =
((*ptr & 0xf0) >> 4) |
((*(ptr + 1) & 0xf) << 4);
@@ -147,7 +137,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
}
} else {
printk_ratelimited("Port %d unknown preamble, packet dropped\n",
- work->ipprt);
+ port);
/*
cvmx_helper_dump_packet(work);
*/
@@ -157,7 +147,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
}
} else {
printk_ratelimited("Port %d receive error code %d, packet dropped\n",
- work->ipprt, work->word2.snoip.err_code);
+ port, work->word2.snoip.err_code);
cvm_oct_free_work(work);
return 1;
}
@@ -175,8 +165,8 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
{
const int coreid = cvmx_get_core_num();
- uint64_t old_group_mask;
- uint64_t old_scratch;
+ u64 old_group_mask;
+ u64 old_scratch;
int rx_count = 0;
int did_work_request = 0;
int packet_not_copied;
@@ -191,9 +181,16 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
}
/* Only allow work for our group (and preserve priorities) */
- old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid));
- cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid),
- (old_group_mask & ~0xFFFFull) | 1 << pow_receive_group);
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ old_group_mask = cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid));
+ cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid),
+ 1ull << pow_receive_group);
+ cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */
+ } else {
+ old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid));
+ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid),
+ (old_group_mask & ~0xFFFFull) | 1 << pow_receive_group);
+ }
if (USE_ASYNC_IOBDMA) {
cvmx_pow_work_request_async(CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT);
@@ -205,6 +202,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
struct sk_buff **pskb = NULL;
int skb_in_hw;
cvmx_wqe_t *work;
+ int port;
if (USE_ASYNC_IOBDMA && did_work_request)
work = cvmx_pow_work_response_async(CVMX_SCR_SCRATCH);
@@ -214,12 +212,19 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
prefetch(work);
did_work_request = 0;
if (work == NULL) {
- union cvmx_pow_wq_int wq_int;
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ cvmx_write_csr(CVMX_SSO_WQ_IQ_DIS,
+ 1ull << pow_receive_group);
+ cvmx_write_csr(CVMX_SSO_WQ_INT,
+ 1ull << pow_receive_group);
+ } else {
+ union cvmx_pow_wq_int wq_int;
- wq_int.u64 = 0;
- wq_int.s.iq_dis = 1 << pow_receive_group;
- wq_int.s.wq_int = 1 << pow_receive_group;
- cvmx_write_csr(CVMX_POW_WQ_INT, wq_int.u64);
+ wq_int.u64 = 0;
+ wq_int.s.iq_dis = 1 << pow_receive_group;
+ wq_int.s.wq_int = 1 << pow_receive_group;
+ cvmx_write_csr(CVMX_POW_WQ_INT, wq_int.u64);
+ }
break;
}
pskb = (struct sk_buff **)(cvm_oct_get_buffer_ptr(work->packet_ptr) -
@@ -233,13 +238,19 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
}
rx_count++;
- skb_in_hw = USE_SKBUFFS_IN_HW && work->word2.s.bufs == 1;
+ skb_in_hw = work->word2.s.bufs == 1;
if (likely(skb_in_hw)) {
skb = *pskb;
prefetch(&skb->head);
prefetch(&skb->len);
}
- prefetch(cvm_oct_device[work->ipprt]);
+
+ if (octeon_has_feature(OCTEON_FEATURE_PKND))
+ port = work->word0.pip.cn68xx.pknd;
+ else
+ port = work->word1.cn38xx.ipprt;
+
+ prefetch(cvm_oct_device[port]);
/* Immediately throw away all packets with receive errors */
if (unlikely(work->word2.snoip.rcv_error)) {
@@ -256,7 +267,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
skb->data = skb->head + work->packet_ptr.s.addr -
cvmx_ptr_to_phys(skb->head);
prefetch(skb->data);
- skb->len = work->len;
+ skb->len = work->word1.len;
skb_set_tail_pointer(skb, skb->len);
packet_not_copied = 1;
} else {
@@ -264,7 +275,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
* We have to copy the packet. First allocate
* an skbuff for it.
*/
- skb = dev_alloc_skb(work->len);
+ skb = dev_alloc_skb(work->word1.len);
if (!skb) {
cvm_oct_free_work(work);
continue;
@@ -275,7 +286,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
* entirely stored in the work entry.
*/
if (unlikely(work->word2.s.bufs == 0)) {
- uint8_t *ptr = work->packet_data;
+ u8 *ptr = work->packet_data;
if (likely(!work->word2.s.not_IP)) {
/*
@@ -287,13 +298,14 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
else
ptr += 6;
}
- memcpy(skb_put(skb, work->len), ptr, work->len);
+ memcpy(skb_put(skb, work->word1.len), ptr,
+ work->word1.len);
/* No packet buffers to free */
} else {
int segments = work->word2.s.bufs;
union cvmx_buf_ptr segment_ptr =
work->packet_ptr;
- int len = work->len;
+ int len = work->word1.len;
while (segments--) {
union cvmx_buf_ptr next_ptr =
@@ -329,10 +341,9 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
}
packet_not_copied = 0;
}
-
- if (likely((work->ipprt < TOTAL_NUMBER_OF_PORTS) &&
- cvm_oct_device[work->ipprt])) {
- struct net_device *dev = cvm_oct_device[work->ipprt];
+ if (likely((port < TOTAL_NUMBER_OF_PORTS) &&
+ cvm_oct_device[port])) {
+ struct net_device *dev = cvm_oct_device[port];
struct octeon_ethernet *priv = netdev_priv(dev);
/*
@@ -352,7 +363,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
skb->ip_summed = CHECKSUM_UNNECESSARY;
/* Increment RX stats for virtual ports */
- if (work->ipprt >= CVMX_PIP_NUM_INPUT_PORTS) {
+ if (port >= CVMX_PIP_NUM_INPUT_PORTS) {
#ifdef CONFIG_64BIT
atomic64_add(1,
(atomic64_t *)&priv->stats.rx_packets);
@@ -387,14 +398,14 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
* doesn't exist.
*/
printk_ratelimited("Port %d not controlled by Linux, packet dropped\n",
- work->ipprt);
+ port);
dev_kfree_skb_irq(skb);
}
/*
* Check to see if the skbuff and work share the same
* packet buffer.
*/
- if (USE_SKBUFFS_IN_HW && likely(packet_not_copied)) {
+ if (likely(packet_not_copied)) {
/*
* This buffer needs to be replaced, increment
* the number of buffers we need to free by
@@ -403,14 +414,19 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE,
1);
- cvmx_fpa_free(work, CVMX_FPA_WQE_POOL,
- DONT_WRITEBACK(1));
+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1);
} else {
cvm_oct_free_work(work);
}
}
/* Restore the original POW group mask */
- cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), old_group_mask);
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid), old_group_mask);
+ cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */
+ } else {
+ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), old_group_mask);
+ }
+
if (USE_ASYNC_IOBDMA) {
/* Restore the scratch area */
cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch);
@@ -442,8 +458,6 @@ void cvm_oct_rx_initialize(void)
{
int i;
struct net_device *dev_for_napi = NULL;
- union cvmx_pow_wq_int_thrx int_thr;
- union cvmx_pow_wq_int_pc int_pc;
for (i = 0; i < TOTAL_NUMBER_OF_PORTS; i++) {
if (cvm_oct_device[i]) {
@@ -469,15 +483,34 @@ void cvm_oct_rx_initialize(void)
disable_irq_nosync(OCTEON_IRQ_WORKQ0 + pow_receive_group);
- int_thr.u64 = 0;
- int_thr.s.tc_en = 1;
- int_thr.s.tc_thr = 1;
/* Enable POW interrupt when our port has at least one packet */
- cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), int_thr.u64);
-
- int_pc.u64 = 0;
- int_pc.s.pc_thr = 5;
- cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64);
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ union cvmx_sso_wq_int_thrx int_thr;
+ union cvmx_pow_wq_int_pc int_pc;
+
+ int_thr.u64 = 0;
+ int_thr.s.tc_en = 1;
+ int_thr.s.tc_thr = 1;
+ cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group),
+ int_thr.u64);
+
+ int_pc.u64 = 0;
+ int_pc.s.pc_thr = 5;
+ cvmx_write_csr(CVMX_SSO_WQ_INT_PC, int_pc.u64);
+ } else {
+ union cvmx_pow_wq_int_thrx int_thr;
+ union cvmx_pow_wq_int_pc int_pc;
+
+ int_thr.u64 = 0;
+ int_thr.s.tc_en = 1;
+ int_thr.s.tc_thr = 1;
+ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group),
+ int_thr.u64);
+
+ int_pc.u64 = 0;
+ int_pc.s.pc_thr = 5;
+ cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64);
+ }
/* Schedule NAPI now. This will indirectly enable the interrupt. */
napi_schedule(&cvm_oct_napi);
diff --git a/kernel/drivers/staging/octeon/ethernet-rx.h b/kernel/drivers/staging/octeon/ethernet-rx.h
index 9240c85ce..a5973fd01 100644
--- a/kernel/drivers/staging/octeon/ethernet-rx.h
+++ b/kernel/drivers/staging/octeon/ethernet-rx.h
@@ -1,29 +1,13 @@
-/*********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-*********************************************************************/
+ */
+
#include <asm/octeon/cvmx-fau.h>
void cvm_oct_poll_controller(struct net_device *dev);
diff --git a/kernel/drivers/staging/octeon/ethernet-sgmii.c b/kernel/drivers/staging/octeon/ethernet-sgmii.c
index 21a7a17ac..7424dc45a 100644
--- a/kernel/drivers/staging/octeon/ethernet-sgmii.c
+++ b/kernel/drivers/staging/octeon/ethernet-sgmii.c
@@ -1,29 +1,13 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
+
#include <linux/phy.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@ -41,101 +25,15 @@
#include <asm/octeon/cvmx-gmxx-defs.h>
-static void cvm_oct_sgmii_poll(struct net_device *dev)
-{
- struct octeon_ethernet *priv = netdev_priv(dev);
- cvmx_helper_link_info_t link_info;
-
- link_info = cvmx_helper_link_get(priv->port);
- if (link_info.u64 == priv->link_info)
- return;
-
- link_info = cvmx_helper_link_autoconf(priv->port);
- priv->link_info = link_info.u64;
-
- /* Tell Linux */
- if (link_info.s.link_up) {
-
- if (!netif_carrier_ok(dev))
- netif_carrier_on(dev);
- if (priv->queue != -1)
- printk_ratelimited
- ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ? "Full" : "Half",
- priv->port, priv->queue);
- else
- printk_ratelimited
- ("%s: %u Mbps %s duplex, port %2d, POW\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ? "Full" : "Half",
- priv->port);
- } else {
- if (netif_carrier_ok(dev))
- netif_carrier_off(dev);
- printk_ratelimited("%s: Link down\n", dev->name);
- }
-}
-
int cvm_oct_sgmii_open(struct net_device *dev)
{
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- struct octeon_ethernet *priv = netdev_priv(dev);
- int interface = INTERFACE(priv->port);
- int index = INDEX(priv->port);
- cvmx_helper_link_info_t link_info;
- int rv;
-
- rv = cvm_oct_phy_setup_device(dev);
- if (rv)
- return rv;
-
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- gmx_cfg.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-
- if (octeon_is_simulation())
- return 0;
-
- if (priv->phydev) {
- int r = phy_read_status(priv->phydev);
-
- if (r == 0 && priv->phydev->link == 0)
- netif_carrier_off(dev);
- cvm_oct_adjust_link(dev);
- } else {
- link_info = cvmx_helper_link_get(priv->port);
- if (!link_info.s.link_up)
- netif_carrier_off(dev);
- priv->poll = cvm_oct_sgmii_poll;
- cvm_oct_sgmii_poll(dev);
- }
- return 0;
-}
-
-int cvm_oct_sgmii_stop(struct net_device *dev)
-{
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- struct octeon_ethernet *priv = netdev_priv(dev);
- int interface = INTERFACE(priv->port);
- int index = INDEX(priv->port);
-
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- gmx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
- return cvm_oct_common_stop(dev);
+ return cvm_oct_common_open(dev, cvm_oct_link_poll);
}
int cvm_oct_sgmii_init(struct net_device *dev)
{
cvm_oct_common_init(dev);
- dev->netdev_ops->ndo_stop(dev);
/* FIXME: Need autoneg logic */
return 0;
}
-
-void cvm_oct_sgmii_uninit(struct net_device *dev)
-{
- cvm_oct_common_uninit(dev);
-}
diff --git a/kernel/drivers/staging/octeon/ethernet-spi.c b/kernel/drivers/staging/octeon/ethernet-spi.c
index 5108bc0bb..2ae1944b3 100644
--- a/kernel/drivers/staging/octeon/ethernet-spi.c
+++ b/kernel/drivers/staging/octeon/ethernet-spi.c
@@ -1,29 +1,13 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
+
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/interrupt.h>
@@ -44,141 +28,104 @@
static int number_spi_ports;
static int need_retrain[2] = { 0, 0 };
-static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id)
+static void cvm_oct_spxx_int_pr(union cvmx_spxx_int_reg spx_int_reg, int index)
{
- irqreturn_t return_status = IRQ_NONE;
- union cvmx_npi_rsl_int_blocks rsl_int_blocks;
-
- /* Check and see if this interrupt was caused by the GMX block */
- rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
- if (rsl_int_blocks.s.spx1) { /* 19 - SPX1_INT_REG & STX1_INT_REG */
-
- union cvmx_spxx_int_reg spx_int_reg;
- union cvmx_stxx_int_reg stx_int_reg;
-
- spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1));
- cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64);
- if (!need_retrain[1]) {
-
- spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1));
- if (spx_int_reg.s.spf)
- pr_err("SPI1: SRX Spi4 interface down\n");
- if (spx_int_reg.s.calerr)
- pr_err("SPI1: SRX Spi4 Calendar table parity error\n");
- if (spx_int_reg.s.syncerr)
- pr_err("SPI1: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n");
- if (spx_int_reg.s.diperr)
- pr_err("SPI1: SRX Spi4 DIP4 error\n");
- if (spx_int_reg.s.tpaovr)
- pr_err("SPI1: SRX Selected port has hit TPA overflow\n");
- if (spx_int_reg.s.rsverr)
- pr_err("SPI1: SRX Spi4 reserved control word detected\n");
- if (spx_int_reg.s.drwnng)
- pr_err("SPI1: SRX Spi4 receive FIFO drowning/overflow\n");
- if (spx_int_reg.s.clserr)
- pr_err("SPI1: SRX Spi4 packet closed on non-16B alignment without EOP\n");
- if (spx_int_reg.s.spiovr)
- pr_err("SPI1: SRX Spi4 async FIFO overflow\n");
- if (spx_int_reg.s.abnorm)
- pr_err("SPI1: SRX Abnormal packet termination (ERR bit)\n");
- if (spx_int_reg.s.prtnxa)
- pr_err("SPI1: SRX Port out of range\n");
- }
-
- stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1));
- cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64);
- if (!need_retrain[1]) {
+ if (spx_int_reg.s.spf)
+ pr_err("SPI%d: SRX Spi4 interface down\n", index);
+ if (spx_int_reg.s.calerr)
+ pr_err("SPI%d: SRX Spi4 Calendar table parity error\n", index);
+ if (spx_int_reg.s.syncerr)
+ pr_err("SPI%d: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n",
+ index);
+ if (spx_int_reg.s.diperr)
+ pr_err("SPI%d: SRX Spi4 DIP4 error\n", index);
+ if (spx_int_reg.s.tpaovr)
+ pr_err("SPI%d: SRX Selected port has hit TPA overflow\n",
+ index);
+ if (spx_int_reg.s.rsverr)
+ pr_err("SPI%d: SRX Spi4 reserved control word detected\n",
+ index);
+ if (spx_int_reg.s.drwnng)
+ pr_err("SPI%d: SRX Spi4 receive FIFO drowning/overflow\n",
+ index);
+ if (spx_int_reg.s.clserr)
+ pr_err("SPI%d: SRX Spi4 packet closed on non-16B alignment without EOP\n",
+ index);
+ if (spx_int_reg.s.spiovr)
+ pr_err("SPI%d: SRX Spi4 async FIFO overflow\n", index);
+ if (spx_int_reg.s.abnorm)
+ pr_err("SPI%d: SRX Abnormal packet termination (ERR bit)\n",
+ index);
+ if (spx_int_reg.s.prtnxa)
+ pr_err("SPI%d: SRX Port out of range\n", index);
+}
- stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1));
- if (stx_int_reg.s.syncerr)
- pr_err("SPI1: STX Interface encountered a fatal error\n");
- if (stx_int_reg.s.frmerr)
- pr_err("SPI1: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n");
- if (stx_int_reg.s.unxfrm)
- pr_err("SPI1: STX Unexpected framing sequence\n");
- if (stx_int_reg.s.nosync)
- pr_err("SPI1: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n");
- if (stx_int_reg.s.diperr)
- pr_err("SPI1: STX DIP2 error on the Spi4 Status channel\n");
- if (stx_int_reg.s.datovr)
- pr_err("SPI1: STX Spi4 FIFO overflow error\n");
- if (stx_int_reg.s.ovrbst)
- pr_err("SPI1: STX Transmit packet burst too big\n");
- if (stx_int_reg.s.calpar1)
- pr_err("SPI1: STX Calendar Table Parity Error Bank1\n");
- if (stx_int_reg.s.calpar0)
- pr_err("SPI1: STX Calendar Table Parity Error Bank0\n");
- }
+static void cvm_oct_stxx_int_pr(union cvmx_stxx_int_reg stx_int_reg, int index)
+{
+ if (stx_int_reg.s.syncerr)
+ pr_err("SPI%d: STX Interface encountered a fatal error\n",
+ index);
+ if (stx_int_reg.s.frmerr)
+ pr_err("SPI%d: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n",
+ index);
+ if (stx_int_reg.s.unxfrm)
+ pr_err("SPI%d: STX Unexpected framing sequence\n", index);
+ if (stx_int_reg.s.nosync)
+ pr_err("SPI%d: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n",
+ index);
+ if (stx_int_reg.s.diperr)
+ pr_err("SPI%d: STX DIP2 error on the Spi4 Status channel\n",
+ index);
+ if (stx_int_reg.s.datovr)
+ pr_err("SPI%d: STX Spi4 FIFO overflow error\n", index);
+ if (stx_int_reg.s.ovrbst)
+ pr_err("SPI%d: STX Transmit packet burst too big\n", index);
+ if (stx_int_reg.s.calpar1)
+ pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n",
+ index, 1);
+ if (stx_int_reg.s.calpar0)
+ pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n",
+ index, 0);
+}
- cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0);
- cvmx_write_csr(CVMX_STXX_INT_MSK(1), 0);
- need_retrain[1] = 1;
- return_status = IRQ_HANDLED;
+static irqreturn_t cvm_oct_spi_spx_int(int index)
+{
+ union cvmx_spxx_int_reg spx_int_reg;
+ union cvmx_stxx_int_reg stx_int_reg;
+
+ spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(index));
+ cvmx_write_csr(CVMX_SPXX_INT_REG(index), spx_int_reg.u64);
+ if (!need_retrain[index]) {
+ spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(index));
+ cvm_oct_spxx_int_pr(spx_int_reg, index);
}
- if (rsl_int_blocks.s.spx0) { /* 18 - SPX0_INT_REG & STX0_INT_REG */
- union cvmx_spxx_int_reg spx_int_reg;
- union cvmx_stxx_int_reg stx_int_reg;
+ stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(index));
+ cvmx_write_csr(CVMX_STXX_INT_REG(index), stx_int_reg.u64);
+ if (!need_retrain[index]) {
+ stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(index));
+ cvm_oct_stxx_int_pr(stx_int_reg, index);
+ }
- spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0));
- cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64);
- if (!need_retrain[0]) {
+ cvmx_write_csr(CVMX_SPXX_INT_MSK(index), 0);
+ cvmx_write_csr(CVMX_STXX_INT_MSK(index), 0);
+ need_retrain[index] = 1;
- spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0));
- if (spx_int_reg.s.spf)
- pr_err("SPI0: SRX Spi4 interface down\n");
- if (spx_int_reg.s.calerr)
- pr_err("SPI0: SRX Spi4 Calendar table parity error\n");
- if (spx_int_reg.s.syncerr)
- pr_err("SPI0: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n");
- if (spx_int_reg.s.diperr)
- pr_err("SPI0: SRX Spi4 DIP4 error\n");
- if (spx_int_reg.s.tpaovr)
- pr_err("SPI0: SRX Selected port has hit TPA overflow\n");
- if (spx_int_reg.s.rsverr)
- pr_err("SPI0: SRX Spi4 reserved control word detected\n");
- if (spx_int_reg.s.drwnng)
- pr_err("SPI0: SRX Spi4 receive FIFO drowning/overflow\n");
- if (spx_int_reg.s.clserr)
- pr_err("SPI0: SRX Spi4 packet closed on non-16B alignment without EOP\n");
- if (spx_int_reg.s.spiovr)
- pr_err("SPI0: SRX Spi4 async FIFO overflow\n");
- if (spx_int_reg.s.abnorm)
- pr_err("SPI0: SRX Abnormal packet termination (ERR bit)\n");
- if (spx_int_reg.s.prtnxa)
- pr_err("SPI0: SRX Port out of range\n");
- }
+ return IRQ_HANDLED;
+}
- stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0));
- cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64);
- if (!need_retrain[0]) {
+static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id)
+{
+ irqreturn_t return_status = IRQ_NONE;
+ union cvmx_npi_rsl_int_blocks rsl_int_blocks;
- stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0));
- if (stx_int_reg.s.syncerr)
- pr_err("SPI0: STX Interface encountered a fatal error\n");
- if (stx_int_reg.s.frmerr)
- pr_err("SPI0: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n");
- if (stx_int_reg.s.unxfrm)
- pr_err("SPI0: STX Unexpected framing sequence\n");
- if (stx_int_reg.s.nosync)
- pr_err("SPI0: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n");
- if (stx_int_reg.s.diperr)
- pr_err("SPI0: STX DIP2 error on the Spi4 Status channel\n");
- if (stx_int_reg.s.datovr)
- pr_err("SPI0: STX Spi4 FIFO overflow error\n");
- if (stx_int_reg.s.ovrbst)
- pr_err("SPI0: STX Transmit packet burst too big\n");
- if (stx_int_reg.s.calpar1)
- pr_err("SPI0: STX Calendar Table Parity Error Bank1\n");
- if (stx_int_reg.s.calpar0)
- pr_err("SPI0: STX Calendar Table Parity Error Bank0\n");
- }
+ /* Check and see if this interrupt was caused by the GMX block */
+ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
+ if (rsl_int_blocks.s.spx1) /* 19 - SPX1_INT_REG & STX1_INT_REG */
+ return_status = cvm_oct_spi_spx_int(1);
- cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0);
- cvmx_write_csr(CVMX_STXX_INT_MSK(0), 0);
- need_retrain[0] = 1;
- return_status = IRQ_HANDLED;
- }
+ if (rsl_int_blocks.s.spx0) /* 18 - SPX0_INT_REG & STX0_INT_REG */
+ return_status = cvm_oct_spi_spx_int(0);
return return_status;
}
diff --git a/kernel/drivers/staging/octeon/ethernet-tx.c b/kernel/drivers/staging/octeon/ethernet-tx.c
index 5b9ac1f6d..c053c4a47 100644
--- a/kernel/drivers/staging/octeon/ethernet-tx.c
+++ b/kernel/drivers/staging/octeon/ethernet-tx.c
@@ -1,29 +1,13 @@
-/*********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2010 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-*********************************************************************/
+ */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@ -159,8 +143,8 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
{
cvmx_pko_command_word0_t pko_command;
union cvmx_buf_ptr hw_buffer;
- uint64_t old_scratch;
- uint64_t old_scratch2;
+ u64 old_scratch;
+ u64 old_scratch2;
int qos;
int i;
enum {QUEUE_CORE, QUEUE_HW, QUEUE_DROP} queue_type;
@@ -411,11 +395,13 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
dont_put_skbuff_in_hw:
/* Check if we can use the hardware checksumming */
- if (USE_HW_TCPUDP_CHECKSUM && (skb->protocol == htons(ETH_P_IP)) &&
- (ip_hdr(skb)->version == 4) && (ip_hdr(skb)->ihl == 5) &&
- ((ip_hdr(skb)->frag_off == 0) || (ip_hdr(skb)->frag_off == htons(1 << 14)))
- && ((ip_hdr(skb)->protocol == IPPROTO_TCP)
- || (ip_hdr(skb)->protocol == IPPROTO_UDP))) {
+ if ((skb->protocol == htons(ETH_P_IP)) &&
+ (ip_hdr(skb)->version == 4) &&
+ (ip_hdr(skb)->ihl == 5) &&
+ ((ip_hdr(skb)->frag_off == 0) ||
+ (ip_hdr(skb)->frag_off == htons(1 << 14))) &&
+ ((ip_hdr(skb)->protocol == IPPROTO_TCP) ||
+ (ip_hdr(skb)->protocol == IPPROTO_UDP))) {
/* Use hardware checksum calc */
pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1;
}
@@ -563,7 +549,7 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
/* Get a work queue entry */
cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
- if (unlikely(work == NULL)) {
+ if (unlikely(!work)) {
printk_ratelimited("%s: Failed to allocate a work queue entry\n",
dev->name);
priv->stats.tx_dropped++;
@@ -576,7 +562,7 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
if (unlikely(packet_buffer == NULL)) {
printk_ratelimited("%s: Failed to allocate a packet buffer\n",
dev->name);
- cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1));
+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1);
priv->stats.tx_dropped++;
dev_kfree_skb_any(skb);
return 0;
@@ -590,7 +576,7 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
* calculation may add a little extra, but that doesn't
* hurt.
*/
- copy_location = packet_buffer + sizeof(uint64_t);
+ copy_location = packet_buffer + sizeof(u64);
copy_location += ((CVMX_HELPER_FIRST_MBUFF_SKIP + 7) & 0xfff8) + 6;
/*
@@ -605,13 +591,14 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
* Fill in some of the work queue fields. We may need to add
* more if the software at the other end needs them.
*/
- work->hw_chksum = skb->csum;
- work->len = skb->len;
- work->ipprt = priv->port;
- work->qos = priv->port & 0x7;
- work->grp = pow_send_group;
- work->tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
- work->tag = pow_send_group; /* FIXME */
+ if (!OCTEON_IS_MODEL(OCTEON_CN68XX))
+ work->word0.pip.cn38xx.hw_chksum = skb->csum;
+ work->word1.len = skb->len;
+ cvmx_wqe_set_port(work, priv->port);
+ cvmx_wqe_set_qos(work, priv->port & 0x7);
+ cvmx_wqe_set_grp(work, pow_send_group);
+ work->word1.tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
+ work->word1.tag = pow_send_group; /* FIXME */
/* Default to zero. Sets of zero later are commented out */
work->word2.u64 = 0;
work->word2.s.bufs = 1;
@@ -691,8 +678,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev)
}
/* Submit the packet to the POW */
- cvmx_pow_work_submit(work, work->tag, work->tag_type, work->qos,
- work->grp);
+ cvmx_pow_work_submit(work, work->word1.tag, work->word1.tag_type,
+ cvmx_wqe_get_qos(work), cvmx_wqe_get_grp(work));
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len;
dev_consume_skb_any(skb);
diff --git a/kernel/drivers/staging/octeon/ethernet-tx.h b/kernel/drivers/staging/octeon/ethernet-tx.h
index 547680c6c..84848e4c1 100644
--- a/kernel/drivers/staging/octeon/ethernet-tx.h
+++ b/kernel/drivers/staging/octeon/ethernet-tx.h
@@ -1,29 +1,12 @@
-/*********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-*********************************************************************/
+ */
int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev);
int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev);
diff --git a/kernel/drivers/staging/octeon/ethernet-util.h b/kernel/drivers/staging/octeon/ethernet-util.h
index 0f9b4a18f..45f024bc5 100644
--- a/kernel/drivers/staging/octeon/ethernet-util.h
+++ b/kernel/drivers/staging/octeon/ethernet-util.h
@@ -1,29 +1,16 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-*********************************************************************/
+ */
+
+#include <asm/octeon/cvmx-pip.h>
+#include <asm/octeon/cvmx-helper.h>
+#include <asm/octeon/cvmx-helper-util.h>
/**
* cvm_oct_get_buffer_ptr - convert packet data address to pointer
@@ -45,14 +32,12 @@ static inline void *cvm_oct_get_buffer_ptr(union cvmx_buf_ptr packet_ptr)
*/
static inline int INTERFACE(int ipd_port)
{
- if (ipd_port < 32) /* Interface 0 or 1 for RGMII,GMII,SPI, etc */
- return ipd_port >> 4;
- else if (ipd_port < 36) /* Interface 2 for NPI */
- return 2;
- else if (ipd_port < 40) /* Interface 3 for loopback */
- return 3;
- else if (ipd_port == 40) /* Non existent interface for POW0 */
- return 4;
+ int interface = cvmx_helper_get_interface_num(ipd_port);
+
+ if (interface >= 0)
+ return interface;
+ else if (ipd_port == CVMX_PIP_NUM_INPUT_PORTS)
+ return 10;
panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port);
}
@@ -64,7 +49,5 @@ static inline int INTERFACE(int ipd_port)
*/
static inline int INDEX(int ipd_port)
{
- if (ipd_port < 32)
- return ipd_port & 15;
- return ipd_port & 3;
+ return cvmx_helper_get_interface_index_num(ipd_port);
}
diff --git a/kernel/drivers/staging/octeon/ethernet-xaui.c b/kernel/drivers/staging/octeon/ethernet-xaui.c
deleted file mode 100644
index fd9d103d8..000000000
--- a/kernel/drivers/staging/octeon/ethernet-xaui.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2007 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
-#include <linux/phy.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/ratelimit.h>
-#include <net/dst.h>
-
-#include <asm/octeon/octeon.h>
-
-#include "ethernet-defines.h"
-#include "octeon-ethernet.h"
-#include "ethernet-util.h"
-#include "ethernet-mdio.h"
-
-#include <asm/octeon/cvmx-helper.h>
-
-#include <asm/octeon/cvmx-gmxx-defs.h>
-
-static void cvm_oct_xaui_poll(struct net_device *dev)
-{
- struct octeon_ethernet *priv = netdev_priv(dev);
- cvmx_helper_link_info_t link_info;
-
- link_info = cvmx_helper_link_get(priv->port);
- if (link_info.u64 == priv->link_info)
- return;
-
- link_info = cvmx_helper_link_autoconf(priv->port);
- priv->link_info = link_info.u64;
-
- /* Tell Linux */
- if (link_info.s.link_up) {
-
- if (!netif_carrier_ok(dev))
- netif_carrier_on(dev);
- if (priv->queue != -1)
- printk_ratelimited
- ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ? "Full" : "Half",
- priv->port, priv->queue);
- else
- printk_ratelimited
- ("%s: %u Mbps %s duplex, port %2d, POW\n",
- dev->name, link_info.s.speed,
- (link_info.s.full_duplex) ? "Full" : "Half",
- priv->port);
- } else {
- if (netif_carrier_ok(dev))
- netif_carrier_off(dev);
- printk_ratelimited("%s: Link down\n", dev->name);
- }
-}
-
-int cvm_oct_xaui_open(struct net_device *dev)
-{
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- struct octeon_ethernet *priv = netdev_priv(dev);
- int interface = INTERFACE(priv->port);
- int index = INDEX(priv->port);
- cvmx_helper_link_info_t link_info;
- int rv;
-
- rv = cvm_oct_phy_setup_device(dev);
- if (rv)
- return rv;
-
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- gmx_cfg.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-
- if (octeon_is_simulation())
- return 0;
-
- if (priv->phydev) {
- int r = phy_read_status(priv->phydev);
-
- if (r == 0 && priv->phydev->link == 0)
- netif_carrier_off(dev);
- cvm_oct_adjust_link(dev);
- } else {
- link_info = cvmx_helper_link_get(priv->port);
- if (!link_info.s.link_up)
- netif_carrier_off(dev);
- priv->poll = cvm_oct_xaui_poll;
- cvm_oct_xaui_poll(dev);
- }
- return 0;
-}
-
-int cvm_oct_xaui_stop(struct net_device *dev)
-{
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- struct octeon_ethernet *priv = netdev_priv(dev);
- int interface = INTERFACE(priv->port);
- int index = INDEX(priv->port);
-
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- gmx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
- return cvm_oct_common_stop(dev);
-}
-
-int cvm_oct_xaui_init(struct net_device *dev)
-{
- struct octeon_ethernet *priv = netdev_priv(dev);
-
- cvm_oct_common_init(dev);
- dev->netdev_ops->ndo_stop(dev);
- if (!octeon_is_simulation() && priv->phydev == NULL)
- priv->poll = cvm_oct_xaui_poll;
-
- return 0;
-}
-
-void cvm_oct_xaui_uninit(struct net_device *dev)
-{
- cvm_oct_common_uninit(dev);
-}
diff --git a/kernel/drivers/staging/octeon/ethernet.c b/kernel/drivers/staging/octeon/ethernet.c
index fbbe86648..f69fb5cc7 100644
--- a/kernel/drivers/staging/octeon/ethernet.c
+++ b/kernel/drivers/staging/octeon/ethernet.c
@@ -1,29 +1,13 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2007 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
+
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -102,19 +86,19 @@ int rx_napi_weight = 32;
module_param(rx_napi_weight, int, 0444);
MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter.");
-/**
+/*
* cvm_oct_poll_queue - Workqueue for polling operations.
*/
struct workqueue_struct *cvm_oct_poll_queue;
-/**
+/*
* cvm_oct_poll_queue_stopping - flag to indicate polling should stop.
*
* Set to one right before cvm_oct_poll_queue is destroyed.
*/
atomic_t cvm_oct_poll_queue_stopping = ATOMIC_INIT(0);
-/**
+/*
* Array of every ethernet device owned by this driver indexed by
* the ipd input port number.
*/
@@ -168,11 +152,12 @@ static void cvm_oct_configure_common_hw(void)
num_packet_buffers);
if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL)
cvm_oct_mem_fill_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL,
- CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
+ CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 1024);
#ifdef __LITTLE_ENDIAN
{
union cvmx_ipd_ctl_status ipd_ctl_status;
+
ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
ipd_ctl_status.s.pkt_lend = 1;
ipd_ctl_status.s.wqe_lend = 1;
@@ -180,10 +165,7 @@ static void cvm_oct_configure_common_hw(void)
}
#endif
- if (USE_RED)
- cvmx_helper_setup_red(num_packet_buffers / 4,
- num_packet_buffers / 8);
-
+ cvmx_helper_setup_red(num_packet_buffers / 4, num_packet_buffers / 8);
}
/**
@@ -206,11 +188,10 @@ int cvm_oct_free_work(void *work_queue_entry)
if (unlikely(!segment_ptr.s.i))
cvmx_fpa_free(cvm_oct_get_buffer_ptr(segment_ptr),
segment_ptr.s.pool,
- DONT_WRITEBACK(CVMX_FPA_PACKET_POOL_SIZE /
- 128));
+ CVMX_FPA_PACKET_POOL_SIZE / 128);
segment_ptr = next_ptr;
}
- cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1));
+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1);
return 0;
}
@@ -383,13 +364,6 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev)
}
}
-/**
- * cvm_oct_common_set_mac_address - set the hardware MAC address for a device
- * @dev: The device in question.
- * @addr: Address structure to change it too.
-
- * Returns Zero on success
- */
static int cvm_oct_set_mac_filter(struct net_device *dev)
{
struct octeon_ethernet *priv = netdev_priv(dev);
@@ -401,11 +375,11 @@ static int cvm_oct_set_mac_filter(struct net_device *dev)
&& (cvmx_helper_interface_get_mode(interface) !=
CVMX_HELPER_INTERFACE_MODE_SPI)) {
int i;
- uint8_t *ptr = dev->dev_addr;
- uint64_t mac = 0;
+ u8 *ptr = dev->dev_addr;
+ u64 mac = 0;
for (i = 0; i < 6; i++)
- mac = (mac << 8) | (uint64_t)ptr[i];
+ mac = (mac << 8) | (u64)ptr[i];
gmx_cfg.u64 =
cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
@@ -432,6 +406,13 @@ static int cvm_oct_set_mac_filter(struct net_device *dev)
return 0;
}
+/**
+ * cvm_oct_common_set_mac_address - set the hardware MAC address for a device
+ * @dev: The device in question.
+ * @addr: Socket address.
+ *
+ * Returns Zero on success
+ */
static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
{
int r = eth_mac_addr(dev, addr);
@@ -468,11 +449,8 @@ int cvm_oct_common_init(struct net_device *dev)
&& (always_use_pow || strstr(pow_send_list, dev->name)))
priv->queue = -1;
- if (priv->queue != -1) {
- dev->features |= NETIF_F_SG;
- if (USE_HW_TCPUDP_CHECKSUM)
- dev->features |= NETIF_F_IP_CSUM;
- }
+ if (priv->queue != -1)
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
/* We do our own locking, Linux doesn't need to */
dev->features |= NETIF_F_LLTX;
@@ -488,6 +466,9 @@ int cvm_oct_common_init(struct net_device *dev)
memset(dev->netdev_ops->ndo_get_stats(dev), 0,
sizeof(struct net_device_stats));
+ if (dev->netdev_ops->ndo_stop)
+ dev->netdev_ops->ndo_stop(dev);
+
return 0;
}
@@ -499,6 +480,70 @@ void cvm_oct_common_uninit(struct net_device *dev)
phy_disconnect(priv->phydev);
}
+int cvm_oct_common_open(struct net_device *dev,
+ void (*link_poll)(struct net_device *))
+{
+ union cvmx_gmxx_prtx_cfg gmx_cfg;
+ struct octeon_ethernet *priv = netdev_priv(dev);
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+ cvmx_helper_link_info_t link_info;
+ int rv;
+
+ rv = cvm_oct_phy_setup_device(dev);
+ if (rv)
+ return rv;
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ gmx_cfg.s.en = 1;
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+
+ if (octeon_is_simulation())
+ return 0;
+
+ if (priv->phydev) {
+ int r = phy_read_status(priv->phydev);
+
+ if (r == 0 && priv->phydev->link == 0)
+ netif_carrier_off(dev);
+ cvm_oct_adjust_link(dev);
+ } else {
+ link_info = cvmx_helper_link_get(priv->port);
+ if (!link_info.s.link_up)
+ netif_carrier_off(dev);
+ priv->poll = link_poll;
+ link_poll(dev);
+ }
+
+ return 0;
+}
+
+void cvm_oct_link_poll(struct net_device *dev)
+{
+ struct octeon_ethernet *priv = netdev_priv(dev);
+ cvmx_helper_link_info_t link_info;
+
+ link_info = cvmx_helper_link_get(priv->port);
+ if (link_info.u64 == priv->link_info)
+ return;
+
+ link_info = cvmx_helper_link_autoconf(priv->port);
+ priv->link_info = link_info.u64;
+
+ if (link_info.s.link_up) {
+ if (!netif_carrier_ok(dev))
+ netif_carrier_on(dev);
+ } else if (netif_carrier_ok(dev)) {
+ netif_carrier_off(dev);
+ }
+ cvm_oct_note_carrier(priv, link_info);
+}
+
+static int cvm_oct_xaui_open(struct net_device *dev)
+{
+ return cvm_oct_common_open(dev, cvm_oct_link_poll);
+}
+
static const struct net_device_ops cvm_oct_npi_netdev_ops = {
.ndo_init = cvm_oct_common_init,
.ndo_uninit = cvm_oct_common_uninit,
@@ -513,10 +558,10 @@ static const struct net_device_ops cvm_oct_npi_netdev_ops = {
#endif
};
static const struct net_device_ops cvm_oct_xaui_netdev_ops = {
- .ndo_init = cvm_oct_xaui_init,
- .ndo_uninit = cvm_oct_xaui_uninit,
+ .ndo_init = cvm_oct_common_init,
+ .ndo_uninit = cvm_oct_common_uninit,
.ndo_open = cvm_oct_xaui_open,
- .ndo_stop = cvm_oct_xaui_stop,
+ .ndo_stop = cvm_oct_common_stop,
.ndo_start_xmit = cvm_oct_xmit,
.ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
@@ -529,9 +574,9 @@ static const struct net_device_ops cvm_oct_xaui_netdev_ops = {
};
static const struct net_device_ops cvm_oct_sgmii_netdev_ops = {
.ndo_init = cvm_oct_sgmii_init,
- .ndo_uninit = cvm_oct_sgmii_uninit,
+ .ndo_uninit = cvm_oct_common_uninit,
.ndo_open = cvm_oct_sgmii_open,
- .ndo_stop = cvm_oct_sgmii_stop,
+ .ndo_stop = cvm_oct_common_stop,
.ndo_start_xmit = cvm_oct_xmit,
.ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
@@ -559,7 +604,7 @@ static const struct net_device_ops cvm_oct_rgmii_netdev_ops = {
.ndo_init = cvm_oct_rgmii_init,
.ndo_uninit = cvm_oct_rgmii_uninit,
.ndo_open = cvm_oct_rgmii_open,
- .ndo_stop = cvm_oct_rgmii_stop,
+ .ndo_stop = cvm_oct_common_stop,
.ndo_start_xmit = cvm_oct_xmit,
.ndo_set_rx_mode = cvm_oct_common_set_multicast_list,
.ndo_set_mac_address = cvm_oct_common_set_mac_address,
@@ -625,7 +670,6 @@ static int cvm_oct_probe(struct platform_device *pdev)
struct device_node *pip;
octeon_mdiobus_force_mod_depencency();
- pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
pip = pdev->dev.of_node;
if (!pip) {
@@ -634,7 +678,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
}
cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet");
- if (cvm_oct_poll_queue == NULL) {
+ if (!cvm_oct_poll_queue) {
pr_err("octeon-ethernet: Cannot create workqueue");
return -ENOMEM;
}
@@ -795,7 +839,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
cvm_oct_device[priv->port] = dev;
fau -=
cvmx_pko_get_num_queues(priv->port) *
- sizeof(uint32_t);
+ sizeof(u32);
queue_delayed_work(cvm_oct_poll_queue,
&priv->port_periodic_work, HZ);
}
@@ -820,7 +864,10 @@ static int cvm_oct_remove(struct platform_device *pdev)
int port;
/* Disable POW interrupt */
- cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0);
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), 0);
+ else
+ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0);
cvmx_ipd_disable();
diff --git a/kernel/drivers/staging/octeon/octeon-ethernet.h b/kernel/drivers/staging/octeon/octeon-ethernet.h
index f48dc766f..fdf24d120 100644
--- a/kernel/drivers/staging/octeon/octeon-ethernet.h
+++ b/kernel/drivers/staging/octeon/octeon-ethernet.h
@@ -1,29 +1,12 @@
-/**********************************************************************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
+/*
+ * This file is based on code from OCTEON SDK by Cavium Networks.
*
* Copyright (c) 2003-2010 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
-**********************************************************************/
+ */
/*
* External interface for the Cavium Octeon ethernet driver.
@@ -33,6 +16,8 @@
#include <linux/of.h>
+#include <asm/octeon/cvmx-helper-board.h>
+
/**
* This is the definition of the Ethernet driver's private
* driver state stored in netdev_priv(dev).
@@ -58,7 +43,7 @@ struct octeon_ethernet {
struct phy_device *phydev;
unsigned int last_link;
/* Last negotiated link state */
- uint64_t link_info;
+ u64 link_info;
/* Called periodically to check link status */
void (*poll)(struct net_device *dev);
struct delayed_work port_periodic_work;
@@ -68,27 +53,25 @@ struct octeon_ethernet {
int cvm_oct_free_work(void *work_queue_entry);
-extern int cvm_oct_rgmii_init(struct net_device *dev);
-extern void cvm_oct_rgmii_uninit(struct net_device *dev);
-extern int cvm_oct_rgmii_open(struct net_device *dev);
-extern int cvm_oct_rgmii_stop(struct net_device *dev);
+int cvm_oct_rgmii_init(struct net_device *dev);
+void cvm_oct_rgmii_uninit(struct net_device *dev);
+int cvm_oct_rgmii_open(struct net_device *dev);
-extern int cvm_oct_sgmii_init(struct net_device *dev);
-extern void cvm_oct_sgmii_uninit(struct net_device *dev);
-extern int cvm_oct_sgmii_open(struct net_device *dev);
-extern int cvm_oct_sgmii_stop(struct net_device *dev);
+int cvm_oct_sgmii_init(struct net_device *dev);
+int cvm_oct_sgmii_open(struct net_device *dev);
-extern int cvm_oct_spi_init(struct net_device *dev);
-extern void cvm_oct_spi_uninit(struct net_device *dev);
-extern int cvm_oct_xaui_init(struct net_device *dev);
-extern void cvm_oct_xaui_uninit(struct net_device *dev);
-extern int cvm_oct_xaui_open(struct net_device *dev);
-extern int cvm_oct_xaui_stop(struct net_device *dev);
+int cvm_oct_spi_init(struct net_device *dev);
+void cvm_oct_spi_uninit(struct net_device *dev);
-extern int cvm_oct_common_init(struct net_device *dev);
-extern void cvm_oct_common_uninit(struct net_device *dev);
+int cvm_oct_common_init(struct net_device *dev);
+void cvm_oct_common_uninit(struct net_device *dev);
void cvm_oct_adjust_link(struct net_device *dev);
int cvm_oct_common_stop(struct net_device *dev);
+int cvm_oct_common_open(struct net_device *dev,
+ void (*link_poll)(struct net_device *));
+void cvm_oct_note_carrier(struct octeon_ethernet *priv,
+ cvmx_helper_link_info_t li);
+void cvm_oct_link_poll(struct net_device *dev);
extern int always_use_pow;
extern int pow_send_group;