diff options
-rw-r--r-- | sys/dev/pci/if_mcx.c | 101 |
1 files changed, 95 insertions, 6 deletions
diff --git a/sys/dev/pci/if_mcx.c b/sys/dev/pci/if_mcx.c index 9108423827d..c4a83a68edb 100644 --- a/sys/dev/pci/if_mcx.c +++ b/sys/dev/pci/if_mcx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mcx.c,v 1.111 2023/11/10 15:51:20 bluhm Exp $ */ +/* $OpenBSD: if_mcx.c,v 1.112 2024/04/11 05:30:55 jmatthew Exp $ */ /* * Copyright (c) 2017 David Gwynne <dlg@openbsd.org> @@ -199,6 +199,19 @@ CTASSERT(MCX_MAX_QUEUES * MCX_WQ_DOORBELL_STRIDE < #define MCX_ETHER_CAP_50G_CR2 30 #define MCX_ETHER_CAP_50G_KR2 31 +#define MCX_ETHER_EXT_CAP_SGMII_100 0 +#define MCX_ETHER_EXT_CAP_1000_X 1 +#define MCX_ETHER_EXT_CAP_5G_R 3 +#define MCX_ETHER_EXT_CAP_XAUI 4 +#define MCX_ETHER_EXT_CAP_XLAUI 5 +#define MCX_ETHER_EXT_CAP_25G_AUI1 6 +#define MCX_ETHER_EXT_CAP_50G_AUI2 7 +#define MCX_ETHER_EXT_CAP_50G_AUI1 8 +#define MCX_ETHER_EXT_CAP_CAUI4 9 +#define MCX_ETHER_EXT_CAP_100G_AUI2 10 +#define MCX_ETHER_EXT_CAP_200G_AUI4 12 +#define MCX_ETHER_EXT_CAP_400G_AUI8 15 + #define MCX_MAX_CQE 32 #define MCX_CMD_QUERY_HCA_CAP 0x100 @@ -406,11 +419,14 @@ struct mcx_reg_ptys { uint8_t rp_reserved2; uint8_t rp_proto_mask; #define MCX_REG_PTYS_PROTO_MASK_ETH (1 << 2) - uint8_t rp_reserved3[8]; + uint8_t rp_reserved3[4]; + uint32_t rp_ext_eth_proto_cap; uint32_t rp_eth_proto_cap; - uint8_t rp_reserved4[8]; + uint8_t rp_reserved4[4]; + uint32_t rp_ext_eth_proto_admin; uint32_t rp_eth_proto_admin; - uint8_t rp_reserved5[8]; + uint8_t rp_reserved5[4]; + uint32_t rp_ext_eth_proto_oper; uint32_t rp_eth_proto_oper; uint8_t rp_reserved6[24]; } __packed __aligned(4); @@ -2691,6 +2707,21 @@ static const struct mcx_eth_proto_capability mcx_eth_cap_map[] = { [MCX_ETHER_CAP_50G_KR2] = { IFM_50G_KR2, IF_Gbps(50) }, }; +static const struct mcx_eth_proto_capability mcx_ext_eth_cap_map[] = { + [MCX_ETHER_EXT_CAP_SGMII_100] = { IFM_100_FX, IF_Mbps(100) }, + [MCX_ETHER_EXT_CAP_1000_X] = { IFM_1000_SX, IF_Gbps(1) }, + [MCX_ETHER_EXT_CAP_5G_R] = { IFM_5000_T, IF_Gbps(5) }, + [MCX_ETHER_EXT_CAP_XAUI] = { IFM_10G_SFI, IF_Gbps(10) }, + [MCX_ETHER_EXT_CAP_XLAUI] = { IFM_40G_XLPPI, IF_Gbps(40) }, + [MCX_ETHER_EXT_CAP_25G_AUI1] = { 0 /*IFM_25G_AUI*/, IF_Gbps(25) }, + [MCX_ETHER_EXT_CAP_50G_AUI2] = { 0 /*IFM_50G_AUI*/, IF_Gbps(50) }, + [MCX_ETHER_EXT_CAP_50G_AUI1] = { 0 /*IFM_50G_AUI*/, IF_Gbps(50) }, + [MCX_ETHER_EXT_CAP_CAUI4] = { 0 /*IFM_100G_AUI*/, IF_Gbps(100) }, + [MCX_ETHER_EXT_CAP_100G_AUI2] = { 0 /*IFM_100G_AUI*/, IF_Gbps(100) }, + [MCX_ETHER_EXT_CAP_200G_AUI4] = { 0 /*IFM_200G_AUI*/, IF_Gbps(200) }, + [MCX_ETHER_EXT_CAP_400G_AUI8] = { 0 /*IFM_400G_AUI*/, IF_Gbps(400) }, +}; + static int mcx_get_id(uint32_t val) { @@ -7956,6 +7987,19 @@ mcx_media_add_types(struct mcx_softc *sc) ifmedia_add(&sc->sc_media, IFM_ETHER | cap->cap_media, 0, NULL); } + + proto_cap = betoh32(ptys.rp_ext_eth_proto_cap); + for (i = 0; i < nitems(mcx_ext_eth_cap_map); i++) { + const struct mcx_eth_proto_capability *cap; + if (!ISSET(proto_cap, 1 << i)) + continue; + + cap = &mcx_ext_eth_cap_map[i]; + if (cap->cap_media == 0) + continue; + + ifmedia_add(&sc->sc_media, IFM_ETHER | cap->cap_media, 0, NULL); + } } static void @@ -7965,6 +8009,7 @@ mcx_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) struct mcx_reg_ptys ptys; int i; uint32_t proto_oper; + uint32_t ext_proto_oper; uint64_t media_oper; memset(&ptys, 0, sizeof(ptys)); @@ -7979,6 +8024,7 @@ mcx_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) } proto_oper = betoh32(ptys.rp_eth_proto_oper); + ext_proto_oper = betoh32(ptys.rp_ext_eth_proto_oper); media_oper = 0; @@ -7993,8 +8039,21 @@ mcx_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) media_oper = cap->cap_media; } + if (media_oper == 0) { + for (i = 0; i < nitems(mcx_ext_eth_cap_map); i++) { + const struct mcx_eth_proto_capability *cap; + if (!ISSET(ext_proto_oper, 1 << i)) + continue; + + cap = &mcx_ext_eth_cap_map[i]; + + if (cap->cap_media != 0) + media_oper = cap->cap_media; + } + } + ifmr->ifm_status = IFM_AVALID; - if (proto_oper != 0) { + if ((proto_oper | ext_proto_oper) != 0) { ifmr->ifm_status |= IFM_ACTIVE; ifmr->ifm_active = IFM_ETHER | IFM_AUTO | media_oper; /* txpause, rxpause, duplex? */ @@ -8010,6 +8069,7 @@ mcx_media_change(struct ifnet *ifp) struct mcx_reg_ptys ptys; struct mcx_reg_paos paos; uint32_t media; + uint32_t ext_media; int i, error; if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER) @@ -8032,6 +8092,7 @@ mcx_media_change(struct ifnet *ifp) } media = betoh32(ptys.rp_eth_proto_cap); + ext_media = betoh32(ptys.rp_ext_eth_proto_cap); } else { /* map media type */ media = 0; @@ -8045,6 +8106,17 @@ mcx_media_change(struct ifnet *ifp) break; } } + + for (i = 0; i < nitems(mcx_ext_eth_cap_map); i++) { + const struct mcx_eth_proto_capability *cap; + + cap = &mcx_ext_eth_cap_map[i]; + if (cap->cap_media == + IFM_SUBTYPE(sc->sc_media.ifm_media)) { + media = (1 << i); + break; + } + } } /* disable the port */ @@ -8063,6 +8135,7 @@ mcx_media_change(struct ifnet *ifp) ptys.rp_local_port = 1; ptys.rp_proto_mask = MCX_REG_PTYS_PROTO_MASK_ETH; ptys.rp_eth_proto_admin = htobe32(media); + ptys.rp_ext_eth_proto_admin = htobe32(ext_media); if (mcx_access_hca_reg(sc, MCX_REG_PTYS, MCX_REG_OP_WRITE, &ptys, sizeof(ptys), MCX_CMDQ_SLOT_IOCTL) != 0) { printf("%s: unable to set port media type/speed\n", @@ -8107,10 +8180,11 @@ mcx_port_change(void *xsc) if (mcx_access_hca_reg(sc, MCX_REG_PTYS, MCX_REG_OP_READ, &ptys, sizeof(ptys), slot) == 0) { uint32_t proto_oper = betoh32(ptys.rp_eth_proto_oper); + uint32_t ext_proto_oper = betoh32(ptys.rp_ext_eth_proto_oper); uint64_t baudrate = 0; unsigned int i; - if (proto_oper != 0) + if ((proto_oper | ext_proto_oper) != 0) link_state = LINK_STATE_FULL_DUPLEX; for (i = 0; i < nitems(mcx_eth_cap_map); i++) { @@ -8126,6 +8200,21 @@ mcx_port_change(void *xsc) break; } + if (baudrate == 0) { + for (i = 0; i < nitems(mcx_ext_eth_cap_map); i++) { + const struct mcx_eth_proto_capability *cap; + if (!ISSET(ext_proto_oper, 1 << i)) + continue; + + cap = &mcx_ext_eth_cap_map[i]; + if (cap->cap_baudrate == 0) + continue; + + baudrate = cap->cap_baudrate; + break; + } + } + ifp->if_baudrate = baudrate; } |