The branch main has been updated by kbowling:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f9ce33b0d8ef233063bd6c27bdba2580f97d9094

commit f9ce33b0d8ef233063bd6c27bdba2580f97d9094
Author:     Kevin Bowling <[email protected]>
AuthorDate: 2026-08-10 16:29:24 +0000
Commit:     Kevin Bowling <[email protected]>
CommitDate: 2026-08-10 16:54:09 +0000

    ixgbe: Add 10GBase-BX BiDi SFP+ module support
    
    10G-BX optics use paired wavelengths to carry 10 Gb/s Ethernet over a
    single strand of single-mode fiber.  Their 10G compliance byte is
    empty, so identify them from the SFF-8472 nominal signaling rate and
    single-mode reach fields.
    
    When an EEPROM also advertises 1G BASE-BX10, give the complete 10G
    bitrate and reach signature precedence.  Otherwise retain FreeBSD's
    permissive 1G-BX identification rather than requiring a nominal
    1.3 GBd rate.
    
    MFC after:      2 weeks
    Relnotes:       yes
---
 sys/dev/ixgbe/if_ix.c       | 10 ++++++++
 sys/dev/ixgbe/ixgbe_82599.c |  7 ++++++
 sys/dev/ixgbe/ixgbe_phy.c   | 61 +++++++++++++++++++++++++++++++++++++++++----
 sys/dev/ixgbe/ixgbe_phy.h   |  3 +++
 sys/dev/ixgbe/ixgbe_type.h  |  3 +++
 sys/dev/ixgbe/ixgbe_x550.c  |  2 ++
 6 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index ba1f3121ae4f..9a59ce6b4fe8 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -1755,6 +1755,10 @@ ixgbe_add_media_types(if_ctx_t ctx)
                        ifmedia_add(sc->media, IFM_ETHER | IFM_1000_LX, 0,
                            NULL);
        }
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_BX) {
+               device_printf(dev, "Media supported: 10Gbase-BX\n");
+               ifmedia_add(sc->media, IFM_ETHER | IFM_10G_BX, 0, NULL);
+       }
        if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
                ifmedia_add(sc->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
                if (hw->phy.multispeed_fiber)
@@ -2896,6 +2900,9 @@ ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * 
ifmr)
                        ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
                        break;
                }
+       if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_BX &&
+           sc->link_speed == IXGBE_LINK_SPEED_10GB_FULL)
+               ifmr->ifm_active |= IFM_10G_BX | IFM_FDX;
        if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM)
                switch (sc->link_speed) {
                case IXGBE_LINK_SPEED_10GB_FULL:
@@ -3028,6 +3035,9 @@ ixgbe_if_media_change(if_ctx_t ctx)
                speed |= IXGBE_LINK_SPEED_1GB_FULL;
                speed |= IXGBE_LINK_SPEED_10GB_FULL;
                break;
+       case IFM_10G_BX:
+               speed |= IXGBE_LINK_SPEED_10GB_FULL;
+               break;
        case IFM_10G_LRM:
        case IFM_10G_LR:
 #ifndef IFM_ETH_XTYPE
diff --git a/sys/dev/ixgbe/ixgbe_82599.c b/sys/dev/ixgbe/ixgbe_82599.c
index d23c84743b33..c8f1fbb9983e 100644
--- a/sys/dev/ixgbe/ixgbe_82599.c
+++ b/sys/dev/ixgbe/ixgbe_82599.c
@@ -454,6 +454,13 @@ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
                goto out;
        }
 
+       if (hw->phy.sfp_type == ixgbe_sfp_type_10g_bx_core0 ||
+           hw->phy.sfp_type == ixgbe_sfp_type_10g_bx_core1) {
+               *speed = IXGBE_LINK_SPEED_10GB_FULL;
+               *autoneg = false;
+               goto out;
+       }
+
        /*
         * Determine link capabilities based on the stored value of AUTOC,
         * which represents EEPROM defaults.  If AUTOC value has not
diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c
index a614ffe50c0d..99bfebd3acf1 100644
--- a/sys/dev/ixgbe/ixgbe_phy.c
+++ b/sys/dev/ixgbe/ixgbe_phy.c
@@ -1299,8 +1299,12 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw 
*hw)
        u8 oui_bytes[3] = {0, 0, 0};
        u8 cable_tech = 0;
        u8 cable_spec = 0;
+       u8 bitrate_nominal = 0;
+       u8 sm_length_100m = 0;
+       u8 sm_length_km = 0;
        u8 retries;
        u16 enforce_sfp = 0;
+       bool is_10g_bx = false;
        static bool warned_once = false;
 
        DEBUGFUNC("ixgbe_identify_sfp_module_generic");
@@ -1358,6 +1362,37 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw 
*hw)
                if (status != IXGBE_SUCCESS)
                        goto err_read_i2c_eeprom;
 
+               /*
+                * SFF-8472 identifies 10G-BX by an empty 10G compliance
+                * byte, a nominal 10.3 GBd rate, and at least 1 km of
+                * single-mode fiber reach.  Resolve that strong signature
+                * before falling back to the permissive 1G-BX check below.
+                */
+               if (hw->mac.type != ixgbe_mac_82598EB &&
+                   comp_codes_10g == 0 &&
+                   (comp_codes_1g & (IXGBE_SFF_1GBASET_CAPABLE |
+                   IXGBE_SFF_1GBASESX_CAPABLE |
+                   IXGBE_SFF_1GBASELX_CAPABLE)) == 0 &&
+                   (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
+                   IXGBE_SFF_DA_ACTIVE_CABLE)) == 0) {
+                       status = hw->phy.ops.read_i2c_eeprom(hw,
+                           IXGBE_SFF_BITRATE_NOMINAL, &bitrate_nominal);
+                       if (status != IXGBE_SUCCESS)
+                               goto err_read_i2c_eeprom;
+                       if (bitrate_nominal == IXGBE_SFF_10G_BX_BITRATE) {
+                               status = hw->phy.ops.read_i2c_eeprom(hw,
+                                   IXGBE_SFF_SM_LENGTH_KM, &sm_length_km);
+                               if (status != IXGBE_SUCCESS)
+                                       goto err_read_i2c_eeprom;
+                               status = hw->phy.ops.read_i2c_eeprom(hw,
+                                   IXGBE_SFF_SM_LENGTH_100M, &sm_length_100m);
+                               if (status != IXGBE_SUCCESS)
+                                       goto err_read_i2c_eeprom;
+                       }
+                       is_10g_bx = bitrate_nominal == IXGBE_SFF_10G_BX_BITRATE 
&&
+                           (sm_length_km > 0 || sm_length_100m >= 10);
+               }
+
                 /* ID Module
                  * =========
                  * 0   SFP_DA_CU
@@ -1437,6 +1472,13 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw 
*hw)
                                else
                                        hw->phy.sfp_type =
                                                ixgbe_sfp_type_1g_lx_core1;
+                       } else if (is_10g_bx) {
+                               if (hw->bus.lan_id == 0)
+                                       hw->phy.sfp_type =
+                                           ixgbe_sfp_type_10g_bx_core0;
+                               else
+                                       hw->phy.sfp_type =
+                                           ixgbe_sfp_type_10g_bx_core1;
                        } else if (comp_codes_1g & IXGBE_SFF_BASEBX10_CAPABLE) {
                                if (hw->bus.lan_id == 0)
                                        hw->phy.sfp_type =
@@ -1536,7 +1578,9 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core0 ||
-                     hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1)) {
+                     hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1 ||
+                     hw->phy.sfp_type == ixgbe_sfp_type_10g_bx_core0 ||
+                     hw->phy.sfp_type == ixgbe_sfp_type_10g_bx_core1)) {
                        hw->phy.type = ixgbe_phy_sfp_unsupported;
                        status = IXGBE_ERR_SFP_NOT_SUPPORTED;
                        goto out;
@@ -1557,7 +1601,9 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
                      hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core0 ||
-                     hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1)) {
+                     hw->phy.sfp_type == ixgbe_sfp_type_1g_bx_core1 ||
+                     hw->phy.sfp_type == ixgbe_sfp_type_10g_bx_core0 ||
+                     hw->phy.sfp_type == ixgbe_sfp_type_10g_bx_core1)) {
                        /* Make sure we're a supported PHY type */
                        if (hw->phy.type == ixgbe_phy_sfp_intel) {
                                status = IXGBE_SUCCESS;
@@ -1612,6 +1658,9 @@ u64 ixgbe_get_supported_phy_sfp_layer_generic(struct 
ixgbe_hw *hw)
        hw->phy.ops.identify_sfp(hw);
        if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
                return physical_layer;
+       if (hw->phy.sfp_type == ixgbe_sfp_type_10g_bx_core0 ||
+           hw->phy.sfp_type == ixgbe_sfp_type_10g_bx_core1)
+               return IXGBE_PHYSICAL_LAYER_10GBASE_BX;
 
        switch (hw->phy.type) {
        case ixgbe_phy_sfp_passive_tyco:
@@ -1884,20 +1933,22 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw 
*hw,
                return IXGBE_ERR_SFP_NOT_SUPPORTED;
 
        /*
-        * Limiting active cables and 1G Phys must be initialized as
+        * Limiting active cables, 10G-BX, and 1G PHYs must be initialized as
         * SR modules
         */
        if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0 ||
            sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
            sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
            sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
-           sfp_type == ixgbe_sfp_type_1g_bx_core0)
+           sfp_type == ixgbe_sfp_type_1g_bx_core0 ||
+           sfp_type == ixgbe_sfp_type_10g_bx_core0)
                sfp_type = ixgbe_sfp_type_srlr_core0;
        else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1 ||
                 sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
                 sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
                 sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
-                sfp_type == ixgbe_sfp_type_1g_bx_core1)
+                sfp_type == ixgbe_sfp_type_1g_bx_core1 ||
+                sfp_type == ixgbe_sfp_type_10g_bx_core1)
                sfp_type = ixgbe_sfp_type_srlr_core1;
 
        /* Read offset to PHY init contents */
diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h
index c1ba73851397..8768267a383a 100644
--- a/sys/dev/ixgbe/ixgbe_phy.h
+++ b/sys/dev/ixgbe/ixgbe_phy.h
@@ -50,6 +50,8 @@
 #define IXGBE_SFF_10GBE_COMP_CODES     0x3
 #define IXGBE_SFF_CABLE_TECHNOLOGY     0x8
 #define IXGBE_SFF_BITRATE_NOMINAL      0xC
+#define IXGBE_SFF_SM_LENGTH_KM         0xE
+#define IXGBE_SFF_SM_LENGTH_100M               0xF
 #define IXGBE_SFF_CABLE_SPEC_COMP      0x3C
 #define IXGBE_SFF_SFF_8472_SWAP                0x5C
 #define IXGBE_SFF_SFF_8472_COMP                0x5E
@@ -75,6 +77,7 @@
 #define IXGBE_SFF_10GBASESR_CAPABLE    0x10
 #define IXGBE_SFF_10GBASELR_CAPABLE    0x20
 #define IXGBE_SFF_BASEBX10_CAPABLE     0x40
+#define IXGBE_SFF_10G_BX_BITRATE       0x67
 #define IXGBE_SFF_SOFT_RS_SELECT_MASK  0x8
 #define IXGBE_SFF_SOFT_RS_SELECT_10G   0x8
 #define IXGBE_SFF_SOFT_RS_SELECT_1G    0x0
diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h
index 648f790194db..4986673b65c4 100644
--- a/sys/dev/ixgbe/ixgbe_type.h
+++ b/sys/dev/ixgbe/ixgbe_type.h
@@ -3551,6 +3551,7 @@ typedef u64 ixgbe_physical_layer;
 #define IXGBE_PHYSICAL_LAYER_2500BASE_KX       0x10000
 #define IXGBE_PHYSICAL_LAYER_2500BASE_T                0x20000
 #define IXGBE_PHYSICAL_LAYER_5000BASE_T                0x40000
+#define IXGBE_PHYSICAL_LAYER_10GBASE_BX                0x80000
 
 /* Flow Control Data Sheet defined values
  * Calculation and defines taken from 802.1bb Annex O
@@ -3827,6 +3828,8 @@ enum ixgbe_sfp_type {
        ixgbe_sfp_type_1g_lx_core1 = 14,
        ixgbe_sfp_type_1g_bx_core0 = 15,
        ixgbe_sfp_type_1g_bx_core1 = 16,
+       ixgbe_sfp_type_10g_bx_core0 = 17,
+       ixgbe_sfp_type_10g_bx_core1 = 18,
        ixgbe_sfp_type_not_present = 0xFFFE,
        ixgbe_sfp_type_unknown = 0xFFFF
 };
diff --git a/sys/dev/ixgbe/ixgbe_x550.c b/sys/dev/ixgbe/ixgbe_x550.c
index 2891bc258db8..4f708e03b00e 100644
--- a/sys/dev/ixgbe/ixgbe_x550.c
+++ b/sys/dev/ixgbe/ixgbe_x550.c
@@ -1508,6 +1508,8 @@ static s32 ixgbe_supported_sfp_modules_X550em(struct 
ixgbe_hw *hw, bool *linear)
        case ixgbe_sfp_type_1g_lx_core1:
        case ixgbe_sfp_type_1g_bx_core0:
        case ixgbe_sfp_type_1g_bx_core1:
+       case ixgbe_sfp_type_10g_bx_core0:
+       case ixgbe_sfp_type_10g_bx_core1:
                *linear = false;
                break;
        case ixgbe_sfp_type_unknown:

Reply via email to