net/netvsc: implement link state change callback
authorStephen Hemminger <sthemmin@microsoft.com>
Thu, 30 Aug 2018 22:35:11 +0000 (15:35 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 14 Sep 2018 18:08:41 +0000 (20:08 +0200)
Implement callback functionality on link state changes.
This is not really driven off of interrupt file descriptor like most other
PMD's. Instead, it happens when a link state change message arrives
in the common ring buffer.

Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
doc/guides/nics/netvsc.rst
drivers/net/netvsc/hn_ethdev.c
drivers/net/netvsc/hn_rndis.c
drivers/net/netvsc/hn_rndis.h
drivers/net/netvsc/hn_rxtx.c
drivers/net/netvsc/hn_var.h

index cc07ce4..c5f9b7c 100644 (file)
@@ -28,7 +28,8 @@ In this release, the hyper PMD driver provides the basic functionality of packet
 
 *   VLAN tags are always stripped and presented in mbuf tci field.
 
-*   The Hyper-V driver does not use or support Link State or Rx interrupt.
+*   The Hyper-V driver does not use or support interrupts. Link state change
+    callback is done via change events in the packet ring.
 
 *   The maximum number of queues is limited by the host (currently 64).
     When used with 4.16 kernel only a single queue is available.
index 764b8d8..9ea5813 100644 (file)
@@ -106,6 +106,10 @@ eth_dev_vmbus_allocate(struct rte_vmbus_device *dev, size_t private_data_size)
        }
 
        eth_dev->device = &dev->device;
+
+       /* interrupt is simulated */
+       dev->intr_handle.type = RTE_INTR_HANDLE_EXT;
+       eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
        eth_dev->intr_handle = &dev->intr_handle;
 
        return eth_dev;
@@ -186,7 +190,7 @@ static int hn_parse_args(const struct rte_eth_dev *dev)
  *   means block this call until link is up.
  *   which is not worth supporting.
  */
-static int
+int
 hn_dev_link_update(struct rte_eth_dev *dev,
                   __rte_unused int wait_to_complete)
 {
@@ -553,12 +557,6 @@ hn_dev_start(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
 
-       /* check if lsc interrupt feature is enabled */
-       if (dev->data->dev_conf.intr_conf.lsc) {
-               PMD_DRV_LOG(ERR, "link status not supported yet");
-               return -ENOTSUP;
-       }
-
        return hn_rndis_set_rxfilter(hv,
                                     NDIS_PACKET_TYPE_BROADCAST |
                                     NDIS_PACKET_TYPE_ALL_MULTICAST |
index 9de99e1..e0ea732 100644 (file)
@@ -11,6 +11,7 @@
 #include <errno.h>
 #include <unistd.h>
 
+#include <rte_ethdev_driver.h>
 #include <rte_ethdev.h>
 #include <rte_string_fns.h>
 #include <rte_memzone.h>
@@ -281,7 +282,7 @@ static int hn_nvs_send_rndis_ctrl(struct vmbus_channel *chan,
                                  &nvs_rndis, sizeof(nvs_rndis), 0U, NULL);
 }
 
-void hn_rndis_link_status(struct hn_data *hv __rte_unused, const void *msg)
+void hn_rndis_link_status(struct rte_eth_dev *dev, const void *msg)
 {
        const struct rndis_status_msg *indicate = msg;
 
@@ -290,15 +291,19 @@ void hn_rndis_link_status(struct hn_data *hv __rte_unused, const void *msg)
        PMD_DRV_LOG(DEBUG, "link status %#x", indicate->status);
 
        switch (indicate->status) {
-       case RNDIS_STATUS_LINK_SPEED_CHANGE:
        case RNDIS_STATUS_NETWORK_CHANGE:
        case RNDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG:
                /* ignore not in DPDK API */
                break;
 
+       case RNDIS_STATUS_LINK_SPEED_CHANGE:
        case RNDIS_STATUS_MEDIA_CONNECT:
        case RNDIS_STATUS_MEDIA_DISCONNECT:
-               /* TODO handle as LSC interrupt  */
+               if (dev->data->dev_conf.intr_conf.lsc &&
+                   hn_dev_link_update(dev, 0) == 0)
+                       _rte_eth_dev_callback_process(dev,
+                                                     RTE_ETH_EVENT_INTR_LSC,
+                                                     NULL);
                break;
        default:
                PMD_DRV_LOG(NOTICE, "unknown RNDIS indication: %#x",
index 89e2e6b..01b5120 100644 (file)
@@ -6,7 +6,7 @@ struct hn_data;
 
 void hn_rndis_receive_response(struct hn_data *hv,
                              const void *data, uint32_t len);
-void   hn_rndis_link_status(struct hn_data *hv, const void *data);
+void   hn_rndis_link_status(struct rte_eth_dev *dev, const void *msg);
 int    hn_rndis_attach(struct hn_data *hv);
 void   hn_rndis_detach(struct hn_data *hv);
 int    hn_rndis_get_eaddr(struct hn_data *hv, uint8_t *eaddr);
index 92de5d0..ad22a95 100644 (file)
@@ -601,7 +601,7 @@ error:
 }
 
 static void
-hn_rndis_receive(const struct rte_eth_dev *dev, struct hn_rx_queue *rxq,
+hn_rndis_receive(struct rte_eth_dev *dev, struct hn_rx_queue *rxq,
                 struct hn_rx_bufinfo *rxb, void *buf, uint32_t len)
 {
        const struct rndis_msghdr *hdr = buf;
@@ -613,7 +613,7 @@ hn_rndis_receive(const struct rte_eth_dev *dev, struct hn_rx_queue *rxq,
                break;
 
        case RNDIS_INDICATE_STATUS_MSG:
-               hn_rndis_link_status(rxq->hv, buf);
+               hn_rndis_link_status(dev, buf);
                break;
 
        case RNDIS_INITIALIZE_CMPLT:
index ff72256..17b6794 100644 (file)
@@ -142,6 +142,7 @@ uint16_t hn_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
                      uint16_t nb_pkts);
 
 int    hn_tx_pool_init(struct rte_eth_dev *dev);
+int    hn_dev_link_update(struct rte_eth_dev *dev, int wait);
 int    hn_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
                              uint16_t nb_desc, unsigned int socket_id,
                              const struct rte_eth_txconf *tx_conf);