From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 84B14374C for ; Thu, 30 Nov 2017 10:47:31 +0100 (CET) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Nov 2017 01:47:30 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,341,1508828400"; d="scan'208";a="1250236789" Received: from unknown (HELO dpdk5.bj.intel.com) ([172.16.182.182]) by fmsmga002.fm.intel.com with ESMTP; 30 Nov 2017 01:47:29 -0800 From: Zhiyong Yang To: dev@dpdk.org, yliu@fridaylinux.org, maxime.coquelin@redhat.com Cc: wei.w.wang@intel.com, jianfeng.tan@intel.com, Zhiyong Yang Date: Thu, 30 Nov 2017 17:46:52 +0800 Message-Id: <20171130094657.11470-7-zhiyong.yang@intel.com> X-Mailer: git-send-email 2.13.3 In-Reply-To: <20171130094657.11470-1-zhiyong.yang@intel.com> References: <20171130094657.11470-1-zhiyong.yang@intel.com> Subject: [dpdk-dev] [PATCH 06/11] net/vhostpci: add support for link status change X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Nov 2017 09:47:32 -0000 Signed-off-by: Zhiyong Yang --- drivers/net/vhostpci/vhostpci_ethdev.c | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/drivers/net/vhostpci/vhostpci_ethdev.c b/drivers/net/vhostpci/vhostpci_ethdev.c index 068c19b2b..76353930a 100644 --- a/drivers/net/vhostpci/vhostpci_ethdev.c +++ b/drivers/net/vhostpci/vhostpci_ethdev.c @@ -54,6 +54,9 @@ vhostpci_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static void +vhostpci_interrupt_handler(void *param); + +static void vhostpci_get_hwaddr(struct vhostpci_hw *hw); static int @@ -63,6 +66,10 @@ static int eth_vhostpci_dev_init(struct rte_eth_dev *eth_dev); static int +vhostpci_dev_atomic_read_link_status(struct rte_eth_dev *dev, + struct rte_eth_link *link); + +static int vhostpci_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link); @@ -85,6 +92,10 @@ vhostpci_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features); static int vhostpci_dev_start(struct rte_eth_dev *dev); +static int +vhostpci_dev_link_update(struct rte_eth_dev *dev, + __rte_unused int wait_to_complete); + static void update_queuing_status(struct rte_eth_dev *dev); @@ -100,6 +111,7 @@ static const struct eth_dev_ops vhostpci_eth_dev_ops = { .dev_close = vhostpci_dev_close, .dev_infos_get = vhostpci_dev_info_get, .dev_configure = vhostpci_dev_configure, + .link_update = vhostpci_dev_link_update, .rx_queue_setup = vhostpci_dev_rx_queue_setup, .tx_queue_setup = vhostpci_dev_tx_queue_setup, }; @@ -296,6 +308,20 @@ vhostpci_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, } static int +vhostpci_dev_atomic_read_link_status(struct rte_eth_dev *dev, + struct rte_eth_link *link) +{ + struct rte_eth_link *dst = link; + struct rte_eth_link *src = &(dev->data->dev_link); + + if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, + *(uint64_t *)src) == 0) + return -1; + + return 0; +} + +static int vhostpci_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { @@ -309,6 +335,70 @@ vhostpci_dev_atomic_write_link_status(struct rte_eth_dev *dev, return 0; } +static int +vhostpci_dev_link_update(struct rte_eth_dev *dev, + int wait_to_complete __rte_unused) +{ + struct rte_eth_link link, old; + uint16_t status; + struct vhostpci_hw *hw = dev->data->dev_private; + + memset(&link, 0, sizeof(link)); + vhostpci_dev_atomic_read_link_status(dev, &link); + old = link; + link.link_duplex = ETH_LINK_FULL_DUPLEX; + link.link_speed = ETH_SPEED_NUM_10G; + + if (hw->started == 0) { + link.link_status = ETH_LINK_DOWN; + } else { + PMD_INIT_LOG(DEBUG, "Get link status from hw"); + vhpci_read_dev_config(hw, + offsetof(struct vpnet_pci_config, status), + &status, sizeof(status)); + if ((status & VHOSTPCI_NET_S_LINK_UP) == 0) { + link.link_status = ETH_LINK_DOWN; + PMD_INIT_LOG(DEBUG, "Port %d is down", + dev->data->port_id); + + } else { + link.link_status = ETH_LINK_UP; + PMD_INIT_LOG(DEBUG, "Port %d is up", + dev->data->port_id); + } + } + + vhostpci_dev_atomic_write_link_status(dev, &link); + + return (old.link_status == link.link_status) ? -1 : 0; +} + +/** + * Process vhostpci Config changed interrupt and call the callback + * if link state changed. + */ +static void +vhostpci_interrupt_handler(void *param) +{ + struct rte_eth_dev *dev = param; + struct vhostpci_hw *hw = dev->data->dev_private; + uint8_t isr; + + /* Read interrupt status which clears interrupt */ + isr = vhpci_isr(hw); + PMD_DRV_LOG(INFO, "interrupt status = %x", isr); + + if (rte_intr_enable(dev->intr_handle) < 0) + PMD_DRV_LOG(ERR, "interrupt enable failed"); + + if (isr & VIRTIO_PCI_ISR_CONFIG) { + if (vhostpci_dev_link_update(dev, 0) == 0) + _rte_eth_dev_callback_process(dev, + RTE_ETH_EVENT_INTR_LSC, NULL, NULL); + } + +} + /* reset device and renegotiate features if needed */ static int vhostpci_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features) @@ -538,6 +628,13 @@ eth_vhostpci_dev_init(struct rte_eth_dev *eth_dev) if (ret < 0) return ret; + eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; /* by default */ + + /* Register and Setup interrupt callback */ + if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) + rte_intr_callback_register(eth_dev->intr_handle, + vhostpci_interrupt_handler, eth_dev); + return 0; } @@ -557,6 +654,11 @@ eth_vhostpci_dev_uninit(struct rte_eth_dev *eth_dev) rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; + /* reset interrupt callback */ + if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) + rte_intr_callback_unregister(eth_dev->intr_handle, + vhostpci_interrupt_handler, eth_dev); + if (eth_dev->device != NULL) rte_pci_unmap_device(RTE_ETH_DEV_TO_PCI(eth_dev)); -- 2.13.3