Signed-off-by: Jingjing Wu <jingjing...@intel.com>
---
 drivers/net/avf/avf_ethdev.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/avf/avf_vchnl.c  | 35 ++++++++++++++++++++++++++++++-
 2 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/drivers/net/avf/avf_ethdev.c b/drivers/net/avf/avf_ethdev.c
index b4d3153..0b9f39a 100644
--- a/drivers/net/avf/avf_ethdev.c
+++ b/drivers/net/avf/avf_ethdev.c
@@ -68,6 +68,8 @@ 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 int avf_dev_link_update(struct rte_eth_dev *dev,
+                              __rte_unused int wait_to_complete);
 
 int avf_logtype_init;
 int avf_logtype_driver;
@@ -82,6 +84,7 @@ 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,
+       .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 +432,53 @@ avf_dev_info_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)
 }
 
 static 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)
 {
        int i, reset;
diff --git a/drivers/net/avf/avf_vchnl.c b/drivers/net/avf/avf_vchnl.c
index 90c77fb..1df33ac 100644
--- a/drivers/net/avf/avf_vchnl.c
+++ b/drivers/net/avf/avf_vchnl.c
@@ -160,6 +160,38 @@ 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;
+               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)
 {
@@ -199,7 +231,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) {
-- 
2.4.11

Reply via email to