From: Richard Houldsworth <rhouldswo...@solarflare.com>

Signed-off-by: Richard Houldsworth <rhouldswo...@solarflare.com>
Signed-off-by: Andrew Rybchenko <arybche...@solarflare.com>
---
 drivers/net/sfc/base/ef10_nic.c | 108 ++++++++++++++++++++++++++++++++++------
 1 file changed, 92 insertions(+), 16 deletions(-)

diff --git a/drivers/net/sfc/base/ef10_nic.c b/drivers/net/sfc/base/ef10_nic.c
index a48f2ac..62d41d2 100644
--- a/drivers/net/sfc/base/ef10_nic.c
+++ b/drivers/net/sfc/base/ef10_nic.c
@@ -1261,26 +1261,58 @@ ef10_get_privilege_mask(
 
 
 /*
- * Table of mapping schemes from port number to the number of the external
- * connector on the board. The external numbering does not distinguish
- * off-board separated outputs such as from multi-headed cables.
+ * Table of mapping schemes from port number to external number.
  *
- * The count of adjacent port numbers that map to each external port
+ * Each port number ultimately corresponds to a connector: either as part of
+ * a cable assembly attached to a module inserted in an SFP+/QSFP+ cage on
+ * the board, or fixed to the board (e.g. 10GBASE-T magjack on SFN5121T
+ * "Salina"). In general:
+ *
+ * Port number (0-based)
+ *     |
+ *   port mapping (n:1)
+ *     |
+ *     v
+ * External port number (normally 1-based)
+ *     |
+ *   fixed (1:1) or cable assembly (1:m)
+ *     |
+ *     v
+ * Connector
+ *
+ * The external numbering refers to the cages or magjacks on the board,
+ * as visibly annotated on the board or back panel. This table describes
+ * 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.
  *
  * 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,
  * so the mapping used is instead the last match in the table to the full
  * set of port modes to which the NIC can be configured. Therefore the
  * ordering of entries in the mapping table is significant.
  */
-static struct {
+static struct ef10_external_port_map_s {
        efx_family_t    family;
        uint32_t        modes_mask;
        int32_t         count;
        int32_t         offset;
 }      __ef10_external_port_mappings[] = {
-       /* Supported modes with 1 output per external port */
+       /*
+        * Modes used by Huntington family controllers where each port
+        * number maps to a separate cage.
+        * SFN7x22F (Torino):
+        *      port 0 -> cage 1
+        *      port 1 -> cage 2
+        * SFN7xx4F (Pavia):
+        *      port 0 -> cage 1
+        *      port 1 -> cage 2
+        *      port 2 -> cage 3
+        *      port 3 -> cage 4
+        */
        {
                EFX_FAMILY_HUNTINGTON,
                (1 << TLV_PORT_MODE_10G) |
@@ -1289,6 +1321,14 @@ static struct {
                1,
                1
        },
+       /*
+        * Modes that on Medford allocate each port number to a separate
+        * cage.
+        *      port 0 -> cage 1
+        *      port 1 -> cage 2
+        *      port 2 -> cage 3
+        *      port 3 -> cage 4
+        */
        {
                EFX_FAMILY_MEDFORD,
                (1 << TLV_PORT_MODE_10G) |
@@ -1296,7 +1336,15 @@ static struct {
                1,
                1
        },
-       /* Supported modes with 2 outputs per external port */
+       /*
+        * Modes which for Huntington identify a chip variant where 2
+        * adjacent port numbers map to each cage.
+        * SFN7x42Q (Monza):
+        *      port 0 -> cage 1
+        *      port 1 -> cage 1
+        *      port 2 -> cage 2
+        *      port 3 -> cage 2
+        */
        {
                EFX_FAMILY_HUNTINGTON,
                (1 << TLV_PORT_MODE_40G) |
@@ -1306,6 +1354,14 @@ static struct {
                2,
                1
        },
+       /*
+        * Modes that on Medford allocate 2 adjacent port numbers to each
+        * cage.
+        *      port 0 -> cage 1
+        *      port 1 -> cage 1
+        *      port 2 -> cage 2
+        *      port 3 -> cage 2
+        */
        {
                EFX_FAMILY_MEDFORD,
                (1 << TLV_PORT_MODE_40G) |
@@ -1316,7 +1372,14 @@ static struct {
                2,
                1
        },
-       /* Supported modes with 4 outputs per external port */
+       /*
+        * Modes that on Medford allocate 4 adjacent port numbers to each
+        * connector, starting on cage 1.
+        *      port 0 -> cage 1
+        *      port 1 -> cage 1
+        *      port 2 -> cage 1
+        *      port 3 -> cage 1
+        */
        {
                EFX_FAMILY_MEDFORD,
                (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
@@ -1324,6 +1387,14 @@ static struct {
                4,
                1,
        },
+       /*
+        * Modes that on Medford allocate 4 adjacent port numbers to each
+        * connector, starting on cage 2.
+        *      port 0 -> cage 2
+        *      port 1 -> cage 2
+        *      port 2 -> cage 2
+        *      port 3 -> cage 2
+        */
        {
                EFX_FAMILY_MEDFORD,
                (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
@@ -1348,7 +1419,7 @@ ef10_external_port_mapping(
 
        if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, &current)) != 0) {
                /*
-                * No current port mode information
+                * No current port mode information (i.e. Huntington)
                 * - infer mapping from available modes
                 */
                if ((rc = efx_mcdi_get_port_modes(enp,
@@ -1365,18 +1436,23 @@ ef10_external_port_mapping(
        }
 
        /*
-        * Infer the internal port -> external port mapping from
+        * Infer the internal port -> external number mapping from
         * the possible port modes for this NIC.
         */
        for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
-               if (__ef10_external_port_mappings[i].family !=
-                   enp->en_family)
+               struct ef10_external_port_map_s *eepmp =
+                   &__ef10_external_port_mappings[i];
+               if (eepmp->family != enp->en_family)
                        continue;
-               matches = (__ef10_external_port_mappings[i].modes_mask &
-                   port_modes);
+               matches = (eepmp->modes_mask & port_modes);
                if (matches != 0) {
-                       count = __ef10_external_port_mappings[i].count;
-                       offset = __ef10_external_port_mappings[i].offset;
+                       /*
+                        * Some modes match. For some Huntington boards
+                        * there will be multiple matches. The mapping on the
+                        * last match is used.
+                        */
+                       count = eepmp->count;
+                       offset = eepmp->offset;
                        port_modes &= ~matches;
                }
        }
-- 
2.7.4

Reply via email to