X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=inline;f=drivers%2Fnet%2Favf%2Favf_ethdev.c;h=f32d15068a47548967e562c6a1879f58fefe9ce3;hb=f4a41a6953af6c7e2112f0ec3f858c5bedfdbb9a;hp=e0ee05a6c7d6e32ea035a07881f8abeac76a58b2;hpb=69dd4c3d0898559ef326ab8f53beec26b62cc098;p=dpdk.git diff --git a/drivers/net/avf/avf_ethdev.c b/drivers/net/avf/avf_ethdev.c index e0ee05a6c7..f32d15068a 100644 --- a/drivers/net/avf/avf_ethdev.c +++ b/drivers/net/avf/avf_ethdev.c @@ -39,6 +39,9 @@ static void avf_dev_stop(struct rte_eth_dev *dev); static void avf_dev_close(struct rte_eth_dev *dev); static void avf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); +static const uint32_t *avf_dev_supported_ptypes_get(struct rte_eth_dev *dev); +static int avf_dev_stats_get(struct rte_eth_dev *dev, + struct rte_eth_stats *stats); int avf_logtype_init; int avf_logtype_driver; @@ -53,6 +56,9 @@ static const struct eth_dev_ops avf_eth_dev_ops = { .dev_stop = avf_dev_stop, .dev_close = avf_dev_close, .dev_infos_get = avf_dev_info_get, + .dev_supported_ptypes_get = avf_dev_supported_ptypes_get, + .link_update = avf_dev_link_update, + .stats_get = avf_dev_stats_get, .rx_queue_start = avf_dev_rx_queue_start, .rx_queue_stop = avf_dev_rx_queue_stop, .tx_queue_start = avf_dev_tx_queue_start, @@ -204,9 +210,12 @@ avf_init_queues(struct rte_eth_dev *dev) if (ret != AVF_SUCCESS) break; } - /* TODO: set rx/tx function to vector/scatter/single-segment + /* set rx/tx function to vector/scatter/single-segment * according to parameters */ + avf_set_rx_function(dev); + avf_set_tx_function(dev); + return ret; } @@ -407,6 +416,94 @@ avf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) }; } +static const uint32_t * +avf_dev_supported_ptypes_get(struct rte_eth_dev *dev) +{ + static const uint32_t ptypes[] = { + RTE_PTYPE_L2_ETHER, + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_NONFRAG, + RTE_PTYPE_L4_SCTP, + RTE_PTYPE_L4_TCP, + RTE_PTYPE_L4_UDP, + RTE_PTYPE_UNKNOWN + }; + return ptypes; +} + +int +avf_dev_link_update(struct rte_eth_dev *dev, + __rte_unused int wait_to_complete) +{ + struct rte_eth_link new_link; + struct avf_info *vf = AVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + + /* Only read status info stored in VF, and the info is updated + * when receive LINK_CHANGE evnet from PF by Virtchnnl. + */ + switch (vf->link_speed) { + case VIRTCHNL_LINK_SPEED_100MB: + new_link.link_speed = ETH_SPEED_NUM_100M; + break; + case VIRTCHNL_LINK_SPEED_1GB: + new_link.link_speed = ETH_SPEED_NUM_1G; + break; + case VIRTCHNL_LINK_SPEED_10GB: + new_link.link_speed = ETH_SPEED_NUM_10G; + break; + case VIRTCHNL_LINK_SPEED_20GB: + new_link.link_speed = ETH_SPEED_NUM_20G; + break; + case VIRTCHNL_LINK_SPEED_25GB: + new_link.link_speed = ETH_SPEED_NUM_25G; + break; + case VIRTCHNL_LINK_SPEED_40GB: + new_link.link_speed = ETH_SPEED_NUM_40G; + break; + default: + new_link.link_speed = ETH_SPEED_NUM_NONE; + break; + } + + new_link.link_duplex = ETH_LINK_FULL_DUPLEX; + new_link.link_status = vf->link_up ? ETH_LINK_UP : + ETH_LINK_DOWN; + new_link.link_autoneg = !!(dev->data->dev_conf.link_speeds & + ETH_LINK_SPEED_FIXED); + + rte_atomic64_cmpset((uint64_t *)&dev->data->dev_link, + *(uint64_t *)&dev->data->dev_link, + *(uint64_t *)&new_link); + + return 0; +} + +static int +avf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) +{ + struct avf_adapter *adapter = + AVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + struct virtchnl_eth_stats *pstats = NULL; + int ret; + + ret = avf_query_stats(adapter, &pstats); + if (ret == 0) { + stats->ipackets = pstats->rx_unicast + pstats->rx_multicast + + pstats->rx_broadcast; + stats->opackets = pstats->tx_broadcast + pstats->tx_multicast + + pstats->tx_unicast; + stats->imissed = pstats->rx_discards; + stats->oerrors = pstats->tx_errors + pstats->tx_discards; + stats->ibytes = pstats->rx_bytes; + stats->obytes = pstats->tx_bytes; + } else { + PMD_DRV_LOG(ERR, "Get statistics failed"); + } + return -EIO; +} + static int avf_check_vf_reset_done(struct avf_hw *hw) { @@ -556,7 +653,19 @@ avf_dev_init(struct rte_eth_dev *eth_dev) /* assign ops func pointer */ eth_dev->dev_ops = &avf_eth_dev_ops; + eth_dev->rx_pkt_burst = &avf_recv_pkts; + eth_dev->tx_pkt_burst = &avf_xmit_pkts; + eth_dev->tx_pkt_prepare = &avf_prep_pkts; + /* For secondary processes, we don't initialise any further as primary + * has already done this work. Only check if we need a different RX + * and TX function. + */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + avf_set_rx_function(eth_dev); + avf_set_tx_function(eth_dev); + return 0; + } rte_eth_copy_pci_info(eth_dev, pci_dev); hw->vendor_id = pci_dev->id.vendor_id; @@ -678,7 +787,8 @@ static int eth_avf_pci_remove(struct rte_pci_device *pci_dev) /* Adaptive virtual function driver struct */ static struct rte_pci_driver rte_avf_pmd = { .id_table = pci_id_avf_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | + RTE_PCI_DRV_IOVA_AS_VA, .probe = eth_avf_pci_probe, .remove = eth_avf_pci_remove, };