From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from stargate.chelsio.com (stargate.chelsio.com [12.32.117.8]) by dpdk.org (Postfix) with ESMTP id 64E525B1E for ; Wed, 28 Feb 2018 19:05:44 +0100 (CET) Received: from localhost (scalar.blr.asicdesigners.com [10.193.185.94]) by stargate.chelsio.com (8.13.8/8.13.8) with ESMTP id w1SI5fLL006751; Wed, 28 Feb 2018 10:05:41 -0800 From: Rahul Lakkireddy To: dev@dpdk.org Cc: kumaras@chelsio.com, surendra@chelsio.com, nirranjan@chelsio.com, indranil@chelsio.com Date: Wed, 28 Feb 2018 23:34:51 +0530 Message-Id: <2fd3273bcc96b5bc0dec3e225ff8a75df5607ba3.1519832644.git.rahul.lakkireddy@chelsio.com> X-Mailer: git-send-email 2.5.3 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH v2 6/7] cxgbe: update link configuration for 32-bit port capability X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Feb 2018 18:05:45 -0000 Update link configuration API to prepare for 32-bit port capability support. Continue using 16-bit port capability for older firmware. Original work by Surendra Mobiya Signed-off-by: Rahul Lakkireddy Signed-off-by: Kumar Sanghvi --- v2: - No changes. drivers/net/cxgbe/base/common.h | 40 +++++--- drivers/net/cxgbe/base/t4_hw.c | 168 +++++++++++++++++++++++--------- drivers/net/cxgbe/base/t4fw_interface.h | 36 ++++++- drivers/net/cxgbe/cxgbe_ethdev.c | 2 +- drivers/net/cxgbe/cxgbe_main.c | 28 +++--- 5 files changed, 200 insertions(+), 74 deletions(-) diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h index 0bd78c1b0..98886288c 100644 --- a/drivers/net/cxgbe/base/common.h +++ b/drivers/net/cxgbe/base/common.h @@ -62,13 +62,13 @@ enum dev_master { MASTER_CANT, MASTER_MAY, MASTER_MUST }; enum dev_state { DEV_STATE_UNINIT, DEV_STATE_INIT, DEV_STATE_ERR }; -enum { +enum cc_pause { PAUSE_RX = 1 << 0, PAUSE_TX = 1 << 1, PAUSE_AUTONEG = 1 << 2 }; -enum { +enum cc_fec { FEC_AUTO = 1 << 0, /* IEEE 802.3 "automatic" */ FEC_RS = 1 << 1, /* Reed-Solomon */ FEC_BASER_RS = 1 << 2, /* BaseR/Reed-Solomon */ @@ -241,20 +241,30 @@ struct adapter_params { bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */ }; +/* Firmware Port Capabilities types. + */ +typedef u16 fw_port_cap16_t; /* 16-bit Port Capabilities integral value */ +typedef u32 fw_port_cap32_t; /* 32-bit Port Capabilities integral value */ + struct link_config { - unsigned short supported; /* link capabilities */ - unsigned short advertising; /* advertised capabilities */ - unsigned int requested_speed; /* speed user has requested */ - unsigned int speed; /* actual link speed */ - unsigned char requested_fc; /* flow control user has requested */ - unsigned char fc; /* actual link flow control */ - unsigned char auto_fec; /* Forward Error Correction (FEC) - * "automatic" (IEEE 802.3) - */ - unsigned char requested_fec; /* FEC requested */ - unsigned char fec; /* FEC actual */ - unsigned char autoneg; /* autonegotiating? */ - unsigned char link_ok; /* link up? */ + fw_port_cap32_t pcaps; /* link capabilities */ + fw_port_cap32_t acaps; /* advertised capabilities */ + + u32 requested_speed; /* speed (Mb/s) user has requested */ + u32 speed; /* actual link speed (Mb/s) */ + + enum cc_pause requested_fc; /* flow control user has requested */ + enum cc_pause fc; /* actual link flow control */ + + enum cc_fec auto_fec; /* Forward Error Correction + * "automatic" (IEEE 802.3) + */ + enum cc_fec requested_fec; /* Forward Error Correction requested */ + enum cc_fec fec; /* Forward Error Correction actual */ + + unsigned char autoneg; /* autonegotiating? */ + + unsigned char link_ok; /* link up? */ }; #include "adapter.h" diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c index e8545ceb0..46b296a9d 100644 --- a/drivers/net/cxgbe/base/t4_hw.c +++ b/drivers/net/cxgbe/base/t4_hw.c @@ -2789,66 +2789,105 @@ void t4_dump_version_info(struct adapter *adapter) G_FW_HDR_FW_VER_BUILD(adapter->params.er_vers)); } -#define ADVERT_MASK (V_FW_PORT_CAP_SPEED(M_FW_PORT_CAP_SPEED) | \ - FW_PORT_CAP_ANEG) +#define ADVERT_MASK (V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED) | \ + FW_PORT_CAP32_ANEG) +/** + * fwcaps32_to_caps16 - convert 32-bit Port Capabilities to 16-bits + * @caps32: a 32-bit Port Capabilities value + * + * Returns the equivalent 16-bit Port Capabilities value. Note that + * not all 32-bit Port Capabilities can be represented in the 16-bit + * Port Capabilities and some fields/values may not make it. + */ +static fw_port_cap16_t fwcaps32_to_caps16(fw_port_cap32_t caps32) +{ + fw_port_cap16_t caps16 = 0; + +#define CAP32_TO_CAP16(__cap) \ + do { \ + if (caps32 & FW_PORT_CAP32_##__cap) \ + caps16 |= FW_PORT_CAP_##__cap; \ + } while (0) + + CAP32_TO_CAP16(SPEED_100M); + CAP32_TO_CAP16(SPEED_1G); + CAP32_TO_CAP16(SPEED_10G); + CAP32_TO_CAP16(SPEED_25G); + CAP32_TO_CAP16(SPEED_40G); + CAP32_TO_CAP16(SPEED_100G); + CAP32_TO_CAP16(FC_RX); + CAP32_TO_CAP16(FC_TX); + CAP32_TO_CAP16(802_3_PAUSE); + CAP32_TO_CAP16(802_3_ASM_DIR); + CAP32_TO_CAP16(ANEG); + CAP32_TO_CAP16(MDIX); + CAP32_TO_CAP16(MDIAUTO); + CAP32_TO_CAP16(FEC_RS); + CAP32_TO_CAP16(FEC_BASER_RS); + +#undef CAP32_TO_CAP16 + + return caps16; +} /* Translate Firmware Pause specification to Common Code */ -static inline unsigned int fwcap_to_cc_pause(unsigned int fw_pause) +static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause) { - unsigned int cc_pause = 0; + enum cc_pause cc_pause = 0; - if (fw_pause & F_FW_PORT_CMD_RXPAUSE) + if (fw_pause & FW_PORT_CAP32_FC_RX) cc_pause |= PAUSE_RX; - if (fw_pause & F_FW_PORT_CMD_TXPAUSE) + if (fw_pause & FW_PORT_CAP32_FC_TX) cc_pause |= PAUSE_TX; return cc_pause; } /* Translate Common Code Pause Frame specification into Firmware */ -static inline unsigned int cc_to_fwcap_pause(unsigned int cc_pause) +static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause) { - unsigned int fw_pause = 0; + fw_port_cap32_t fw_pause = 0; if (cc_pause & PAUSE_RX) - fw_pause |= F_FW_PORT_CMD_RXPAUSE; + fw_pause |= FW_PORT_CAP32_FC_RX; if (cc_pause & PAUSE_TX) - fw_pause |= F_FW_PORT_CMD_TXPAUSE; + fw_pause |= FW_PORT_CAP32_FC_TX; return fw_pause; } /* Translate Firmware Forward Error Correction specification to Common Code */ -static inline unsigned int fwcap_to_cc_fec(unsigned int fw_fec) +static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec) { - unsigned int cc_fec = 0; + enum cc_fec cc_fec = 0; - if (fw_fec & FW_PORT_CAP_FEC_RS) + if (fw_fec & FW_PORT_CAP32_FEC_RS) cc_fec |= FEC_RS; - if (fw_fec & FW_PORT_CAP_FEC_BASER_RS) + if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS) cc_fec |= FEC_BASER_RS; return cc_fec; } /* Translate Common Code Forward Error Correction specification to Firmware */ -static inline unsigned int cc_to_fwcap_fec(unsigned int cc_fec) +static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec) { - unsigned int fw_fec = 0; + fw_port_cap32_t fw_fec = 0; if (cc_fec & FEC_RS) - fw_fec |= FW_PORT_CAP_FEC_RS; + fw_fec |= FW_PORT_CAP32_FEC_RS; if (cc_fec & FEC_BASER_RS) - fw_fec |= FW_PORT_CAP_FEC_BASER_RS; + fw_fec |= FW_PORT_CAP32_FEC_BASER_RS; return fw_fec; } /** * t4_link_l1cfg - apply link configuration to MAC/PHY - * @phy: the PHY to setup - * @mac: the MAC to setup - * @lc: the requested link configuration + * @adapter: the adapter + * @mbox: the Firmware Mailbox to use + * @port: the Port ID + * @lc: the Port's Link Configuration * * Set up a port's MAC and PHY according to a desired link configuration. * - If the PHY can auto-negotiate first decide what to advertise, then @@ -2860,9 +2899,9 @@ static inline unsigned int cc_to_fwcap_fec(unsigned int cc_fec) int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port, struct link_config *lc) { - struct fw_port_cmd c; - unsigned int fw_mdi = V_FW_PORT_CAP_MDI(FW_PORT_CAP_MDI_AUTO); - unsigned int fw_fc, cc_fec, fw_fec; + unsigned int fw_mdi = V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO); + fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap; + struct fw_port_cmd cmd; lc->link_ok = 0; @@ -2881,30 +2920,32 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port, cc_fec = lc->requested_fec; fw_fec = cc_to_fwcap_fec(cc_fec); - memset(&c, 0, sizeof(c)); - c.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) | - F_FW_CMD_REQUEST | F_FW_CMD_EXEC | - V_FW_PORT_CMD_PORTID(port)); - c.action_to_len16 = - cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) | - FW_LEN16(c)); - - if (!(lc->supported & FW_PORT_CAP_ANEG)) { - c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) | - fw_fc | fw_fec); + /* Figure out what our Requested Port Capabilities are going to be. + */ + if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) { + rcap = (lc->pcaps & ADVERT_MASK) | fw_fc | fw_fec; lc->fc = lc->requested_fc & ~PAUSE_AUTONEG; lc->fec = cc_fec; } else if (lc->autoneg == AUTONEG_DISABLE) { - c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fw_fc | - fw_fec | fw_mdi); + rcap = lc->requested_speed | fw_fc | fw_fec | fw_mdi; lc->fc = lc->requested_fc & ~PAUSE_AUTONEG; lc->fec = cc_fec; } else { - c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fw_fc | fw_fec | - fw_mdi); + rcap = lc->acaps | fw_fc | fw_fec | fw_mdi; } - return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); + /* And send that on to the Firmware ... + */ + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) | + F_FW_CMD_REQUEST | F_FW_CMD_EXEC | + V_FW_PORT_CMD_PORTID(port)); + cmd.action_to_len16 = + cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) | + FW_LEN16(cmd)); + cmd.u.l1cfg.rcap = cpu_to_be32(fwcaps32_to_caps16(rcap)); + + return t4_wr_mbox(adap, mbox, &cmd, sizeof(cmd), NULL); } /** @@ -4237,6 +4278,28 @@ int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } +/* Return the highest speed set in the port capabilities, in Mb/s. */ +static unsigned int fwcap_to_speed(fw_port_cap32_t caps) +{ +#define TEST_SPEED_RETURN(__caps_speed, __speed) \ + do { \ + if (caps & FW_PORT_CAP32_SPEED_##__caps_speed) \ + return __speed; \ + } while (0) + + TEST_SPEED_RETURN(100G, 100000); + TEST_SPEED_RETURN(50G, 50000); + TEST_SPEED_RETURN(40G, 40000); + TEST_SPEED_RETURN(25G, 25000); + TEST_SPEED_RETURN(10G, 10000); + TEST_SPEED_RETURN(1G, 1000); + TEST_SPEED_RETURN(100M, 100); + +#undef TEST_SPEED_RETURN + + return 0; +} + /** * t4_handle_fw_rpl - process a FW reply message * @adap: the adapter @@ -4319,7 +4382,21 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl) lc->speed = speed; lc->fc = fc; lc->fec = fec; - lc->supported = be16_to_cpu(p->u.info.pcap); + lc->pcaps = be16_to_cpu(p->u.info.pcap); + lc->acaps = be16_to_cpu(p->u.info.acap) & ADVERT_MASK; + if (lc->acaps & FW_PORT_CAP32_ANEG) { + lc->autoneg = AUTONEG_ENABLE; + } else { + /* When Autoneg is disabled, user needs to set + * single speed. + */ + lc->acaps = 0; + lc->requested_speed = + be16_to_cpu(p->u.info.acap); + lc->requested_speed = + fwcap_to_speed(lc->requested_speed); + lc->autoneg = AUTONEG_DISABLE; + } } } else { dev_warn(adap, "Unknown firmware reply %d\n", opcode); @@ -4352,7 +4429,7 @@ void t4_reset_link_config(struct adapter *adap, int idx) static void init_link_config(struct link_config *lc, unsigned int pcaps, unsigned int acaps) { - lc->supported = pcaps; + lc->pcaps = pcaps; lc->requested_speed = 0; lc->speed = 0; lc->requested_fc = 0; @@ -4366,11 +4443,12 @@ static void init_link_config(struct link_config *lc, unsigned int pcaps, lc->requested_fec = FEC_AUTO; lc->fec = lc->auto_fec; - if (lc->supported & FW_PORT_CAP_ANEG) { - lc->advertising = lc->supported & ADVERT_MASK; + if (lc->pcaps & FW_PORT_CAP32_ANEG) { + lc->acaps = lc->pcaps & ADVERT_MASK; lc->autoneg = AUTONEG_ENABLE; + lc->requested_fc |= PAUSE_AUTONEG; } else { - lc->advertising = 0; + lc->acaps = 0; lc->autoneg = AUTONEG_DISABLE; } } diff --git a/drivers/net/cxgbe/base/t4fw_interface.h b/drivers/net/cxgbe/base/t4fw_interface.h index 883a1c7f5..0e139377f 100644 --- a/drivers/net/cxgbe/base/t4fw_interface.h +++ b/drivers/net/cxgbe/base/t4fw_interface.h @@ -1154,7 +1154,7 @@ struct fw_vi_stats_cmd { } u; }; -/* port capabilities bitmap */ +/* old 16-bit port capabilities bitmap */ enum fw_port_cap { FW_PORT_CAP_SPEED_100M = 0x0001, FW_PORT_CAP_SPEED_1G = 0x0002, @@ -1189,6 +1189,40 @@ enum fw_port_mdi { #define V_FW_PORT_CAP_MDI(x) ((x) << S_FW_PORT_CAP_MDI) #define G_FW_PORT_CAP_MDI(x) (((x) >> S_FW_PORT_CAP_MDI) & M_FW_PORT_CAP_MDI) +/* new 32-bit port capabilities bitmap (fw_port_cap32_t) */ +#define FW_PORT_CAP32_SPEED_100M 0x00000001UL +#define FW_PORT_CAP32_SPEED_1G 0x00000002UL +#define FW_PORT_CAP32_SPEED_10G 0x00000004UL +#define FW_PORT_CAP32_SPEED_25G 0x00000008UL +#define FW_PORT_CAP32_SPEED_40G 0x00000010UL +#define FW_PORT_CAP32_SPEED_50G 0x00000020UL +#define FW_PORT_CAP32_SPEED_100G 0x00000040UL +#define FW_PORT_CAP32_FC_RX 0x00010000UL +#define FW_PORT_CAP32_FC_TX 0x00020000UL +#define FW_PORT_CAP32_802_3_PAUSE 0x00040000UL +#define FW_PORT_CAP32_802_3_ASM_DIR 0x00080000UL +#define FW_PORT_CAP32_ANEG 0x00100000UL +#define FW_PORT_CAP32_MDIX 0x00200000UL +#define FW_PORT_CAP32_MDIAUTO 0x00400000UL +#define FW_PORT_CAP32_FEC_RS 0x00800000UL +#define FW_PORT_CAP32_FEC_BASER_RS 0x01000000UL + +#define S_FW_PORT_CAP32_SPEED 0 +#define M_FW_PORT_CAP32_SPEED 0xfff +#define V_FW_PORT_CAP32_SPEED(x) ((x) << S_FW_PORT_CAP32_SPEED) +#define G_FW_PORT_CAP32_SPEED(x) \ + (((x) >> S_FW_PORT_CAP32_SPEED) & M_FW_PORT_CAP32_SPEED) + +enum fw_port_mdi32 { + FW_PORT_CAP32_MDI_AUTO, +}; + +#define S_FW_PORT_CAP32_MDI 21 +#define M_FW_PORT_CAP32_MDI 3 +#define V_FW_PORT_CAP32_MDI(x) ((x) << S_FW_PORT_CAP32_MDI) +#define G_FW_PORT_CAP32_MDI(x) \ + (((x) >> S_FW_PORT_CAP32_MDI) & M_FW_PORT_CAP32_MDI) + enum fw_port_action { FW_PORT_ACTION_L1_CFG = 0x0001, FW_PORT_ACTION_GET_PORT_INFO = 0x0003, diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c index 769146cdf..781d75cc2 100644 --- a/drivers/net/cxgbe/cxgbe_ethdev.c +++ b/drivers/net/cxgbe/cxgbe_ethdev.c @@ -751,7 +751,7 @@ static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev, struct adapter *adapter = pi->adapter; struct link_config *lc = &pi->link_cfg; - if (lc->supported & FW_PORT_CAP_ANEG) { + if (lc->pcaps & FW_PORT_CAP32_ANEG) { if (fc_conf->autoneg) lc->requested_fc |= PAUSE_AUTONEG; else diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c index 2ee0698c3..5792032e7 100644 --- a/drivers/net/cxgbe/cxgbe_main.c +++ b/drivers/net/cxgbe/cxgbe_main.c @@ -199,15 +199,16 @@ int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us, static inline bool is_x_1g_port(const struct link_config *lc) { - return (lc->supported & FW_PORT_CAP_SPEED_1G) != 0; + return (lc->pcaps & FW_PORT_CAP32_SPEED_1G) != 0; } static inline bool is_x_10g_port(const struct link_config *lc) { unsigned int speeds, high_speeds; - speeds = V_FW_PORT_CAP_SPEED(G_FW_PORT_CAP_SPEED(lc->supported)); - high_speeds = speeds & ~(FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G); + speeds = V_FW_PORT_CAP32_SPEED(G_FW_PORT_CAP32_SPEED(lc->pcaps)); + high_speeds = speeds & + ~(FW_PORT_CAP32_SPEED_100M | FW_PORT_CAP32_SPEED_1G); return high_speeds != 0; } @@ -387,17 +388,19 @@ static void print_port_info(struct adapter *adap) const struct port_info *pi = adap2pinfo(adap, i); char *bufp = buf; - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M) + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100M) bufp += sprintf(bufp, "100M/"); - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G) + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_1G) bufp += sprintf(bufp, "1G/"); - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G) + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_10G) bufp += sprintf(bufp, "10G/"); - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_25G) + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_25G) bufp += sprintf(bufp, "25G/"); - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G) + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_40G) bufp += sprintf(bufp, "40G/"); - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100G) + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_50G) + bufp += sprintf(bufp, "50G/"); + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100G) bufp += sprintf(bufp, "100G/"); if (bufp != buf) --bufp; @@ -1096,7 +1099,7 @@ static void fw_caps_to_speed_caps(enum fw_port_type port_type, #define FW_CAPS_TO_SPEED(__fw_name) \ do { \ - if (fw_caps & FW_PORT_CAP_ ## __fw_name) \ + if (fw_caps & FW_PORT_CAP32_ ## __fw_name) \ SET_SPEED(__fw_name); \ } while (0) @@ -1151,6 +1154,7 @@ static void fw_caps_to_speed_caps(enum fw_port_type port_type, case FW_PORT_TYPE_CR4_QSFP: FW_CAPS_TO_SPEED(SPEED_25G); FW_CAPS_TO_SPEED(SPEED_40G); + FW_CAPS_TO_SPEED(SPEED_50G); FW_CAPS_TO_SPEED(SPEED_100G); break; @@ -1173,10 +1177,10 @@ void cxgbe_get_speed_caps(struct port_info *pi, u32 *speed_caps) { *speed_caps = 0; - fw_caps_to_speed_caps(pi->port_type, pi->link_cfg.supported, + fw_caps_to_speed_caps(pi->port_type, pi->link_cfg.pcaps, speed_caps); - if (!(pi->link_cfg.supported & FW_PORT_CAP_ANEG)) + if (!(pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)) *speed_caps |= ETH_LINK_SPEED_FIXED; } -- 2.14.1