From fc3c5bbd05f6732b29cbec16ed089cf6b9c9c46c Mon Sep 17 00:00:00 2001 From: Richard Houldsworth Date: Thu, 7 Feb 2019 16:29:07 +0000 Subject: [PATCH] net/sfc/base: update external port number calculation Revise the external port calculation to support all X2 port modes. The previous algorithm could not handle different port numbering schemes on each cage. Signed-off-by: Richard Houldsworth Signed-off-by: Andrew Rybchenko --- drivers/net/sfc/base/ef10_nic.c | 126 ++++++++++++++++---------------- 1 file changed, 62 insertions(+), 64 deletions(-) diff --git a/drivers/net/sfc/base/ef10_nic.c b/drivers/net/sfc/base/ef10_nic.c index 50e23b7d4e..d689206384 100644 --- a/drivers/net/sfc/base/ef10_nic.c +++ b/drivers/net/sfc/base/ef10_nic.c @@ -1441,6 +1441,9 @@ fail1: } +#define EFX_EXT_PORT_MAX 4 +#define EFX_EXT_PORT_NA 0xFF + /* * Table of mapping schemes from port number to external number. * @@ -1454,7 +1457,7 @@ fail1: * port mapping (n:1) * | * v - * External port number (normally 1-based) + * External port number (1-based) * | * fixed (1:1) or cable assembly (1:m) * | @@ -1466,9 +1469,8 @@ fail1: * how to determine which external cage/magjack corresponds to the port * numbers used by the driver. * - * The count of adjacent port numbers that map to each external number, - * and the offset in the numbering, is determined by the chip family and - * current port mode. + * The count of consecutive port numbers that map to each external number, + * is determined by the chip family and the current port mode. * * For the Huntington family, the current port mode cannot be discovered, * but a single mapping is used by all modes for a given chip variant, @@ -1479,8 +1481,7 @@ fail1: static struct ef10_external_port_map_s { efx_family_t family; uint32_t modes_mask; - int32_t count; - int32_t offset; + uint8_t base_port[EFX_EXT_PORT_MAX]; } __ef10_external_port_mappings[] = { /* * Modes used by Huntington family controllers where each port @@ -1499,8 +1500,7 @@ static struct ef10_external_port_map_s { (1U << TLV_PORT_MODE_10G) | /* mode 0 */ (1U << TLV_PORT_MODE_10G_10G) | /* mode 2 */ (1U << TLV_PORT_MODE_10G_10G_10G_10G), /* mode 4 */ - 1, /* ports per cage */ - 1 /* first cage */ + { 0, 1, 2, 3 } }, /* * Modes which for Huntington identify a chip variant where 2 @@ -1517,8 +1517,7 @@ static struct ef10_external_port_map_s { (1U << TLV_PORT_MODE_40G_40G) | /* mode 3 */ (1U << TLV_PORT_MODE_40G_10G_10G) | /* mode 6 */ (1U << TLV_PORT_MODE_10G_10G_40G), /* mode 7 */ - 2, /* ports per cage */ - 1 /* first cage */ + { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA } }, /* * Modes that on Medford allocate each port number to a separate @@ -1531,9 +1530,9 @@ static struct ef10_external_port_map_s { { EFX_FAMILY_MEDFORD, (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */ + (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */ (1U << TLV_PORT_MODE_1x1_1x1), /* mode 2 */ - 1, /* ports per cage */ - 1 /* first cage */ + { 0, 1, 2, 3 } }, /* * Modes that on Medford allocate 2 adjacent port numbers to each @@ -1545,18 +1544,17 @@ static struct ef10_external_port_map_s { */ { EFX_FAMILY_MEDFORD, - (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */ (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */ + (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 5 */ (1U << TLV_PORT_MODE_1x4_2x1) | /* mode 6 */ (1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */ /* Do not use 10G_10G_10G_10G_Q1_Q2 (see bug63270) */ (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2), /* mode 9 */ - 2, /* ports per cage */ - 1 /* first cage */ + { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA } }, /* - * Modes that on Medford allocate 4 adjacent port numbers to each - * connector, starting on cage 1. + * Modes that on Medford allocate 4 adjacent port numbers to + * cage 1. * port 0 -> cage 1 * port 1 -> cage 1 * port 2 -> cage 1 @@ -1564,15 +1562,13 @@ static struct ef10_external_port_map_s { */ { EFX_FAMILY_MEDFORD, - (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 5 */ /* Do not use 10G_10G_10G_10G_Q1 (see bug63270) */ (1U << TLV_PORT_MODE_4x1_NA), /* mode 4 */ - 4, /* ports per cage */ - 1 /* first cage */ + { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA } }, /* - * Modes that on Medford allocate 4 adjacent port numbers to each - * connector, starting on cage 2. + * Modes that on Medford allocate 4 adjacent port numbers to + * cage 2. * port 0 -> cage 2 * port 1 -> cage 2 * port 2 -> cage 2 @@ -1581,8 +1577,7 @@ static struct ef10_external_port_map_s { { EFX_FAMILY_MEDFORD, (1U << TLV_PORT_MODE_NA_4x1), /* mode 8 */ - 4, /* ports per cage */ - 2 /* first cage */ + { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA } }, /* * Modes that on Medford2 allocate each port number to a separate @@ -1597,23 +1592,29 @@ static struct ef10_external_port_map_s { (1U << TLV_PORT_MODE_1x1_NA) | /* mode 0 */ (1U << TLV_PORT_MODE_1x4_NA) | /* mode 1 */ (1U << TLV_PORT_MODE_1x1_1x1) | /* mode 2 */ + (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */ (1U << TLV_PORT_MODE_1x2_NA) | /* mode 10 */ (1U << TLV_PORT_MODE_1x2_1x2) | /* mode 12 */ (1U << TLV_PORT_MODE_1x4_1x2) | /* mode 15 */ (1U << TLV_PORT_MODE_1x2_1x4), /* mode 16 */ - 1, /* ports per cage */ - 1 /* first cage */ + { 0, 1, 2, 3 } }, /* - * FIXME: Some port modes are not representable in this mapping: - * - TLV_PORT_MODE_1x2_2x1 (mode 17): + * Modes that on Medford2 allocate 1 port to cage 1 and the rest + * to cage 2. * port 0 -> cage 1 * port 1 -> cage 2 * port 2 -> cage 2 */ + { + EFX_FAMILY_MEDFORD2, + (1U << TLV_PORT_MODE_1x2_2x1) | /* mode 17 */ + (1U << TLV_PORT_MODE_1x4_2x1), /* mode 6 */ + { 0, 1, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA } + }, /* - * Modes that on Medford2 allocate 2 adjacent port numbers to each - * cage, starting on cage 1. + * Modes that on Medford2 allocate 2 adjacent port numbers to cage 1 + * and the rest to cage 2. * port 0 -> cage 1 * port 1 -> cage 1 * port 2 -> cage 2 @@ -1621,30 +1622,15 @@ static struct ef10_external_port_map_s { */ { EFX_FAMILY_MEDFORD2, - (1U << TLV_PORT_MODE_1x4_1x4) | /* mode 3 */ (1U << TLV_PORT_MODE_2x1_2x1) | /* mode 4 */ - (1U << TLV_PORT_MODE_1x4_2x1) | /* mode 6 */ (1U << TLV_PORT_MODE_2x1_1x4) | /* mode 7 */ (1U << TLV_PORT_MODE_2x2_NA) | /* mode 13 */ (1U << TLV_PORT_MODE_2x1_1x2), /* mode 18 */ - 2, /* ports per cage */ - 1 /* first cage */ - }, - /* - * Modes that on Medford2 allocate 2 adjacent port numbers to each - * cage, starting on cage 2. - * port 0 -> cage 2 - * port 1 -> cage 2 - */ - { - EFX_FAMILY_MEDFORD2, - (1U << TLV_PORT_MODE_NA_2x2), /* mode 14 */ - 2, /* ports per cage */ - 2 /* first cage */ + { 0, 2, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA } }, /* - * Modes that on Medford2 allocate 4 adjacent port numbers to each - * connector, starting on cage 1. + * Modes that on Medford2 allocate up to 4 adjacent port numbers + * to cage 1. * port 0 -> cage 1 * port 1 -> cage 1 * port 2 -> cage 1 @@ -1653,12 +1639,11 @@ static struct ef10_external_port_map_s { { EFX_FAMILY_MEDFORD2, (1U << TLV_PORT_MODE_4x1_NA), /* mode 5 */ - 4, /* ports per cage */ - 1 /* first cage */ + { 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA } }, /* - * Modes that on Medford2 allocate 4 adjacent port numbers to each - * connector, starting on cage 2. + * Modes that on Medford2 allocate up to 4 adjacent port numbers + * to cage 2. * port 0 -> cage 2 * port 1 -> cage 2 * port 2 -> cage 2 @@ -1667,9 +1652,9 @@ static struct ef10_external_port_map_s { { EFX_FAMILY_MEDFORD2, (1U << TLV_PORT_MODE_NA_4x1) | /* mode 8 */ - (1U << TLV_PORT_MODE_NA_1x2), /* mode 11 */ - 4, /* ports per cage */ - 2 /* first cage */ + (1U << TLV_PORT_MODE_NA_1x2) | /* mode 11 */ + (1U << TLV_PORT_MODE_NA_2x2), /* mode 14 */ + { EFX_EXT_PORT_NA, 0, EFX_EXT_PORT_NA, EFX_EXT_PORT_NA } }, }; @@ -1684,8 +1669,8 @@ ef10_external_port_mapping( uint32_t port_modes; uint32_t matches; uint32_t current; - int32_t count = 1; /* Default 1-1 mapping */ - int32_t offset = 1; /* Default starting external port number */ + struct ef10_external_port_map_s *mapp = NULL; + int ext_index = port; /* Default 1-1 mapping */ if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, ¤t, NULL)) != 0) { @@ -1722,8 +1707,7 @@ ef10_external_port_mapping( * there will be multiple matches. The mapping on the * last match is used. */ - count = eepmp->count; - offset = eepmp->offset; + mapp = eepmp; port_modes &= ~matches; } } @@ -1735,11 +1719,25 @@ ef10_external_port_mapping( } out: - /* - * Scale as required by last matched mode and then convert to - * correctly offset numbering - */ - *external_portp = (uint8_t)((port / count) + offset); + if (mapp != NULL) { + /* + * External ports are assigned a sequence of consecutive + * port numbers, so find the one with the closest base_port. + */ + uint32_t delta = EFX_EXT_PORT_NA; + + for (i = 0; i < EFX_EXT_PORT_MAX; i++) { + uint32_t base = mapp->base_port[i]; + if ((base != EFX_EXT_PORT_NA) && (base <= port)) { + if ((port - base) < delta) { + delta = (port - base); + ext_index = i; + } + } + } + } + *external_portp = (uint8_t)(ext_index + 1); + return (0); fail1: -- 2.20.1