Skip to contentSkip to conversation

sfc: Add support for SFC9000 family (2)

PATCH Applied Ben Hutchings 2 participants 2 messages Nov 30, 2009

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 10/12 sfc: Add support for SFC9000 family (2)

This integrates support for the SFC9000 family of 10G Ethernet controllers and LAN-on-motherboard chips, starting with the SFL9021 'Siena' and SFC9020 'Bethpage'.

Credit for this code is largely due to my colleagues at Solarflare:

Guido Barzini
Steve Hodgson
Kieran Mansley
Matthew Slattery
Neil Turton

---
 drivers/net/sfc/Kconfig       |   13 +-
 drivers/net/sfc/Makefile      |    7 +-
 drivers/net/sfc/bitfield.h    |    2 +
 drivers/net/sfc/efx.c         |   26 ++++
 drivers/net/sfc/efx.h         |    2 +
 drivers/net/sfc/enum.h        |    2 +
 drivers/net/sfc/ethtool.c     |    3 +
 drivers/net/sfc/mac.h         |    3 +
 drivers/net/sfc/mtd.c         |  267 ++++++++++++++++++++++++++++++++++++++++-
 drivers/net/sfc/net_driver.h  |   10 ++-
 drivers/net/sfc/nic.c         |   63 ++++++++--
 drivers/net/sfc/nic.h         |   23 ++++
 drivers/net/sfc/phy.h         |   17 +++
 drivers/net/sfc/workarounds.h |    5 +
 14 files changed, 414 insertions(+), 29 deletions(-)
drivers/net/sfc/Kconfig +7 -6
index 260aafa..a65c986 100644
@@ -1,5 +1,5 @@
 config SFC
-	tristate "Solarflare Solarstorm SFC4000 support"
+	tristate "Solarflare Solarstorm SFC4000/SFC9000-family support"
 	depends on PCI && INET
 	select MDIO
 	select CRC32
@@ -7,15 +7,16 @@ config SFC
 	select I2C_ALGOBIT
 	help
 	  This driver supports 10-gigabit Ethernet cards based on
-	  the Solarflare Communications Solarstorm SFC4000 controller.
+	  the Solarflare Communications Solarstorm SFC4000 and
+	  SFC9000-family controllers.
 
 	  To compile this driver as a module, choose M here.  The module
 	  will be called sfc.
 config SFC_MTD
-	bool "Solarflare Solarstorm SFC4000 flash MTD support"
+	bool "Solarflare Solarstorm SFC4000/SFC9000-family MTD support"
 	depends on SFC && MTD && !(SFC=y && MTD=m)
 	default y
 	help
-	  This exposes the on-board flash memory as an MTD device (e.g.
-          /dev/mtd1).  This makes it possible to upload new boot code
-          to the NIC.
+	  This exposes the on-board flash memory as MTD devices (e.g.
+	  /dev/mtd1).  This makes it possible to upload new firmware
+	  to the NIC.
drivers/net/sfc/Makefile +4 -3
index 223106b..1047b19 100644
@@ -1,6 +1,7 @@
-sfc-y			+= efx.o nic.o falcon.o tx.o rx.o falcon_gmac.o \
-			   falcon_xmac.o selftest.o ethtool.o qt202x_phy.o \
-			   mdio_10g.o tenxpress.o falcon_boards.o
+sfc-y			+= efx.o nic.o falcon.o siena.o tx.o rx.o \
+			   falcon_gmac.o falcon_xmac.o mcdi_mac.o \
+			   selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
+			   tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o
 sfc-$(CONFIG_SFC_MTD)	+= mtd.o
 
 obj-$(CONFIG_SFC)	+= sfc.o
drivers/net/sfc/bitfield.h +2 -0
index 6ad909b..bb5de4f 100644
@@ -37,6 +37,8 @@
 #define EFX_DWORD_2_WIDTH 32
 #define EFX_DWORD_3_LBN 96
 #define EFX_DWORD_3_WIDTH 32
+#define EFX_QWORD_0_LBN 0
+#define EFX_QWORD_0_WIDTH 64
 
 /* Specified attribute (e.g. LBN) of the specified field */
 #define EFX_VAL(field, attribute) field ## _ ## attribute
drivers/net/sfc/efx.c +26 -0
index 97a6ebd..4b5c786 100644
@@ -25,6 +25,8 @@
 #include "mdio_10g.h"
 #include "nic.h"
 
+#include "mcdi.h"
+
 /**************************************************************************
  *
  * Type name strings
@@ -84,6 +86,7 @@ const char *efx_reset_type_names[] = {
 	[RESET_TYPE_RX_DESC_FETCH] = "RX_DESC_FETCH",
 	[RESET_TYPE_TX_DESC_FETCH] = "TX_DESC_FETCH",
 	[RESET_TYPE_TX_SKIP]       = "TX_SKIP",
+	[RESET_TYPE_MC_FAILURE]    = "MC_FAILURE",
 };
 
 #define EFX_MAX_MTU (9 * 1024)
@@ -1191,6 +1194,15 @@ static void efx_start_all(struct efx_nic *efx)
 
 	efx_nic_enable_interrupts(efx);
 
+	/* Switch to event based MCDI completions after enabling interrupts.
+	 * If a reset has been scheduled, then we need to stay in polled mode.
+	 * Rather than serialising efx_mcdi_mode_event() [which sleeps] and
+	 * reset_pending [modified from an atomic context], we instead guarantee
+	 * that efx_mcdi_mode_poll() isn't reverted erroneously */
+	efx_mcdi_mode_event(efx);
+	if (efx->reset_pending != RESET_TYPE_NONE)
+		efx_mcdi_mode_poll(efx);
+
 	/* Start the hardware monitor if there is one. Otherwise (we're link
 	 * event driven), we have to poll the PHY because after an event queue
 	 * flush, we could have a missed a link state change */
@@ -1242,6 +1254,9 @@ static void efx_stop_all(struct efx_nic *efx)
 
 	efx->type->stop_stats(efx);
 
+	/* Switch to MCDI polling on Siena before disabling interrupts */
+	efx_mcdi_mode_poll(efx);
+
 	/* Disable interrupts and wait for ISR to complete */
 	efx_nic_disable_interrupts(efx);
 	if (efx->legacy_irq)
@@ -1445,6 +1460,8 @@ static int efx_net_open(struct net_device *net_dev)
 		return -EIO;
 	if (efx->phy_mode & PHY_MODE_SPECIAL)
 		return -EBUSY;
+	if (efx_mcdi_poll_reboot(efx) && efx_reset(efx, RESET_TYPE_ALL))
+		return -EIO;
 
 	/* Notify the kernel of the link state polled during driver load,
 	 * before the monitor starts running */
@@ -1895,6 +1912,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
 	case RESET_TYPE_TX_SKIP:
 		method = RESET_TYPE_INVISIBLE;
 		break;
+	case RESET_TYPE_MC_FAILURE:
 	default:
 		method = RESET_TYPE_ALL;
 		break;
@@ -1908,6 +1926,10 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
 
 	efx->reset_pending = method;
 
+	/* efx_process_channel() will no longer read events once a
+	 * reset is scheduled. So switch back to poll'd MCDI completions. */
+	efx_mcdi_mode_poll(efx);
+
 	queue_work(reset_workqueue, &efx->reset_work);
 }
 
@@ -1923,6 +1945,10 @@ static struct pci_device_id efx_pci_table[] __devinitdata = {
 	 .driver_data = (unsigned long) &falcon_a1_nic_type},
 	{PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID),
 	 .driver_data = (unsigned long) &falcon_b0_nic_type},
+	{PCI_DEVICE(EFX_VENDID_SFC, BETHPAGE_A_P_DEVID),
+	 .driver_data = (unsigned long) &siena_a0_nic_type},
+	{PCI_DEVICE(EFX_VENDID_SFC, SIENA_A_P_DEVID),
+	 .driver_data = (unsigned long) &siena_a0_nic_type},
 	{0}			/* end of list */
 };
 
drivers/net/sfc/efx.h +2 -0
index fa40c7b..b4470da 100644
@@ -18,6 +18,8 @@
 #define FALCON_A_P_DEVID	0x0703
 #define FALCON_A_S_DEVID        0x6703
 #define FALCON_B_P_DEVID        0x0710
+#define BETHPAGE_A_P_DEVID      0x0803
+#define SIENA_A_P_DEVID         0x0813
 
 /* Solarstorm controllers use BAR 0 for I/O space and BAR 2(&3) for memory */
 #define EFX_MEM_BAR 2
drivers/net/sfc/enum.h +2 -0
index 7a9e79a..b1f7a40 100644
@@ -144,6 +144,7 @@ enum efx_loopback_mode {
  * @RESET_TYPE_RX_DESC_FETCH: pcie error during rx descriptor fetch
  * @RESET_TYPE_TX_DESC_FETCH: pcie error during tx descriptor fetch
  * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors
+ * @RESET_TYPE_MC_FAILURE: MC reboot/assertion
  */
 enum reset_type {
 	RESET_TYPE_NONE = -1,
@@ -158,6 +159,7 @@ enum reset_type {
 	RESET_TYPE_RX_DESC_FETCH,
 	RESET_TYPE_TX_DESC_FETCH,
 	RESET_TYPE_TX_SKIP,
+	RESET_TYPE_MC_FAILURE,
 	RESET_TYPE_MAX,
 };
 
drivers/net/sfc/ethtool.c +3 -0
index 012ee31..5492b63 100644
@@ -236,6 +236,9 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
 
 	strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver));
 	strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
+	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
+		siena_print_fwver(efx, info->fw_version,
+				  sizeof(info->fw_version));
 	strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
 }
 
drivers/net/sfc/mac.h +3 -0
index d2af50f..c733863 100644
@@ -15,6 +15,9 @@
 
 extern struct efx_mac_operations falcon_gmac_operations;
 extern struct efx_mac_operations falcon_xmac_operations;
+extern struct efx_mac_operations efx_mcdi_mac_operations;
 extern void falcon_reconfigure_xmac_core(struct efx_nic *efx);
+extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
+			      u32 dma_len, int enable, int clear);
 
 #endif
drivers/net/sfc/mtd.c +262 -5

305 lines not on this page · raw message

drivers/net/sfc/net_driver.h +9 -1
index 96d3f00..ec13203 100644
@@ -706,6 +706,7 @@ union efx_multicast_hash {
  * @phy_op: PHY interface
  * @phy_data: PHY private data (including PHY-specific stats)
  * @mdio: PHY MDIO interface
+ * @mdio_bus: PHY MDIO bus ID (only used by Siena)
  * @phy_mode: PHY operating mode. Serialised by @mac_lock.
  * @xmac_poll_required: XMAC link state needs polling
  * @link_advertising: Autonegotiation advertising flags
@@ -756,6 +757,7 @@ struct efx_nic {
 
 	struct efx_buffer irq_status;
 	volatile signed int last_irq_cpu;
+	unsigned long irq_zero_count;
 
 	struct efx_spi_device *spi_flash;
 	struct efx_spi_device *spi_eeprom;
@@ -766,7 +768,7 @@ struct efx_nic {
 
 	unsigned n_rx_nodesc_drop_cnt;
 
-	struct falcon_nic_data *nic_data;
+	void *nic_data;
 
 	struct mutex mac_lock;
 	struct work_struct mac_work;
@@ -792,6 +794,7 @@ struct efx_nic {
 	struct efx_phy_operations *phy_op;
 	void *phy_data;
 	struct mdio_if_info mdio;
+	unsigned int mdio_bus;
 	enum efx_phy_mode phy_mode;
 
 	bool xmac_poll_required;
@@ -824,6 +827,11 @@ static inline const char *efx_dev_name(struct efx_nic *efx)
 	return efx_dev_registered(efx) ? efx->name : "";
 }
 
+static inline unsigned int efx_port_num(struct efx_nic *efx)
+{
+	return PCI_FUNC(efx->pci_dev->devfn);
+}
+
 /**
  * struct efx_nic_type - Efx device type definition
  * @probe: Probe the controller
drivers/net/sfc/nic.c +49 -14

115 lines not on this page · raw message

drivers/net/sfc/nic.h +23 -0
index e7eb304..57c510d 100644
@@ -14,6 +14,7 @@
 #include <linux/i2c-algo-bit.h>
 #include "net_driver.h"
 #include "efx.h"
+#include "mcdi.h"
 
 /*
  * Falcon hardware control
@@ -23,6 +24,7 @@ enum {
 	EFX_REV_FALCON_A0 = 0,
 	EFX_REV_FALCON_A1 = 1,
 	EFX_REV_FALCON_B0 = 2,
+	EFX_REV_SIENA_A0 = 3,
 };
 
 static inline int efx_nic_rev(struct efx_nic *efx)
@@ -32,6 +34,10 @@ static inline int efx_nic_rev(struct efx_nic *efx)
 
 extern u32 efx_nic_fpga_ver(struct efx_nic *efx);
 
+static inline bool efx_nic_has_mc(struct efx_nic *efx)
+{
+	return efx_nic_rev(efx) >= EFX_REV_SIENA_A0;
+}
 /* NIC has two interlinked PCI functions for the same port. */
 static inline bool efx_nic_is_dual_func(struct efx_nic *efx)
 {
@@ -123,8 +129,25 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
 	return &data->board;
 }
 
+/**
+ * struct siena_nic_data - Siena NIC state
+ * @fw_version: Management controller firmware version
+ * @fw_build: Firmware build number
+ * @mcdi: Management-Controller-to-Driver Interface
+ * @wol_filter_id: Wake-on-LAN packet filter id
+ */
+struct siena_nic_data {
+	u64 fw_version;
+	u32 fw_build;
+	struct efx_mcdi_iface mcdi;
+	int wol_filter_id;
+};
+
+extern void siena_print_fwver(struct efx_nic *efx, char *buf, size_t len);
+
 extern struct efx_nic_type falcon_a1_nic_type;
 extern struct efx_nic_type falcon_b0_nic_type;
+extern struct efx_nic_type siena_a0_nic_type;
 
 /**************************************************************************
  *
drivers/net/sfc/phy.h +17 -0
index 2ad1cec..64dff2d 100644
@@ -41,4 +41,21 @@ extern struct efx_phy_operations falcon_qt202x_phy_ops;
 
 extern void falcon_qt202x_set_led(struct efx_nic *p, int led, int state);
 
+/****************************************************************************
+ * Siena managed PHYs
+ */
+extern struct efx_phy_operations efx_mcdi_phy_ops;
+
+extern int efx_mcdi_mdio_read(struct efx_nic *efx, unsigned int bus,
+			      unsigned int prtad, unsigned int devad,
+			      u16 addr, u16 *value_out, u32 *status_out);
+extern int efx_mcdi_mdio_write(struct efx_nic *efx, unsigned int bus,
+			       unsigned int prtad, unsigned int devad,
+			       u16 addr, u16 value, u32 *status_out);
+extern void efx_mcdi_phy_decode_link(struct efx_nic *efx,
+				     struct efx_link_state *link_state,
+				     u32 speed, u32 flags, u32 fcntl);
+extern int efx_mcdi_phy_reconfigure(struct efx_nic *efx);
+extern void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa);
+
 #endif
drivers/net/sfc/workarounds.h +5 -0
index 021d0d2..ecee8f5 100644
@@ -18,6 +18,7 @@
 #define EFX_WORKAROUND_ALWAYS(efx) 1
 #define EFX_WORKAROUND_FALCON_A(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_A1)
 #define EFX_WORKAROUND_FALCON_AB(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_B0)
+#define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0)
 #define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
 #define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \
 				     (efx)->phy_type == PHY_TYPE_SFT9001B)
@@ -35,6 +36,10 @@
 #define EFX_WORKAROUND_11482 EFX_WORKAROUND_FALCON_AB
 /* Truncated IPv4 packets can confuse the TX packet parser */
 #define EFX_WORKAROUND_15592 EFX_WORKAROUND_FALCON_AB
+/* Legacy ISR read can return zero once */
+#define EFX_WORKAROUND_15783 EFX_WORKAROUND_SIENA
+/* Legacy interrupt storm when interrupt fifo fills */
+#define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA
 
 /* Spurious parity errors in TSORT buffers */
 #define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A
Signature · 9 lines
1.6.5.3




-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
maintainer Applied
#1 lore raw

From: Ben Hutchings <[email protected]>
Date: Mon, 30 Nov 2009 01:15:41 +0000

Quoted 6 lines

This integrates support for the SFC9000 family of 10G Ethernet controllers and LAN-on-motherboard chips, starting with the SFL9021 'Siena' and SFC9020 'Bethpage'.

Credit for this code is largely due to my colleagues at Solarflare:

Quoted 7 lines

Guido Barzini
Steve Hodgson
Kieran Mansley
Matthew Slattery
Neil Turton

Applied.