Skip to contentSkip to conversation

sfc version 2.3

PATCH Applied Ben Hutchings 2 participants 74 messages Dec 12, 2008 – Dec 13, 2008 1 message not in the archive

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

cover sfc version 2.3

The big changes here are to add support for Solarflare's new multi-speed PHY and reference design. There are also a number of small fixes, clean- up and new features.

Ben.

Ben Hutchings (31):
sfc: Board support fixes
sfc: Change SPI lengths to type size_t
sfc: Do not use pci_disable_device() to disable bus mastering
sfc: Remove unneeded register write
sfc: Correct interpretation of second param to ethtool phys_id()
sfc: Clean up waits for flash/EEPROM operations
sfc: Work around unreliable strap pins
sfc: Restore phy_flash_cfg module parameter
sfc: Provide hints to irqbalance daemon
sfc: Abbreviate self-test names so they are not truncated
sfc: Don't count RX checksum errors during loopback self-test
sfc: Remove MII extension cruft
sfc: Add support for MMDs numbered >15
sfc: Add phy_type device attribute
sfc: Clean up board identification
sfc: Clean up MDIO flag setting
sfc: Add support for sub-10G speeds
sfc: Implement auto-negotiation
sfc: Rework MAC, PHY and board event handling
sfc: Add support for Solarflare 10Xpress SFT9001
sfc: Add support for SFN4111T
sfc: Fix format arguments for warning about MSI-X allocation
sfc: Generate unique names for per-NIC workqueues
sfc: Remove leading spaces
sfc: Specify a meaningful component for loopback RX-side and PHY
tests
sfc: Use mutex_lock_interruptible() for ethtool EEPROM access
sfc: Use model numbers for PHY type names
sfc: Treat probe as unsuccessful if it scheduled a reset
sfc: Use kzalloc() to ensure struct efx_spi_device is fully
initialised
sfc: Fix synchronisation of efx_mtd_{probe,rename,remove}
sfc: Version 2.3

Neil Turton (1):
sfc: Add option to use a separate channel for TX completions

Steve Hodgson (1):
sfc: Make reset_workqueue driver-global rather than per-NIC

 drivers/net/sfc/Makefile        |    4 +-
 drivers/net/sfc/boards.c        |   70 ++---
 drivers/net/sfc/boards.h        |   14 +-
 drivers/net/sfc/efx.c           |  331 ++++++++++++-------
 drivers/net/sfc/enum.h          |   32 +-
 drivers/net/sfc/ethtool.c       |  137 ++++++---
 drivers/net/sfc/falcon.c        |  472 ++++++++++++++++-----------
 drivers/net/sfc/falcon.h        |    3 +
 drivers/net/sfc/falcon_gmac.c   |  229 +++++++++++++
 drivers/net/sfc/falcon_hwdefs.h |  160 +++++++++
 drivers/net/sfc/falcon_xmac.c   |  261 +++------------
 drivers/net/sfc/gmii.h          |  137 +--------
 drivers/net/sfc/mac.h           |   16 +-
 drivers/net/sfc/mdio_10g.c      |  453 ++++++++++++++++++--------
 drivers/net/sfc/mdio_10g.h      |   52 +++-
 drivers/net/sfc/mtd.c           |    2 +-
 drivers/net/sfc/net_driver.h    |  113 ++++++-
 drivers/net/sfc/phy.h           |    7 +-
 drivers/net/sfc/selftest.c      |   41 ++-
 drivers/net/sfc/selftest.h      |    2 -
 drivers/net/sfc/sfe4001.c       |  153 +++++++--
 drivers/net/sfc/spi.h           |    2 +-
 drivers/net/sfc/tenxpress.c     |  686 +++++++++++++++++++++++++++++----------
 drivers/net/sfc/workarounds.h   |   12 +-
 drivers/net/sfc/xfp_phy.c       |   38 +--
 25 files changed, 2232 insertions(+), 1195 deletions(-)
 create mode 100644 drivers/net/sfc/falcon_gmac.c
Signature · 3 lines
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.
#1 lore raw

PATCH 1/33 sfc: Board support fixes

Set dummy monitor method for unrecognised boards.

Clean up board resources if efx_pci_probe_main() fails after board has been initialised.

---
 drivers/net/sfc/efx.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/net/sfc/efx.c +2 -0
index e5024bb..bbc8402 100644
@@ -1743,6 +1743,7 @@ static struct efx_board efx_dummy_board_info = {
 	.init		= efx_port_dummy_op_int,
 	.init_leds	= efx_port_dummy_op_int,
 	.set_fault_led	= efx_port_dummy_op_blink,
+	.monitor	= efx_port_dummy_op_int,
 	.blink		= efx_port_dummy_op_blink,
 	.fini		= efx_port_dummy_op_void,
 };
@@ -1983,6 +1984,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
 	efx_fini_port(efx);
  fail5:
  fail4:
+	efx->board_info.fini(efx);
  fail3:
 	efx_fini_napi(efx);
  fail2:
Signature · 3 lines
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
#2 lore raw

Re: [PATCH 01/33] sfc: Board support fixes

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:48:26 +0000

Quoted 6 lines

Set dummy monitor method for unrecognised boards.

Clean up board resources if efx_pci_probe_main() fails after board has been initialised.

Applied.

#3 lore raw

PATCH 2/33 sfc: Change SPI lengths to type size_t

In reply to Ben Hutchings

Based on a patch by Andrew Morton.

---
 drivers/net/sfc/falcon.c |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)
drivers/net/sfc/falcon.c +10 -9
index 71e0bed..271cbf8 100644
@@ -1605,7 +1605,7 @@ void falcon_fini_interrupt(struct efx_nic *efx)
  **************************************************************************
  */
 
-#define FALCON_SPI_MAX_LEN ((unsigned) sizeof(efx_oword_t))
+#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
 
 /* Wait for SPI command completion */
 static int falcon_spi_wait(struct efx_nic *efx)
@@ -1630,7 +1630,7 @@ static int falcon_spi_wait(struct efx_nic *efx)
 
 int falcon_spi_cmd(const struct efx_spi_device *spi,
 		   unsigned int command, int address,
-		   const void *in, void *out, unsigned int len)
+		   const void *in, void *out, size_t len)
 {
 	struct efx_nic *efx = spi->efx;
 	bool addressed = (address >= 0);
@@ -1686,8 +1686,8 @@ int falcon_spi_cmd(const struct efx_spi_device *spi,
 	return 0;
 }
 
-static unsigned int
-falcon_spi_write_limit(const struct efx_spi_device *spi, unsigned int start)
+static size_t
+falcon_spi_write_limit(const struct efx_spi_device *spi, size_t start)
 {
 	return min(FALCON_SPI_MAX_LEN,
 		   (spi->block_size - (start & (spi->block_size - 1))));
@@ -1725,12 +1725,12 @@ int falcon_spi_fast_wait(const struct efx_spi_device *spi)
 int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
 		    size_t len, size_t *retlen, u8 *buffer)
 {
-	unsigned int command, block_len, pos = 0;
+	size_t block_len, pos = 0;
+	unsigned int command;
 	int rc = 0;
 
 	while (pos < len) {
-		block_len = min((unsigned int)len - pos,
-				FALCON_SPI_MAX_LEN);
+		block_len = min(len - pos, FALCON_SPI_MAX_LEN);
 
 		command = efx_spi_munge_command(spi, SPI_READ, start + pos);
 		rc = falcon_spi_cmd(spi, command, start + pos, NULL,
@@ -1756,7 +1756,8 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
 		     size_t len, size_t *retlen, const u8 *buffer)
 {
 	u8 verify_buffer[FALCON_SPI_MAX_LEN];
-	unsigned int command, block_len, pos = 0;
+	size_t block_len, pos = 0;
+	unsigned int command;
 	int rc = 0;
 
 	while (pos < len) {
@@ -1764,7 +1765,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
 		if (rc)
 			break;
 
-		block_len = min((unsigned int)len - pos,
+		block_len = min(len - pos,
 				falcon_spi_write_limit(spi, start + pos));
 		command = efx_spi_munge_command(spi, SPI_WRITE, start + pos);
 		rc = falcon_spi_cmd(spi, command, start + pos,
Signature · 3 lines
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
#5 lore raw

Re: [PATCH 02/33] sfc: Change SPI lengths to type size_t

In reply to Ben Hutchings

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:48:51 +0000

Quoted 3 lines

Based on a patch by Andrew Morton.

Sigh, this isn't what you actually build tested, that's for sure:

drivers/net/sfc/falcon.c:1664: error: conflicting types for 'falcon_spi_cmd' drivers/net/sfc/spi.h:71: error: previous declaration of 'falcon_spi_cmd' was here

I'll fix it up this time, but never will I do this again.

Test what you send me.

#6 lore raw

Re: [PATCH 02/33] sfc: Change SPI lengths to type size_t

Quoted 9 lines · David Miller

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:48:51 +0000

Quoted 3 lines

Based on a patch by Andrew Morton.

Sigh, this isn't what you actually build tested, that's for sure:

Of course it is. But it looks like I forgot to test the final version of this patch on a 64-bit architecture. On i386 size_t = unsigned.

Quoted 4 lines

drivers/net/sfc/falcon.c:1664: error: conflicting types for 'falcon_spi_cmd' drivers/net/sfc/spi.h:71: error: previous declaration of 'falcon_spi_cmd' was here

I'll fix it up this time, but never will I do this again.

Thanks.

Ben.

Quoted 1 line

Test what you send me.

Signature · 3 lines
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.
#7 lore raw

PATCH 3/33 sfc: Do not use pci_disable_device() to disable bus mastering

In reply to Ben Hutchings

pci_disable_device() disables many features, like MSI-X, which we never reenable in efx_reset(). Further, calls to pci_enable_device() and pci_disable_device() must be matched since the nesting count was introduced.

---
 drivers/net/sfc/falcon.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)
drivers/net/sfc/falcon.c +13 -2
index 271cbf8..ac0b671 100644
@@ -1344,6 +1344,17 @@ static inline void falcon_irq_ack_a1(struct efx_nic *efx)
 	falcon_readl(efx, &reg, WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1);
 }
 
+static void efx_pci_clear_master(struct pci_dev *dev)
+{
+	u16 command;
+
+	if (dev->is_busmaster &&
+	    !pci_read_config_word(dev, PCI_COMMAND, &command) &&
+	    !pci_write_config_word(dev, PCI_COMMAND,
+				   command & ~PCI_COMMAND_MASTER))
+		dev->is_busmaster = false;
+}
+
 /* Process a fatal interrupt
  * Disable bus mastering ASAP and schedule a reset
  */
@@ -1375,9 +1386,9 @@ static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx)
 	}
 
 	/* Disable both devices */
-	pci_disable_device(efx->pci_dev);
+	efx_pci_clear_master(efx->pci_dev);
 	if (FALCON_IS_DUAL_FUNC(efx))
-		pci_disable_device(nic_data->pci_dev2);
+		efx_pci_clear_master(nic_data->pci_dev2);
 	falcon_disable_interrupts(efx);
 
 	if (++n_int_errors < FALCON_MAX_INT_ERRORS) {
Signature · 3 lines
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
#8 lore raw

Re: [PATCH 03/33] sfc: Do not use pci_disable_device() to disable bus mastering

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:49:14 +0000

Quoted 6 lines

pci_disable_device() disables many features, like MSI-X, which we never reenable in efx_reset(). Further, calls to pci_enable_device() and pci_disable_device() must be matched since the nesting count was introduced.

Since the PCI layer provides interfaces which do manage this setting, there is no way you should be doing this behind it's back.

You know why?

Because someone is going to change some of the internals of this stuff in the PIC layer and it will break your driver.

Please instead submit an interface to the PCI layer maintainers that does what you want, then use it.

Patch not applied.

#9 lore raw

Re: [PATCH 03/33] sfc: Do not use pci_disable_device() to disable bus mastering

Quoted 14 lines · David Miller

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:49:14 +0000

Quoted 6 lines

pci_disable_device() disables many features, like MSI-X, which we never reenable in efx_reset(). Further, calls to pci_enable_device() and pci_disable_device() must be matched since the nesting count was introduced.

Since the PCI layer provides interfaces which do manage this setting, there is no way you should be doing this behind it's back.

Quoted 8 lines

You know why?

Because someone is going to change some of the internals of this stuff in the PIC layer and it will break your driver.

Please instead submit an interface to the PCI layer maintainers that does what you want, then use it.

I did ask on #linux-pci why this didn't exist; apparently it wasn't considered to be worth providing. So obviously I can submit a patch to the PCI layer but I'm not sure it would be accepted.

Ben.

Quoted 1 line

Patch not applied.

Signature · 3 lines
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.
#10 lore raw

PATCH 4/33 sfc: Remove unneeded register write

In reply to Ben Hutchings

This was only ever needed for an FPGA version of Falcon.

---
 drivers/net/sfc/falcon.c |    9 ---------
 1 files changed, 0 insertions(+), 9 deletions(-)
drivers/net/sfc/falcon.c +0 -9
index ac0b671..3af361a 100644
@@ -2881,15 +2881,6 @@ int falcon_init_nic(struct efx_nic *efx)
 	unsigned thresh;
 	int rc;
 
-	/* Set up the address region register. This is only needed
-	 * for the B0 FPGA, but since we are just pushing in the
-	 * reset defaults this may as well be unconditional. */
-	EFX_POPULATE_OWORD_4(temp, ADR_REGION0, 0,
-				   ADR_REGION1, (1 << 16),
-				   ADR_REGION2, (2 << 16),
-				   ADR_REGION3, (3 << 16));
-	falcon_write(efx, &temp, ADR_REGION_REG_KER);
-
 	/* Use on-chip SRAM */
 	falcon_read(efx, &temp, NIC_STAT_REG);
 	EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
Signature · 3 lines
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.
#12 lore raw

PATCH 5/33 sfc: Correct interpretation of second param to ethtool phys_id()

In reply to Ben Hutchings

A value of 0 means indefinite repetition (until interrupted).

---
 drivers/net/sfc/ethtool.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)
drivers/net/sfc/ethtool.c +6 -2
index cd92c4d..9c533e0 100644
@@ -182,12 +182,16 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = {
  */
 
 /* Identify device by flashing LEDs */
-static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds)
+static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 
 	efx->board_info.blink(efx, 1);
-	schedule_timeout_interruptible(seconds * HZ);
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (count)
+		schedule_timeout(count * HZ);
+	else
+		schedule();
 	efx->board_info.blink(efx, 0);
 	return 0;
 }
Signature · 3 lines
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.
#14 lore raw

PATCH 6/33 sfc: Make reset_workqueue driver-global rather than per-NIC

In reply to Ben Hutchings

From: Steve Hodgson <[email protected]>

Each reset is serialised by the rtnl_lock anyway, so there's no win per-NIC.

---
 drivers/net/sfc/efx.c        |   45 ++++++++++++++++++-----------------------
 drivers/net/sfc/net_driver.h |    2 -
 2 files changed, 20 insertions(+), 27 deletions(-)
drivers/net/sfc/efx.c +20 -25
index bbc8402..127b4da 100644
@@ -39,6 +39,12 @@
  */
 static struct workqueue_struct *refill_workqueue;
 
+/* Reset workqueue. If any NIC has a hardware failure then a reset will be
+ * queued onto this work queue. This is not a per-nic work queue, because
+ * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised.
+ */
+static struct workqueue_struct *reset_workqueue;
+
 /**************************************************************************
  *
  * Configurable values
@@ -1697,7 +1703,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
 
 	efx->reset_pending = method;
 
-	queue_work(efx->reset_workqueue, &efx->reset_work);
+	queue_work(reset_workqueue, &efx->reset_work);
 }
 
 /**************************************************************************
@@ -1763,7 +1769,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 	struct efx_channel *channel;
 	struct efx_tx_queue *tx_queue;
 	struct efx_rx_queue *rx_queue;
-	int i, rc;
+	int i;
 
 	/* Initialise common structures */
 	memset(efx, 0, sizeof(*efx));
@@ -1832,33 +1838,14 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 				  interrupt_mode);
 
 	efx->workqueue = create_singlethread_workqueue("sfc_work");
-	if (!efx->workqueue) {
-		rc = -ENOMEM;
-		goto fail1;
-	}
-
-	efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
-	if (!efx->reset_workqueue) {
-		rc = -ENOMEM;
-		goto fail2;
-	}
+	if (!efx->workqueue)
+		return -ENOMEM;
 
 	return 0;
-
- fail2:
-	destroy_workqueue(efx->workqueue);
-	efx->workqueue = NULL;
-
- fail1:
-	return rc;
 }
 
 static void efx_fini_struct(struct efx_nic *efx)
 {
-	if (efx->reset_workqueue) {
-		destroy_workqueue(efx->reset_workqueue);
-		efx->reset_workqueue = NULL;
-	}
 	if (efx->workqueue) {
 		destroy_workqueue(efx->workqueue);
 		efx->workqueue = NULL;
@@ -1923,7 +1910,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
 	 * scheduled from this point because efx_stop_all() has been
 	 * called, we are no longer registered with driverlink, and
 	 * the net_device's have been removed. */
-	flush_workqueue(efx->reset_workqueue);
+	cancel_work_sync(&efx->reset_work);
 
 	efx_pci_remove_main(efx);
 
@@ -2045,7 +2032,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 		 * scheduled since efx_stop_all() has been called, and we
 		 * have not and never have been registered with either
 		 * the rtnetlink or driverlink layers. */
-		flush_workqueue(efx->reset_workqueue);
+		cancel_work_sync(&efx->reset_work);
 
 		/* Retry if a recoverably reset event has been scheduled */
 		if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
@@ -2121,6 +2108,11 @@ static int __init efx_init_module(void)
 		rc = -ENOMEM;
 		goto err_refill;
 	}
+	reset_workqueue = create_singlethread_workqueue("sfc_reset");
+	if (!reset_workqueue) {
+		rc = -ENOMEM;
+		goto err_reset;
+	}
 
 	rc = pci_register_driver(&efx_pci_driver);
 	if (rc < 0)
@@ -2129,6 +2121,8 @@ static int __init efx_init_module(void)
 	return 0;
 
  err_pci:
+	destroy_workqueue(reset_workqueue);
+ err_reset:
 	destroy_workqueue(refill_workqueue);
  err_refill:
 	unregister_netdevice_notifier(&efx_netdev_notifier);
@@ -2141,6 +2135,7 @@ static void __exit efx_exit_module(void)
 	printk(KERN_INFO "Solarflare NET driver unloading\n");
 
 	pci_unregister_driver(&efx_pci_driver);
+	destroy_workqueue(reset_workqueue);
 	destroy_workqueue(refill_workqueue);
 	unregister_netdevice_notifier(&efx_netdev_notifier);
 
drivers/net/sfc/net_driver.h +0 -2
index e596c9a..f910609 100644
@@ -635,7 +635,6 @@ union efx_multicast_hash {
  * @legacy_irq: IRQ number
  * @workqueue: Workqueue for port reconfigures and the HW monitor.
  *	Work items do not hold and must not acquire RTNL.
- * @reset_workqueue: Workqueue for resets.  Work item will acquire RTNL.
  * @reset_work: Scheduled reset workitem
  * @monitor_work: Hardware monitor workitem
  * @membase_phys: Memory BAR value as physical address
@@ -711,7 +710,6 @@ struct efx_nic {
 	const struct efx_nic_type *type;
 	int legacy_irq;
 	struct workqueue_struct *workqueue;
-	struct workqueue_struct *reset_workqueue;
 	struct work_struct reset_work;
 	struct delayed_work monitor_work;
 	resource_size_t membase_phys;
Signature · 3 lines
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.
#16 lore raw

PATCH 7/33 sfc: Clean up waits for flash/EEPROM operations

In reply to Ben Hutchings

Make falcon_spi_wait() ignore the write timer - it is only relevant to write commands, it only works for the device that contains VPD, and it might not be initialised properly at all.

Rename falcon_spi_fast_wait() to falcon_spi_wait_write(), reflecting its use, and make it wait up to 10 ms (not 1 ms) since buffered writes to EEPROM may take this long to complete.

Make both wait functions sleep instead of busy-waiting.

Replace wait for command completion at top of falcon_spi_cmd() with a single poll; no command should be running when the function starts.

Correct some comments.

---
 drivers/net/sfc/falcon.c |   58 +++++++++++++++++++++++++++++----------------
 drivers/net/sfc/mtd.c    |    2 +-
 drivers/net/sfc/spi.h    |    2 +-
 3 files changed, 39 insertions(+), 23 deletions(-)
drivers/net/sfc/falcon.c +37 -21
index 3af361a..4b2ec12 100644
@@ -1618,24 +1618,37 @@ void falcon_fini_interrupt(struct efx_nic *efx)
 
 #define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
 
+static int falcon_spi_poll(struct efx_nic *efx)
+{
+	efx_oword_t reg;
+	falcon_read(efx, &reg, EE_SPI_HCMD_REG_KER);
+	return EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0;
+}
+
 /* Wait for SPI command completion */
 static int falcon_spi_wait(struct efx_nic *efx)
 {
-	unsigned long timeout = jiffies + DIV_ROUND_UP(HZ, 10);
-	efx_oword_t reg;
-	bool cmd_en, timer_active;
+	/* Most commands will finish quickly, so we start polling at
+	 * very short intervals.  Sometimes the command may have to
+	 * wait for VPD or expansion ROM access outside of our
+	 * control, so we allow up to 100 ms. */
+	unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 10);
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		if (!falcon_spi_poll(efx))
+			return 0;
+		udelay(10);
+	}
 
 	for (;;) {
-		falcon_read(efx, &reg, EE_SPI_HCMD_REG_KER);
-		cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN);
-		timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE);
-		if (!cmd_en && !timer_active)
+		if (!falcon_spi_poll(efx))
 			return 0;
 		if (time_after_eq(jiffies, timeout)) {
 			EFX_ERR(efx, "timed out waiting for SPI\n");
 			return -ETIMEDOUT;
 		}
-		cpu_relax();
+		schedule_timeout_uninterruptible(1);
 	}
 }
 
@@ -1654,8 +1667,8 @@ int falcon_spi_cmd(const struct efx_spi_device *spi,
 		return -EINVAL;
 	BUG_ON(!mutex_is_locked(&efx->spi_lock));
 
-	/* Check SPI not currently being accessed */
-	rc = falcon_spi_wait(efx);
+	/* Check that previous command is not still running */
+	rc = falcon_spi_poll(efx);
 	if (rc)
 		return rc;
 
@@ -1711,26 +1724,29 @@ efx_spi_munge_command(const struct efx_spi_device *spi,
 	return command | (((address >> 8) & spi->munge_address) << 3);
 }
 
-int falcon_spi_fast_wait(const struct efx_spi_device *spi)
+/* Wait up to 10 ms for buffered write completion */
+int falcon_spi_wait_write(const struct efx_spi_device *spi)
 {
+	struct efx_nic *efx = spi->efx;
+	unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100);
 	u8 status;
-	int i, rc;
-
-	/* Wait up to 1000us for flash/EEPROM to finish a fast operation. */
-	for (i = 0; i < 50; i++) {
-		udelay(20);
+	int rc;
 
+	for (;;) {
 		rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
 				    &status, sizeof(status));
 		if (rc)
 			return rc;
 		if (!(status & SPI_STATUS_NRDY))
 			return 0;
+		if (time_after_eq(jiffies, timeout)) {
+			EFX_ERR(efx, "SPI write timeout on device %d"
+				" last status=0x%02x\n",
+				spi->device_id, status);
+			return -ETIMEDOUT;
+		}
+		schedule_timeout_uninterruptible(1);
 	}
-	EFX_ERR(spi->efx,
-		"timed out waiting for device %d last status=0x%02x\n",
-		spi->device_id, status);
-	return -ETIMEDOUT;
 }
 
 int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
@@ -1784,7 +1800,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
 		if (rc)
 			break;
 
-		rc = falcon_spi_fast_wait(spi);
+		rc = falcon_spi_wait_write(spi);
 		if (rc)
 			break;
 
drivers/net/sfc/mtd.c +1 -1
index a1e6c28..665cafb 100644
@@ -76,7 +76,7 @@ static int efx_spi_unlock(const struct efx_spi_device *spi)
 	rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status));
 	if (rc)
 		return rc;
-	rc = falcon_spi_fast_wait(spi);
+	rc = falcon_spi_wait_write(spi);
 	if (rc)
 		return rc;
 
drivers/net/sfc/spi.h +1 -1
index c4aca13..4e45d54 100644
@@ -69,7 +69,7 @@ struct efx_spi_device {
 
 int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command,
 		   int address, const void* in, void *out, unsigned int len);
-int falcon_spi_fast_wait(const struct efx_spi_device *spi);
+int falcon_spi_wait_write(const struct efx_spi_device *spi);
 int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
 		    size_t len, size_t *retlen, u8 *buffer);
 int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
Signature · 3 lines
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
#17 lore raw

Re: [PATCH 07/33] sfc: Clean up waits for flash/EEPROM operations

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:51:01 +0000

Quoted 8 lines

Make falcon_spi_wait() ignore the write timer - it is only relevant to write commands, it only works for the device that contains VPD, and it might not be initialised properly at all.

Rename falcon_spi_fast_wait() to falcon_spi_wait_write(), reflecting its use, and make it wait up to 10 ms (not 1 ms) since buffered writes to EEPROM may take this long to complete.

Quoted 8 lines

Make both wait functions sleep instead of busy-waiting.

Replace wait for command completion at top of falcon_spi_cmd() with a single poll; no command should be running when the function starts.

Correct some comments.

Applied.

#18 lore raw

PATCH 8/33 sfc: Work around unreliable strap pins

In reply to Ben Hutchings

The SFC4000 has strap pins indicating the presence of SPI flash and/or EEPROM. These pins are also used for GPIO, and in some cases they may be read wrongly at reset. However, on production boards it must boot from one or the other device, so we can assume the boot device is present and read the board config from there.

---
 drivers/net/sfc/falcon.c |  110 +++++++++++++++++----------------------------
 1 files changed, 42 insertions(+), 68 deletions(-)
drivers/net/sfc/falcon.c +44 -70
index 4b2ec12..9563c13 100644
@@ -70,6 +70,20 @@ static int disable_dma_stats;
 #define RX_DC_ENTRIES_ORDER 2
 #define RX_DC_BASE 0x100000
 
+static const unsigned int
+/* "Large" EEPROM device: Atmel AT25640 or similar
+ * 8 KB, 16-bit address, 32 B write block */
+large_eeprom_type = ((13 << SPI_DEV_TYPE_SIZE_LBN)
+		     | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+		     | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)),
+/* Default flash device: Atmel AT25F1024
+ * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */
+default_flash_type = ((17 << SPI_DEV_TYPE_SIZE_LBN)
+		      | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+		      | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
+		      | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
+		      | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN));
+
 /* RX FIFO XOFF watermark
  *
  * When the amount of the RX FIFO increases used increases past this
@@ -2281,12 +2295,15 @@ int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
 	__le16 *word, *limit;
 	u32 csum;
 
+	spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
+	if (!spi)
+		return -EINVAL;
+
 	region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL);
 	if (!region)
 		return -ENOMEM;
 	nvconfig = region + NVCONFIG_OFFSET;
 
-	spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
 	mutex_lock(&efx->spi_lock);
 	rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region);
 	mutex_unlock(&efx->spi_lock);
@@ -2724,80 +2741,37 @@ static int falcon_probe_nic_variant(struct efx_nic *efx)
 static void falcon_probe_spi_devices(struct efx_nic *efx)
 {
 	efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
-	bool has_flash, has_eeprom, boot_is_external;
+	int boot_dev;
 
 	falcon_read(efx, &gpio_ctl, GPIO_CTL_REG_KER);
 	falcon_read(efx, &nic_stat, NIC_STAT_REG);
 	falcon_read(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
 
-	has_flash = EFX_OWORD_FIELD(nic_stat, SF_PRST);
-	has_eeprom = EFX_OWORD_FIELD(nic_stat, EE_PRST);
-	boot_is_external = EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE);
-
-	if (has_flash) {
-		/* Default flash SPI device: Atmel AT25F1024
-		 * 128 KB, 24-bit address, 32 KB erase block,
-		 * 256 B write block
-		 */
-		u32 flash_device_type =
-			(17 << SPI_DEV_TYPE_SIZE_LBN)
-			| (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
-			| (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
-			| (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
-			| (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
-
-		falcon_spi_device_init(efx, &efx->spi_flash,
-				       EE_SPI_FLASH, flash_device_type);
-
-		if (!boot_is_external) {
-			/* Disable VPD and set clock dividers to safe
-			 * values for initial programming.
-			 */
-			EFX_LOG(efx, "Booted from internal ASIC settings;"
-				" setting SPI config\n");
-			EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
-					     /* 125 MHz / 7 ~= 20 MHz */
-					     EE_SF_CLOCK_DIV, 7,
-					     /* 125 MHz / 63 ~= 2 MHz */
-					     EE_EE_CLOCK_DIV, 63);
-			falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
-		}
-	}
-
-	if (has_eeprom) {
-		u32 eeprom_device_type;
-
-		/* If it has no flash, it must have a large EEPROM
-		 * for chip config; otherwise check whether 9-bit
-		 * addressing is used for VPD configuration
-		 */
-		if (has_flash &&
-		    (!boot_is_external ||
-		     EFX_OWORD_FIELD(ee_vpd_cfg, EE_VPD_EN_AD9_MODE))) {
-			/* Default SPI device: Atmel AT25040 or similar
-			 * 512 B, 9-bit address, 8 B write block
-			 */
-			eeprom_device_type =
-				(9 << SPI_DEV_TYPE_SIZE_LBN)
-				| (1 << SPI_DEV_TYPE_ADDR_LEN_LBN)
-				| (3 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
-		} else {
-			/* "Large" SPI device: Atmel AT25640 or similar
-			 * 8 KB, 16-bit address, 32 B write block
-			 */
-			eeprom_device_type =
-				(13 << SPI_DEV_TYPE_SIZE_LBN)
-				| (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
-				| (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
-		}
-
-		falcon_spi_device_init(efx, &efx->spi_eeprom,
-				       EE_SPI_EEPROM, eeprom_device_type);
-	}
-
-	EFX_LOG(efx, "flash is %s, EEPROM is %s\n",
-		(has_flash ? "present" : "absent"),
-		(has_eeprom ? "present" : "absent"));
+	if (EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE)) {
+		boot_dev = (EFX_OWORD_FIELD(nic_stat, SF_PRST) ?
+			    EE_SPI_FLASH : EE_SPI_EEPROM);
+		EFX_LOG(efx, "Booted from %s\n",
+			boot_dev == EE_SPI_FLASH ? "flash" : "EEPROM");
+	} else {
+		/* Disable VPD and set clock dividers to safe
+		 * values for initial programming. */
+		boot_dev = -1;
+		EFX_LOG(efx, "Booted from internal ASIC settings;"
+			" setting SPI config\n");
+		EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
+				     /* 125 MHz / 7 ~= 20 MHz */
+				     EE_SF_CLOCK_DIV, 7,
+				     /* 125 MHz / 63 ~= 2 MHz */
+				     EE_EE_CLOCK_DIV, 63);
+		falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
+	}
+
+	if (boot_dev == EE_SPI_FLASH)
+		falcon_spi_device_init(efx, &efx->spi_flash, EE_SPI_FLASH,
+				       default_flash_type);
+	if (boot_dev == EE_SPI_EEPROM)
+		falcon_spi_device_init(efx, &efx->spi_eeprom, EE_SPI_EEPROM,
+				       large_eeprom_type);
 }
 
 int falcon_probe_nic(struct efx_nic *efx)
Signature · 3 lines
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
#19 lore raw

Re: [PATCH 08/33] sfc: Work around unreliable strap pins

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:51:28 +0000

Quoted 7 lines

The SFC4000 has strap pins indicating the presence of SPI flash and/or EEPROM. These pins are also used for GPIO, and in some cases they may be read wrongly at reset. However, on production boards it must boot from one or the other device, so we can assume the boot device is present and read the board config from there.

Applied.

#20 lore raw

PATCH 9/33 sfc: Restore phy_flash_cfg module parameter

In reply to Ben Hutchings

This is needed for recovery in case a PHY firmware upgrade is aborted.

---
 drivers/net/sfc/efx.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
drivers/net/sfc/efx.c +7 -0
index 127b4da..15ae2fc 100644
@@ -129,6 +129,10 @@ static unsigned int rss_cpus;
 module_param(rss_cpus, uint, 0444);
 MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
 
+static int phy_flash_cfg;
+module_param(phy_flash_cfg, int, 0644);
+MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially");
+
 /**************************************************************************
  *
  * Utility functions and prototypes
@@ -609,6 +613,9 @@ static int efx_probe_port(struct efx_nic *efx)
 	if (rc)
 		goto err;
 
+	if (phy_flash_cfg)
+		efx->phy_mode = PHY_MODE_SPECIAL;
+
 	/* Sanity check MAC address */
 	if (is_valid_ether_addr(efx->mac_address)) {
 		memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
Signature · 3 lines
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.
#22 lore raw

PATCH 13/33 sfc: Don't count RX checksum errors during loopback self-test

In reply to Ben Hutchings

The loopback self-test checks that IP packets with incorrect checksums are not altered when sent on a queue with checksum generation off. These should not contribute to RX error statistics.

---
 drivers/net/sfc/falcon.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)
drivers/net/sfc/falcon.c +8 -5
index 7421945..dbab9db 100644
@@ -784,15 +784,18 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
 			   rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
 			   rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
 
-	/* Count errors that are not in MAC stats. */
+	/* Count errors that are not in MAC stats.  Ignore expected
+	 * checksum errors during self-test. */
 	if (rx_ev_frm_trunc)
 		++rx_queue->channel->n_rx_frm_trunc;
 	else if (rx_ev_tobe_disc)
 		++rx_queue->channel->n_rx_tobe_disc;
-	else if (rx_ev_ip_hdr_chksum_err)
-		++rx_queue->channel->n_rx_ip_hdr_chksum_err;
-	else if (rx_ev_tcp_udp_chksum_err)
-		++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+	else if (!efx->loopback_selftest) {
+		if (rx_ev_ip_hdr_chksum_err)
+			++rx_queue->channel->n_rx_ip_hdr_chksum_err;
+		else if (rx_ev_tcp_udp_chksum_err)
+			++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+	}
 	if (rx_ev_ip_frag_err)
 		++rx_queue->channel->n_rx_ip_frag_err;
 
Signature · 3 lines
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
#23 lore raw

Re: [PATCH 13/33] sfc: Don't count RX checksum errors during loopback self-test

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:53:07 +0000

Quoted 5 lines

The loopback self-test checks that IP packets with incorrect checksums are not altered when sent on a queue with checksum generation off. These should not contribute to RX error statistics.

Applied.

#24 lore raw

PATCH 14/33 sfc: Remove MII extension cruft

In reply to Ben Hutchings

Replace efx_nic::link_options bitfield with link_speed (speed in Mbit/s) and link_fd (full duplex flag).

Remove broken auto-negotiation functions.

---
 drivers/net/sfc/efx.c         |   23 +------
 drivers/net/sfc/ethtool.c     |    1 -
 drivers/net/sfc/falcon.c      |   16 ++---
 drivers/net/sfc/falcon_xmac.c |    1 -
 drivers/net/sfc/gmii.h        |  137 +----------------------------------------
 drivers/net/sfc/net_driver.h  |    6 +-
 drivers/net/sfc/tenxpress.c   |    4 +-
 drivers/net/sfc/xfp_phy.c     |    4 +-
 8 files changed, 18 insertions(+), 174 deletions(-)
drivers/net/sfc/efx.c +2 -21
index 183a440..844580f 100644
@@ -21,7 +21,6 @@
 #include <linux/ethtool.h>
 #include <linux/topology.h>
 #include "net_driver.h"
-#include "gmii.h"
 #include "ethtool.h"
 #include "tx.h"
 #include "rx.h"
@@ -551,26 +550,8 @@ static void efx_link_status_changed(struct efx_nic *efx)
 
 	/* Status message for kernel log */
 	if (efx->link_up) {
-		struct mii_if_info *gmii = &efx->mii;
-		unsigned adv, lpa;
-		/* NONE here means direct XAUI from the controller, with no
-		 * MDIO-attached device we can query. */
-		if (efx->phy_type != PHY_TYPE_NONE) {
-			adv = gmii_advertised(gmii);
-			lpa = gmii_lpa(gmii);
-		} else {
-			lpa = GM_LPA_10000 | LPA_DUPLEX;
-			adv = lpa;
-		}
-		EFX_INFO(efx, "link up at %dMbps %s-duplex "
-			 "(adv %04x lpa %04x) (MTU %d)%s\n",
-			 (efx->link_options & GM_LPA_10000 ? 10000 :
-			  (efx->link_options & GM_LPA_1000 ? 1000 :
-			   (efx->link_options & GM_LPA_100 ? 100 :
-			    10))),
-			 (efx->link_options & GM_LPA_DUPLEX ?
-			  "full" : "half"),
-			 adv, lpa,
+		EFX_INFO(efx, "link up at %uMbps %s-duplex (MTU %d)%s\n",
+			 efx->link_speed, efx->link_fd ? "full" : "half",
 			 efx->net_dev->mtu,
 			 (efx->promiscuous ? " [PROMISC]" : ""));
 	} else {
drivers/net/sfc/ethtool.c +0 -1
index 931ce14..43d6d8b 100644
@@ -16,7 +16,6 @@
 #include "efx.h"
 #include "ethtool.h"
 #include "falcon.h"
-#include "gmii.h"
 #include "spi.h"
 #include "mac.h"
 
drivers/net/sfc/falcon.c +7 -9
index dbab9db..ac765cb 100644
@@ -15,11 +15,11 @@
 #include <linux/seq_file.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/mii.h>
 #include "net_driver.h"
 #include "bitfield.h"
 #include "efx.h"
 #include "mac.h"
-#include "gmii.h"
 #include "spi.h"
 #include "falcon.h"
 #include "falcon_hwdefs.h"
@@ -1926,14 +1926,12 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
 	int link_speed;
 	bool tx_fc;
 
-	if (efx->link_options & GM_LPA_10000)
-		link_speed = 0x3;
-	else if (efx->link_options & GM_LPA_1000)
-		link_speed = 0x2;
-	else if (efx->link_options & GM_LPA_100)
-		link_speed = 0x1;
-	else
-		link_speed = 0x0;
+	switch (efx->link_speed) {
+	case 10000: link_speed = 3; break;
+	case 1000:  link_speed = 2; break;
+	case 100:   link_speed = 1; break;
+	default:    link_speed = 0; break;
+	}
 	/* MAC_LINK_STATUS controls MAC backpressure but doesn't work
 	 * as advertised.  Disable to ensure packets are not
 	 * indefinitely held and TX queue can be flushed at any point
drivers/net/sfc/falcon_xmac.c +0 -1
index d401231..4a54d09 100644
@@ -15,7 +15,6 @@
 #include "falcon_hwdefs.h"
 #include "falcon_io.h"
 #include "mac.h"
-#include "gmii.h"
 #include "mdio_10g.h"
 #include "phy.h"
 #include "boards.h"
drivers/net/sfc/gmii.h +1 -136

147 lines not on this page · raw message

drivers/net/sfc/net_driver.h +4 -2
index abff908..6cac5ed 100644
@@ -694,7 +694,8 @@ union efx_multicast_hash {
  * @mii: PHY interface
  * @phy_mode: PHY operating mode. Serialised by @mac_lock.
  * @link_up: Link status
- * @link_options: Link options (MII/GMII format)
+ * @link_fd: Link is full duplex
+ * @link_speed: Link speed (Mbps)
  * @n_link_state_changes: Number of times the link has changed state
  * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
  * @multicast_hash: Multicast hash table
@@ -772,7 +773,8 @@ struct efx_nic {
 	enum efx_phy_mode phy_mode;
 
 	bool link_up;
-	unsigned int link_options;
+	bool link_fd;
+	unsigned int link_speed;
 	unsigned int n_link_state_changes;
 
 	bool promiscuous;
drivers/net/sfc/tenxpress.c +2 -2
index 8d41c29..3fa7ccb 100644
@@ -10,7 +10,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include "efx.h"
-#include "gmii.h"
 #include "mdio_10g.h"
 #include "falcon.h"
 #include "phy.h"
@@ -362,7 +361,8 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
 	phy_data->loopback_mode = efx->loopback_mode;
 	phy_data->phy_mode = efx->phy_mode;
 	efx->link_up = tenxpress_link_ok(efx, false);
-	efx->link_options = GM_LPA_10000FULL;
+	efx->link_speed = 10000;
+	efx->link_fd = true;
 }
 
 static void tenxpress_phy_clear_interrupt(struct efx_nic *efx)
drivers/net/sfc/xfp_phy.c +2 -2
index 91f0246..971a24b 100644
@@ -14,7 +14,6 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include "efx.h"
-#include "gmii.h"
 #include "mdio_10g.h"
 #include "xenpack.h"
 #include "phy.h"
@@ -154,7 +153,8 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
 
 	phy_data->phy_mode = efx->phy_mode;
 	efx->link_up = xfp_link_ok(efx);
-	efx->link_options = GM_LPA_10000FULL;
+	efx->link_speed = 10000;
+	efx->link_fd = true;
 }
 
 
Signature · 3 lines
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
#25 lore raw

Re: [PATCH 14/33] sfc: Remove MII extension cruft

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:53:24 +0000

Quoted 6 lines

Replace efx_nic::link_options bitfield with link_speed (speed in Mbit/s) and link_fd (full duplex flag).

Remove broken auto-negotiation functions.

Applied.

#26 lore raw

PATCH 15/33 sfc: Add support for MMDs numbered >15

In reply to Ben Hutchings

Combine DEVS0 and DEVS1 registers into a 32-bit mask instead of reading just DEVS0.

---
 drivers/net/sfc/mdio_10g.c  |   24 +++++++++++++-----------
 drivers/net/sfc/mdio_10g.h  |    8 ++++----
 drivers/net/sfc/tenxpress.c |    6 +++---
 drivers/net/sfc/xfp_phy.c   |    8 ++++----
 4 files changed, 24 insertions(+), 22 deletions(-)
drivers/net/sfc/mdio_10g.c +13 -11
index 19e2521..1eed484 100644
@@ -121,16 +121,18 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
 int mdio_clause45_check_mmds(struct efx_nic *efx,
 			     unsigned int mmd_mask, unsigned int fatal_mask)
 {
-	int devices, mmd = 0;
-	int probe_mmd;
+	u32 devices;
+	int mmd = 0, probe_mmd;
 
 	/* Historically we have probed the PHYXS to find out what devices are
 	 * present,but that doesn't work so well if the PHYXS isn't expected
 	 * to exist, if so just find the first item in the list supplied. */
-	probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS0_PHYXS) ? MDIO_MMD_PHYXS :
+	probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS_PHYXS) ? MDIO_MMD_PHYXS :
 	    __ffs(mmd_mask);
-	devices = mdio_clause45_read(efx, efx->mii.phy_id,
-				     probe_mmd, MDIO_MMDREG_DEVS0);
+	devices = (mdio_clause45_read(efx, efx->mii.phy_id,
+				      probe_mmd, MDIO_MMDREG_DEVS0) |
+		   mdio_clause45_read(efx, efx->mii.phy_id,
+				      probe_mmd, MDIO_MMDREG_DEVS1) << 16);
 
 	/* Check all the expected MMDs are present */
 	if (devices < 0) {
@@ -175,14 +177,14 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
 	else if (efx_phy_mode_disabled(efx->phy_mode))
 		return false;
 	else if (efx->loopback_mode == LOOPBACK_PHYXS)
-		mmd_mask &= ~(MDIO_MMDREG_DEVS0_PHYXS |
-			      MDIO_MMDREG_DEVS0_PCS |
-			      MDIO_MMDREG_DEVS0_PMAPMD);
+		mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS |
+			      MDIO_MMDREG_DEVS_PCS |
+			      MDIO_MMDREG_DEVS_PMAPMD);
 	else if (efx->loopback_mode == LOOPBACK_PCS)
-		mmd_mask &= ~(MDIO_MMDREG_DEVS0_PCS |
-			      MDIO_MMDREG_DEVS0_PMAPMD);
+		mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS |
+			      MDIO_MMDREG_DEVS_PMAPMD);
 	else if (efx->loopback_mode == LOOPBACK_PMAPMD)
-		mmd_mask &= ~MDIO_MMDREG_DEVS0_PMAPMD;
+		mmd_mask &= ~MDIO_MMDREG_DEVS_PMAPMD;
 
 	while (mmd_mask) {
 		if (mmd_mask & 1) {
drivers/net/sfc/mdio_10g.h +4 -4
index db9f358..4516383 100644
@@ -73,14 +73,14 @@
 #define MDIO_ID_MODEL(_id32)	((_id32 >> 4) & 0x3f)
 #define MDIO_ID_OUI(_id32)	(_id32 >> 10)
 
-/* Bits in MMDREG_DEVS0. Someone thoughtfully layed things out
+/* Bits in MMDREG_DEVS0/1. Someone thoughtfully layed things out
  * so the 'bit present' bit number of an MMD is the number of
  * that MMD */
 #define DEV_PRESENT_BIT(_b) (1 << _b)
 
-#define MDIO_MMDREG_DEVS0_PHYXS	 DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
-#define MDIO_MMDREG_DEVS0_PCS	 DEV_PRESENT_BIT(MDIO_MMD_PCS)
-#define MDIO_MMDREG_DEVS0_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
+#define MDIO_MMDREG_DEVS_PHYXS	DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
+#define MDIO_MMDREG_DEVS_PCS	DEV_PRESENT_BIT(MDIO_MMD_PCS)
+#define MDIO_MMDREG_DEVS_PMAPMD	DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
 
 /* Bits in MMDREG_STAT2 */
 #define MDIO_MMDREG_STAT2_PRESENT_VAL	(2)
drivers/net/sfc/tenxpress.c +3 -3
index 3fa7ccb..197b544 100644
@@ -19,9 +19,9 @@
 
 /* We expect these MMDs to be in the package */
 /* AN not here as mdio_check_mmds() requires STAT2 support */
-#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PMAPMD | \
-				 MDIO_MMDREG_DEVS0_PCS    | \
-				 MDIO_MMDREG_DEVS0_PHYXS)
+#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PMAPMD	| \
+				 MDIO_MMDREG_DEVS_PCS		| \
+				 MDIO_MMDREG_DEVS_PHYXS)
 
 #define TENXPRESS_LOOPBACKS ((1 << LOOPBACK_PHYXS) |	\
 			     (1 << LOOPBACK_PCS) |	\
drivers/net/sfc/xfp_phy.c +4 -4
index 971a24b..0413d13 100644
@@ -19,9 +19,9 @@
 #include "phy.h"
 #include "mac.h"
 
-#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PCS |	\
-			   MDIO_MMDREG_DEVS0_PMAPMD |	\
-			   MDIO_MMDREG_DEVS0_PHYXS)
+#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS |	\
+			   MDIO_MMDREG_DEVS_PMAPMD |	\
+			   MDIO_MMDREG_DEVS_PHYXS)
 
 #define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) |		\
 		       (1 << LOOPBACK_PMAPMD) |		\
@@ -64,7 +64,7 @@ static int xfp_reset_phy(struct efx_nic *efx)
 	/* Check that all the MMDs we expect are present and responding. We
 	 * expect faults on some if the link is down, but not on the PHY XS */
 	rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS,
-				      MDIO_MMDREG_DEVS0_PHYXS);
+				      MDIO_MMDREG_DEVS_PHYXS);
 	if (rc < 0)
 		goto fail;
 
Signature · 3 lines
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.
#28 lore raw

PATCH 16/33 sfc: Add phy_type device attribute

In reply to Ben Hutchings
---
 drivers/net/sfc/efx.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)
drivers/net/sfc/efx.c +19 -0
index 844580f..4fb5ba2 100644
@@ -1496,6 +1496,14 @@ static struct notifier_block efx_netdev_notifier = {
 	.notifier_call = efx_netdev_event,
 };
 
+static ssize_t
+show_phy_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+	return sprintf(buf, "%d\n", efx->phy_type);
+}
+static DEVICE_ATTR(phy_type, 0644, show_phy_type, NULL);
+
 static int efx_register_netdev(struct efx_nic *efx)
 {
 	struct net_device *net_dev = efx->net_dev;
@@ -1522,7 +1530,17 @@ static int efx_register_netdev(struct efx_nic *efx)
 	strcpy(efx->name, net_dev->name);
 	efx_set_channel_names(efx);
 
+	rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+	if (rc) {
+		EFX_ERR(efx, "failed to init net dev attributes\n");
+		goto fail_registered;
+	}
+
 	return 0;
+
+fail_registered:
+	unregister_netdev(net_dev);
+	return rc;
 }
 
 static void efx_unregister_netdev(struct efx_nic *efx)
@@ -1542,6 +1560,7 @@ static void efx_unregister_netdev(struct efx_nic *efx)
 
 	if (efx_dev_registered(efx)) {
 		strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+		device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
 		unregister_netdev(efx->net_dev);
 	}
 }
Signature · 3 lines
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.
#30 lore raw

PATCH 17/33 sfc: Clean up board identification

In reply to Ben Hutchings

Remove kluge for development boards with unspecified board type.

Remove assumption of contiguous board type code assignments.

---
 drivers/net/sfc/boards.c |   68 ++++++++++++---------------------------------
 drivers/net/sfc/boards.h |    7 +---
 2 files changed, 20 insertions(+), 55 deletions(-)
drivers/net/sfc/boards.c +18 -50
index edf0262..08fa4e3 100644
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published
@@ -231,70 +231,38 @@ static int sfe4002_init(struct efx_nic *efx)
 /* This will get expanded as board-specific details get moved out of the
  * PHY drivers. */
 struct efx_board_data {
+	enum efx_board_type type;
 	const char *ref_model;
 	const char *gen_type;
 	int (*init) (struct efx_nic *nic);
 };
 
-static int dummy_init(struct efx_nic *nic)
-{
-	return 0;
-}
 
 static struct efx_board_data board_data[] = {
-	[EFX_BOARD_INVALID] =
-	{NULL,	    NULL,                  dummy_init},
-	[EFX_BOARD_SFE4001] =
-	{"SFE4001", "10GBASE-T adapter",   sfe4001_init},
-	[EFX_BOARD_SFE4002] =
-	{"SFE4002", "XFP adapter",         sfe4002_init},
+	{ EFX_BOARD_SFE4001, "SFE4001", "10GBASE-T adapter", sfe4001_init },
+	{ EFX_BOARD_SFE4002, "SFE4002", "XFP adapter", sfe4002_init },
 };
 
-int efx_set_board_info(struct efx_nic *efx, u16 revision_info)
+void efx_set_board_info(struct efx_nic *efx, u16 revision_info)
 {
-	int rc = 0;
-	struct efx_board_data *data;
+	struct efx_board_data *data = NULL;
+	int i;
 
-	if (BOARD_TYPE(revision_info) >= EFX_BOARD_MAX) {
-		EFX_ERR(efx, "squashing unknown board type %d\n",
-			BOARD_TYPE(revision_info));
-		revision_info = 0;
-	}
-
-	if (BOARD_TYPE(revision_info) == 0) {
-		efx->board_info.major = 0;
-		efx->board_info.minor = 0;
-		/* For early boards that don't have revision info. there is
-		 * only 1 board for each PHY type, so we can work it out, with
-		 * the exception of the PHY-less boards. */
-		switch (efx->phy_type) {
-		case PHY_TYPE_10XPRESS:
-			efx->board_info.type = EFX_BOARD_SFE4001;
-			break;
-		case PHY_TYPE_XFP:
-			efx->board_info.type = EFX_BOARD_SFE4002;
-			break;
-		default:
-			efx->board_info.type = 0;
-			break;
-		}
-	} else {
-		efx->board_info.type = BOARD_TYPE(revision_info);
-		efx->board_info.major = BOARD_MAJOR(revision_info);
-		efx->board_info.minor = BOARD_MINOR(revision_info);
-	}
+	efx->board_info.type = BOARD_TYPE(revision_info);
+	efx->board_info.major = BOARD_MAJOR(revision_info);
+	efx->board_info.minor = BOARD_MINOR(revision_info);
 
-	data = &board_data[efx->board_info.type];
+	for (i = 0; i < ARRAY_SIZE(board_data); i++)
+		if (board_data[i].type == efx->board_info.type)
+			data = &board_data[i];
 
-	/* Report the board model number or generic type for recognisable
-	 * boards. */
-	if (efx->board_info.type != 0)
+	if (data) {
 		EFX_INFO(efx, "board is %s rev %c%d\n",
 			 (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
 			 ? data->ref_model : data->gen_type,
 			 'A' + efx->board_info.major, efx->board_info.minor);
-
-	efx->board_info.init = data->init;
-
-	return rc;
+		efx->board_info.init = data->init;
+	} else {
+		EFX_ERR(efx, "unknown board type %d\n", efx->board_info.type);
+	}
 }
drivers/net/sfc/boards.h +2 -5
index c6e01b6..5e0dde5 100644
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published
@@ -12,14 +12,11 @@
 
 /* Board IDs (must fit in 8 bits) */
 enum efx_board_type {
-	EFX_BOARD_INVALID = 0,
 	EFX_BOARD_SFE4001 = 1,   /* SFE4001 (10GBASE-T) */
 	EFX_BOARD_SFE4002 = 2,
-	/* Insert new types before here */
-	EFX_BOARD_MAX
 };
 
-extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info);
+extern void efx_set_board_info(struct efx_nic *efx, u16 revision_info);
 extern int sfe4001_init(struct efx_nic *efx);
 
 #endif
Signature · 3 lines
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
#31 lore raw

Re: [PATCH 17/33] sfc: Clean up board identification

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:54:19 +0000

Quoted 5 lines

Remove kluge for development boards with unspecified board type.

Remove assumption of contiguous board type code assignments.

Applied.

#32 lore raw

PATCH 18/33 sfc: Clean up MDIO flag setting

In reply to Ben Hutchings

We often want to set or clear a flag in an MDIO register, but avoid writing if no change is required since this can have side-effects. Encapsulate this in a function, mdio_clause45_set_flag().

---
 drivers/net/sfc/mdio_10g.c |   87 ++++++++++++++------------------------------
 drivers/net/sfc/mdio_10g.h |    4 ++
 2 files changed, 32 insertions(+), 59 deletions(-)
drivers/net/sfc/mdio_10g.c +28 -59
index 1eed484..8d91131 100644
@@ -205,61 +205,24 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
 
 void mdio_clause45_transmit_disable(struct efx_nic *efx)
 {
-	int phy_id = efx->mii.phy_id;
-	int ctrl1, ctrl2;
-
-	ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-					   MDIO_MMDREG_TXDIS);
-	if (efx->phy_mode & PHY_MODE_TX_DISABLED)
-		ctrl2 |= (1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
-	else
-		ctrl1 &= ~(1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
-	if (ctrl1 != ctrl2)
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
-				    MDIO_MMDREG_TXDIS, ctrl2);
+	mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
+			       MDIO_MMDREG_TXDIS, MDIO_MMDREG_TXDIS_GLOBAL_LBN,
+			       efx->phy_mode & PHY_MODE_TX_DISABLED);
 }
 
 void mdio_clause45_phy_reconfigure(struct efx_nic *efx)
 {
 	int phy_id = efx->mii.phy_id;
-	int ctrl1, ctrl2;
-
-	/* Handle (with debouncing) PMA/PMD loopback */
-	ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-					   MDIO_MMDREG_CTRL1);
-
-	if (efx->loopback_mode == LOOPBACK_PMAPMD)
-		ctrl2 |= (1 << MDIO_PMAPMD_CTRL1_LBACK_LBN);
-	else
-		ctrl2 &= ~(1 << MDIO_PMAPMD_CTRL1_LBACK_LBN);
-
-	if (ctrl1 != ctrl2)
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
-				    MDIO_MMDREG_CTRL1, ctrl2);
-
-	/* Handle (with debouncing) PCS loopback */
-	ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
-					   MDIO_MMDREG_CTRL1);
-	if (efx->loopback_mode == LOOPBACK_PCS)
-		ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
-	else
-		ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
 
-	if (ctrl1 != ctrl2)
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_PCS,
-				    MDIO_MMDREG_CTRL1, ctrl2);
-
-	/* Handle (with debouncing) PHYXS network loopback */
-	ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
-					   MDIO_MMDREG_CTRL1);
-	if (efx->loopback_mode == LOOPBACK_NETWORK)
-		ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
-	else
-		ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
-
-	if (ctrl1 != ctrl2)
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS,
-				    MDIO_MMDREG_CTRL1, ctrl2);
+	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD,
+			       MDIO_MMDREG_CTRL1, MDIO_PMAPMD_CTRL1_LBACK_LBN,
+			       efx->loopback_mode == LOOPBACK_PMAPMD);
+	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PCS,
+			       MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN,
+			       efx->loopback_mode == LOOPBACK_PCS);
+	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS,
+			       MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN,
+			       efx->loopback_mode == LOOPBACK_NETWORK);
 }
 
 static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx,
@@ -267,21 +230,13 @@ static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx,
 {
 	int phy = efx->mii.phy_id;
 	int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1);
-	int ctrl1, ctrl2;
 
 	EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n",
 		  mmd, lpower);
 
 	if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) {
-		ctrl1 = ctrl2 = mdio_clause45_read(efx, phy,
-						   mmd, MDIO_MMDREG_CTRL1);
-		if (lpower)
-			ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LPOWER_LBN);
-		else
-			ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LPOWER_LBN);
-		if (ctrl1 != ctrl2)
-			mdio_clause45_write(efx, phy, mmd,
-					    MDIO_MMDREG_CTRL1, ctrl2);
+		mdio_clause45_set_flag(efx, phy, mmd, MDIO_MMDREG_CTRL1,
+				       MDIO_MMDREG_CTRL1_LPOWER_LBN, lpower);
 	}
 }
 
@@ -395,3 +350,17 @@ int mdio_clause45_set_settings(struct efx_nic *efx,
 		return 0;
 	return -EOPNOTSUPP;
 }
+
+void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev,
+			    u16 addr, int bit, bool sense)
+{
+	int old_val = mdio_clause45_read(efx, prt, dev, addr);
+	int new_val;
+
+	if (sense)
+		new_val = old_val | (1 << bit);
+	else
+		new_val = old_val & ~(1 << bit);
+	if (old_val != new_val)
+		mdio_clause45_write(efx, prt, dev, addr, new_val);
+}
drivers/net/sfc/mdio_10g.h +4 -0
index 4516383..4830e0c 100644
@@ -259,4 +259,8 @@ extern int mdio_clause45_set_settings(struct efx_nic *efx,
 extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
 					 unsigned int mmd_mask);
 
+/* Set or clear flag, debouncing */
+extern void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev,
+				   u16 addr, int bit, bool sense);
+
 #endif /* EFX_MDIO_10G_H */
Signature · 3 lines
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
#33 lore raw

Re: [PATCH 18/33] sfc: Clean up MDIO flag setting

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:54:34 +0000

Quoted 5 lines

We often want to set or clear a flag in an MDIO register, but avoid writing if no change is required since this can have side-effects. Encapsulate this in a function, mdio_clause45_set_flag().

Applied.

#34 lore raw

PATCH 19/33 sfc: Add support for sub-10G speeds

In reply to Ben Hutchings

The SFC4000 has a separate MAC for use at sub-10G speeds. Introduce an efx_mac_operations structure with implementations for the two MACs. Switch between the MACs as necessary.

PHY settings are independent of the MAC, so add get_settings() and set_settings() to efx_phy_operations. Also add macs field to indicate which MACs the PHY is connected to.

---
 drivers/net/sfc/Makefile        |    4 +-
 drivers/net/sfc/efx.c           |   62 +++++++---
 drivers/net/sfc/enum.h          |   29 +++--
 drivers/net/sfc/ethtool.c       |   38 +++----
 drivers/net/sfc/falcon.c        |  179 +++++++++++++++++++++++-------
 drivers/net/sfc/falcon.h        |    3 +
 drivers/net/sfc/falcon_gmac.c   |  233 +++++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/falcon_hwdefs.h |  156 ++++++++++++++++++++++++++
 drivers/net/sfc/falcon_xmac.c   |  222 +++++--------------------------------
 drivers/net/sfc/mac.h           |   16 +--
 drivers/net/sfc/net_driver.h    |   31 +++++
 drivers/net/sfc/selftest.c      |   26 ++---
 drivers/net/sfc/selftest.h      |    2 -
 drivers/net/sfc/sfe4001.c       |    2 +-
 drivers/net/sfc/tenxpress.c     |   10 +-
 drivers/net/sfc/xfp_phy.c       |    7 +-
 16 files changed, 699 insertions(+), 321 deletions(-)
 create mode 100644 drivers/net/sfc/falcon_gmac.c
drivers/net/sfc/Makefile +2 -2
index e507daa..b89f9be 100644
@@ -1,5 +1,5 @@
-sfc-y			+= efx.o falcon.o tx.o rx.o falcon_xmac.o \
-			   selftest.o ethtool.o xfp_phy.o \
+sfc-y			+= efx.o falcon.o tx.o rx.o falcon_gmac.o \
+			   falcon_xmac.o selftest.o ethtool.o xfp_phy.o \
 			   mdio_10g.o tenxpress.o boards.o sfe4001.o
 sfc-$(CONFIG_SFC_MTD)	+= mtd.o
 
drivers/net/sfc/efx.c +43 -19

149 lines not on this page · raw message

drivers/net/sfc/enum.h +16 -13
index 41e758e..0c2e41c 100644
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published
@@ -13,22 +13,24 @@
 /**
  * enum efx_loopback_mode - loopback modes
  * @LOOPBACK_NONE: no loopback
- * @LOOPBACK_XGMII: loopback within MAC at XGMII level
- * @LOOPBACK_XGXS: loopback within MAC at XGXS level
- * @LOOPBACK_XAUI: loopback within MAC at XAUI level
- * @LOOPBACK_PHYXS: loopback within PHY at PHYXS level
- * @LOOPBACK_PCS: loopback within PHY at PCS level
- * @LOOPBACK_PMAPMD: loopback within PHY at PMAPMD level
+ * @LOOPBACK_GMAC: loopback within GMAC at unspecified level
+ * @LOOPBACK_XGMII: loopback within XMAC at XGMII level
+ * @LOOPBACK_XGXS: loopback within XMAC at XGXS level
+ * @LOOPBACK_XAUI: loopback within XMAC at XAUI level
+ * @LOOPBACK_GPHY: loopback within 1G PHY at unspecified level
+ * @LOOPBACK_PHYXS: loopback within 10G PHY at PHYXS level
+ * @LOOPBACK_PCS: loopback within 10G PHY at PCS level
+ * @LOOPBACK_PMAPMD: loopback within 10G PHY at PMAPMD level
  * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!)
  */
 /* Please keep in order and up-to-date w.r.t the following two #defines */
 enum efx_loopback_mode {
 	LOOPBACK_NONE = 0,
-	LOOPBACK_MAC = 1,
+	LOOPBACK_GMAC = 1,
 	LOOPBACK_XGMII = 2,
 	LOOPBACK_XGXS = 3,
 	LOOPBACK_XAUI = 4,
-	LOOPBACK_PHY = 5,
+	LOOPBACK_GPHY = 5,
 	LOOPBACK_PHYXS = 6,
 	LOOPBACK_PCS = 7,
 	LOOPBACK_PMAPMD = 8,
@@ -45,15 +47,16 @@ extern const char *efx_loopback_mode_names[];
 	LOOPBACK_MODE_NAME(efx->loopback_mode)
 
 /* These loopbacks occur within the controller */
-#define LOOPBACKS_10G_INTERNAL ((1 << LOOPBACK_XGMII)| \
-				(1 << LOOPBACK_XGXS) | \
-				(1 << LOOPBACK_XAUI))
+#define LOOPBACKS_INTERNAL ((1 << LOOPBACK_GMAC) |     \
+			    (1 << LOOPBACK_XGMII)|     \
+			    (1 << LOOPBACK_XGXS) |     \
+			    (1 << LOOPBACK_XAUI))
 
 #define LOOPBACK_MASK(_efx)			\
 	(1 << (_efx)->loopback_mode)
 
 #define LOOPBACK_INTERNAL(_efx)				\
-	(!!(LOOPBACKS_10G_INTERNAL & LOOPBACK_MASK(_efx)))
+	(!!(LOOPBACKS_INTERNAL & LOOPBACK_MASK(_efx)))
 
 #define LOOPBACK_OUT_OF(_from, _to, _mask)				\
 	((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask)))
drivers/net/sfc/ethtool.c +17 -21
index 43d6d8b..1b33f89 100644
@@ -17,15 +17,14 @@
 #include "ethtool.h"
 #include "falcon.h"
 #include "spi.h"
-#include "mac.h"
 
 const char *efx_loopback_mode_names[] = {
 	[LOOPBACK_NONE]		= "NONE",
-	[LOOPBACK_MAC]		= "MAC",
+	[LOOPBACK_GMAC]		= "GMAC",
 	[LOOPBACK_XGMII]	= "XGMII",
 	[LOOPBACK_XGXS]		= "XGXS",
 	[LOOPBACK_XAUI] 	= "XAUI",
-	[LOOPBACK_PHY]		= "PHY",
+	[LOOPBACK_GPHY]		= "GPHY",
 	[LOOPBACK_PHYXS]	= "PHYXS",
 	[LOOPBACK_PCS]	 	= "PCS",
 	[LOOPBACK_PMAPMD]	= "PMA/PMD",
@@ -200,13 +199,15 @@ int efx_ethtool_get_settings(struct net_device *net_dev,
 			     struct ethtool_cmd *ecmd)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	int rc;
 
 	mutex_lock(&efx->mac_lock);
-	rc = falcon_xmac_get_settings(efx, ecmd);
+	efx->phy_op->get_settings(efx, ecmd);
 	mutex_unlock(&efx->mac_lock);
 
-	return rc;
+	/* Falcon GMAC does not support 1000Mbps HD */
+	ecmd->supported &= ~SUPPORTED_1000baseT_Half;
+
+	return 0;
 }
 
 /* This must be called with rtnl_lock held. */
@@ -216,8 +217,15 @@ int efx_ethtool_set_settings(struct net_device *net_dev,
 	struct efx_nic *efx = netdev_priv(net_dev);
 	int rc;
 
+	/* Falcon GMAC does not support 1000Mbps HD */
+	if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) {
+		EFX_LOG(efx, "rejecting unsupported 1000Mbps HD"
+			" setting\n");
+		return -EINVAL;
+	}
+
 	mutex_lock(&efx->mac_lock);
-	rc = falcon_xmac_set_settings(efx, ecmd);
+	rc = efx->phy_op->set_settings(efx, ecmd);
 	mutex_unlock(&efx->mac_lock);
 	if (!rc)
 		efx_reconfigure_port(efx);
@@ -362,10 +370,6 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
 		      EFX_PORT_NAME, "phy", NULL);
 
 	/* Loopback tests */
-	efx_fill_test(n++, strings, data, &tests->loopback_speed,
-		      EFX_PORT_NAME, "loopback.speed", NULL);
-	efx_fill_test(n++, strings, data, &tests->loopback_full_duplex,
-		      EFX_PORT_NAME, "loopback.full_duplex", NULL);
 	for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
 		if (!(efx->loopback_modes & (1 << mode)))
 			continue;
@@ -671,22 +675,14 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	enum efx_fc_type flow_control = efx->flow_control;
-	int rc;
 
 	flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO);
 	flow_control |= pause->rx_pause ? EFX_FC_RX : 0;
 	flow_control |= pause->tx_pause ? EFX_FC_TX : 0;
 	flow_control |= pause->autoneg ? EFX_FC_AUTO : 0;
 
-	/* Try to push the pause parameters */
-	mutex_lock(&efx->mac_lock);
-	rc = falcon_xmac_set_pause(efx, flow_control);
-	mutex_unlock(&efx->mac_lock);
-
-	if (!rc)
-		efx_reconfigure_port(efx);
-
-	return rc;
+	efx_reconfigure_port(efx);
+	return 0;
 }
 
 static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
drivers/net/sfc/falcon.c +141 -38

270 lines not on this page · raw message

drivers/net/sfc/falcon.h +3 -0
index be025ba..7869c3d 100644
@@ -12,6 +12,7 @@
 #define EFX_FALCON_H
 
 #include "net_driver.h"
+#include "efx.h"
 
 /*
  * Falcon hardware control
@@ -65,6 +66,7 @@ extern int falcon_probe_port(struct efx_nic *efx);
 extern void falcon_remove_port(struct efx_nic *efx);
 
 /* MAC/PHY */
+extern int falcon_switch_mac(struct efx_nic *efx);
 extern bool falcon_xaui_link_ok(struct efx_nic *efx);
 extern int falcon_dma_stats(struct efx_nic *efx,
 			    unsigned int done_offset);
@@ -77,6 +79,7 @@ extern int falcon_init_interrupt(struct efx_nic *efx);
 extern void falcon_enable_interrupts(struct efx_nic *efx);
 extern void falcon_generate_test_event(struct efx_channel *channel,
 				       unsigned int magic);
+extern void falcon_sim_phy_event(struct efx_nic *efx);
 extern void falcon_generate_interrupt(struct efx_nic *efx);
 extern void falcon_set_int_moderation(struct efx_channel *channel);
 extern void falcon_disable_interrupts(struct efx_nic *efx);
drivers/net/sfc/falcon_gmac.c new file +233 -0

233 lines not on this page · raw message

drivers/net/sfc/falcon_hwdefs.h +156 -0

228 lines not on this page · raw message

drivers/net/sfc/falcon_xmac.c +31 -191

288 lines not on this page · raw message

drivers/net/sfc/mac.h +3 -13
index a31571c..4e70742 100644
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2007 Solarflare Communications Inc.
+ * Copyright 2006-2008 Solarflare Communications Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published
@@ -13,17 +13,7 @@
 
 #include "net_driver.h"
 
-extern int falcon_init_xmac(struct efx_nic *efx);
-extern void falcon_reconfigure_xmac(struct efx_nic *efx);
-extern void falcon_update_stats_xmac(struct efx_nic *efx);
-extern void falcon_fini_xmac(struct efx_nic *efx);
-extern int falcon_check_xmac(struct efx_nic *efx);
-extern void falcon_xmac_sim_phy_event(struct efx_nic *efx);
-extern int falcon_xmac_get_settings(struct efx_nic *efx,
-				    struct ethtool_cmd *ecmd);
-extern int falcon_xmac_set_settings(struct efx_nic *efx,
-				    struct ethtool_cmd *ecmd);
-extern int falcon_xmac_set_pause(struct efx_nic *efx,
-				 enum efx_fc_type pause_params);
+extern struct efx_mac_operations falcon_gmac_operations;
+extern struct efx_mac_operations falcon_xmac_operations;
 
 #endif
drivers/net/sfc/net_driver.h +31 -0
index 6cac5ed..883086e 100644
@@ -463,6 +463,8 @@ enum phy_type {
 
 #define PHY_ADDR_INVALID 0xff
 
+#define EFX_IS10G(efx) ((efx)->link_speed == 10000)
+
 enum nic_state {
 	STATE_INIT = 0,
 	STATE_RUNNING = 1,
@@ -503,6 +505,24 @@ enum efx_fc_type {
 	EFX_FC_AUTO = 4,
 };
 
+/* Supported MAC bit-mask */
+enum efx_mac_type {
+	EFX_GMAC = 1,
+	EFX_XMAC = 2,
+};
+
+/**
+ * struct efx_mac_operations - Efx MAC operations table
+ * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
+ * @update_stats: Update statistics
+ * @check_hw: Check hardware. Serialised by the mac_lock
+ */
+struct efx_mac_operations {
+	void (*reconfigure) (struct efx_nic *efx);
+	void (*update_stats) (struct efx_nic *efx);
+	int (*check_hw) (struct efx_nic *efx);
+};
+
 /**
  * struct efx_phy_operations - Efx PHY operations table
  * @init: Initialise PHY
@@ -511,16 +531,23 @@ enum efx_fc_type {
  * @clear_interrupt: Clear down interrupt
  * @blink: Blink LEDs
  * @check_hw: Check hardware
+ * @get_settings: Get ethtool settings. Serialised by the mac_lock.
+ * @set_settings: Set ethtool settings. Serialised by the mac_lock.
  * @mmds: MMD presence mask
  * @loopbacks: Supported loopback modes mask
  */
 struct efx_phy_operations {
+	enum efx_mac_type macs;
 	int (*init) (struct efx_nic *efx);
 	void (*fini) (struct efx_nic *efx);
 	void (*reconfigure) (struct efx_nic *efx);
 	void (*clear_interrupt) (struct efx_nic *efx);
 	int (*check_hw) (struct efx_nic *efx);
 	int (*test) (struct efx_nic *efx);
+	void (*get_settings) (struct efx_nic *efx,
+			      struct ethtool_cmd *ecmd);
+	int (*set_settings) (struct efx_nic *efx,
+			     struct ethtool_cmd *ecmd);
 	int mmds;
 	unsigned loopbacks;
 };
@@ -686,6 +713,7 @@ union efx_multicast_hash {
  * @stats_lock: Statistics update lock. Serialises statistics fetches
  * @stats_enabled: Temporarily disable statistics fetches.
  *	Serialised by @stats_lock
+ * @mac_op: MAC interface
  * @mac_address: Permanent MAC address
  * @phy_type: PHY type
  * @phy_lock: PHY access lock
@@ -693,6 +721,7 @@ union efx_multicast_hash {
  * @phy_data: PHY private data (including PHY-specific stats)
  * @mii: PHY interface
  * @phy_mode: PHY operating mode. Serialised by @mac_lock.
+ * @mac_up: MAC link state
  * @link_up: Link status
  * @link_fd: Link is full duplex
  * @link_speed: Link speed (Mbps)
@@ -763,6 +792,7 @@ struct efx_nic {
 	spinlock_t stats_lock;
 	bool stats_enabled;
 
+	struct efx_mac_operations *mac_op;
 	unsigned char mac_address[ETH_ALEN];
 
 	enum phy_type phy_type;
@@ -772,6 +802,7 @@ struct efx_nic {
 	struct mii_if_info mii;
 	enum efx_phy_mode phy_mode;
 
+	bool mac_up;
 	bool link_up;
 	bool link_fd;
 	unsigned int link_speed;
drivers/net/sfc/selftest.c +11 -15
index 362956e..8142e37 100644
@@ -26,7 +26,6 @@
 #include "selftest.h"
 #include "boards.h"
 #include "workarounds.h"
-#include "mac.h"
 #include "spi.h"
 #include "falcon_io.h"
 #include "mdio_10g.h"
@@ -105,9 +104,11 @@ static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests)
 		goto out;
 	}
 
-	rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0);
-	if (rc)
-		goto out;
+	if (EFX_IS10G(efx)) {
+		rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0);
+		if (rc)
+			goto out;
+	}
 
 out:
 	mutex_unlock(&efx->mac_lock);
@@ -598,7 +599,7 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
 		do {
 			struct efx_channel *channel = &efx->channel[0];
 
-			falcon_check_xmac(efx);
+			efx->mac_op->check_hw(efx);
 			schedule_timeout_uninterruptible(HZ / 10);
 			if (channel->work_pending)
 				efx_process_channel_now(channel);
@@ -606,13 +607,12 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
 			flush_workqueue(efx->workqueue);
 			rmb();
 
-			/* efx->link_up can be 1 even if the XAUI link is down,
-			 * (bug5762). Usually, it's not worth bothering with the
-			 * difference, but for selftests, we need that extra
-			 * guarantee that the link is really, really, up.
-			 */
+			/* We need both the phy and xaui links to be ok.
+			 * rather than relying on the falcon_xmac irq/poll
+			 * regime, just poll xaui directly */
 			link_up = efx->link_up;
-			if (!falcon_xaui_link_ok(efx))
+			if (link_up && EFX_IS10G(efx) &&
+			    !falcon_xaui_link_ok(efx))
 				link_up = false;
 
 		} while ((++count < 20) && !link_up);
@@ -721,7 +721,6 @@ int efx_offline_test(struct efx_nic *efx,
 	if (ecmd_test.autoneg == AUTONEG_ENABLE) {
 		ecmd_test.autoneg = AUTONEG_DISABLE;
 		ecmd_test.duplex = DUPLEX_FULL;
-		ecmd_test.speed = SPEED_10000;
 	}
 	efx->loopback_mode = LOOPBACK_NONE;
 
@@ -732,9 +731,6 @@ int efx_offline_test(struct efx_nic *efx,
 		return rc;
 	}
 
-	tests->loopback_speed = ecmd_test.speed;
-	tests->loopback_full_duplex = ecmd_test.duplex;
-
 	rc = efx_test_phy(efx, tests);
 	if (rc && !rc2)
 		rc2 = rc;
drivers/net/sfc/selftest.h +0 -2
index fc15df1..252f7d7 100644
@@ -39,8 +39,6 @@ struct efx_self_tests {
 	/* offline tests */
 	int registers;
 	int phy;
-	int loopback_speed;
-	int loopback_full_duplex;
 	struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1];
 };
 
drivers/net/sfc/sfe4001.c +1 -1
index aa576c5..af65284 100644
@@ -176,7 +176,7 @@ static int sfe4001_check_hw(struct efx_nic *efx)
 	s32 status;
 
 	/* If XAUI link is up then do not monitor */
-	if (EFX_WORKAROUND_7884(efx) && falcon_xaui_link_ok(efx))
+	if (EFX_WORKAROUND_7884(efx) && efx->mac_up)
 		return 0;
 
 	/* Check the powered status of the PHY. Lack of power implies that
drivers/net/sfc/tenxpress.c +6 -4
index 197b544..d60353b 100644
@@ -1,6 +1,6 @@
 /****************************************************************************
- * Driver for Solarflare 802.3an compliant PHY
- * Copyright 2007 Solarflare Communications Inc.
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2007-2008 Solarflare Communications Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published
@@ -15,7 +15,6 @@
 #include "phy.h"
 #include "falcon_hwdefs.h"
 #include "boards.h"
-#include "mac.h"
 
 /* We expect these MMDs to be in the package */
 /* AN not here as mdio_check_mmds() requires STAT2 support */
@@ -381,7 +380,7 @@ static int tenxpress_phy_check_hw(struct efx_nic *efx)
 	link_ok = tenxpress_link_ok(efx, true);
 
 	if (link_ok != efx->link_up)
-		falcon_xmac_sim_phy_event(efx);
+		falcon_sim_phy_event(efx);
 
 	if (phy_data->phy_mode != PHY_MODE_NORMAL)
 		return 0;
@@ -453,12 +452,15 @@ static int tenxpress_phy_test(struct efx_nic *efx)
 }
 
 struct efx_phy_operations falcon_tenxpress_phy_ops = {
+	.macs		  = EFX_XMAC,
 	.init             = tenxpress_phy_init,
 	.reconfigure      = tenxpress_phy_reconfigure,
 	.check_hw         = tenxpress_phy_check_hw,
 	.fini             = tenxpress_phy_fini,
 	.clear_interrupt  = tenxpress_phy_clear_interrupt,
 	.test             = tenxpress_phy_test,
+	.get_settings	  = mdio_clause45_get_settings,
+	.set_settings	  = mdio_clause45_set_settings,
 	.mmds             = TENXPRESS_REQUIRED_DEVS,
 	.loopbacks        = TENXPRESS_LOOPBACKS,
 };
drivers/net/sfc/xfp_phy.c +5 -2
index 0413d13..d4e203d 100644
@@ -17,7 +17,7 @@
 #include "mdio_10g.h"
 #include "xenpack.h"
 #include "phy.h"
-#include "mac.h"
+#include "falcon.h"
 
 #define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS |	\
 			   MDIO_MMDREG_DEVS_PMAPMD |	\
@@ -125,7 +125,7 @@ static int xfp_phy_check_hw(struct efx_nic *efx)
 	int link_up = xfp_link_ok(efx);
 	/* Simulate a PHY event if link state has changed */
 	if (link_up != efx->link_up)
-		falcon_xmac_sim_phy_event(efx);
+		falcon_sim_phy_event(efx);
 
 	rc = efx->board_info.monitor(efx);
 	if (rc) {
@@ -169,11 +169,14 @@ static void xfp_phy_fini(struct efx_nic *efx)
 }
 
 struct efx_phy_operations falcon_xfp_phy_ops = {
+	.macs		 = EFX_XMAC,
 	.init            = xfp_phy_init,
 	.reconfigure     = xfp_phy_reconfigure,
 	.check_hw        = xfp_phy_check_hw,
 	.fini            = xfp_phy_fini,
 	.clear_interrupt = xfp_phy_clear_interrupt,
+	.get_settings    = mdio_clause45_get_settings,
+	.set_settings	 = mdio_clause45_set_settings,
 	.mmds            = XFP_REQUIRED_DEVS,
 	.loopbacks       = XFP_LOOPBACKS,
 };
Signature · 3 lines
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
#35 lore raw

Re: [PATCH 19/33] sfc: Add support for sub-10G speeds

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:54:51 +0000

Quoted 9 lines

The SFC4000 has a separate MAC for use at sub-10G speeds. Introduce an efx_mac_operations structure with implementations for the two MACs. Switch between the MACs as necessary.

PHY settings are independent of the MAC, so add get_settings() and set_settings() to efx_phy_operations. Also add macs field to indicate which MACs the PHY is connected to.

Applied.

#36 lore raw

PATCH 20/33 sfc: Implement auto-negotiation

In reply to Ben Hutchings

Add infrastructure for auto-negotiation of speed, duplex and flow control.

When using 10Xpress, auto-negotiate flow control. While we're at it, clean up the code to warn when partner is not 10GBASE-T capable.

---
 drivers/net/sfc/ethtool.c     |   57 ++++++-
 drivers/net/sfc/falcon.c      |    6 +-
 drivers/net/sfc/falcon_gmac.c |    4 +-
 drivers/net/sfc/falcon_xmac.c |    2 +-
 drivers/net/sfc/mdio_10g.c    |  348 ++++++++++++++++++++++++++++++++---------
 drivers/net/sfc/mdio_10g.h    |   32 ++++
 drivers/net/sfc/net_driver.h  |   38 +++++-
 drivers/net/sfc/tenxpress.c   |  138 +++++++++--------
 drivers/net/sfc/xfp_phy.c     |    1 +
 9 files changed, 472 insertions(+), 154 deletions(-)
drivers/net/sfc/ethtool.c +48 -9
index 1b33f89..0e81af6 100644
@@ -12,11 +12,13 @@
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
 #include "net_driver.h"
+#include "workarounds.h"
 #include "selftest.h"
 #include "efx.h"
 #include "ethtool.h"
 #include "falcon.h"
 #include "spi.h"
+#include "mdio_10g.h"
 
 const char *efx_loopback_mode_names[] = {
 	[LOOPBACK_NONE]		= "NONE",
@@ -674,14 +676,51 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
 				      struct ethtool_pauseparam *pause)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	enum efx_fc_type flow_control = efx->flow_control;
+	enum efx_fc_type wanted_fc;
+	bool reset;
 
-	flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO);
-	flow_control |= pause->rx_pause ? EFX_FC_RX : 0;
-	flow_control |= pause->tx_pause ? EFX_FC_TX : 0;
-	flow_control |= pause->autoneg ? EFX_FC_AUTO : 0;
+	wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) |
+		     (pause->tx_pause ? EFX_FC_TX : 0) |
+		     (pause->autoneg ? EFX_FC_AUTO : 0));
+
+	if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) {
+		EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n");
+		return -EINVAL;
+	}
+
+	if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) &&
+	    (wanted_fc & EFX_FC_AUTO)) {
+		EFX_LOG(efx, "PHY does not support flow control "
+			"autonegotiation\n");
+		return -EINVAL;
+	}
+
+	/* TX flow control may automatically turn itself off if the
+	 * link partner (intermittently) stops responding to pause
+	 * frames. There isn't any indication that this has happened,
+	 * so the best we do is leave it up to the user to spot this
+	 * and fix it be cycling transmit flow control on this end. */
+	reset = (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX);
+	if (EFX_WORKAROUND_11482(efx) && reset) {
+		if (falcon_rev(efx) >= FALCON_REV_B0) {
+			/* Recover by resetting the EM block */
+			if (efx->link_up)
+				falcon_drain_tx_fifo(efx);
+		} else {
+			/* Schedule a reset to recover */
+			efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
+		}
+	}
+
+	/* Try to push the pause parameters */
+	mutex_lock(&efx->mac_lock);
+
+	efx->wanted_fc = wanted_fc;
+	mdio_clause45_set_pause(efx);
+	__efx_reconfigure_port(efx);
+
+	mutex_unlock(&efx->mac_lock);
 
-	efx_reconfigure_port(efx);
 	return 0;
 }
 
@@ -690,9 +729,9 @@ static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 
-	pause->rx_pause = !!(efx->flow_control & EFX_FC_RX);
-	pause->tx_pause = !!(efx->flow_control & EFX_FC_TX);
-	pause->autoneg = !!(efx->flow_control & EFX_FC_AUTO);
+	pause->rx_pause = !!(efx->wanted_fc & EFX_FC_RX);
+	pause->tx_pause = !!(efx->wanted_fc & EFX_FC_TX);
+	pause->autoneg = !!(efx->wanted_fc & EFX_FC_AUTO);
 }
 
 
drivers/net/sfc/falcon.c +3 -3
index 22419a0..60b3b95 100644
@@ -2009,7 +2009,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
 	/* Transmission of pause frames when RX crosses the threshold is
 	 * covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
 	 * Action on receipt of pause frames is controller by XM_DIS_FCNTL */
-	tx_fc = !!(efx->flow_control & EFX_FC_TX);
+	tx_fc = !!(efx->link_fc & EFX_FC_TX);
 	falcon_read(efx, &reg, RX_CFG_REG_KER);
 	EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
 
@@ -2339,9 +2339,9 @@ int falcon_probe_port(struct efx_nic *efx)
 
 	/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
 	if (falcon_rev(efx) >= FALCON_REV_B0)
-		efx->flow_control = EFX_FC_RX | EFX_FC_TX;
+		efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
 	else
-		efx->flow_control = EFX_FC_RX;
+		efx->wanted_fc = EFX_FC_RX;
 
 	/* Allocate buffer for stats */
 	rc = falcon_alloc_buffer(efx, &efx->stats_buffer,
drivers/net/sfc/falcon_gmac.c +2 -2
index 247f802..b6e6eb9 100644
@@ -31,8 +31,8 @@ static void falcon_reconfigure_gmac(struct efx_nic *efx)
 	efx_oword_t reg;
 
 	/* Configuration register 1 */
-	tx_fc = (efx->flow_control & EFX_FC_TX) || !efx->link_fd;
-	rx_fc = !!(efx->flow_control & EFX_FC_RX);
+	tx_fc = (efx->link_fc & EFX_FC_TX) || !efx->link_fd;
+	rx_fc = !!(efx->link_fc & EFX_FC_RX);
 	loopback = (efx->loopback_mode == LOOPBACK_GMAC);
 	bytemode = (efx->link_speed == 1000);
 
drivers/net/sfc/falcon_xmac.c +1 -1
index 2206ead..0ce8f01 100644
@@ -142,7 +142,7 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
 {
 	unsigned int max_frame_len;
 	efx_oword_t reg;
-	bool rx_fc = !!(efx->flow_control & EFX_FC_RX);
+	bool rx_fc = !!(efx->link_fc & EFX_FC_RX);
 
 	/* Configure MAC  - cut-thru mode is hard wired on */
 	EFX_POPULATE_DWORD_3(reg,
drivers/net/sfc/mdio_10g.c +277 -71

411 lines not on this page · raw message

drivers/net/sfc/mdio_10g.h +32 -0
index 4830e0c..80c63dd 100644
@@ -81,6 +81,17 @@
 #define MDIO_MMDREG_DEVS_PHYXS	DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
 #define MDIO_MMDREG_DEVS_PCS	DEV_PRESENT_BIT(MDIO_MMD_PCS)
 #define MDIO_MMDREG_DEVS_PMAPMD	DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
+#define MDIO_MMDREG_DEVS_AN	DEV_PRESENT_BIT(MDIO_MMD_AN)
+
+/* Bits in MMDREG_SPEED */
+#define MDIO_MMDREG_SPEED_10G_LBN	0
+#define MDIO_MMDREG_SPEED_10G_WIDTH	1
+#define MDIO_MMDREG_SPEED_1000M_LBN	4
+#define MDIO_MMDREG_SPEED_1000M_WIDTH	1
+#define MDIO_MMDREG_SPEED_100M_LBN	5
+#define MDIO_MMDREG_SPEED_100M_WIDTH	1
+#define MDIO_MMDREG_SPEED_10M_LBN	6
+#define MDIO_MMDREG_SPEED_10M_WIDTH	1
 
 /* Bits in MMDREG_STAT2 */
 #define MDIO_MMDREG_STAT2_PRESENT_VAL	(2)
@@ -119,12 +130,20 @@
 #define MDIO_PHYXS_LANE_ALIGNED_LBN	(12)
 
 /* AN registers */
+#define MDIO_AN_CTRL_XNP_LBN		13
 #define MDIO_AN_STATUS			(1)
 #define MDIO_AN_STATUS_XNP_LBN		(7)
 #define MDIO_AN_STATUS_PAGE_LBN		(6)
 #define MDIO_AN_STATUS_AN_DONE_LBN	(5)
 #define MDIO_AN_STATUS_LP_AN_CAP_LBN	(0)
 
+#define MDIO_AN_ADVERTISE		16
+#define MDIO_AN_ADVERTISE_XNP_LBN	12
+#define MDIO_AN_LPA			19
+#define MDIO_AN_XNP			22
+#define MDIO_AN_LPA_XNP			25
+
+#define MDIO_AN_10GBT_ADVERTISE		32
 #define MDIO_AN_10GBT_STATUS		(33)
 #define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */
 #define MDIO_AN_10GBT_STATUS_MS_LBN     (14) /* MASTER/SLAVE config */
@@ -251,10 +270,23 @@ extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
 extern void mdio_clause45_get_settings(struct efx_nic *efx,
 				       struct ethtool_cmd *ecmd);
 
+/* Read (some of) the PHY settings over MDIO */
+extern void
+mdio_clause45_get_settings_ext(struct efx_nic *efx, struct ethtool_cmd *ecmd,
+			       u32 xnp, u32 xnp_lpa);
+
 /* Set (some of) the PHY settings over MDIO */
 extern int mdio_clause45_set_settings(struct efx_nic *efx,
 				      struct ethtool_cmd *ecmd);
 
+/* Set pause parameters to be advertised through AN (if available) */
+extern void mdio_clause45_set_pause(struct efx_nic *efx);
+
+/* Get pause parameters from AN if available (otherwise return
+ * requested pause parameters)
+ */
+enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx);
+
 /* Wait for specified MMDs to exit reset within a timeout */
 extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
 					 unsigned int mmd_mask);
drivers/net/sfc/net_driver.h +36 -2
index 883086e..fb8d725 100644
@@ -511,6 +511,35 @@ enum efx_mac_type {
 	EFX_XMAC = 2,
 };
 
+static inline unsigned int efx_fc_advertise(enum efx_fc_type wanted_fc)
+{
+	unsigned int adv = 0;
+	if (wanted_fc & EFX_FC_RX)
+		adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+	if (wanted_fc & EFX_FC_TX)
+		adv ^= ADVERTISE_PAUSE_ASYM;
+	return adv;
+}
+
+static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc,
+					      unsigned int lpa)
+{
+	unsigned int adv = efx_fc_advertise(wanted_fc);
+
+	if (!(wanted_fc & EFX_FC_AUTO))
+		return wanted_fc;
+
+	if (adv & lpa & ADVERTISE_PAUSE_CAP)
+		return EFX_FC_RX | EFX_FC_TX;
+	if (adv & lpa & ADVERTISE_PAUSE_ASYM) {
+		if (adv & ADVERTISE_PAUSE_CAP)
+			return EFX_FC_RX;
+		if (lpa & ADVERTISE_PAUSE_CAP)
+			return EFX_FC_TX;
+	}
+	return 0;
+}
+
 /**
  * struct efx_mac_operations - Efx MAC operations table
  * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
@@ -533,6 +562,8 @@ struct efx_mac_operations {
  * @check_hw: Check hardware
  * @get_settings: Get ethtool settings. Serialised by the mac_lock.
  * @set_settings: Set ethtool settings. Serialised by the mac_lock.
+ * @set_xnp_advertise: Set abilities advertised in Extended Next Page
+ *	(only needed where AN bit is set in mmds)
  * @mmds: MMD presence mask
  * @loopbacks: Supported loopback modes mask
  */
@@ -548,6 +579,7 @@ struct efx_phy_operations {
 			      struct ethtool_cmd *ecmd);
 	int (*set_settings) (struct efx_nic *efx,
 			     struct ethtool_cmd *ecmd);
+	bool (*set_xnp_advertise) (struct efx_nic *efx, u32);
 	int mmds;
 	unsigned loopbacks;
 };
@@ -724,11 +756,12 @@ union efx_multicast_hash {
  * @mac_up: MAC link state
  * @link_up: Link status
  * @link_fd: Link is full duplex
+ * @link_fc: Actualy flow control flags
  * @link_speed: Link speed (Mbps)
  * @n_link_state_changes: Number of times the link has changed state
  * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
  * @multicast_hash: Multicast hash table
- * @flow_control: Flow control flags - separate RX/TX so can't use link_options
+ * @wanted_fc: Wanted flow control flags
  * @reconfigure_work: work item for dealing with PHY events
  * @loopback_mode: Loopback status
  * @loopback_modes: Supported loopback mode bitmask
@@ -805,12 +838,13 @@ struct efx_nic {
 	bool mac_up;
 	bool link_up;
 	bool link_fd;
+	enum efx_fc_type link_fc;
 	unsigned int link_speed;
 	unsigned int n_link_state_changes;
 
 	bool promiscuous;
 	union efx_multicast_hash multicast_hash;
-	enum efx_fc_type flow_control;
+	enum efx_fc_type wanted_fc;
 	struct work_struct reconfigure_work;
 
 	atomic_t rx_reset;
drivers/net/sfc/tenxpress.c +72 -66

195 lines not on this page · raw message

drivers/net/sfc/xfp_phy.c +1 -0
index d4e203d..fbe8e25 100644
@@ -155,6 +155,7 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
 	efx->link_up = xfp_link_ok(efx);
 	efx->link_speed = 10000;
 	efx->link_fd = true;
+	efx->link_fc = efx->wanted_fc;
 }
 
 
Signature · 3 lines
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
#37 lore raw

Re: [PATCH 20/33] sfc: Implement auto-negotiation

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:55:10 +0000

Quoted 8 lines

Add infrastructure for auto-negotiation of speed, duplex and flow control.

When using 10Xpress, auto-negotiate flow control. While we're at it, clean up the code to warn when partner is not 10GBASE-T capable.

Applied.

#38 lore raw

PATCH 21/33 sfc: Rework MAC, PHY and board event handling

In reply to Ben Hutchings

From: Steve Hodgson <[email protected]>

MAC, PHY and board events may be separately enabled and signalled. Our current arrangement of chaining the polling functions can result in events being missed. Change them to be more independent.

---
 drivers/net/sfc/efx.c           |   63 ++++++++++++++++++++++++++-------------
 drivers/net/sfc/falcon.c        |   20 +++++-------
 drivers/net/sfc/falcon_gmac.c   |    8 +----
 drivers/net/sfc/falcon_hwdefs.h |    2 +
 drivers/net/sfc/falcon_xmac.c   |   42 +++++++++++++------------
 drivers/net/sfc/net_driver.h    |   24 ++++++++------
 drivers/net/sfc/selftest.c      |    6 ++-
 drivers/net/sfc/tenxpress.c     |   44 ++++++++------------------
 drivers/net/sfc/xfp_phy.c       |   16 +--------
 9 files changed, 111 insertions(+), 114 deletions(-)
drivers/net/sfc/efx.c +42 -21
index 0227dfe..b99ccfb 100644
@@ -612,10 +612,9 @@ void efx_reconfigure_port(struct efx_nic *efx)
 /* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all()
  * we don't efx_reconfigure_port() if the port is disabled. Care is taken
  * in efx_stop_all() and efx_start_port() to prevent PHY events being lost */
-static void efx_reconfigure_work(struct work_struct *data)
+static void efx_phy_work(struct work_struct *data)
 {
-	struct efx_nic *efx = container_of(data, struct efx_nic,
-					   reconfigure_work);
+	struct efx_nic *efx = container_of(data, struct efx_nic, phy_work);
 
 	mutex_lock(&efx->mac_lock);
 	if (efx->port_enabled)
@@ -623,6 +622,16 @@ static void efx_reconfigure_work(struct work_struct *data)
 	mutex_unlock(&efx->mac_lock);
 }
 
+static void efx_mac_work(struct work_struct *data)
+{
+	struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
+
+	mutex_lock(&efx->mac_lock);
+	if (efx->port_enabled)
+		efx->mac_op->irq(efx);
+	mutex_unlock(&efx->mac_lock);
+}
+
 static int efx_probe_port(struct efx_nic *efx)
 {
 	int rc;
@@ -688,7 +697,7 @@ fail:
 
 /* Allow efx_reconfigure_port() to be scheduled, and close the window
  * between efx_stop_port and efx_flush_all whereby a previously scheduled
- * efx_reconfigure_port() may have been cancelled */
+ * efx_phy_work()/efx_mac_work() may have been cancelled */
 static void efx_start_port(struct efx_nic *efx)
 {
 	EFX_LOG(efx, "start port\n");
@@ -697,13 +706,14 @@ static void efx_start_port(struct efx_nic *efx)
 	mutex_lock(&efx->mac_lock);
 	efx->port_enabled = true;
 	__efx_reconfigure_port(efx);
+	efx->mac_op->irq(efx);
 	mutex_unlock(&efx->mac_lock);
 }
 
-/* Prevent efx_reconfigure_work and efx_monitor() from executing, and
- * efx_set_multicast_list() from scheduling efx_reconfigure_work.
- * efx_reconfigure_work can still be scheduled via NAPI processing
- * until efx_flush_all() is called */
+/* Prevent efx_phy_work, efx_mac_work, and efx_monitor() from executing,
+ * and efx_set_multicast_list() from scheduling efx_phy_work. efx_phy_work
+ * and efx_mac_work may still be scheduled via NAPI processing until
+ * efx_flush_all() is called */
 static void efx_stop_port(struct efx_nic *efx)
 {
 	EFX_LOG(efx, "stop port\n");
@@ -1094,7 +1104,8 @@ static void efx_flush_all(struct efx_nic *efx)
 		cancel_delayed_work_sync(&rx_queue->work);
 
 	/* Stop scheduled port reconfigurations */
-	cancel_work_sync(&efx->reconfigure_work);
+	cancel_work_sync(&efx->mac_work);
+	cancel_work_sync(&efx->phy_work);
 
 }
 
@@ -1131,7 +1142,7 @@ static void efx_stop_all(struct efx_nic *efx)
 	 * window to loose phy events */
 	efx_stop_port(efx);
 
-	/* Flush reconfigure_work, refill_workqueue, monitor_work */
+	/* Flush efx_phy_work, efx_mac_work, refill_workqueue, monitor_work */
 	efx_flush_all(efx);
 
 	/* Isolate the MAC from the TX and RX engines, so that queue
@@ -1203,24 +1214,31 @@ static void efx_monitor(struct work_struct *data)
 {
 	struct efx_nic *efx = container_of(data, struct efx_nic,
 					   monitor_work.work);
+	int rc;
 
 	EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
 		  raw_smp_processor_id());
 
-
 	/* If the mac_lock is already held then it is likely a port
 	 * reconfiguration is already in place, which will likely do
 	 * most of the work of check_hw() anyway. */
-	if (!mutex_trylock(&efx->mac_lock)) {
-		queue_delayed_work(efx->workqueue, &efx->monitor_work,
-				   efx_monitor_interval);
-		return;
+	if (!mutex_trylock(&efx->mac_lock))
+		goto out_requeue;
+	if (!efx->port_enabled)
+		goto out_unlock;
+	rc = efx->board_info.monitor(efx);
+	if (rc) {
+		EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
+			(rc == -ERANGE) ? "reported fault" : "failed");
+		efx->phy_mode |= PHY_MODE_LOW_POWER;
+		falcon_sim_phy_event(efx);
 	}
+	efx->phy_op->poll(efx);
+	efx->mac_op->poll(efx);
 
-	if (efx->port_enabled)
-		efx->mac_op->check_hw(efx);
+out_unlock:
 	mutex_unlock(&efx->mac_lock);
-
+out_requeue:
 	queue_delayed_work(efx->workqueue, &efx->monitor_work,
 			   efx_monitor_interval);
 }
@@ -1477,7 +1495,7 @@ static void efx_set_multicast_list(struct net_device *net_dev)
 		return;
 
 	if (changed)
-		queue_work(efx->workqueue, &efx->reconfigure_work);
+		queue_work(efx->workqueue, &efx->phy_work);
 
 	/* Create and activate new global multicast hash table */
 	falcon_set_multicast_hash(efx);
@@ -1800,12 +1818,14 @@ void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {}
 
 static struct efx_mac_operations efx_dummy_mac_operations = {
 	.reconfigure	= efx_port_dummy_op_void,
+	.poll		= efx_port_dummy_op_void,
+	.irq		= efx_port_dummy_op_void,
 };
 
 static struct efx_phy_operations efx_dummy_phy_operations = {
 	.init		 = efx_port_dummy_op_int,
 	.reconfigure	 = efx_port_dummy_op_void,
-	.check_hw        = efx_port_dummy_op_int,
+	.poll		 = efx_port_dummy_op_void,
 	.fini		 = efx_port_dummy_op_void,
 	.clear_interrupt = efx_port_dummy_op_void,
 };
@@ -1857,7 +1877,8 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 	efx->mac_op = &efx_dummy_mac_operations;
 	efx->phy_op = &efx_dummy_phy_operations;
 	efx->mii.dev = net_dev;
-	INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work);
+	INIT_WORK(&efx->phy_work, efx_phy_work);
+	INIT_WORK(&efx->mac_work, efx_mac_work);
 	atomic_set(&efx->netif_stop_count, 1);
 
 	for (i = 0; i < EFX_MAX_CHANNELS; i++) {
drivers/net/sfc/falcon.c +9 -11
index 60b3b95..734add1 100644
@@ -910,22 +910,20 @@ static void falcon_handle_global_event(struct efx_channel *channel,
 				       efx_qword_t *event)
 {
 	struct efx_nic *efx = channel->efx;
-	bool is_phy_event = false, handled = false;
+	bool handled = false;
 
-	/* Check for interrupt on either port.  Some boards have a
-	 * single PHY wired to the interrupt line for port 1. */
 	if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
 	    EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
-	    EFX_QWORD_FIELD(*event, XG_PHY_INTR))
-		is_phy_event = true;
+	    EFX_QWORD_FIELD(*event, XG_PHY_INTR) ||
+	    EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) {
+		efx->phy_op->clear_interrupt(efx);
+		queue_work(efx->workqueue, &efx->phy_work);
+		handled = true;
+	}
 
 	if ((falcon_rev(efx) >= FALCON_REV_B0) &&
-	    EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0))
-		is_phy_event = true;
-
-	if (is_phy_event) {
-		efx->phy_op->clear_interrupt(efx);
-		queue_work(efx->workqueue, &efx->reconfigure_work);
+	    EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) {
+		queue_work(efx->workqueue, &efx->mac_work);
 		handled = true;
 	}
 
drivers/net/sfc/falcon_gmac.c +2 -6
index b6e6eb9..8865eae 100644
@@ -221,13 +221,9 @@ static void falcon_update_stats_gmac(struct efx_nic *efx)
 	mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
 }
 
-static int falcon_check_gmac(struct efx_nic *efx)
-{
-	return efx->phy_op->check_hw(efx);
-}
-
 struct efx_mac_operations falcon_gmac_operations = {
 	.reconfigure	= falcon_reconfigure_gmac,
 	.update_stats	= falcon_update_stats_gmac,
-	.check_hw	= falcon_check_gmac,
+	.irq		= efx_port_dummy_op_void,
+	.poll		= efx_port_dummy_op_void,
 };
drivers/net/sfc/falcon_hwdefs.h +2 -0
index 5553df8..a58c627 100644
@@ -1051,6 +1051,8 @@
 #define XG_MNT_INTR_B0_WIDTH 1
 #define RX_RECOVERY_A1_LBN 11
 #define RX_RECOVERY_A1_WIDTH 1
+#define XFP_PHY_INTR_LBN 10
+#define XFP_PHY_INTR_WIDTH 1
 #define XG_PHY_INTR_LBN 9
 #define XG_PHY_INTR_WIDTH 1
 #define G_PHY1_INTR_LBN 8
drivers/net/sfc/falcon_xmac.c +22 -20

55 lines not on this page · raw message

drivers/net/sfc/net_driver.h +14 -10
index fb8d725..61d09a2 100644
@@ -544,12 +544,14 @@ static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc,
  * struct efx_mac_operations - Efx MAC operations table
  * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
  * @update_stats: Update statistics
- * @check_hw: Check hardware. Serialised by the mac_lock
+ * @irq: Hardware MAC event callback. Serialised by the mac_lock
+ * @poll: Poll for hardware state. Serialised by the mac_lock
  */
 struct efx_mac_operations {
 	void (*reconfigure) (struct efx_nic *efx);
 	void (*update_stats) (struct efx_nic *efx);
-	int (*check_hw) (struct efx_nic *efx);
+	void (*irq) (struct efx_nic *efx);
+	void (*poll) (struct efx_nic *efx);
 };
 
 /**
@@ -559,7 +561,7 @@ struct efx_mac_operations {
  * @reconfigure: Reconfigure PHY (e.g. for new link parameters)
  * @clear_interrupt: Clear down interrupt
  * @blink: Blink LEDs
- * @check_hw: Check hardware
+ * @poll: Poll for hardware state. Serialised by the mac_lock.
  * @get_settings: Get ethtool settings. Serialised by the mac_lock.
  * @set_settings: Set ethtool settings. Serialised by the mac_lock.
  * @set_xnp_advertise: Set abilities advertised in Extended Next Page
@@ -573,7 +575,7 @@ struct efx_phy_operations {
 	void (*fini) (struct efx_nic *efx);
 	void (*reconfigure) (struct efx_nic *efx);
 	void (*clear_interrupt) (struct efx_nic *efx);
-	int (*check_hw) (struct efx_nic *efx);
+	void (*poll) (struct efx_nic *efx);
 	int (*test) (struct efx_nic *efx);
 	void (*get_settings) (struct efx_nic *efx,
 			      struct ethtool_cmd *ecmd);
@@ -728,10 +730,10 @@ union efx_multicast_hash {
  * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
  *	@port_inhibited, efx_monitor() and efx_reconfigure_port()
  * @port_enabled: Port enabled indicator.
- *	Serialises efx_stop_all(), efx_start_all() and efx_monitor() and
- *	efx_reconfigure_work with kernel interfaces. Safe to read under any
- *	one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
- *	be held to modify it.
+ *	Serialises efx_stop_all(), efx_start_all(), efx_monitor(),
+ *	efx_phy_work(), and efx_mac_work() with kernel interfaces. Safe to read
+ *	under any one of the rtnl_lock, mac_lock, or netif_tx_lock, but all
+ *	three must be held to modify it.
  * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock
  * @port_initialized: Port initialized?
  * @net_dev: Operating system network device. Consider holding the rtnl lock
@@ -762,7 +764,8 @@ union efx_multicast_hash {
  * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
  * @multicast_hash: Multicast hash table
  * @wanted_fc: Wanted flow control flags
- * @reconfigure_work: work item for dealing with PHY events
+ * @phy_work: work item for dealing with PHY events
+ * @mac_work: work item for dealing with MAC events
  * @loopback_mode: Loopback status
  * @loopback_modes: Supported loopback mode bitmask
  * @loopback_selftest: Offline self-test private state
@@ -810,6 +813,7 @@ struct efx_nic {
 	struct falcon_nic_data *nic_data;
 
 	struct mutex mac_lock;
+	struct work_struct mac_work;
 	bool port_enabled;
 	bool port_inhibited;
 
@@ -830,6 +834,7 @@ struct efx_nic {
 
 	enum phy_type phy_type;
 	spinlock_t phy_lock;
+	struct work_struct phy_work;
 	struct efx_phy_operations *phy_op;
 	void *phy_data;
 	struct mii_if_info mii;
@@ -845,7 +850,6 @@ struct efx_nic {
 	bool promiscuous;
 	union efx_multicast_hash multicast_hash;
 	enum efx_fc_type wanted_fc;
-	struct work_struct reconfigure_work;
 
 	atomic_t rx_reset;
 	enum efx_loopback_mode loopback_mode;
drivers/net/sfc/selftest.c +4 -2
index 8142e37..578b7f4 100644
@@ -594,12 +594,14 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
 		efx->loopback_mode = mode;
 		efx_reconfigure_port(efx);
 
-		/* Wait for the PHY to signal the link is up */
+		/* Wait for the PHY to signal the link is up. Interrupts
+		 * are enabled for PHY's using LASI, otherwise we poll()
+		 * quickly */
 		count = 0;
 		do {
 			struct efx_channel *channel = &efx->channel[0];
 
-			efx->mac_op->check_hw(efx);
+			efx->phy_op->poll(efx);
 			schedule_timeout_uninterruptible(HZ / 10);
 			if (channel->work_pending)
 				efx_process_channel_now(channel);
drivers/net/sfc/tenxpress.c +14 -30

73 lines not on this page · raw message

drivers/net/sfc/xfp_phy.c +2 -14
index fbe8e25..345ffc3 100644
@@ -119,24 +119,12 @@ static int xfp_link_ok(struct efx_nic *efx)
 	return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS);
 }
 
-static int xfp_phy_check_hw(struct efx_nic *efx)
+static void xfp_phy_poll(struct efx_nic *efx)
 {
-	int rc = 0;
 	int link_up = xfp_link_ok(efx);
 	/* Simulate a PHY event if link state has changed */
 	if (link_up != efx->link_up)
 		falcon_sim_phy_event(efx);
-
-	rc = efx->board_info.monitor(efx);
-	if (rc) {
-		struct xfp_phy_data *phy_data = efx->phy_data;
-		EFX_ERR(efx, "XFP sensor alert; putting PHY into low power\n");
-		efx->phy_mode |= PHY_MODE_LOW_POWER;
-		mdio_clause45_set_mmds_lpower(efx, 1, XFP_REQUIRED_DEVS);
-		phy_data->phy_mode |= PHY_MODE_LOW_POWER;
-	}
-
-	return rc;
 }
 
 static void xfp_phy_reconfigure(struct efx_nic *efx)
@@ -173,7 +161,7 @@ struct efx_phy_operations falcon_xfp_phy_ops = {
 	.macs		 = EFX_XMAC,
 	.init            = xfp_phy_init,
 	.reconfigure     = xfp_phy_reconfigure,
-	.check_hw        = xfp_phy_check_hw,
+	.poll            = xfp_phy_poll,
 	.fini            = xfp_phy_fini,
 	.clear_interrupt = xfp_phy_clear_interrupt,
 	.get_settings    = mdio_clause45_get_settings,
Signature · 3 lines
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
#39 lore raw

Re: [PATCH 21/33] sfc: Rework MAC, PHY and board event handling

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:55:47 +0000

Quoted 7 lines

From: Steve Hodgson <[email protected]>

MAC, PHY and board events may be separately enabled and signalled. Our current arrangement of chaining the polling functions can result in events being missed. Change them to be more independent.

Applied.

#40 lore raw

PATCH 22/33 sfc: Add support for Solarflare 10Xpress SFT9001

In reply to Ben Hutchings

Add type codes for the new PHY and rename the SFX7101 type code.

Add definition of clause 22 extension MMD.

Adapt the 10Xpress SFX7101 code to support the SFT9001 as well. Clean up register definitions.

---
 drivers/net/sfc/enum.h        |    3 +
 drivers/net/sfc/ethtool.c     |    3 +
 drivers/net/sfc/falcon.c      |   10 +-
 drivers/net/sfc/mdio_10g.h    |    8 +
 drivers/net/sfc/net_driver.h  |    4 +-
 drivers/net/sfc/phy.h         |    7 +-
 drivers/net/sfc/tenxpress.c   |  528 +++++++++++++++++++++++++++++++++--------
 drivers/net/sfc/workarounds.h |    9 +-
 8 files changed, 467 insertions(+), 105 deletions(-)
drivers/net/sfc/enum.h +3 -0
index 0c2e41c..60cbc6e 100644
@@ -58,6 +58,9 @@ extern const char *efx_loopback_mode_names[];
 #define LOOPBACK_INTERNAL(_efx)				\
 	(!!(LOOPBACKS_INTERNAL & LOOPBACK_MASK(_efx)))
 
+#define LOOPBACK_CHANGED(_from, _to, _mask)				\
+	(!!((LOOPBACK_MASK(_from) ^ LOOPBACK_MASK(_to)) & (_mask)))
+
 #define LOOPBACK_OUT_OF(_from, _to, _mask)				\
 	((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask)))
 
drivers/net/sfc/ethtool.c +3 -0
index 0e81af6..aad0d1b 100644
@@ -219,6 +219,9 @@ int efx_ethtool_set_settings(struct net_device *net_dev,
 	struct efx_nic *efx = netdev_priv(net_dev);
 	int rc;
 
+	if (EFX_WORKAROUND_13963(efx) && !ecmd->autoneg)
+		return -EINVAL;
+
 	/* Falcon GMAC does not support 1000Mbps HD */
 	if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) {
 		EFX_LOG(efx, "rejecting unsupported 1000Mbps HD"
drivers/net/sfc/falcon.c +7 -3
index 734add1..68747c8 100644
@@ -826,7 +826,7 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
 #endif
 
 	if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) &&
-		     efx->phy_type == PHY_TYPE_10XPRESS))
+		     efx->phy_type == PHY_TYPE_SFX7101))
 		tenxpress_crc_err(efx);
 }
 
@@ -2256,8 +2256,12 @@ static void falcon_init_mdio(struct mii_if_info *gmii)
 static int falcon_probe_phy(struct efx_nic *efx)
 {
 	switch (efx->phy_type) {
-	case PHY_TYPE_10XPRESS:
-		efx->phy_op = &falcon_tenxpress_phy_ops;
+	case PHY_TYPE_SFX7101:
+		efx->phy_op = &falcon_sfx7101_phy_ops;
+		break;
+	case PHY_TYPE_SFT9001A:
+	case PHY_TYPE_SFT9001B:
+		efx->phy_op = &falcon_sft9001_phy_ops;
 		break;
 	case PHY_TYPE_XFP:
 		efx->phy_op = &falcon_xfp_phy_ops;
drivers/net/sfc/mdio_10g.h +8 -0
index 80c63dd..4091182 100644
@@ -33,6 +33,8 @@
 #define MDIO_MMD_TC	(6)
 /* Auto negotiation */
 #define MDIO_MMD_AN	(7)
+/* Clause 22 extension */
+#define MDIO_MMD_C22EXT	29
 
 /* Generic register locations */
 #define MDIO_MMDREG_CTRL1	(0)
@@ -82,6 +84,7 @@
 #define MDIO_MMDREG_DEVS_PCS	DEV_PRESENT_BIT(MDIO_MMD_PCS)
 #define MDIO_MMDREG_DEVS_PMAPMD	DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
 #define MDIO_MMDREG_DEVS_AN	DEV_PRESENT_BIT(MDIO_MMD_AN)
+#define MDIO_MMDREG_DEVS_C22EXT	DEV_PRESENT_BIT(MDIO_MMD_C22EXT)
 
 /* Bits in MMDREG_SPEED */
 #define MDIO_MMDREG_SPEED_10G_LBN	0
@@ -125,6 +128,11 @@
 #define MDIO_PMAPMD_CTRL2_10_BT		(0xf)
 #define MDIO_PMAPMD_CTRL2_TYPE_MASK	(0xf)
 
+/* PMA 10GBT registers */
+#define MDIO_PMAPMD_10GBT_TXPWR		(131)
+#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0)
+#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1)
+
 /* PHY XGXS lane state */
 #define MDIO_PHYXS_LANE_STATE		(0x18)
 #define MDIO_PHYXS_LANE_ALIGNED_LBN	(12)
drivers/net/sfc/net_driver.h +3 -1
index 61d09a2..1728329 100644
@@ -455,9 +455,11 @@ enum phy_type {
 	PHY_TYPE_NONE = 0,
 	PHY_TYPE_CX4_RTMR = 1,
 	PHY_TYPE_1G_ALASKA = 2,
-	PHY_TYPE_10XPRESS = 3,
+	PHY_TYPE_SFX7101 = 3,
 	PHY_TYPE_XFP = 4,
 	PHY_TYPE_PM8358 = 6,
+	PHY_TYPE_SFT9001A = 8,
+	PHY_TYPE_SFT9001B = 10,
 	PHY_TYPE_MAX	/* Insert any new items before this */
 };
 
drivers/net/sfc/phy.h +4 -3
index f746536..58c493e 100644
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published
@@ -11,9 +11,10 @@
 #define EFX_PHY_H
 
 /****************************************************************************
- * 10Xpress (SFX7101) PHY
+ * 10Xpress (SFX7101 and SFT9001) PHYs
  */
-extern struct efx_phy_operations falcon_tenxpress_phy_ops;
+extern struct efx_phy_operations falcon_sfx7101_phy_ops;
+extern struct efx_phy_operations falcon_sft9001_phy_ops;
 
 extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink);
 extern void tenxpress_crc_err(struct efx_nic *efx);
drivers/net/sfc/tenxpress.c +431 -97

722 lines not on this page · raw message

drivers/net/sfc/workarounds.h +8 -1
index ec50b90..ecebff2 100644
@@ -17,6 +17,8 @@
 
 #define EFX_WORKAROUND_ALWAYS(efx) 1
 #define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1)
+#define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101)
+#define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A)
 
 /* XAUI resets if link not detected */
 #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
@@ -27,7 +29,7 @@
 /* TX pkt parser problem with <= 16 byte TXes */
 #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
 /* Low rate CRC errors require XAUI reset */
-#define EFX_WORKAROUND_10750 EFX_WORKAROUND_ALWAYS
+#define EFX_WORKAROUND_10750 EFX_WORKAROUND_SFX7101
 /* TX_EV_PKT_ERR can be caused by a dangling TX descriptor
  * or a PCIe error (bug 11028) */
 #define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS
@@ -51,4 +53,9 @@
 /* Leak overlength packets rather than free */
 #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
 
+/* Need to send XNP pages for 100BaseT */
+#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001A
+/* Need to keep AN enabled */
+#define EFX_WORKAROUND_13963 EFX_WORKAROUND_SFT9001A
+
 #endif /* EFX_WORKAROUNDS_H */
Signature · 3 lines
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
#41 lore raw

Re: [PATCH 22/33] sfc: Add support for Solarflare 10Xpress SFT9001

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:56:06 +0000

Quoted 8 lines

Add type codes for the new PHY and rename the SFX7101 type code.

Add definition of clause 22 extension MMD.

Adapt the 10Xpress SFX7101 code to support the SFT9001 as well. Clean up register definitions.

Applied.

#42 lore raw

PATCH 23/33 sfc: Add support for SFN4111T

In reply to Ben Hutchings

Add support code for the SFN4111T 100/1000/10GBASE-T reference design, based in part on the existing code for the SFE4001.

---
 drivers/net/sfc/boards.c        |    2 +
 drivers/net/sfc/boards.h        |    7 ++-
 drivers/net/sfc/falcon.c        |    7 ++
 drivers/net/sfc/falcon_hwdefs.h |    2 +
 drivers/net/sfc/selftest.c      |   11 +++-
 drivers/net/sfc/sfe4001.c       |  153 +++++++++++++++++++++++++++++++--------
 drivers/net/sfc/workarounds.h   |    3 +-
 7 files changed, 150 insertions(+), 35 deletions(-)
drivers/net/sfc/boards.c +2 -0
index 08fa4e3..6490349 100644
@@ -241,6 +241,8 @@ struct efx_board_data {
 static struct efx_board_data board_data[] = {
 	{ EFX_BOARD_SFE4001, "SFE4001", "10GBASE-T adapter", sfe4001_init },
 	{ EFX_BOARD_SFE4002, "SFE4002", "XFP adapter", sfe4002_init },
+	{ EFX_BOARD_SFN4111T, "SFN4111T", "100/1000/10GBASE-T adapter",
+	  sfn4111t_init },
 };
 
 void efx_set_board_info(struct efx_nic *efx, u16 revision_info)
drivers/net/sfc/boards.h +6 -1
index 5e0dde5..d93c6c6 100644
@@ -12,11 +12,16 @@
 
 /* Board IDs (must fit in 8 bits) */
 enum efx_board_type {
-	EFX_BOARD_SFE4001 = 1,   /* SFE4001 (10GBASE-T) */
+	EFX_BOARD_SFE4001 = 1,
 	EFX_BOARD_SFE4002 = 2,
+	EFX_BOARD_SFN4111T = 0x51,
 };
 
 extern void efx_set_board_info(struct efx_nic *efx, u16 revision_info);
+
+/* SFE4001 (10GBASE-T) */
 extern int sfe4001_init(struct efx_nic *efx);
+/* SFN4111T (100/1000/10GBASE-T) */
+extern int sfn4111t_init(struct efx_nic *efx);
 
 #endif
drivers/net/sfc/falcon.c +7 -0
index 68747c8..2c53ef4 100644
@@ -2982,6 +2982,13 @@ int falcon_init_nic(struct efx_nic *efx)
 	EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
 	falcon_write(efx, &temp, NIC_STAT_REG);
 
+	/* Set the source of the GMAC clock */
+	if (falcon_rev(efx) == FALCON_REV_B0) {
+		falcon_read(efx, &temp, GPIO_CTL_REG_KER);
+		EFX_SET_OWORD_FIELD(temp, GPIO_USE_NIC_CLK, true);
+		falcon_write(efx, &temp, GPIO_CTL_REG_KER);
+	}
+
 	/* Set buffer table mode */
 	EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL);
 	falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER);
drivers/net/sfc/falcon_hwdefs.h +2 -0
index a58c627..bda8d5b 100644
@@ -136,6 +136,8 @@
 
 /* GPIO control register */
 #define GPIO_CTL_REG_KER 0x0210
+#define GPIO_USE_NIC_CLK_LBN (30)
+#define GPIO_USE_NIC_CLK_WIDTH (1)
 #define GPIO_OUTPUTS_LBN   (16)
 #define GPIO_OUTPUTS_WIDTH (4)
 #define GPIO_INPUTS_LBN (8)
drivers/net/sfc/selftest.c +9 -2
index 578b7f4..6bb09f2 100644
@@ -702,8 +702,15 @@ int efx_offline_test(struct efx_nic *efx,
 	 */
 	mutex_lock(&efx->mac_lock);
 	efx->port_inhibited = true;
-	if (efx->loopback_modes)
-		efx->loopback_mode = __ffs(efx->loopback_modes);
+	if (efx->loopback_modes) {
+		/* We need the 312 clock from the PHY to test the XMAC
+		 * registers, so move into XGMII loopback if available */
+		if (efx->loopback_modes & (1 << LOOPBACK_XGMII))
+			efx->loopback_mode = LOOPBACK_XGMII;
+		else
+			efx->loopback_mode = __ffs(efx->loopback_modes);
+	}
+
 	__efx_reconfigure_port(efx);
 	mutex_unlock(&efx->mac_lock);
 
drivers/net/sfc/sfe4001.c +122 -31

193 lines not on this page · raw message

drivers/net/sfc/workarounds.h +2 -1
index ecebff2..82e03e1 100644
@@ -17,6 +17,7 @@
 
 #define EFX_WORKAROUND_ALWAYS(efx) 1
 #define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1)
+#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
 #define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101)
 #define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A)
 
@@ -25,7 +26,7 @@
 /* RX PCIe double split performance issue */
 #define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS
 /* Bit-bashed I2C reads cause performance drop */
-#define EFX_WORKAROUND_7884 EFX_WORKAROUND_ALWAYS
+#define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G
 /* TX pkt parser problem with <= 16 byte TXes */
 #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
 /* Low rate CRC errors require XAUI reset */
Signature · 3 lines
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
#43 lore raw

Re: [PATCH 23/33] sfc: Add support for SFN4111T

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:56:24 +0000

Quoted 4 lines

Add support code for the SFN4111T 100/1000/10GBASE-T reference design, based in part on the existing code for the SFE4001.

Applied.

#44 lore raw

PATCH 25/33 sfc: Generate unique names for per-NIC workqueues

In reply to Ben Hutchings
---
 drivers/net/sfc/efx.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/net/sfc/efx.c +4 -1
index ce1c7d3..c094845 100644
@@ -1854,6 +1854,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 	struct efx_channel *channel;
 	struct efx_tx_queue *tx_queue;
 	struct efx_rx_queue *rx_queue;
+	char name[16];
 	int i;
 
 	/* Initialise common structures */
@@ -1924,7 +1925,9 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 	efx->interrupt_mode = max(efx->type->max_interrupt_mode,
 				  interrupt_mode);
 
-	efx->workqueue = create_singlethread_workqueue("sfc_work");
+	/* Would be good to use the net_dev name, but we're too early */
+	snprintf(name, sizeof(name), "sfc%s", pci_name(pci_dev));
+	efx->workqueue = create_singlethread_workqueue(name);
 	if (!efx->workqueue)
 		return -ENOMEM;
 
Signature · 3 lines
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
#45 lore raw

Re: [PATCH 25/33] sfc: Generate unique names for per-NIC workqueues

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:56:57 +0000

Quoted 5 lines
drivers/net/sfc/efx.c +1 -0
@@ -1854,6 +1854,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 	struct efx_channel *channel;
 	struct efx_tx_queue *tx_queue;
 	struct efx_rx_queue *rx_queue;
+	char name[16];

...

drivers/net/sfc/efx.c static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, · line 1931

Quoted 9 lines
drivers/net/sfc/efx.c +3 -1
@@ -1924,7 +1925,9 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 	efx->interrupt_mode = max(efx->type->max_interrupt_mode,
 				  interrupt_mode);
 
-	efx->workqueue = create_singlethread_workqueue("sfc_work");
+	/* Would be good to use the net_dev name, but we're too early */
+	snprintf(name, sizeof(name), "sfc%s", pci_name(pci_dev));
+	efx->workqueue = create_singlethread_workqueue(name);
 	if (!efx->workqueue)

This change is buggy.

create_singlethread_workqueue() is going to reference this name buffer on the stack for the life of the workqueue, but once this function returns that reference will no longer be valid.

You'll need to use kmalloc()'d memory and free it later, or something like that.

Patch not applied.

#46 lore raw

Re: [PATCH 25/33] sfc: Generate unique names for per-NIC workqueues

Quoted 21 lines · David Miller

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:56:57 +0000

Quoted 5 lines
drivers/net/sfc/efx.c +1 -0
@@ -1854,6 +1854,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 	struct efx_channel *channel;
 	struct efx_tx_queue *tx_queue;
 	struct efx_rx_queue *rx_queue;
+	char name[16];

...

drivers/net/sfc/efx.c static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, · line 1931

Quoted 9 lines
drivers/net/sfc/efx.c +3 -1
@@ -1924,7 +1925,9 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
 	efx->interrupt_mode = max(efx->type->max_interrupt_mode,
 				  interrupt_mode);
 
-	efx->workqueue = create_singlethread_workqueue("sfc_work");
+	/* Would be good to use the net_dev name, but we're too early */
+	snprintf(name, sizeof(name), "sfc%s", pci_name(pci_dev));
+	efx->workqueue = create_singlethread_workqueue(name);
 	if (!efx->workqueue)

This change is buggy.

Quoted 4 lines

create_singlethread_workqueue() is going to reference this name buffer on the stack for the life of the workqueue, but once this function returns that reference will no longer be valid.

No, it's copied into the "comm" field of task_struct.

Ben.

Signature · 3 lines
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
#47 lore raw

Re: [PATCH 25/33] sfc: Generate unique names for per-NIC workqueues

From: Ben Hutchings <[email protected]>
Date: Sat, 13 Dec 2008 06:23:03 +0000

Quoted 7 lines
Quoted 4 lines · David Miller

create_singlethread_workqueue() is going to reference this name buffer on the stack for the life of the workqueue, but once this function returns that reference will no longer be valid.

No, it's copied into the "comm" field of task_struct.

Hmmm...

create_singlethread_workqueue(name...

	--> __create_workqueue(name...
	--> __create_workqueue_key(name...

which goes:

	wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);
 ...
	wq->name = name;

Which looks like a dynamic memory assumption to me.

#48 lore raw

Re: [PATCH 25/33] sfc: Generate unique names for per-NIC workqueues

Quoted 17 lines · David Miller

From: Ben Hutchings <[email protected]>
Date: Sat, 13 Dec 2008 06:23:03 +0000

Quoted 7 lines
Quoted 4 lines · David Miller

create_singlethread_workqueue() is going to reference this name buffer on the stack for the life of the workqueue, but once this function returns that reference will no longer be valid.

No, it's copied into the "comm" field of task_struct.

Hmmm...

create_singlethread_workqueue(name...

	--> __create_workqueue(name...
	--> __create_workqueue_key(name...
Quoted 6 lines

which goes:

	wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);
 ...
	wq->name = name;

Which looks like a dynamic memory assumption to me.

If you look carefully you'll see that wq->name is never used after initialisation of single-threaded workqueues. But I'd agree it's not nice to have that dangling pointer around, so I'll respin this.

Ben.

Signature · 3 lines
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.
#49 lore raw

PATCH 26/33 sfc: Remove leading spaces

In reply to Ben Hutchings
---
 drivers/net/sfc/falcon.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/sfc/falcon.c +2 -2
index 2c53ef4..8107460 100644
@@ -2940,10 +2940,10 @@ int falcon_probe_nic(struct efx_nic *efx)
 		goto fail5;
 
 	/* Initialise I2C adapter */
- 	efx->i2c_adap.owner = THIS_MODULE;
+	efx->i2c_adap.owner = THIS_MODULE;
 	nic_data->i2c_data = falcon_i2c_bit_operations;
 	nic_data->i2c_data.data = efx;
- 	efx->i2c_adap.algo_data = &nic_data->i2c_data;
+	efx->i2c_adap.algo_data = &nic_data->i2c_data;
 	efx->i2c_adap.dev.parent = &efx->pci_dev->dev;
 	strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
 	rc = i2c_bit_add_bus(&efx->i2c_adap);
Signature · 3 lines
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.
#51 lore raw

PATCH 27/33 sfc: Specify a meaningful component for loopback RX-side and PHY tests

In reply to Ben Hutchings

Our ethtool self-test result names each begin with a component name. For some results this is "port0", which is not very meaningful. Change that to "rx" or "phy" as appropriate.

---
 drivers/net/sfc/ethtool.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)
drivers/net/sfc/ethtool.c +8 -6
index aad0d1b..eab3e5c 100644
@@ -274,8 +274,11 @@ static void efx_fill_test(unsigned int test_index,
 
 	/* Fill string, if applicable */
 	if (strings) {
-		snprintf(unit_str.name, sizeof(unit_str.name),
-			 unit_format, unit_id);
+		if (strchr(unit_format, '%'))
+			snprintf(unit_str.name, sizeof(unit_str.name),
+				 unit_format, unit_id);
+		else
+			strcpy(unit_str.name, unit_format);
 		snprintf(test_str.name, sizeof(test_str.name),
 			 test_format, test_id);
 		snprintf(strings[test_index].name,
@@ -284,7 +287,6 @@ static void efx_fill_test(unsigned int test_index,
 	}
 }
 
-#define EFX_PORT_NAME "port%d", 0
 #define EFX_CHANNEL_NAME(_channel) "chan%d", _channel->channel
 #define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue
 #define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue
@@ -320,11 +322,11 @@ static int efx_fill_loopback_test(struct efx_nic *efx,
 	}
 	efx_fill_test(test_index++, strings, data,
 		      &lb_tests->rx_good,
-		      EFX_PORT_NAME,
+		      "rx", 0,
 		      EFX_LOOPBACK_NAME(mode, "rx_good"));
 	efx_fill_test(test_index++, strings, data,
 		      &lb_tests->rx_bad,
-		      EFX_PORT_NAME,
+		      "rx", 0,
 		      EFX_LOOPBACK_NAME(mode, "rx_bad"));
 
 	return test_index;
@@ -372,7 +374,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
 	efx_fill_test(n++, strings, data, &tests->registers,
 		      "core", 0, "registers", NULL);
 	efx_fill_test(n++, strings, data, &tests->phy,
-		      EFX_PORT_NAME, "phy", NULL);
+		      "phy", 0, "bist", NULL);
 
 	/* Loopback tests */
 	for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
Signature · 3 lines
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
#52 lore raw

Re: [PATCH 27/33] sfc: Specify a meaningful component for loopback RX-side and PHY tests

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:57:34 +0000

Quoted 5 lines

Our ethtool self-test result names each begin with a component name. For some results this is "port0", which is not very meaningful. Change that to "rx" or "phy" as appropriate.

Applied.

#53 lore raw

PATCH 28/33 sfc: Use mutex_lock_interruptible() for ethtool EEPROM access

In reply to Ben Hutchings

ethtool must contend with the MTD driver for the SPI bus lock, which may carry out long operations such as flash erase. Allow it to be interrupted while waiting.

---
 drivers/net/sfc/ethtool.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)
drivers/net/sfc/ethtool.c +8 -2
index eab3e5c..3aaece6 100644
@@ -568,10 +568,13 @@ static int efx_ethtool_get_eeprom(struct net_device *net_dev,
 	size_t len;
 	int rc;
 
-	mutex_lock(&efx->spi_lock);
+	rc = mutex_lock_interruptible(&efx->spi_lock);
+	if (rc)
+		return rc;
 	rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
 			     eeprom->len, &len, buf);
 	mutex_unlock(&efx->spi_lock);
+
 	eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC;
 	eeprom->len = len;
 	return rc;
@@ -588,10 +591,13 @@ static int efx_ethtool_set_eeprom(struct net_device *net_dev,
 	if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC)
 		return -EINVAL;
 
-	mutex_lock(&efx->spi_lock);
+	rc = mutex_lock_interruptible(&efx->spi_lock);
+	if (rc)
+		return rc;
 	rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
 			      eeprom->len, &len, buf);
 	mutex_unlock(&efx->spi_lock);
+
 	eeprom->len = len;
 	return rc;
 }
Signature · 3 lines
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
#54 lore raw

Re: [PATCH 28/33] sfc: Use mutex_lock_interruptible() for ethtool EEPROM access

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:59:23 +0000

Quoted 5 lines

ethtool must contend with the MTD driver for the SPI bus lock, which may carry out long operations such as flash erase. Allow it to be interrupted while waiting.

Applied.

#55 lore raw

PATCH 29/33 sfc: Use model numbers for PHY type names

In reply to Ben Hutchings

Some of the PHY type names are overly generic. Change them to include the model numbers of the PHYs they represent.

Correct the model number reference at the top of xfp_phy.c.

---
 drivers/net/sfc/falcon.c     |    2 +-
 drivers/net/sfc/net_driver.h |    6 +++---
 drivers/net/sfc/xfp_phy.c    |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)
drivers/net/sfc/falcon.c +1 -1
index 8107460..63414ce 100644
@@ -2263,7 +2263,7 @@ static int falcon_probe_phy(struct efx_nic *efx)
 	case PHY_TYPE_SFT9001B:
 		efx->phy_op = &falcon_sft9001_phy_ops;
 		break;
-	case PHY_TYPE_XFP:
+	case PHY_TYPE_QT2022C2:
 		efx->phy_op = &falcon_xfp_phy_ops;
 		break;
 	default:
drivers/net/sfc/net_driver.h +3 -3
index 1728329..7033dba 100644
@@ -453,10 +453,10 @@ enum efx_int_mode {
 
 enum phy_type {
 	PHY_TYPE_NONE = 0,
-	PHY_TYPE_CX4_RTMR = 1,
-	PHY_TYPE_1G_ALASKA = 2,
+	PHY_TYPE_TXC43128 = 1,
+	PHY_TYPE_88E1111 = 2,
 	PHY_TYPE_SFX7101 = 3,
-	PHY_TYPE_XFP = 4,
+	PHY_TYPE_QT2022C2 = 4,
 	PHY_TYPE_PM8358 = 6,
 	PHY_TYPE_SFT9001A = 8,
 	PHY_TYPE_SFT9001B = 10,
drivers/net/sfc/xfp_phy.c +1 -1
index 345ffc3..2d50b6e 100644
@@ -7,7 +7,7 @@
  * by the Free Software Foundation, incorporated herein by reference.
  */
 /*
- * Driver for XFP optical PHYs (plus some support specific to the Quake 2032)
+ * Driver for XFP optical PHYs (plus some support specific to the Quake 2022/32)
  * See www.amcc.com for details (search for qt2032)
  */
 
Signature · 3 lines
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
#56 lore raw

Re: [PATCH 29/33] sfc: Use model numbers for PHY type names

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:59:44 +0000

Quoted 6 lines

Some of the PHY type names are overly generic. Change them to include the model numbers of the PHYs they represent.

Correct the model number reference at the top of xfp_phy.c.

Applied.

#57 lore raw

PATCH 30/33 sfc: Treat probe as unsuccessful if it scheduled a reset

In reply to Ben Hutchings

From: Steve Hodgson <[email protected]>

efx_pci_probe_main() can return success despite a reset being scheduled. Catch this and retry or abort probe depending on the reset type.

---
 drivers/net/sfc/efx.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)
drivers/net/sfc/efx.c +11 -2
index c094845..0d57c6d 100644
@@ -2115,8 +2115,6 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 	 * we're in STATE_INIT. */
 	for (i = 0; i < 5; i++) {
 		rc = efx_pci_probe_main(efx);
-		if (rc == 0)
-			break;
 
 		/* Serialise against efx_reset(). No more resets will be
 		 * scheduled since efx_stop_all() has been called, and we
@@ -2124,6 +2122,17 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 		 * the rtnetlink or driverlink layers. */
 		cancel_work_sync(&efx->reset_work);
 
+		if (rc == 0) {
+			if (efx->reset_pending != RESET_TYPE_NONE) {
+				/* If there was a scheduled reset during
+				 * probe, the NIC is probably hosed anyway */
+				efx_pci_remove_main(efx);
+				rc = -EIO;
+			} else {
+				break;
+			}
+		}
+
 		/* Retry if a recoverably reset event has been scheduled */
 		if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
 		    (efx->reset_pending != RESET_TYPE_ALL))
Signature · 3 lines
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
#58 lore raw

Re: [PATCH 30/33] sfc: Treat probe as unsuccessful if it scheduled a reset

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 13:00:12 +0000

Quoted 6 lines

From: Steve Hodgson <[email protected]>

efx_pci_probe_main() can return success despite a reset being scheduled. Catch this and retry or abort probe depending on the reset type.

Applied.

#59 lore raw

PATCH 31/33 sfc: Use kzalloc() to ensure struct efx_spi_device is fully initialised

In reply to Ben Hutchings

Currently the mtd field is not initialised early enough.

---
 drivers/net/sfc/falcon.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/sfc/falcon.c +1 -1
index 63414ce..e09a01d 100644
@@ -2701,7 +2701,7 @@ static int falcon_spi_device_init(struct efx_nic *efx,
 	struct efx_spi_device *spi_device;
 
 	if (device_type != 0) {
-		spi_device = kmalloc(sizeof(*spi_device), GFP_KERNEL);
+		spi_device = kzalloc(sizeof(*spi_device), GFP_KERNEL);
 		if (!spi_device)
 			return -ENOMEM;
 		spi_device->device_id = device_id;
Signature · 3 lines
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.

A message that is not in the archive (sent off-list or not yet received): [email protected]

#62 lore raw

PATCH 10/33 sfc: Add option to use a separate channel for TX completions

From: Neil Turton <[email protected]>

In a bidirectional forwarding test, we find that the best performance is achieved by sending the TX completion interrupts from one NIC to a CPU which shares an L2 cache with RX completion interrupts from the other NIC. To facilitate this, add an option (through a module parameter) to create separate channels for RX and TX completion with separate IRQs when MSI-X is available.

---
 drivers/net/sfc/efx.c        |   41 ++++++++++++++++++++++++++---------------
 drivers/net/sfc/net_driver.h |    2 ++
 2 files changed, 28 insertions(+), 15 deletions(-)
drivers/net/sfc/efx.c +26 -15
index 15ae2fc..58cbbd5 100644
@@ -64,13 +64,15 @@ MODULE_PARM_DESC(lro, "Large receive offload acceleration");
 /*
  * Use separate channels for TX and RX events
  *
- * Set this to 1 to use separate channels for TX and RX. It allows us to
- * apply a higher level of interrupt moderation to TX events.
+ * Set this to 1 to use separate channels for TX and RX. It allows us
+ * to control interrupt affinity separately for TX and RX.
  *
- * This is forced to 0 for MSI interrupt mode as the interrupt vector
- * is not written
+ * This is only used in MSI-X interrupt mode
  */
-static unsigned int separate_tx_and_rx_channels = true;
+static unsigned int separate_tx_channels;
+module_param(separate_tx_channels, uint, 0644);
+MODULE_PARM_DESC(separate_tx_channels,
+		 "Use separate channels for TX and RX");
 
 /* This is the weight assigned to each of the (per-channel) virtual
  * NAPI devices.
@@ -846,26 +848,33 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 	if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
 		struct msix_entry xentries[EFX_MAX_CHANNELS];
 		int wanted_ints;
+		int rx_queues;
 
 		/* We want one RX queue and interrupt per CPU package
 		 * (or as specified by the rss_cpus module parameter).
 		 * We will need one channel per interrupt.
 		 */
-		wanted_ints = rss_cpus ? rss_cpus : efx_wanted_rx_queues();
-		efx->n_rx_queues = min(wanted_ints, max_channels);
+		rx_queues = rss_cpus ? rss_cpus : efx_wanted_rx_queues();
+		wanted_ints = rx_queues + (separate_tx_channels ? 1 : 0);
+		wanted_ints = min(wanted_ints, max_channels);
 
-		for (i = 0; i < efx->n_rx_queues; i++)
+		for (i = 0; i < wanted_ints; i++)
 			xentries[i].entry = i;
-		rc = pci_enable_msix(efx->pci_dev, xentries, efx->n_rx_queues);
+		rc = pci_enable_msix(efx->pci_dev, xentries, wanted_ints);
 		if (rc > 0) {
-			EFX_BUG_ON_PARANOID(rc >= efx->n_rx_queues);
-			efx->n_rx_queues = rc;
+			EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors"
+				" available (%d < %d).\n", wanted_ints, rc);
+			EFX_ERR(efx, "WARNING: Performance may be reduced.\n");
+			EFX_BUG_ON_PARANOID(rc >= wanted_ints);
+			wanted_ints = rc;
 			rc = pci_enable_msix(efx->pci_dev, xentries,
-					     efx->n_rx_queues);
+					     wanted_ints);
 		}
 
 		if (rc == 0) {
-			for (i = 0; i < efx->n_rx_queues; i++)
+			efx->n_rx_queues = min(rx_queues, wanted_ints);
+			efx->n_channels = wanted_ints;
+			for (i = 0; i < wanted_ints; i++)
 				efx->channel[i].irq = xentries[i].vector;
 		} else {
 			/* Fall back to single channel MSI */
@@ -877,6 +886,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 	/* Try single interrupt MSI */
 	if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
 		efx->n_rx_queues = 1;
+		efx->n_channels = 1;
 		rc = pci_enable_msi(efx->pci_dev);
 		if (rc == 0) {
 			efx->channel[0].irq = efx->pci_dev->irq;
@@ -889,6 +899,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 	/* Assume legacy interrupts */
 	if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
 		efx->n_rx_queues = 1;
+		efx->n_channels = 1 + (separate_tx_channels ? 1 : 0);
 		efx->legacy_irq = efx->pci_dev->irq;
 	}
 }
@@ -913,8 +924,8 @@ static void efx_set_channels(struct efx_nic *efx)
 	struct efx_rx_queue *rx_queue;
 
 	efx_for_each_tx_queue(tx_queue, efx) {
-		if (!EFX_INT_MODE_USE_MSI(efx) && separate_tx_and_rx_channels)
-			tx_queue->channel = &efx->channel[1];
+		if (separate_tx_channels)
+			tx_queue->channel = &efx->channel[efx->n_channels-1];
 		else
 			tx_queue->channel = &efx->channel[0];
 		tx_queue->channel->used_flags |= EFX_USED_BY_TX;
drivers/net/sfc/net_driver.h +2 -0
index f910609..2c5b5fa 100644
@@ -649,6 +649,7 @@ union efx_multicast_hash {
  * @rx_queue: RX DMA queues
  * @channel: Channels
  * @n_rx_queues: Number of RX queues
+ * @n_channels: Number of channels in use
  * @rx_buffer_len: RX buffer length
  * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
  * @irq_status: Interrupt status buffer
@@ -728,6 +729,7 @@ struct efx_nic {
 	struct efx_channel channel[EFX_MAX_CHANNELS];
 
 	int n_rx_queues;
+	int n_channels;
 	unsigned int rx_buffer_len;
 	unsigned int rx_buffer_order;
 
Signature · 3 lines
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
#63 lore raw

Re: [PATCH 10/33] sfc: Add option to use a separate channel for TX completions

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:52:16 +0000

Quoted 10 lines

From: Neil Turton <[email protected]>

In a bidirectional forwarding test, we find that the best performance is achieved by sending the TX completion interrupts from one NIC to a CPU which shares an L2 cache with RX completion interrupts from the other NIC. To facilitate this, add an option (through a module parameter) to create separate channels for RX and TX completion with separate IRQs when MSI-X is available.

Applied.

#64 lore raw

PATCH 11/33 sfc: Provide hints to irqbalance daemon

In reply to a message not in the archive

Allocate IRQs with the name format <device>[-<type>]-<number> so that future versions of irqbalanced understand what we're doing.

---
 drivers/net/sfc/efx.c        |   24 ++++++++++++++++++++++++
 drivers/net/sfc/falcon.c     |    2 +-
 drivers/net/sfc/net_driver.h |    2 ++
 3 files changed, 27 insertions(+), 1 deletions(-)
drivers/net/sfc/efx.c +24 -0
index 58cbbd5..183a440 100644
@@ -356,6 +356,27 @@ static int efx_probe_channel(struct efx_channel *channel)
 }
 
 
+static void efx_set_channel_names(struct efx_nic *efx)
+{
+	struct efx_channel *channel;
+	const char *type = "";
+	int number;
+
+	efx_for_each_channel(channel, efx) {
+		number = channel->channel;
+		if (efx->n_channels > efx->n_rx_queues) {
+			if (channel->channel < efx->n_rx_queues) {
+				type = "-rx";
+			} else {
+				type = "-tx";
+				number -= efx->n_rx_queues;
+			}
+		}
+		snprintf(channel->name, sizeof(channel->name),
+			 "%s%s-%d", efx->name, type, number);
+	}
+}
+
 /* Channels are shutdown and reinitialised whilst the NIC is running
  * to propagate configuration changes (mtu, checksum offload), or
  * to clear hardware error conditions
@@ -1002,6 +1023,7 @@ static int efx_probe_all(struct efx_nic *efx)
 			goto fail3;
 		}
 	}
+	efx_set_channel_names(efx);
 
 	return 0;
 
@@ -1483,6 +1505,7 @@ static int efx_netdev_event(struct notifier_block *this,
 
 		strcpy(efx->name, net_dev->name);
 		efx_mtd_rename(efx);
+		efx_set_channel_names(efx);
 	}
 
 	return NOTIFY_DONE;
@@ -1516,6 +1539,7 @@ static int efx_register_netdev(struct efx_nic *efx)
 		return rc;
 	}
 	strcpy(efx->name, net_dev->name);
+	efx_set_channel_names(efx);
 
 	return 0;
 }
drivers/net/sfc/falcon.c +1 -1
index 9563c13..7421945 100644
@@ -1585,7 +1585,7 @@ int falcon_init_interrupt(struct efx_nic *efx)
 	efx_for_each_channel(channel, efx) {
 		rc = request_irq(channel->irq, falcon_msi_interrupt,
 				 IRQF_PROBE_SHARED, /* Not shared */
-				 efx->name, channel);
+				 channel->name, channel);
 		if (rc) {
 			EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq);
 			goto fail2;
drivers/net/sfc/net_driver.h +2 -0
index 2c5b5fa..abff908 100644
@@ -327,6 +327,7 @@ enum efx_rx_alloc_method {
  *
  * @efx: Associated Efx NIC
  * @channel: Channel instance number
+ * @name: Name for channel and IRQ
  * @used_flags: Channel is used by net driver
  * @enabled: Channel enabled indicator
  * @irq: IRQ number (MSI and MSI-X only)
@@ -357,6 +358,7 @@ enum efx_rx_alloc_method {
 struct efx_channel {
 	struct efx_nic *efx;
 	int channel;
+	char name[IFNAMSIZ + 6];
 	int used_flags;
 	bool enabled;
 	int irq;
Signature · 3 lines
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
#65 lore raw

Re: [PATCH 11/33] sfc: Provide hints to irqbalance daemon

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 12:52:30 +0000

Quoted 4 lines

Allocate IRQs with the name format <device>[-<type>]-<number> so that future versions of irqbalanced understand what we're doing.

Applied, thanks for doing this Ben.

#66 lore raw

PATCH 12/33 sfc: Abbreviate self-test names so they are not truncated

In reply to a message not in the archive

Change "channel" to "chan".

Shorten PHY loopback names.

---
 drivers/net/sfc/ethtool.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)
drivers/net/sfc/ethtool.c +8 -8
index 9c533e0..931ce14 100644
@@ -27,9 +27,9 @@ const char *efx_loopback_mode_names[] = {
 	[LOOPBACK_XGXS]		= "XGXS",
 	[LOOPBACK_XAUI] 	= "XAUI",
 	[LOOPBACK_PHY]		= "PHY",
-	[LOOPBACK_PHYXS]	= "PHY(XS)",
-	[LOOPBACK_PCS]	 	= "PHY(PCS)",
-	[LOOPBACK_PMAPMD]	= "PHY(PMAPMD)",
+	[LOOPBACK_PHYXS]	= "PHYXS",
+	[LOOPBACK_PCS]	 	= "PCS",
+	[LOOPBACK_PMAPMD]	= "PMA/PMD",
 	[LOOPBACK_NETWORK]	= "NETWORK",
 };
 
@@ -242,10 +242,10 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
  * @strings:		Ethtool strings, or %NULL
  * @data:		Ethtool test results, or %NULL
  * @test:		Pointer to test result (used only if data != %NULL)
- * @unit_format:	Unit name format (e.g. "channel\%d")
- * @unit_id:		Unit id (e.g. 0 for "channel0")
+ * @unit_format:	Unit name format (e.g. "chan\%d")
+ * @unit_id:		Unit id (e.g. 0 for "chan0")
  * @test_format:	Test name format (e.g. "loopback.\%s.tx.sent")
- * @test_id:		Test id (e.g. "PHY" for "loopback.PHY.tx_sent")
+ * @test_id:		Test id (e.g. "PHYXS" for "loopback.PHYXS.tx_sent")
  *
  * Fill in an individual self-test entry.
  */
@@ -268,12 +268,12 @@ static void efx_fill_test(unsigned int test_index,
 			 test_format, test_id);
 		snprintf(strings[test_index].name,
 			 sizeof(strings[test_index].name),
-			 "%-9s%-17s", unit_str.name, test_str.name);
+			 "%-6s %-24s", unit_str.name, test_str.name);
 	}
 }
 
 #define EFX_PORT_NAME "port%d", 0
-#define EFX_CHANNEL_NAME(_channel) "channel%d", _channel->channel
+#define EFX_CHANNEL_NAME(_channel) "chan%d", _channel->channel
 #define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue
 #define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue
 #define EFX_LOOPBACK_NAME(_mode, _counter)			\
Signature · 3 lines
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.
#68 lore raw

PATCH 24/33 sfc: Fix format arguments for warning about MSI-X allocation

In reply to a message not in the archive
---
 drivers/net/sfc/efx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/sfc/efx.c +1 -1
index b99ccfb..ce1c7d3 100644
@@ -899,7 +899,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 		rc = pci_enable_msix(efx->pci_dev, xentries, wanted_ints);
 		if (rc > 0) {
 			EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors"
-				" available (%d < %d).\n", wanted_ints, rc);
+				" available (%d < %d).\n", rc, wanted_ints);
 			EFX_ERR(efx, "WARNING: Performance may be reduced.\n");
 			EFX_BUG_ON_PARANOID(rc >= wanted_ints);
 			wanted_ints = rc;
Signature · 3 lines
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.
#69 lore raw

Re: [PATCH 24/33] sfc: Fix format arguments for warning about MSI-X allocation

Quoted 10 lines · Ben Hutchings
---
 drivers/net/sfc/efx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/sfc/efx.c +0 -0
index b99ccfb..ce1c7d3 100644

drivers/net/sfc/efx.c static void efx_probe_interrupts(struct efx_nic *efx) · line 905

Quoted 8 lines
drivers/net/sfc/efx.c +1 -1
@@ -899,7 +899,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 		rc = pci_enable_msix(efx->pci_dev, xentries, wanted_ints);
 		if (rc > 0) {
 			EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors"
-				" available (%d < %d).\n", wanted_ints, rc);
+				" available (%d < %d).\n", rc, wanted_ints);
 			EFX_ERR(efx, "WARNING: Performance may be reduced.\n");
 			EFX_BUG_ON_PARANOID(rc >= wanted_ints);
 			wanted_ints = rc;

I thought this warning was already present, but it is actually introduced by patch 10/33. There's no point in introducing it wrongly, so please combine the two. Or I can post the combined patch myself.

Ben.

Signature · 3 lines
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
#70 lore raw

Re: [PATCH 24/33] sfc: Fix format arguments for warning about MSI-X allocation

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 20:34:47 +0000

Quoted 3 lines

I thought this warning was already present, but it is actually introduced by patch 10/33. There's no point in introducing it wrongly, so please combine the two. Or I can post the combined patch myself.

I'll take care of this, thanks Ben.

#71 lore raw

PATCH 32/33 sfc: Fix synchronisation of efx_mtd_{probe,rename,remove}

In reply to a message not in the archive

Currently efx_mtd_rename() can race with the probe() and remove() functions.

Move probe() before device registration and remove() after unregistration. Move initialisation/update of all names based on the netdev name into a new function and call it under the RTNL immediately after registration.

---
 drivers/net/sfc/efx.c |   33 ++++++++++++++++++---------------
 1 files changed, 18 insertions(+), 15 deletions(-)
drivers/net/sfc/efx.c +18 -15
index 0d57c6d..8d9d0b4 100644
@@ -1517,18 +1517,21 @@ static const struct net_device_ops efx_netdev_ops = {
 #endif
 };
 
+static void efx_update_name(struct efx_nic *efx)
+{
+	strcpy(efx->name, efx->net_dev->name);
+	efx_mtd_rename(efx);
+	efx_set_channel_names(efx);
+}
+
 static int efx_netdev_event(struct notifier_block *this,
 			    unsigned long event, void *ptr)
 {
 	struct net_device *net_dev = ptr;
 
-	if (net_dev->netdev_ops == &efx_netdev_ops && event == NETDEV_CHANGENAME) {
-		struct efx_nic *efx = netdev_priv(net_dev);
-
-		strcpy(efx->name, net_dev->name);
-		efx_mtd_rename(efx);
-		efx_set_channel_names(efx);
-	}
+	if (net_dev->netdev_ops == &efx_netdev_ops &&
+	    event == NETDEV_CHANGENAME)
+		efx_update_name(netdev_priv(net_dev));
 
 	return NOTIFY_DONE;
 }
@@ -1568,8 +1571,10 @@ static int efx_register_netdev(struct efx_nic *efx)
 		EFX_ERR(efx, "could not register net dev\n");
 		return rc;
 	}
-	strcpy(efx->name, net_dev->name);
-	efx_set_channel_names(efx);
+
+	rtnl_lock();
+	efx_update_name(efx);
+	rtnl_unlock();
 
 	rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
 	if (rc) {
@@ -1981,8 +1986,6 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
 	if (!efx)
 		return;
 
-	efx_mtd_remove(efx);
-
 	/* Mark the NIC as fini, then stop the interface */
 	rtnl_lock();
 	efx->state = STATE_FINI;
@@ -1996,6 +1999,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
 
 	efx_unregister_netdev(efx);
 
+	efx_mtd_remove(efx);
+
 	/* Wait for any scheduled resets to complete. No more will be
 	 * scheduled from this point because efx_stop_all() has been
 	 * called, we are no longer registered with driverlink, and
@@ -2149,17 +2154,15 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 	/* Switch to the running state before we expose the device to
 	 * the OS.  This is to ensure that the initial gathering of
 	 * MAC stats succeeds. */
-	rtnl_lock();
 	efx->state = STATE_RUNNING;
-	rtnl_unlock();
+
+	efx_mtd_probe(efx); /* allowed to fail */
 
 	rc = efx_register_netdev(efx);
 	if (rc)
 		goto fail5;
 
 	EFX_LOG(efx, "initialisation successful\n");
-
-	efx_mtd_probe(efx); /* allowed to fail */
 	return 0;
 
  fail5:
Signature · 3 lines
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
#72 lore raw

Re: [PATCH 32/33] sfc: Fix synchronisation of efx_mtd_{probe,rename,remove}

From: Ben Hutchings <[email protected]>
Date: Fri, 12 Dec 2008 13:00:51 +0000

Quoted 9 lines

Currently efx_mtd_rename() can race with the probe() and remove() functions.

Move probe() before device registration and remove() after unregistration. Move initialisation/update of all names based on the netdev name into a new function and call it under the RTNL immediately after registration.

Applied.

#73 lore raw

PATCH 33/33 sfc: Version 2.3

In reply to a message not in the archive
---
 drivers/net/sfc/net_driver.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/sfc/net_driver.h +1 -1
index 7033dba..03feaee 100644
@@ -42,7 +42,7 @@
 #ifndef EFX_DRIVER_NAME
 #define EFX_DRIVER_NAME	"sfc"
 #endif
-#define EFX_DRIVER_VERSION	"2.2"
+#define EFX_DRIVER_VERSION	"2.3"
 
 #ifdef EFX_ENABLE_DEBUG
 #define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
Signature · 3 lines
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.