From: Jingjing Wu Date: Wed, 10 Jan 2018 13:01:57 +0000 (+0800) Subject: net/avf: enable link status update X-Git-Tag: spdx-start~415 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=48de41ca11f0;p=dpdk.git net/avf: enable link status update Signed-off-by: Jingjing Wu --- diff --git a/doc/guides/nics/features/avf.ini b/doc/guides/nics/features/avf.ini index 8a294e9dae..77e4f53cdd 100644 --- a/doc/guides/nics/features/avf.ini +++ b/doc/guides/nics/features/avf.ini @@ -4,6 +4,9 @@ ; Refer to default.ini for the full list of available PMD features. ; [Features] +Speed capabilities = Y +Link status = Y +Link status event = Y Queue start/stop = Y Jumbo frame = Y Scattered Rx = Y diff --git a/drivers/net/avf/avf.h b/drivers/net/avf/avf.h index 4e53d9c019..b56ae023e9 100644 --- a/drivers/net/avf/avf.h +++ b/drivers/net/avf/avf.h @@ -199,4 +199,6 @@ int avf_configure_rss_key(struct avf_adapter *adapter); int avf_configure_queues(struct avf_adapter *adapter); int avf_config_irq_map(struct avf_adapter *adapter); void avf_add_del_all_mac_addr(struct avf_adapter *adapter, bool add); +int avf_dev_link_update(struct rte_eth_dev *dev, + __rte_unused int wait_to_complete); #endif /* _AVF_ETHDEV_H_ */ diff --git a/drivers/net/avf/avf_ethdev.c b/drivers/net/avf/avf_ethdev.c index 4597de17a9..d89df8d15f 100644 --- a/drivers/net/avf/avf_ethdev.c +++ b/drivers/net/avf/avf_ethdev.c @@ -55,6 +55,7 @@ static const struct eth_dev_ops avf_eth_dev_ops = { .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, .rx_queue_start = avf_dev_rx_queue_start, .rx_queue_stop = avf_dev_rx_queue_stop, .tx_queue_start = avf_dev_tx_queue_start, @@ -429,6 +430,53 @@ avf_dev_supported_ptypes_get(struct rte_eth_dev *dev) 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_check_vf_reset_done(struct avf_hw *hw) { @@ -712,7 +760,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, }; diff --git a/drivers/net/avf/avf_vchnl.c b/drivers/net/avf/avf_vchnl.c index 55a425a7fe..f5da601503 100644 --- a/drivers/net/avf/avf_vchnl.c +++ b/drivers/net/avf/avf_vchnl.c @@ -133,6 +133,41 @@ avf_execute_vf_cmd(struct avf_adapter *adapter, struct avf_cmd_info *args) return err; } +static void +avf_handle_pf_event_msg(struct rte_eth_dev *dev, uint8_t *msg, + uint16_t msglen) +{ + struct virtchnl_pf_event *pf_msg = + (struct virtchnl_pf_event *)msg; + struct avf_info *vf = AVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + + if (msglen < sizeof(struct virtchnl_pf_event)) { + PMD_DRV_LOG(DEBUG, "Error event"); + return; + } + switch (pf_msg->event) { + case VIRTCHNL_EVENT_RESET_IMPENDING: + PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_RESET_IMPENDING event"); + _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET, + NULL, NULL); + break; + case VIRTCHNL_EVENT_LINK_CHANGE: + PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event"); + vf->link_up = pf_msg->event_data.link_event.link_status; + vf->link_speed = pf_msg->event_data.link_event.link_speed; + avf_dev_link_update(dev, 0); + _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, + NULL, NULL); + break; + case VIRTCHNL_EVENT_PF_DRIVER_CLOSE: + PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_PF_DRIVER_CLOSE event"); + break; + default: + PMD_DRV_LOG(ERR, " unknown event received %u", pf_msg->event); + break; + } +} + void avf_handle_virtchnl_msg(struct rte_eth_dev *dev) { @@ -172,7 +207,8 @@ avf_handle_virtchnl_msg(struct rte_eth_dev *dev) switch (aq_opc) { case avf_aqc_opc_send_msg_to_vf: if (msg_opc == VIRTCHNL_OP_EVENT) { - /* TODO */ + avf_handle_pf_event_msg(dev, info.msg_buf, + info.msg_len); } else { /* read message and it's expected one */ if (msg_opc == vf->pend_cmd) {