Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Add media and flow changes support for ixl(4)
details: https://anonhg.NetBSD.org/src/rev/8abc2710b784
branches: trunk
changeset: 744368:8abc2710b784
user: yamaguchi <yamaguchi%NetBSD.org@localhost>
date: Fri Jan 31 02:16:26 2020 +0000
description:
Add media and flow changes support for ixl(4)
diffstat:
sys/dev/pci/if_ixl.c | 198 +++++++++++++++++++++++++++++++++++++++++++----
sys/dev/pci/if_ixlvar.h | 35 ++++++-
2 files changed, 206 insertions(+), 27 deletions(-)
diffs (truncated from 389 to 300 lines):
diff -r 7468aed6b8a4 -r 8abc2710b784 sys/dev/pci/if_ixl.c
--- a/sys/dev/pci/if_ixl.c Fri Jan 31 02:11:06 2020 +0000
+++ b/sys/dev/pci/if_ixl.c Fri Jan 31 02:16:26 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ixl.c,v 1.30 2020/01/31 02:11:06 yamaguchi Exp $ */
+/* $NetBSD: if_ixl.c,v 1.31 2020/01/31 02:16:26 yamaguchi Exp $ */
/*
* Copyright (c) 2013-2015, Intel Corporation
@@ -634,6 +634,13 @@
struct ifmedia sc_media;
uint64_t sc_media_status;
uint64_t sc_media_active;
+ uint64_t sc_phy_types;
+ uint8_t sc_phy_abilities;
+ uint8_t sc_phy_linkspeed;
+ uint8_t sc_phy_fec_cfg;
+ uint16_t sc_eee_cap;
+ uint32_t sc_eeer_val;
+ uint8_t sc_d3_lpan;
kmutex_t sc_cfg_lock;
enum i40e_mac_type sc_mac_type;
uint32_t sc_rss_table_size;
@@ -786,7 +793,9 @@
static int ixl_get_mac(struct ixl_softc *);
static int ixl_get_switch_config(struct ixl_softc *);
static int ixl_phy_mask_ints(struct ixl_softc *);
-static int ixl_get_phy_types(struct ixl_softc *, uint64_t *);
+static int ixl_get_phy_info(struct ixl_softc *);
+static int ixl_set_phy_config(struct ixl_softc *, uint8_t, uint8_t, bool);
+static int ixl_set_phy_autoselect(struct ixl_softc *);
static int ixl_restart_an(struct ixl_softc *);
static int ixl_hmc(struct ixl_softc *);
static void ixl_hmc_free(struct ixl_softc *);
@@ -797,6 +806,8 @@
static int ixl_get_link_status_poll(struct ixl_softc *);
static int ixl_set_link_status(struct ixl_softc *,
const struct ixl_aq_desc *);
+static uint64_t ixl_search_link_speed(uint8_t);
+static uint8_t ixl_search_baudrate(uint64_t);
static void ixl_config_rss(struct ixl_softc *);
static int ixl_add_macvlan(struct ixl_softc *, const uint8_t *,
uint16_t, uint16_t);
@@ -813,7 +824,7 @@
static void ixl_attach(device_t, device_t, void *);
static int ixl_detach(device_t, int);
-static void ixl_media_add(struct ixl_softc *, uint64_t);
+static void ixl_media_add(struct ixl_softc *);
static int ixl_media_change(struct ifnet *);
static void ixl_media_status(struct ifnet *, struct ifmediareq *);
static void ixl_watchdog(struct ifnet *);
@@ -1081,7 +1092,6 @@
struct ifnet *ifp;
pcireg_t memtype;
uint32_t firstq, port, ari, func;
- uint64_t phy_types = 0;
char xnamebuf[32];
int tries, rv;
@@ -1280,8 +1290,8 @@
goto free_hmc;
}
- if (ixl_get_phy_types(sc, &phy_types) != 0) {
- /* error printed by ixl_get_phy_abilities */
+ if (ixl_get_phy_info(sc) != 0) {
+ /* error printed by ixl_get_phy_info */
goto free_hmc;
}
@@ -1380,8 +1390,14 @@
ifmedia_init(&sc->sc_media, IFM_IMASK, ixl_media_change,
ixl_media_status);
- ixl_media_add(sc, phy_types);
+ ixl_media_add(sc);
ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ if (ISSET(sc->sc_phy_abilities,
+ (IXL_PHY_ABILITY_PAUSE_TX | IXL_PHY_ABILITY_PAUSE_RX))) {
+ ifmedia_add(&sc->sc_media,
+ IFM_ETHER | IFM_AUTO | IFM_FLOW, 0, NULL);
+ }
+ ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_NONE, 0, NULL);
ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
if_attach(ifp);
@@ -1395,6 +1411,8 @@
ixl_config_other_intr(sc);
ixl_enable_other_intr(sc);
+ ixl_set_phy_autoselect(sc);
+
/* remove default mac filter and replace it so we can see vlans */
rv = ixl_remove_macvlan(sc, sc->sc_enaddr, 0, 0);
if (rv != ENOENT) {
@@ -1614,21 +1632,41 @@
}
static void
-ixl_media_add(struct ixl_softc *sc, uint64_t phy_types)
+ixl_media_add(struct ixl_softc *sc)
{
struct ifmedia *ifm = &sc->sc_media;
const struct ixl_phy_type *itype;
unsigned int i;
+ bool flow;
+
+ if (ISSET(sc->sc_phy_abilities,
+ (IXL_PHY_ABILITY_PAUSE_TX | IXL_PHY_ABILITY_PAUSE_RX))) {
+ flow = true;
+ } else {
+ flow = false;
+ }
for (i = 0; i < __arraycount(ixl_phy_type_map); i++) {
itype = &ixl_phy_type_map[i];
- if (ISSET(phy_types, itype->phy_type)) {
+ if (ISSET(sc->sc_phy_types, itype->phy_type)) {
ifmedia_add(ifm,
IFM_ETHER | IFM_FDX | itype->ifm_type, 0, NULL);
- if (itype->ifm_type == IFM_100_TX) {
- ifmedia_add(ifm, IFM_ETHER | itype->ifm_type,
+ if (flow) {
+ ifmedia_add(ifm,
+ IFM_ETHER | IFM_FDX | IFM_FLOW |
+ itype->ifm_type, 0, NULL);
+ }
+
+ if (itype->ifm_type != IFM_100_TX)
+ continue;
+
+ ifmedia_add(ifm, IFM_ETHER | itype->ifm_type,
+ 0, NULL);
+ if (flow) {
+ ifmedia_add(ifm,
+ IFM_ETHER | IFM_FLOW | itype->ifm_type,
0, NULL);
}
}
@@ -1652,8 +1690,49 @@
static int
ixl_media_change(struct ifnet *ifp)
{
-
- return 0;
+ struct ixl_softc *sc = ifp->if_softc;
+ struct ifmedia *ifm = &sc->sc_media;
+ uint64_t ifm_active = sc->sc_media_active;
+ uint8_t link_speed, abilities;
+
+ switch (IFM_SUBTYPE(ifm_active)) {
+ case IFM_1000_SGMII:
+ case IFM_1000_KX:
+ case IFM_10G_KX4:
+ case IFM_10G_KR:
+ case IFM_40G_KR4:
+ case IFM_20G_KR2:
+ case IFM_25G_KR:
+ /* backplanes */
+ return EINVAL;
+ }
+
+ abilities = IXL_PHY_ABILITY_AUTONEGO | IXL_PHY_ABILITY_LINKUP;
+
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ link_speed = sc->sc_phy_linkspeed;
+ break;
+ case IFM_NONE:
+ link_speed = 0;
+ CLR(abilities, IXL_PHY_ABILITY_LINKUP);
+ break;
+ default:
+ link_speed = ixl_search_baudrate(
+ ifmedia_baudrate(ifm->ifm_media));
+ }
+
+ if (ISSET(abilities, IXL_PHY_ABILITY_LINKUP)) {
+ if (ISSET(link_speed, sc->sc_phy_linkspeed) == 0)
+ return EINVAL;
+ }
+
+ if (ifm->ifm_media & IFM_FLOW) {
+ abilities |= sc->sc_phy_abilities &
+ (IXL_PHY_ABILITY_PAUSE_TX | IXL_PHY_ABILITY_PAUSE_RX);
+ }
+
+ return ixl_set_phy_config(sc, link_speed, abilities, false);
}
static void
@@ -4292,11 +4371,10 @@
}
static int
-ixl_get_phy_types(struct ixl_softc *sc, uint64_t *phy_types_ptr)
+ixl_get_phy_info(struct ixl_softc *sc)
{
struct ixl_dmamem idm;
struct ixl_aq_phy_abilities *phy;
- uint64_t phy_types;
int rv;
if (ixl_dmamem_alloc(sc, &idm, IXL_AQ_BUFLEN, 0) != 0) {
@@ -4323,10 +4401,17 @@
phy = IXL_DMA_KVA(&idm);
- phy_types = le32toh(phy->phy_type);
- phy_types |= (uint64_t)le32toh(phy->phy_type_ext) << 32;
-
- *phy_types_ptr = phy_types;
+ sc->sc_phy_types = le32toh(phy->phy_type);
+ sc->sc_phy_types |= (uint64_t)le32toh(phy->phy_type_ext) << 32;
+
+ sc->sc_phy_abilities = phy->abilities;
+ sc->sc_phy_linkspeed = phy->link_speed;
+ sc->sc_phy_fec_cfg = phy->fec_cfg_curr_mod_ext_info &
+ (IXL_AQ_ENABLE_FEC_KR | IXL_AQ_ENABLE_FEC_RS |
+ IXL_AQ_REQUEST_FEC_KR | IXL_AQ_REQUEST_FEC_RS);
+ sc->sc_eee_cap = phy->eee_capability;
+ sc->sc_eeer_val = phy->eeer_val;
+ sc->sc_d3_lpan = phy->d3_lpan;
rv = 0;
@@ -4336,6 +4421,60 @@
}
static int
+ixl_set_phy_config(struct ixl_softc *sc,
+ uint8_t link_speed, uint8_t abilities, bool polling)
+{
+ struct ixl_aq_phy_param *param;
+ struct ixl_atq iatq;
+ struct ixl_aq_desc *iaq;
+ int error;
+
+ memset(&iatq, 0, sizeof(iatq));
+
+ iaq = &iatq.iatq_desc;
+ iaq->iaq_opcode = htole16(IXL_AQ_OP_PHY_SET_CONFIG);
+ param = (struct ixl_aq_phy_param *)&iaq->iaq_param;
+ param->phy_types = htole32((uint32_t)sc->sc_phy_types);
+ param->phy_type_ext = (uint8_t)(sc->sc_phy_types >> 32);
+ param->link_speed = link_speed;
+ param->abilities = abilities | IXL_AQ_PHY_ABILITY_AUTO_LINK;
+ param->fec_cfg = sc->sc_phy_fec_cfg;
+ param->eee_capability = sc->sc_eee_cap;
+ param->eeer_val = sc->sc_eeer_val;
+ param->d3_lpan = sc->sc_d3_lpan;
+
+ if (polling)
+ error = ixl_atq_poll(sc, iaq, 250);
+ else
+ error = ixl_atq_exec(sc, &iatq);
+
+ if (error != 0)
+ return error;
+
+ switch (le16toh(iaq->iaq_retval)) {
+ case IXL_AQ_RC_OK:
+ break;
+ case IXL_AQ_RC_EPERM:
+ return EPERM;
+ default:
+ return EIO;
+ }
+
+ return 0;
+}
+
+static int
+ixl_set_phy_autoselect(struct ixl_softc *sc)
+{
+ uint8_t link_speed, abilities;
+
+ link_speed = sc->sc_phy_linkspeed;
+ abilities = IXL_PHY_ABILITY_LINKUP | IXL_PHY_ABILITY_AUTONEGO;
+
+ return ixl_set_phy_config(sc, link_speed, abilities, true);
+}
+
+static int
ixl_get_link_status_poll(struct ixl_softc *sc)
{
struct ixl_aq_desc iaq;
@@ -4621,6 +4760,23 @@
return 0;
}
+static uint8_t
+ixl_search_baudrate(uint64_t baudrate)
+{
+ const struct ixl_speed_type *type;
+ unsigned int i;
+
Home |
Main Index |
Thread Index |
Old Index