X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fcxgbe%2Fcxgbe_ethdev.c;h=bfa57c979df9bf96e0d19f82cda12508edbbe20d;hb=df96fd0d73955bdc7ca3909e772ff2ad903249c6;hp=329b7cb5acdb27058137a919c3e4c4dfba54181f;hpb=7b3d52989a1af69831fdc739f4c4e9566b3b6cbc;p=dpdk.git diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c index 329b7cb5ac..bfa57c979d 100644 --- a/drivers/net/cxgbe/cxgbe_ethdev.c +++ b/drivers/net/cxgbe/cxgbe_ethdev.c @@ -28,8 +28,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -193,11 +193,12 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete) { struct port_info *pi = eth_dev->data->dev_private; + unsigned int i, work_done, budget = 32; + struct link_config *lc = &pi->link_cfg; struct adapter *adapter = pi->adapter; - struct sge *s = &adapter->sge; struct rte_eth_link new_link = { 0 }; - unsigned int i, work_done, budget = 32; u8 old_link = pi->link_cfg.link_ok; + struct sge *s = &adapter->sge; for (i = 0; i < CXGBE_LINK_STATUS_POLL_CNT; i++) { if (!s->fw_evtq.desc) @@ -218,9 +219,9 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev, new_link.link_status = cxgbe_force_linkup(adapter) ? ETH_LINK_UP : pi->link_cfg.link_ok; - new_link.link_autoneg = pi->link_cfg.autoneg; + new_link.link_autoneg = (lc->link_caps & FW_PORT_CAP32_ANEG) ? 1 : 0; new_link.link_duplex = ETH_LINK_FULL_DUPLEX; - new_link.link_speed = pi->link_cfg.speed; + new_link.link_speed = t4_fwcap_to_speed(lc->link_caps); return rte_eth_linkstatus_set(eth_dev, &new_link); } @@ -300,7 +301,7 @@ int cxgbe_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) return -EINVAL; /* set to jumbo mode if needed */ - if (new_mtu > RTE_ETHER_MAX_LEN) + if (new_mtu > CXGBE_ETH_MAX_LEN) eth_dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; else @@ -318,7 +319,7 @@ int cxgbe_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) /* * Stop device. */ -void cxgbe_dev_close(struct rte_eth_dev *eth_dev) +int cxgbe_dev_close(struct rte_eth_dev *eth_dev) { struct port_info *temp_pi, *pi = eth_dev->data->dev_private; struct adapter *adapter = pi->adapter; @@ -326,11 +327,14 @@ void cxgbe_dev_close(struct rte_eth_dev *eth_dev) CXGBE_FUNC_TRACE(); + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; + if (!(adapter->flags & FULL_INIT_DONE)) - return; + return 0; if (!pi->viid) - return; + return 0; cxgbe_down(pi); t4_sge_eth_release_queues(pi); @@ -343,11 +347,13 @@ void cxgbe_dev_close(struct rte_eth_dev *eth_dev) for_each_port(adapter, i) { temp_pi = adap2pinfo(adapter, i); if (temp_pi->viid) - return; + return 0; } cxgbe_close(adapter); rte_free(adapter); + + return 0; } /* Start the device. @@ -411,7 +417,7 @@ out: /* * Stop device: disable rx and tx functions to allow for reconfiguring. */ -void cxgbe_dev_stop(struct rte_eth_dev *eth_dev) +int cxgbe_dev_stop(struct rte_eth_dev *eth_dev) { struct port_info *pi = eth_dev->data->dev_private; struct adapter *adapter = pi->adapter; @@ -419,7 +425,7 @@ void cxgbe_dev_stop(struct rte_eth_dev *eth_dev) CXGBE_FUNC_TRACE(); if (!(adapter->flags & FULL_INIT_DONE)) - return; + return 0; cxgbe_down(pi); @@ -429,6 +435,8 @@ void cxgbe_dev_stop(struct rte_eth_dev *eth_dev) */ t4_sge_eth_clear_queues(pi); eth_dev->data->scattered_rx = 0; + + return 0; } int cxgbe_dev_configure(struct rte_eth_dev *eth_dev) @@ -562,17 +570,16 @@ void cxgbe_dev_tx_queue_release(void *q) int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) { - int ret; struct port_info *pi = eth_dev->data->dev_private; struct adapter *adap = pi->adapter; - struct sge_rspq *q; + struct sge_eth_rxq *rxq; + int ret; dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n", __func__, pi->port_id, rx_queue_id); - q = eth_dev->data->rx_queues[rx_queue_id]; - - ret = t4_sge_eth_rxq_start(adap, q); + rxq = eth_dev->data->rx_queues[rx_queue_id]; + ret = t4_sge_eth_rxq_start(adap, rxq); if (ret == 0) eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED; @@ -581,16 +588,16 @@ int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) int cxgbe_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) { - int ret; struct port_info *pi = eth_dev->data->dev_private; struct adapter *adap = pi->adapter; - struct sge_rspq *q; + struct sge_eth_rxq *rxq; + int ret; dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n", __func__, pi->port_id, rx_queue_id); - q = eth_dev->data->rx_queues[rx_queue_id]; - ret = t4_sge_eth_rxq_stop(adap, q); + rxq = eth_dev->data->rx_queues[rx_queue_id]; + ret = t4_sge_eth_rxq_stop(adap, rxq); if (ret == 0) eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED; @@ -663,7 +670,7 @@ int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, rxq->fl.size = temp_nb_desc; /* Set to jumbo mode if necessary */ - if (pkt_len > RTE_ETHER_MAX_LEN) + if (pkt_len > CXGBE_ETH_MAX_LEN) eth_dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; else @@ -781,11 +788,17 @@ static int cxgbe_flow_ctrl_get(struct rte_eth_dev *eth_dev, { struct port_info *pi = eth_dev->data->dev_private; struct link_config *lc = &pi->link_cfg; - int rx_pause, tx_pause; + u8 rx_pause = 0, tx_pause = 0; + u32 caps = lc->link_caps; + + if (caps & FW_PORT_CAP32_ANEG) + fc_conf->autoneg = 1; - fc_conf->autoneg = lc->fc & PAUSE_AUTONEG; - rx_pause = lc->fc & PAUSE_RX; - tx_pause = lc->fc & PAUSE_TX; + if (caps & FW_PORT_CAP32_FC_TX) + tx_pause = 1; + + if (caps & FW_PORT_CAP32_FC_RX) + rx_pause = 1; if (rx_pause && tx_pause) fc_conf->mode = RTE_FC_FULL; @@ -802,30 +815,39 @@ static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev, struct rte_eth_fc_conf *fc_conf) { struct port_info *pi = eth_dev->data->dev_private; - struct adapter *adapter = pi->adapter; struct link_config *lc = &pi->link_cfg; + u32 new_caps = lc->admin_caps; + u8 tx_pause = 0, rx_pause = 0; + int ret; - if (lc->pcaps & FW_PORT_CAP32_ANEG) { - if (fc_conf->autoneg) - lc->requested_fc |= PAUSE_AUTONEG; - else - lc->requested_fc &= ~PAUSE_AUTONEG; + if (fc_conf->mode == RTE_FC_FULL) { + tx_pause = 1; + rx_pause = 1; + } else if (fc_conf->mode == RTE_FC_TX_PAUSE) { + tx_pause = 1; + } else if (fc_conf->mode == RTE_FC_RX_PAUSE) { + rx_pause = 1; } - if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || - (fc_conf->mode & RTE_FC_RX_PAUSE)) - lc->requested_fc |= PAUSE_RX; - else - lc->requested_fc &= ~PAUSE_RX; + ret = t4_set_link_pause(pi, fc_conf->autoneg, tx_pause, + rx_pause, &new_caps); + if (ret != 0) + return ret; - if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || - (fc_conf->mode & RTE_FC_TX_PAUSE)) - lc->requested_fc |= PAUSE_TX; - else - lc->requested_fc &= ~PAUSE_TX; + if (!fc_conf->autoneg) { + if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE) + new_caps |= FW_PORT_CAP32_FORCE_PAUSE; + } else { + new_caps &= ~FW_PORT_CAP32_FORCE_PAUSE; + } - return t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan, - &pi->link_cfg); + if (new_caps != lc->admin_caps) { + ret = t4_link_l1cfg(pi, new_caps); + if (ret == 0) + lc->admin_caps = new_caps; + } + + return ret; } const uint32_t * @@ -924,6 +946,69 @@ static int cxgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev, return 0; } +static int cxgbe_dev_rss_reta_update(struct rte_eth_dev *dev, + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size) +{ + struct port_info *pi = dev->data->dev_private; + struct adapter *adapter = pi->adapter; + u16 i, idx, shift, *rss; + int ret; + + if (!(adapter->flags & FULL_INIT_DONE)) + return -ENOMEM; + + if (!reta_size || reta_size > pi->rss_size) + return -EINVAL; + + rss = rte_calloc(NULL, pi->rss_size, sizeof(u16), 0); + if (!rss) + return -ENOMEM; + + rte_memcpy(rss, pi->rss, pi->rss_size * sizeof(u16)); + for (i = 0; i < reta_size; i++) { + idx = i / RTE_RETA_GROUP_SIZE; + shift = i % RTE_RETA_GROUP_SIZE; + if (!(reta_conf[idx].mask & (1ULL << shift))) + continue; + + rss[i] = reta_conf[idx].reta[shift]; + } + + ret = cxgbe_write_rss(pi, rss); + if (!ret) + rte_memcpy(pi->rss, rss, pi->rss_size * sizeof(u16)); + + rte_free(rss); + return ret; +} + +static int cxgbe_dev_rss_reta_query(struct rte_eth_dev *dev, + struct rte_eth_rss_reta_entry64 *reta_conf, + uint16_t reta_size) +{ + struct port_info *pi = dev->data->dev_private; + struct adapter *adapter = pi->adapter; + u16 i, idx, shift; + + if (!(adapter->flags & FULL_INIT_DONE)) + return -ENOMEM; + + if (!reta_size || reta_size > pi->rss_size) + return -EINVAL; + + for (i = 0; i < reta_size; i++) { + idx = i / RTE_RETA_GROUP_SIZE; + shift = i % RTE_RETA_GROUP_SIZE; + if (!(reta_conf[idx].mask & (1ULL << shift))) + continue; + + reta_conf[idx].reta[shift] = pi->rss[i]; + } + + return 0; +} + static int cxgbe_get_eeprom_length(struct rte_eth_dev *dev) { RTE_SET_USED(dev); @@ -1108,6 +1193,125 @@ int cxgbe_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *addr) return 0; } +static int cxgbe_fec_get_capa_speed_to_fec(struct link_config *lc, + struct rte_eth_fec_capa *capa_arr) +{ + int num = 0; + + if (lc->pcaps & FW_PORT_CAP32_SPEED_100G) { + if (capa_arr) { + capa_arr[num].speed = ETH_SPEED_NUM_100G; + capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) | + RTE_ETH_FEC_MODE_CAPA_MASK(RS); + } + num++; + } + + if (lc->pcaps & FW_PORT_CAP32_SPEED_50G) { + if (capa_arr) { + capa_arr[num].speed = ETH_SPEED_NUM_50G; + capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) | + RTE_ETH_FEC_MODE_CAPA_MASK(BASER); + } + num++; + } + + if (lc->pcaps & FW_PORT_CAP32_SPEED_25G) { + if (capa_arr) { + capa_arr[num].speed = ETH_SPEED_NUM_25G; + capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) | + RTE_ETH_FEC_MODE_CAPA_MASK(BASER) | + RTE_ETH_FEC_MODE_CAPA_MASK(RS); + } + num++; + } + + return num; +} + +static int cxgbe_fec_get_capability(struct rte_eth_dev *dev, + struct rte_eth_fec_capa *speed_fec_capa, + unsigned int num) +{ + struct port_info *pi = dev->data->dev_private; + struct link_config *lc = &pi->link_cfg; + u8 num_entries; + + if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC))) + return -EOPNOTSUPP; + + num_entries = cxgbe_fec_get_capa_speed_to_fec(lc, NULL); + if (!speed_fec_capa || num < num_entries) + return num_entries; + + return cxgbe_fec_get_capa_speed_to_fec(lc, speed_fec_capa); +} + +static int cxgbe_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa) +{ + struct port_info *pi = dev->data->dev_private; + struct link_config *lc = &pi->link_cfg; + u32 fec_caps = 0, caps = lc->link_caps; + + if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC))) + return -EOPNOTSUPP; + + if (caps & FW_PORT_CAP32_FEC_RS) + fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(RS); + else if (caps & FW_PORT_CAP32_FEC_BASER_RS) + fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(BASER); + else + fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC); + + *fec_capa = fec_caps; + return 0; +} + +static int cxgbe_fec_set(struct rte_eth_dev *dev, uint32_t fec_capa) +{ + struct port_info *pi = dev->data->dev_private; + u8 fec_rs = 0, fec_baser = 0, fec_none = 0; + struct link_config *lc = &pi->link_cfg; + u32 new_caps = lc->admin_caps; + int ret; + + if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC))) + return -EOPNOTSUPP; + + if (!fec_capa) + return -EINVAL; + + if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(AUTO)) + goto set_fec; + + if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC)) + fec_none = 1; + + if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(BASER)) + fec_baser = 1; + + if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(RS)) + fec_rs = 1; + +set_fec: + ret = t4_set_link_fec(pi, fec_rs, fec_baser, fec_none, &new_caps); + if (ret != 0) + return ret; + + if (lc->pcaps & FW_PORT_CAP32_FORCE_FEC) + new_caps |= FW_PORT_CAP32_FORCE_FEC; + else + new_caps &= ~FW_PORT_CAP32_FORCE_FEC; + + if (new_caps != lc->admin_caps) { + ret = t4_link_l1cfg(pi, new_caps); + if (ret == 0) + lc->admin_caps = new_caps; + } + + return ret; +} + static const struct eth_dev_ops cxgbe_eth_dev_ops = { .dev_start = cxgbe_dev_start, .dev_stop = cxgbe_dev_stop, @@ -1143,6 +1347,11 @@ static const struct eth_dev_ops cxgbe_eth_dev_ops = { .rss_hash_update = cxgbe_dev_rss_hash_update, .rss_hash_conf_get = cxgbe_dev_rss_hash_conf_get, .mac_addr_set = cxgbe_mac_addr_set, + .reta_update = cxgbe_dev_rss_reta_update, + .reta_query = cxgbe_dev_rss_reta_query, + .fec_get_capability = cxgbe_fec_get_capability, + .fec_get = cxgbe_fec_get, + .fec_set = cxgbe_fec_set, }; /* @@ -1191,6 +1400,8 @@ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev) return 0; } + eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; + snprintf(name, sizeof(name), "cxgbeadapter%d", eth_dev->data->port_id); adapter = rte_zmalloc(name, sizeof(*adapter), 0); if (!adapter) @@ -1227,12 +1438,13 @@ static int eth_cxgbe_dev_uninit(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); uint16_t port_id; + int err = 0; /* Free up other ports and all resources */ RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) - rte_eth_dev_close(port_id); + err |= rte_eth_dev_close(port_id); - return 0; + return err == 0 ? 0 : -EIO; } static int eth_cxgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,