X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fi40e%2Fi40e_ethdev_vf.c;h=8eb68a3c212f84f9c3313cb715eb73c04f2d31ac;hb=fcdbe1fe1ab45d0572eec145850bd4e7991dff56;hp=8cf22eed8a9de3fc62f0e5f06ec6679a185f3ac3;hpb=82113036e4e54a82ec485a05acce9a43ceb60552;p=dpdk.git diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index 8cf22eed8a..8eb68a3c21 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -111,7 +111,10 @@ static int i40evf_dev_link_update(struct rte_eth_dev *dev, static void i40evf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int i40evf_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n); + struct rte_eth_xstat *xstats, unsigned n); +static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + unsigned limit); static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev); static int i40evf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); @@ -196,6 +199,7 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = { .link_update = i40evf_dev_link_update, .stats_get = i40evf_dev_stats_get, .xstats_get = i40evf_dev_xstats_get, + .xstats_get_names = i40evf_dev_xstats_get_names, .xstats_reset = i40evf_dev_xstats_reset, .dev_close = i40evf_dev_close, .dev_infos_get = i40evf_dev_info_get, @@ -214,6 +218,9 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = { .rx_descriptor_done = i40e_dev_rx_descriptor_done, .tx_queue_setup = i40e_dev_tx_queue_setup, .tx_queue_release = i40e_dev_tx_queue_release, + .rx_queue_count = i40e_dev_rx_queue_count, + .rxq_info_get = i40e_rxq_info_get, + .txq_info_get = i40e_txq_info_get, .mac_addr_add = i40evf_add_mac_addr, .mac_addr_remove = i40evf_del_mac_addr, .reta_update = i40evf_dev_rss_reta_update, @@ -258,6 +265,8 @@ i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info *data) case I40E_VIRTCHNL_EVENT_LINK_CHANGE: vf->link_up = vpe->event_data.link_event.link_status; + vf->link_speed = + vpe->event_data.link_event.link_speed; vf->pend_msg |= PFMSG_LINK_CHANGE; PMD_DRV_LOG(INFO, "Link status update:%s", vf->link_up ? "up" : "down"); @@ -325,8 +334,7 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40evf_arq_msg_info info; enum i40evf_aq_result ret; - int err = -1; - int i = 0; + int err, i = 0; if (_atomic_set_cmd(vf, args->ops)) return -1; @@ -347,19 +355,19 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) switch (args->ops) { case I40E_VIRTCHNL_OP_RESET_VF: /*no need to process in this function */ + err = 0; break; case I40E_VIRTCHNL_OP_VERSION: case I40E_VIRTCHNL_OP_GET_VF_RESOURCES: /* for init adminq commands, need to poll the response */ + err = -1; do { ret = i40evf_read_pfmsg(dev, &info); if (ret == I40EVF_MSG_CMD) { err = 0; break; - } else if (ret == I40EVF_MSG_ERR) { - err = -1; + } else if (ret == I40EVF_MSG_ERR) break; - } rte_delay_ms(ASQ_DELAY_MS); /* If don't read msg or read sys event, continue */ } while (i++ < MAX_TRY_TIMES); @@ -368,6 +376,7 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) default: /* for other adminq in running time, waiting the cmd done flag */ + err = -1; do { if (vf->pend_cmd == I40E_VIRTCHNL_OP_UNKNOWN) { err = 0; @@ -536,7 +545,7 @@ i40evf_config_vlan_pvid(struct rte_eth_dev *dev, struct vf_cmd_info args; struct i40e_virtchnl_pvid_info tpid_info; - if (dev == NULL || info == NULL) { + if (info == NULL) { PMD_DRV_LOG(ERR, "invalid parameters"); return I40E_ERR_PARAM; } @@ -979,8 +988,23 @@ i40evf_dev_xstats_reset(struct rte_eth_dev *dev) vf->vsi.eth_stats_offset = vf->vsi.eth_stats; } +static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + __rte_unused unsigned limit) +{ + unsigned i; + + if (xstats_names != NULL) + for (i = 0; i < I40EVF_NB_XSTATS; i++) { + snprintf(xstats_names[i].name, + sizeof(xstats_names[i].name), + "%s", rte_i40evf_stats_strings[i].name); + } + return I40EVF_NB_XSTATS; +} + static int i40evf_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstats *xstats, unsigned n) + struct rte_eth_xstat *xstats, unsigned n) { int ret; unsigned i; @@ -998,8 +1022,7 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev, /* loop over xstats array and values from pstats */ for (i = 0; i < I40EVF_NB_XSTATS; i++) { - snprintf(xstats[i].name, sizeof(xstats[i].name), - "%s", rte_i40evf_stats_strings[i].name); + xstats[i].id = i; xstats[i].value = *(uint64_t *)(((char *)pstats) + rte_i40evf_stats_strings[i].offset); } @@ -1087,9 +1110,12 @@ i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) } static const struct rte_pci_id pci_id_i40evf_map[] = { -#define RTE_PCI_DEV_ID_DECL_I40EVF(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, -#include "rte_pci_dev_ids.h" -{ .vendor_id = 0, /* sentinel */ }, + { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF) }, + { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF_HV) }, + { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_X722_A0_VF) }, + { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_X722_VF) }, + { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_X722_VF_HV) }, + { .vendor_id = 0, /* sentinel */ }, }; static inline int @@ -1310,14 +1336,17 @@ i40evf_handle_pf_event(__rte_unused struct rte_eth_dev *dev, { struct i40e_virtchnl_pf_event *pf_msg = (struct i40e_virtchnl_pf_event *)msg; + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); switch (pf_msg->event) { case I40E_VIRTCHNL_EVENT_RESET_IMPENDING: PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_RESET_IMPENDING event\n"); - _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET); + _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, NULL); break; case I40E_VIRTCHNL_EVENT_LINK_CHANGE: PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event\n"); + vf->link_up = pf_msg->event_data.link_event.link_status; + vf->link_speed = pf_msg->event_data.link_event.link_speed; break; case I40E_VIRTCHNL_EVENT_PF_DRIVER_CLOSE: PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_PF_DRIVER_CLOSE event\n"); @@ -1525,43 +1554,26 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev) */ static struct eth_driver rte_i40evf_pmd = { .pci_drv = { - .name = "rte_i40evf_pmd", .id_table = pci_id_i40evf_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE, + .probe = rte_eth_dev_pci_probe, + .remove = rte_eth_dev_pci_remove, }, .eth_dev_init = i40evf_dev_init, .eth_dev_uninit = i40evf_dev_uninit, .dev_private_size = sizeof(struct i40e_adapter), }; -/* - * VF Driver initialization routine. - * Invoked one at EAL init time. - * Register itself as the [Virtual Poll Mode] Driver of PCI Fortville devices. - */ -static int -rte_i40evf_pmd_init(const char *name __rte_unused, - const char *params __rte_unused) -{ - PMD_INIT_FUNC_TRACE(); - - rte_eth_driver_register(&rte_i40evf_pmd); - - return 0; -} - -static struct rte_driver rte_i40evf_driver = { - .type = PMD_PDEV, - .init = rte_i40evf_pmd_init, -}; - -PMD_REGISTER_DRIVER(rte_i40evf_driver); +RTE_PMD_REGISTER_PCI(net_i40e_vf, rte_i40evf_pmd.pci_drv); +RTE_PMD_REGISTER_PCI_TABLE(net_i40e_vf, pci_id_i40evf_map); static int i40evf_dev_configure(struct rte_eth_dev *dev) { struct i40e_adapter *ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + struct rte_eth_conf *conf = &dev->data->dev_conf; + struct i40e_vf *vf; /* Initialize to TRUE. If any of Rx queues doesn't meet the bulk * allocation or vector Rx preconditions we will reset it. @@ -1571,6 +1583,19 @@ i40evf_dev_configure(struct rte_eth_dev *dev) ad->tx_simple_allowed = true; ad->tx_vec_allowed = true; + /* For non-DPDK PF drivers, VF has no ability to disable HW + * CRC strip, and is implicitly enabled by the PF. + */ + if (!conf->rxmode.hw_strip_crc) { + vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + if ((vf->version_major == I40E_VIRTCHNL_VERSION_MAJOR) && + (vf->version_minor <= I40E_VIRTCHNL_VERSION_MINOR)) { + /* Peer is running non-DPDK PF driver. */ + PMD_INIT_LOG(ERR, "VF can't disable HW CRC Strip"); + return -EINVAL; + } + } + return i40evf_init_vlan(dev); } @@ -2121,14 +2146,34 @@ i40evf_dev_link_update(struct rte_eth_dev *dev, * DPDK pf host provide interfacet to acquire link status * while Linux driver does not */ - if (vf->version_major == I40E_DPDK_VERSION_MAJOR) { + if (vf->version_major == I40E_DPDK_VERSION_MAJOR) i40evf_get_link_status(dev, &new_link); - } else { - /* Always assume it's up, for Linux driver PF host */ - new_link.link_speed = ETH_SPEED_NUM_10G; + else { + /* Linux driver PF host */ + switch (vf->link_speed) { + case I40E_LINK_SPEED_100MB: + new_link.link_speed = ETH_SPEED_NUM_100M; + break; + case I40E_LINK_SPEED_1GB: + new_link.link_speed = ETH_SPEED_NUM_1G; + break; + case I40E_LINK_SPEED_10GB: + new_link.link_speed = ETH_SPEED_NUM_10G; + break; + case I40E_LINK_SPEED_20GB: + new_link.link_speed = ETH_SPEED_NUM_20G; + break; + case I40E_LINK_SPEED_40GB: + new_link.link_speed = ETH_SPEED_NUM_40G; + break; + default: + new_link.link_speed = ETH_SPEED_NUM_100M; + break; + } + /* full duplex only */ new_link.link_duplex = ETH_LINK_FULL_DUPLEX; - new_link.link_autoneg = ETH_LINK_SPEED_AUTONEG; - new_link.link_status = ETH_LINK_UP; + new_link.link_status = vf->link_up ? ETH_LINK_UP : + ETH_LINK_DOWN; } i40evf_dev_atomic_write_link_status(dev, &new_link); @@ -2316,13 +2361,16 @@ i40evf_get_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size) static int i40evf_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size) { - struct i40e_vf *vf = I40E_VSI_TO_VF(vsi); - struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); + struct i40e_vf *vf; + struct i40e_hw *hw; int ret; if (!vsi || !lut) return -EINVAL; + vf = I40E_VSI_TO_VF(vsi); + hw = I40E_VSI_TO_HW(vsi); + if (vf->flags & I40E_FLAG_RSS_AQ_CAPABLE) { ret = i40e_aq_set_rss_lut(hw, vsi->vsi_id, FALSE, lut, lut_size);