X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fcxgbe%2Fcxgbe_main.c;h=54eb23dfb6d92ca95ec3f0a134cb4823f395ff2c;hb=ea9382dc2ba155ed7d6485b61c149214f2686fa3;hp=3617e28027b9420bb23c4d2aaaf33bbdbcb766ff;hpb=04868e5bfddda2021df2fb191c1b9b2ee09d71ce;p=dpdk.git diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c index 3617e28027..54eb23dfb6 100644 --- a/drivers/net/cxgbe/cxgbe_main.c +++ b/drivers/net/cxgbe/cxgbe_main.c @@ -1,34 +1,6 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2014-2017 Chelsio Communications. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Chelsio Communications nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2014-2018 Chelsio Communications. + * All rights reserved. */ #include @@ -51,17 +23,15 @@ #include #include #include -#include #include #include #include #include -#include +#include #include -#include -#include #include #include +#include #include "common.h" #include "t4_regs.h" @@ -201,14 +171,18 @@ 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) { - return ((lc->supported & FW_PORT_CAP_SPEED_10G) != 0 || - (lc->supported & FW_PORT_CAP_SPEED_40G) != 0 || - (lc->supported & FW_PORT_CAP_SPEED_100G) != 0); + unsigned int speeds, high_speeds; + + 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; } inline void init_rspq(struct adapter *adap, struct sge_rspq *q, @@ -298,7 +272,7 @@ void cfg_queues(struct rte_eth_dev *eth_dev) for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) { struct sge_eth_rxq *r = &s->ethrxq[i]; - init_rspq(adap, &r->rspq, 0, 0, 1024, 64); + init_rspq(adap, &r->rspq, 5, 32, 1024, 64); r->usembufs = 1; r->fl.size = (r->usembufs ? 1024 : 72); } @@ -344,14 +318,17 @@ static void setup_memwin(struct adapter *adap) MEMWIN_NIC)); } -static int init_rss(struct adapter *adap) +int init_rss(struct adapter *adap) { unsigned int i; - int err; - err = t4_init_rss_mode(adap, adap->mbox); - if (err) - return err; + if (is_pf4(adap)) { + int err; + + err = t4_init_rss_mode(adap, adap->mbox); + if (err) + return err; + } for_each_port(adap, i) { struct port_info *pi = adap2pinfo(adap, i); @@ -359,28 +336,47 @@ static int init_rss(struct adapter *adap) pi->rss = rte_zmalloc(NULL, pi->rss_size * sizeof(u16), 0); if (!pi->rss) return -ENOMEM; + + pi->rss_hf = CXGBE_RSS_HF_ALL; } return 0; } -static void print_port_info(struct adapter *adap) +/** + * Dump basic information about the adapter. + */ +void print_adapter_info(struct adapter *adap) +{ + /** + * Hardware/Firmware/etc. Version/Revision IDs. + */ + t4_dump_version_info(adap); +} + +void print_port_info(struct adapter *adap) { int i; char buf[80]; struct rte_pci_addr *loc = &adap->pdev->addr; for_each_port(adap, i) { - const struct port_info *pi = &adap->port[i]; + const struct port_info *pi = adap2pinfo(adap, i); char *bufp = buf; - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M) - bufp += sprintf(bufp, "100/"); - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G) - bufp += sprintf(bufp, "1000/"); - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G) + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100M) + bufp += sprintf(bufp, "100M/"); + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_1G) + bufp += sprintf(bufp, "1G/"); + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_10G) bufp += sprintf(bufp, "10G/"); - if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G) + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_25G) + bufp += sprintf(bufp, "25G/"); + if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_40G) bufp += sprintf(bufp, "40G/"); + 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; sprintf(bufp, "BASE-%s", @@ -396,6 +392,114 @@ static void print_port_info(struct adapter *adap) } } +static int +check_devargs_handler(__rte_unused const char *key, const char *value, + __rte_unused void *opaque) +{ + if (strcmp(value, "1")) + return -1; + + return 0; +} + +int cxgbe_get_devargs(struct rte_devargs *devargs, const char *key) +{ + struct rte_kvargs *kvlist; + + if (!devargs) + return 0; + + kvlist = rte_kvargs_parse(devargs->args, NULL); + if (!kvlist) + return 0; + + if (!rte_kvargs_count(kvlist, key)) { + rte_kvargs_free(kvlist); + return 0; + } + + if (rte_kvargs_process(kvlist, key, + check_devargs_handler, NULL) < 0) { + rte_kvargs_free(kvlist); + return 0; + } + rte_kvargs_free(kvlist); + + return 1; +} + +static void configure_vlan_types(struct adapter *adapter) +{ + struct rte_pci_device *pdev = adapter->pdev; + int i; + + for_each_port(adapter, i) { + /* OVLAN Type 0x88a8 */ + t4_set_reg_field(adapter, MPS_PORT_RX_OVLAN_REG(i, A_RX_OVLAN0), + V_OVLAN_MASK(M_OVLAN_MASK) | + V_OVLAN_ETYPE(M_OVLAN_ETYPE), + V_OVLAN_MASK(M_OVLAN_MASK) | + V_OVLAN_ETYPE(0x88a8)); + /* OVLAN Type 0x9100 */ + t4_set_reg_field(adapter, MPS_PORT_RX_OVLAN_REG(i, A_RX_OVLAN1), + V_OVLAN_MASK(M_OVLAN_MASK) | + V_OVLAN_ETYPE(M_OVLAN_ETYPE), + V_OVLAN_MASK(M_OVLAN_MASK) | + V_OVLAN_ETYPE(0x9100)); + /* OVLAN Type 0x8100 */ + t4_set_reg_field(adapter, MPS_PORT_RX_OVLAN_REG(i, A_RX_OVLAN2), + V_OVLAN_MASK(M_OVLAN_MASK) | + V_OVLAN_ETYPE(M_OVLAN_ETYPE), + V_OVLAN_MASK(M_OVLAN_MASK) | + V_OVLAN_ETYPE(0x8100)); + + /* IVLAN 0X8100 */ + t4_set_reg_field(adapter, MPS_PORT_RX_IVLAN(i), + V_IVLAN_ETYPE(M_IVLAN_ETYPE), + V_IVLAN_ETYPE(0x8100)); + + t4_set_reg_field(adapter, MPS_PORT_RX_CTL(i), + F_OVLAN_EN0 | F_OVLAN_EN1 | + F_OVLAN_EN2 | F_IVLAN_EN, + F_OVLAN_EN0 | F_OVLAN_EN1 | + F_OVLAN_EN2 | F_IVLAN_EN); + } + + if (cxgbe_get_devargs(pdev->device.devargs, CXGBE_DEVARG_KEEP_OVLAN)) + t4_tp_wr_bits_indirect(adapter, A_TP_INGRESS_CONFIG, + V_RM_OVLAN(1), V_RM_OVLAN(0)); +} + +static void configure_pcie_ext_tag(struct adapter *adapter) +{ + u16 v; + int pos = t4_os_find_pci_capability(adapter, PCI_CAP_ID_EXP); + + if (!pos) + return; + + if (pos > 0) { + t4_os_pci_read_cfg2(adapter, pos + PCI_EXP_DEVCTL, &v); + v |= PCI_EXP_DEVCTL_EXT_TAG; + t4_os_pci_write_cfg2(adapter, pos + PCI_EXP_DEVCTL, v); + if (is_t6(adapter->params.chip)) { + t4_set_reg_field(adapter, A_PCIE_CFG2, + V_T6_TOTMAXTAG(M_T6_TOTMAXTAG), + V_T6_TOTMAXTAG(7)); + t4_set_reg_field(adapter, A_PCIE_CMD_CFG, + V_T6_MINTAG(M_T6_MINTAG), + V_T6_MINTAG(8)); + } else { + t4_set_reg_field(adapter, A_PCIE_CFG2, + V_TOTMAXTAG(M_TOTMAXTAG), + V_TOTMAXTAG(3)); + t4_set_reg_field(adapter, A_PCIE_CMD_CFG, + V_MINTAG(M_MINTAG), + V_MINTAG(8)); + } + } +} + /* * Tweak configuration based on system architecture, etc. Most of these have * defaults assigned to them by Firmware Configuration Files (if we're using @@ -427,6 +531,9 @@ static int adap_init0_tweaks(struct adapter *adapter) V_CREDITCNT(M_CREDITCNT) | M_CREDITCNTPACKING, V_CREDITCNT(3) | V_CREDITCNTPACKING(1)); + t4_set_reg_field(adapter, A_SGE_INGRESS_RX_THRESHOLD, + V_THRESHOLD_3(M_THRESHOLD_3), V_THRESHOLD_3(32U)); + t4_set_reg_field(adapter, A_SGE_CONTROL2, V_IDMAARBROUNDROBIN(1U), V_IDMAARBROUNDROBIN(1U)); @@ -575,7 +682,7 @@ static int adap_init0_config(struct adapter *adapter, int reset) /* * Return successfully and note that we're operating with parameters * not supplied by the driver, rather than from hard-wired - * initialization constants burried in the driver. + * initialization constants buried in the driver. */ dev_info(adapter, "Successfully configured using Firmware Configuration File \"%s\", version %#x, computed checksum %#x\n", @@ -641,18 +748,7 @@ static int adap_init0(struct adapter *adap) state = (enum dev_state)((unsigned)state & ~DEV_STATE_INIT); } - t4_get_fw_version(adap, &adap->params.fw_vers); - t4_get_tp_version(adap, &adap->params.tp_vers); - - dev_info(adap, "fw: %u.%u.%u.%u, TP: %u.%u.%u.%u\n", - G_FW_HDR_FW_VER_MAJOR(adap->params.fw_vers), - G_FW_HDR_FW_VER_MINOR(adap->params.fw_vers), - G_FW_HDR_FW_VER_MICRO(adap->params.fw_vers), - G_FW_HDR_FW_VER_BUILD(adap->params.fw_vers), - G_FW_HDR_FW_VER_MAJOR(adap->params.tp_vers), - G_FW_HDR_FW_VER_MINOR(adap->params.tp_vers), - G_FW_HDR_FW_VER_MICRO(adap->params.tp_vers), - G_FW_HDR_FW_VER_BUILD(adap->params.tp_vers)); + t4_get_version_info(adap); ret = t4_get_core_clock(adap, &adap->params.vpd); if (ret < 0) { @@ -661,26 +757,6 @@ static int adap_init0(struct adapter *adap) goto bye; } - /* - * Find out what ports are available to us. Note that we need to do - * this before calling adap_init0_no_config() since it needs nports - * and portvec ... - */ - v = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | - V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC); - ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, &v, &port_vec); - if (ret < 0) { - dev_err(adap, "%s: failure in t4_queury_params; error = %d\n", - __func__, ret); - goto bye; - } - - adap->params.nports = hweight32(port_vec); - adap->params.portvec = port_vec; - - dev_debug(adap, "%s: adap->params.nports = %u\n", __func__, - adap->params.nports); - /* * If the firmware is initialized already (and we're not forcing a * master initialization), note that we're living with existing @@ -705,6 +781,22 @@ static int adap_init0(struct adapter *adap) goto bye; } + /* Find out what ports are available to us. */ + v = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | + V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC); + ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, &v, &port_vec); + if (ret < 0) { + dev_err(adap, "%s: failure in t4_query_params; error = %d\n", + __func__, ret); + goto bye; + } + + adap->params.nports = hweight32(port_vec); + adap->params.portvec = port_vec; + + dev_debug(adap, "%s: adap->params.nports = %u\n", __func__, + adap->params.nports); + /* * Give the SGE code a chance to pull in anything that it needs ... * Note that this must be called after we retrieve our VPD parameters @@ -793,6 +885,8 @@ static int adap_init0(struct adapter *adap) } t4_init_sge_params(adap); t4_init_tp_params(adap); + configure_pcie_ext_tag(adap); + configure_vlan_types(adap); adap->params.drv_memwin = MEMWIN_NIC; adap->flags |= FW_OK; @@ -825,7 +919,7 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id) NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM" }; - const struct port_info *pi = &adap->port[port_id]; + const struct port_info *pi = adap2pinfo(adap, port_id); if (pi->mod_type == FW_PORT_MOD_TYPE_NONE) dev_info(adap, "Port%d: port module unplugged\n", pi->port_id); @@ -833,10 +927,10 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id) dev_info(adap, "Port%d: %s port module inserted\n", pi->port_id, mod_str[pi->mod_type]); else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) - dev_info(adap, "Port%d: unsupported optical port module inserted\n", + dev_info(adap, "Port%d: unsupported port module inserted\n", pi->port_id); else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) - dev_info(adap, "Port%d: unknown port module inserted, forcing TWINAX\n", + dev_info(adap, "Port%d: unknown port module inserted\n", pi->port_id); else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR) dev_info(adap, "Port%d: transceiver module error\n", @@ -846,6 +940,18 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id) pi->port_id, pi->mod_type); } +inline bool force_linkup(struct adapter *adap) +{ + struct rte_pci_device *pdev = adap->pdev; + + if (is_pf4(adap)) + return false; /* force_linkup not required for pf driver*/ + if (!cxgbe_get_devargs(pdev->device.devargs, + CXGBE_DEVARG_FORCE_LINK_UP)) + return false; + return true; +} + /** * link_start - enable a port * @dev: the port to enable @@ -877,7 +983,7 @@ int link_start(struct port_info *pi) ret = 0; } } - if (ret == 0) + if (ret == 0 && is_pf4(adapter)) ret = t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan, &pi->link_cfg); if (ret == 0) { @@ -891,18 +997,78 @@ int link_start(struct port_info *pi) ret = t4_enable_vi_params(adapter, adapter->mbox, pi->viid, true, true, false); } + + if (ret == 0 && force_linkup(adapter)) + pi->eth_dev->data->dev_link.link_status = ETH_LINK_UP; return ret; } /** - * cxgb4_write_rss - write the RSS table for a given port + * cxgbe_write_rss_conf - flash the RSS configuration for a given port + * @pi: the port + * @rss_hf: Hash configuration to apply + */ +int cxgbe_write_rss_conf(const struct port_info *pi, uint64_t rss_hf) +{ + struct adapter *adapter = pi->adapter; + const struct sge_eth_rxq *rxq; + u64 flags = 0; + u16 rss; + int err; + + /* Should never be called before setting up sge eth rx queues */ + if (!(adapter->flags & FULL_INIT_DONE)) { + dev_err(adap, "%s No RXQs available on port %d\n", + __func__, pi->port_id); + return -EINVAL; + } + + /* Don't allow unsupported hash functions */ + if (rss_hf & ~CXGBE_RSS_HF_ALL) + return -EINVAL; + + if (rss_hf & ETH_RSS_IPV4) + flags |= F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN; + + if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) + flags |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN; + + if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) + flags |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN | + F_FW_RSS_VI_CONFIG_CMD_UDPEN; + + if (rss_hf & ETH_RSS_IPV6) + flags |= F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN; + + if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) + flags |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN; + + if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) + flags |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN | + F_FW_RSS_VI_CONFIG_CMD_UDPEN; + + rxq = &adapter->sge.ethrxq[pi->first_qset]; + rss = rxq[0].rspq.abs_id; + + /* If Tunnel All Lookup isn't specified in the global RSS + * Configuration, then we need to specify a default Ingress + * Queue for any ingress packets which aren't hashed. We'll + * use our first ingress queue ... + */ + err = t4_config_vi_rss(adapter, adapter->mbox, pi->viid, + flags, rss); + return err; +} + +/** + * cxgbe_write_rss - write the RSS table for a given port * @pi: the port * @queues: array of queue indices for RSS * * Sets up the portion of the HW RSS table for the port's VI to distribute * packets to the Rx queues in @queues. */ -int cxgb4_write_rss(const struct port_info *pi, const u16 *queues) +int cxgbe_write_rss(const struct port_info *pi, const u16 *queues) { u16 *rss; int i, err; @@ -923,20 +1089,6 @@ int cxgb4_write_rss(const struct port_info *pi, const u16 *queues) err = t4_config_rss_range(adapter, adapter->pf, pi->viid, 0, pi->rss_size, rss, pi->rss_size); - /* - * If Tunnel All Lookup isn't specified in the global RSS - * Configuration, then we need to specify a default Ingress - * Queue for any ingress packets which aren't hashed. We'll - * use our first ingress queue ... - */ - if (!err) - err = t4_config_vi_rss(adapter, adapter->mbox, pi->viid, - F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN | - F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN | - F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN | - F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN | - F_FW_RSS_VI_CONFIG_CMD_UDPEN, - rss[0]); rte_free(rss); return err; } @@ -966,7 +1118,11 @@ int setup_rss(struct port_info *pi) for (j = 0; j < pi->rss_size; j++) pi->rss[j] = j % pi->n_rx_qsets; - err = cxgb4_write_rss(pi, pi->rss); + err = cxgbe_write_rss(pi, pi->rss); + if (err) + return err; + + err = cxgbe_write_rss_conf(pi, pi->rss_hf); if (err) return err; pi->flags |= PORT_RSS_DONE; @@ -978,33 +1134,128 @@ int setup_rss(struct port_info *pi) /* * Enable NAPI scheduling and interrupt generation for all Rx queues. */ -static void enable_rx(struct adapter *adap) +static void enable_rx(struct adapter *adap, struct sge_rspq *q) { - struct sge *s = &adap->sge; - struct sge_rspq *q = &s->fw_evtq; - int i, j; - /* 0-increment GTS to start the timer and enable interrupts */ - t4_write_reg(adap, MYPF_REG(A_SGE_PF_GTS), + t4_write_reg(adap, is_pf4(adap) ? MYPF_REG(A_SGE_PF_GTS) : + T4VF_SGE_BASE_ADDR + A_SGE_VF_GTS, V_SEINTARM(q->intr_params) | V_INGRESSQID(q->cntxt_id)); +} - for_each_port(adap, i) { - const struct port_info *pi = &adap->port[i]; - struct rte_eth_dev *eth_dev = pi->eth_dev; - - for (j = 0; j < eth_dev->data->nb_rx_queues; j++) { - q = eth_dev->data->rx_queues[j]; - - /* - * 0-increment GTS to start the timer and enable - * interrupts - */ - t4_write_reg(adap, MYPF_REG(A_SGE_PF_GTS), - V_SEINTARM(q->intr_params) | - V_INGRESSQID(q->cntxt_id)); - } +void cxgbe_enable_rx_queues(struct port_info *pi) +{ + struct adapter *adap = pi->adapter; + struct sge *s = &adap->sge; + unsigned int i; + + for (i = 0; i < pi->n_rx_qsets; i++) + enable_rx(adap, &s->ethrxq[pi->first_qset + i].rspq); +} + +/** + * fw_caps_to_speed_caps - translate Firmware Port Caps to Speed Caps. + * @port_type: Firmware Port Type + * @fw_caps: Firmware Port Capabilities + * @speed_caps: Device Info Speed Capabilities + * + * Translate a Firmware Port Capabilities specification to Device Info + * Speed Capabilities. + */ +static void fw_caps_to_speed_caps(enum fw_port_type port_type, + unsigned int fw_caps, + u32 *speed_caps) +{ +#define SET_SPEED(__speed_name) \ + do { \ + *speed_caps |= ETH_LINK_ ## __speed_name; \ + } while (0) + +#define FW_CAPS_TO_SPEED(__fw_name) \ + do { \ + if (fw_caps & FW_PORT_CAP32_ ## __fw_name) \ + SET_SPEED(__fw_name); \ + } while (0) + + switch (port_type) { + case FW_PORT_TYPE_BT_SGMII: + case FW_PORT_TYPE_BT_XFI: + case FW_PORT_TYPE_BT_XAUI: + FW_CAPS_TO_SPEED(SPEED_100M); + FW_CAPS_TO_SPEED(SPEED_1G); + FW_CAPS_TO_SPEED(SPEED_10G); + break; + + case FW_PORT_TYPE_KX4: + case FW_PORT_TYPE_KX: + case FW_PORT_TYPE_FIBER_XFI: + case FW_PORT_TYPE_FIBER_XAUI: + case FW_PORT_TYPE_SFP: + case FW_PORT_TYPE_QSFP_10G: + case FW_PORT_TYPE_QSA: + FW_CAPS_TO_SPEED(SPEED_1G); + FW_CAPS_TO_SPEED(SPEED_10G); + break; + + case FW_PORT_TYPE_KR: + SET_SPEED(SPEED_10G); + break; + + case FW_PORT_TYPE_BP_AP: + case FW_PORT_TYPE_BP4_AP: + SET_SPEED(SPEED_1G); + SET_SPEED(SPEED_10G); + break; + + case FW_PORT_TYPE_BP40_BA: + case FW_PORT_TYPE_QSFP: + SET_SPEED(SPEED_40G); + break; + + case FW_PORT_TYPE_CR_QSFP: + case FW_PORT_TYPE_SFP28: + case FW_PORT_TYPE_KR_SFP28: + FW_CAPS_TO_SPEED(SPEED_1G); + FW_CAPS_TO_SPEED(SPEED_10G); + FW_CAPS_TO_SPEED(SPEED_25G); + break; + + case FW_PORT_TYPE_CR2_QSFP: + SET_SPEED(SPEED_50G); + break; + + case FW_PORT_TYPE_KR4_100G: + 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; + + default: + break; } + +#undef FW_CAPS_TO_SPEED +#undef SET_SPEED +} + +/** + * cxgbe_get_speed_caps - Fetch supported speed capabilities + * @pi: Underlying port's info + * @speed_caps: Device Info speed capabilities + * + * Fetch supported speed capabilities of the underlying port. + */ +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.pcaps, + speed_caps); + + if (!(pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)) + *speed_caps |= ETH_LINK_SPEED_FIXED; } /** @@ -1017,9 +1268,10 @@ static void enable_rx(struct adapter *adap) */ int cxgbe_up(struct adapter *adap) { - enable_rx(adap); + enable_rx(adap, &adap->sge.fw_evtq); t4_sge_tx_monitor_start(adap); - t4_intr_enable(adap); + if (is_pf4(adap)) + t4_intr_enable(adap); adap->flags |= FULL_INIT_DONE; /* TODO: deadman watchdog ?? */ @@ -1040,7 +1292,7 @@ int cxgbe_down(struct port_info *pi) return err; } - t4_reset_link_config(adapter, pi->port_id); + t4_reset_link_config(adapter, pi->pidx); return 0; } @@ -1053,7 +1305,8 @@ void cxgbe_close(struct adapter *adapter) int i; if (adapter->flags & FULL_INIT_DONE) { - t4_intr_disable(adapter); + if (is_pf4(adapter)) + t4_intr_disable(adapter); t4_sge_tx_monitor_stop(adapter); t4_free_sge_resources(adapter); for_each_port(adapter, i) { @@ -1062,11 +1315,16 @@ void cxgbe_close(struct adapter *adapter) t4_free_vi(adapter, adapter->mbox, adapter->pf, 0, pi->viid); rte_free(pi->eth_dev->data->mac_addrs); + /* Skip first port since it'll be freed by DPDK stack */ + if (i) { + rte_free(pi->eth_dev->data->dev_private); + rte_eth_dev_release_port(pi->eth_dev); + } } adapter->flags &= ~FULL_INIT_DONE; } - if (adapter->flags & FW_OK) + if (is_pf4(adapter) && (adapter->flags & FW_OK)) t4_fw_bye(adapter, adapter->mbox); } @@ -1137,21 +1395,16 @@ int cxgbe_probe(struct adapter *adapter) } for_each_port(adapter, i) { - char name[RTE_ETH_NAME_MAX_LEN]; - struct rte_eth_dev_data *data = NULL; const unsigned int numa_node = rte_socket_id(); + char name[RTE_ETH_NAME_MAX_LEN]; + struct rte_eth_dev *eth_dev; - pi = &adapter->port[i]; - pi->adapter = adapter; - pi->xact_addr_filt = -1; - pi->port_id = i; - - snprintf(name, sizeof(name), "cxgbe%d", - adapter->eth_dev->data->port_id + i); + snprintf(name, sizeof(name), "%s_%d", + adapter->pdev->device.name, i); if (i == 0) { /* First port is already allocated by DPDK */ - pi->eth_dev = adapter->eth_dev; + eth_dev = adapter->eth_dev; goto allocate_mac; } @@ -1161,21 +1414,26 @@ int cxgbe_probe(struct adapter *adapter) */ /* reserve an ethdev entry */ - pi->eth_dev = rte_eth_dev_allocate(name); - if (!pi->eth_dev) + eth_dev = rte_eth_dev_allocate(name); + if (!eth_dev) goto out_free; - data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); - if (!data) + eth_dev->data->dev_private = + rte_zmalloc_socket(name, sizeof(struct port_info), + RTE_CACHE_LINE_SIZE, numa_node); + if (!eth_dev->data->dev_private) goto out_free; - data->port_id = adapter->eth_dev->data->port_id + i; - - pi->eth_dev->data = data; - allocate_mac: + pi = (struct port_info *)eth_dev->data->dev_private; + adapter->port[i] = pi; + pi->eth_dev = eth_dev; + pi->adapter = adapter; + pi->xact_addr_filt = -1; + pi->port_id = i; + pi->pidx = i; + pi->eth_dev->device = &adapter->pdev->device; - pi->eth_dev->data->dev_private = pi; pi->eth_dev->dev_ops = adapter->eth_dev->dev_ops; pi->eth_dev->tx_pkt_burst = adapter->eth_dev->tx_pkt_burst; pi->eth_dev->rx_pkt_burst = adapter->eth_dev->rx_pkt_burst; @@ -1190,6 +1448,11 @@ allocate_mac: err = -1; goto out_free; } + + if (i > 0) { + /* First port will be notified by upper layer */ + rte_eth_dev_probing_finish(eth_dev); + } } if (adapter->flags & FW_OK) { @@ -1203,6 +1466,7 @@ allocate_mac: cfg_queues(adapter->eth_dev); + print_adapter_info(adapter); print_port_info(adapter); err = init_rss(adapter); @@ -1220,8 +1484,11 @@ out_free: /* Skip first port since it'll be de-allocated by DPDK */ if (i == 0) continue; - if (pi->eth_dev->data) - rte_free(pi->eth_dev->data); + if (pi->eth_dev) { + if (pi->eth_dev->data->dev_private) + rte_free(pi->eth_dev->data->dev_private); + rte_eth_dev_release_port(pi->eth_dev); + } } if (adapter->flags & FW_OK)