diff --git a/drivers/net/sfc/base/ef10_nic.c b/drivers/net/sfc/base/ef10_nic.c
index 50e23b7d4..d68920638 100644
--- a/drivers/net/sfc/base/ef10_nic.c
+++ b/drivers/net/sfc/base/ef10_nic.c
@@ -1441,6 +1441,9 @@ ef10_get_privilege_mask(
 }
 
 
+#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 @@ ef10_get_privilege_mask(
  *   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 @@ ef10_get_privilege_mask(
  * 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 @@ ef10_get_privilege_mask(
 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, &current,
 		    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:
