Index: if_mcx.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_mcx.c,v retrieving revision 1.34 diff -u -p -r1.34 if_mcx.c --- if_mcx.c 30 Sep 2019 01:53:05 -0000 1.34 +++ if_mcx.c 30 Sep 2019 08:40:33 -0000 @@ -143,27 +143,27 @@ #define MCX_REG_PPCNT 0x5008 #define MCX_REG_MCIA 0x9014 -#define MCX_ETHER_CAP_SGMII (1 << 0) -#define MCX_ETHER_CAP_1000_KX (1 << 1) -#define MCX_ETHER_CAP_10G_CX4 (1 << 2) -#define MCX_ETHER_CAP_10G_KX4 (1 << 3) -#define MCX_ETHER_CAP_10G_KR (1 << 4) -#define MCX_ETHER_CAP_40G_CR4 (1 << 6) -#define MCX_ETHER_CAP_40G_KR4 (1 << 7) -#define MCX_ETHER_CAP_10G_CR (1 << 12) -#define MCX_ETHER_CAP_10G_SR (1 << 13) -#define MCX_ETHER_CAP_10G_LR (1 << 14) -#define MCX_ETHER_CAP_40G_SR4 (1 << 15) -#define MCX_ETHER_CAP_40G_LR4 (1 << 16) -#define MCX_ETHER_CAP_50G_SR2 (1 << 18) -#define MCX_ETHER_CAP_100G_CR4 (1 << 20) -#define MCX_ETHER_CAP_100G_SR4 (1 << 21) -#define MCX_ETHER_CAP_100G_KR4 (1 << 22) -#define MCX_ETHER_CAP_25G_CR (1 << 27) -#define MCX_ETHER_CAP_25G_KR (1 << 28) -#define MCX_ETHER_CAP_25G_SR (1 << 29) -#define MCX_ETHER_CAP_50G_CR2 (1 << 30) -#define MCX_ETHER_CAP_50G_KR2 (1 << 31) +#define MCX_ETHER_CAP_SGMII 0 +#define MCX_ETHER_CAP_1000_KX 1 +#define MCX_ETHER_CAP_10G_CX4 2 +#define MCX_ETHER_CAP_10G_KX4 3 +#define MCX_ETHER_CAP_10G_KR 4 +#define MCX_ETHER_CAP_40G_CR4 6 +#define MCX_ETHER_CAP_40G_KR4 7 +#define MCX_ETHER_CAP_10G_CR 12 +#define MCX_ETHER_CAP_10G_SR 13 +#define MCX_ETHER_CAP_10G_LR 14 +#define MCX_ETHER_CAP_40G_SR4 15 +#define MCX_ETHER_CAP_40G_LR4 16 +#define MCX_ETHER_CAP_50G_SR2 18 +#define MCX_ETHER_CAP_100G_CR4 20 +#define MCX_ETHER_CAP_100G_SR4 21 +#define MCX_ETHER_CAP_100G_KR4 22 +#define MCX_ETHER_CAP_25G_CR 27 +#define MCX_ETHER_CAP_25G_KR 28 +#define MCX_ETHER_CAP_25G_SR 29 +#define MCX_ETHER_CAP_50G_CR2 30 +#define MCX_ETHER_CAP_50G_KR2 31 #define MCX_PAGE_SHIFT 12 #define MCX_PAGE_SIZE (1 << MCX_PAGE_SHIFT) @@ -2122,39 +2122,33 @@ static const struct pci_matchid mcx_devi { PCI_VENDOR_MELLANOX, PCI_PRODUCT_MELLANOX_MT28800 }, }; -static const uint64_t mcx_eth_cap_map[] = { - IFM_1000_SGMII, - IFM_1000_KX, - IFM_10G_CX4, - IFM_10G_KX4, - IFM_10G_KR, - 0, - IFM_40G_CR4, - IFM_40G_KR4, - 0, - 0, - 0, - 0, - IFM_10G_SFP_CU, - IFM_10G_SR, - IFM_10G_LR, - IFM_40G_SR4, - IFM_40G_LR4, - 0, - 0, /* IFM_50G_SR2 */ - 0, - IFM_100G_CR4, - IFM_100G_SR4, - IFM_100G_KR4, - 0, - 0, - 0, - 0, - IFM_25G_CR, - IFM_25G_KR, - IFM_25G_SR, - IFM_50G_CR2, - IFM_50G_KR2 +struct mcx_eth_proto_capability { + uint64_t cap_media; + uint64_t cap_baudrate; +}; + +static const struct mcx_eth_proto_capability mcx_eth_cap_map[] = { + [MCX_ETHER_CAP_SGMII] = { IFM_1000_SGMII, IF_Gbps(1) }, + [MCX_ETHER_CAP_1000_KX] = { IFM_1000_KX, IF_Gbps(1) }, + [MCX_ETHER_CAP_10G_CX4] = { IFM_10G_CX4, IF_Gbps(10) }, + [MCX_ETHER_CAP_10G_KX4] = { IFM_10G_KX4, IF_Gbps(10) }, + [MCX_ETHER_CAP_10G_KR] = { IFM_10G_KR, IF_Gbps(10) }, + [MCX_ETHER_CAP_40G_CR4] = { IFM_40G_CR4, IF_Gbps(40) }, + [MCX_ETHER_CAP_40G_KR4] = { IFM_40G_KR4, IF_Gbps(40) }, + [MCX_ETHER_CAP_10G_CR] = { IFM_10G_SFP_CU, IF_Gbps(10) }, + [MCX_ETHER_CAP_10G_SR] = { IFM_10G_SR, IF_Gbps(10) }, + [MCX_ETHER_CAP_10G_LR] = { IFM_10G_LR, IF_Gbps(10) }, + [MCX_ETHER_CAP_40G_SR4] = { IFM_40G_SR4, IF_Gbps(40) }, + [MCX_ETHER_CAP_40G_LR4] = { IFM_40G_LR4, IF_Gbps(40) }, + [MCX_ETHER_CAP_50G_SR2] = { 0 /*IFM_50G_SR2*/, IF_Gbps(50) }, + [MCX_ETHER_CAP_100G_CR4] = { IFM_100G_CR4, IF_Gbps(100) }, + [MCX_ETHER_CAP_100G_SR4] = { IFM_100G_SR4, IF_Gbps(100) }, + [MCX_ETHER_CAP_100G_KR4] = { IFM_100G_KR4, IF_Gbps(100) }, + [MCX_ETHER_CAP_25G_CR] = { IFM_25G_CR, IF_Gbps(25) }, + [MCX_ETHER_CAP_25G_KR] = { IFM_25G_KR, IF_Gbps(25) }, + [MCX_ETHER_CAP_25G_SR] = { IFM_25G_SR, IF_Gbps(25) }, + [MCX_ETHER_CAP_50G_CR2] = { IFM_50G_CR2, IF_Gbps(50) }, + [MCX_ETHER_CAP_50G_KR2] = { IFM_50G_KR2, IF_Gbps(50) }, }; static int @@ -6434,9 +6428,15 @@ mcx_media_add_types(struct mcx_softc *sc proto_cap = betoh32(ptys.rp_eth_proto_cap); for (i = 0; i < nitems(mcx_eth_cap_map); i++) { - if ((proto_cap & (1 << i)) && (mcx_eth_cap_map[i] != 0)) - ifmedia_add(&sc->sc_media, IFM_ETHER | - mcx_eth_cap_map[i], 0, NULL); + const struct mcx_eth_proto_capability *cap; + if (!ISSET(proto_cap, 1 << i)) + continue; + + cap = &mcx_eth_cap_map[i]; + if (cap->cap_media == 0) + continue; + + ifmedia_add(&sc->sc_media, IFM_ETHER | cap->cap_media, 0, NULL); } } @@ -6446,7 +6446,7 @@ mcx_media_status(struct ifnet *ifp, stru struct mcx_softc *sc = (struct mcx_softc *)ifp->if_softc; struct mcx_reg_ptys ptys; int i; - uint32_t proto_cap, proto_oper; + uint32_t proto_oper; uint64_t media_oper; memset(&ptys, 0, sizeof(ptys)); @@ -6459,14 +6459,19 @@ mcx_media_status(struct ifnet *ifp, stru return; } - proto_cap = betoh32(ptys.rp_eth_proto_cap); proto_oper = betoh32(ptys.rp_eth_proto_oper); media_oper = 0; + for (i = 0; i < nitems(mcx_eth_cap_map); i++) { - if (proto_oper & (1 << i)) { - media_oper = mcx_eth_cap_map[i]; - } + const struct mcx_eth_proto_capability *cap; + if (!ISSET(proto_oper, 1 << i)) + continue; + + cap = &mcx_eth_cap_map[i]; + + if (cap->cap_media != 0) + media_oper = cap->cap_media; } ifmr->ifm_status = IFM_AVALID; @@ -6509,7 +6514,10 @@ mcx_media_change(struct ifnet *ifp) /* map media type */ media = 0; for (i = 0; i < nitems(mcx_eth_cap_map); i++) { - if (mcx_eth_cap_map[i] == + const struct mcx_eth_proto_capability *cap; + + cap = &mcx_eth_cap_map[i]; + if (cap->cap_media == IFM_SUBTYPE(sc->sc_media.ifm_media)) { media = (1 << i); break; @@ -6558,23 +6566,48 @@ mcx_port_change(void *xsc) { struct mcx_softc *sc = xsc; struct ifnet *ifp = &sc->sc_ac.ac_if; - struct mcx_reg_paos paos; + struct mcx_reg_paos paos = { + .rp_local_port = 1, + }; + struct mcx_reg_ptys ptys = { + .rp_local_port = 1, + .rp_proto_mask = MCX_REG_PTYS_PROTO_MASK_ETH, + }; int link_state = LINK_STATE_DOWN; - memset(&paos, 0, sizeof(paos)); - paos.rp_local_port = 1; if (mcx_access_hca_reg(sc, MCX_REG_PAOS, MCX_REG_OP_READ, &paos, sizeof(paos)) == 0) { if (paos.rp_oper_status == MCX_REG_PAOS_OPER_STATUS_UP) link_state = LINK_STATE_FULL_DUPLEX; } + if (mcx_access_hca_reg(sc, MCX_REG_PTYS, MCX_REG_OP_READ, &ptys, + sizeof(ptys)) == 0) { + uint32_t proto_oper = betoh32(ptys.rp_eth_proto_oper); + uint64_t baudrate = 0; + unsigned int i; + + for (i = 0; i < nitems(mcx_eth_cap_map); i++) { + const struct mcx_eth_proto_capability *cap; + if (!ISSET(proto_oper, 1 << i)) + continue; + + cap = &mcx_eth_cap_map[i]; + if (cap->cap_baudrate == 0) + continue; + + baudrate = cap->cap_baudrate; + break; + } + + ifp->if_baudrate = baudrate; + } + if (link_state != ifp->if_link_state) { ifp->if_link_state = link_state; if_link_state_change(ifp); } } - static inline uint32_t mcx_rd(struct mcx_softc *sc, bus_size_t r)