net/avf: enable link status update
authorJingjing Wu <jingjing.wu@intel.com>
Wed, 10 Jan 2018 13:01:57 +0000 (21:01 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 16 Jan 2018 17:47:49 +0000 (18:47 +0100)
Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
doc/guides/nics/features/avf.ini
drivers/net/avf/avf.h
drivers/net/avf/avf_ethdev.c
drivers/net/avf/avf_vchnl.c

index 8a294e9..77e4f53 100644 (file)
@@ -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
index 4e53d9c..b56ae02 100644 (file)
@@ -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_ */
index 4597de1..d89df8d 100644 (file)
@@ -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,
 };
index 55a425a..f5da601 100644 (file)
@@ -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) {