From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id AC12F3B5 for ; Mon, 8 Dec 2014 07:22:21 +0100 (CET) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP; 07 Dec 2014 22:20:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,536,1413270000"; d="scan'208";a="620242641" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga001.jf.intel.com with ESMTP; 07 Dec 2014 22:22:11 -0800 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id sB86MAlM019086; Mon, 8 Dec 2014 14:22:10 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id sB86M72J005033; Mon, 8 Dec 2014 14:22:09 +0800 Received: (from couyang@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id sB86M7Y2005028; Mon, 8 Dec 2014 14:22:07 +0800 From: Ouyang Changchun To: dev@dpdk.org Date: Mon, 8 Dec 2014 14:21:43 +0800 Message-Id: <1418019716-4962-5-git-send-email-changchun.ouyang@intel.com> X-Mailer: git-send-email 1.7.12.2 In-Reply-To: <1418019716-4962-1-git-send-email-changchun.ouyang@intel.com> References: <1418019716-4962-1-git-send-email-changchun.ouyang@intel.com> Subject: [dpdk-dev] [RFC PATCH 04/17] virtio: Add support for Link State interrupt X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Dec 2014 06:22:22 -0000 Virtio has link state interrupt which can be used. Signed-off-by: Changchun Ouyang Signed-off-by: Stephen Hemminger --- lib/librte_pmd_virtio/virtio_ethdev.c | 78 +++++++++++++++++++++++++++-------- lib/librte_pmd_virtio/virtio_pci.c | 22 ++++++++++ lib/librte_pmd_virtio/virtio_pci.h | 4 ++ 3 files changed, 86 insertions(+), 18 deletions(-) diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 4bff0fe..d37f2e9 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -845,6 +845,34 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) #endif /* + * Process Virtio Config changed interrupt and call the callback + * if link state changed. + */ +static void +virtio_interrupt_handler(__rte_unused struct rte_intr_handle *handle, + void *param) +{ + struct rte_eth_dev *dev = param; + struct virtio_hw *hw = + VIRTIO_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint8_t isr; + + /* Read interrupt status which clears interrupt */ + isr = vtpci_isr(hw); + PMD_DRV_LOG(INFO, "interrupt status = %#x", isr); + + if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0) + PMD_DRV_LOG(ERR, "interrupt enable failed"); + + if (isr & VIRTIO_PCI_ISR_CONFIG) { + if (virtio_dev_link_update(dev, 0) == 0) + _rte_eth_dev_callback_process(dev, + RTE_ETH_EVENT_INTR_LSC); + } + +} + +/* * This function is based on probe() function in virtio_pci.c * It returns 0 on success. */ @@ -968,6 +996,10 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); + + /* Setup interrupt callback */ + rte_intr_callback_register(&pci_dev->intr_handle, + virtio_interrupt_handler, eth_dev); return 0; } @@ -975,7 +1007,7 @@ static struct eth_driver rte_virtio_pmd = { { .name = "rte_virtio_pmd", .id_table = pci_id_virtio_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, }, .eth_dev_init = eth_virtio_dev_init, .dev_private_size = sizeof(struct virtio_adapter), @@ -1021,6 +1053,9 @@ static int virtio_dev_configure(struct rte_eth_dev *dev) { const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; + struct virtio_hw *hw = + VIRTIO_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret; PMD_INIT_LOG(DEBUG, "configure"); @@ -1029,7 +1064,11 @@ virtio_dev_configure(struct rte_eth_dev *dev) return (-EINVAL); } - return 0; + ret = vtpci_irq_config(hw, 0); + if (ret != 0) + PMD_DRV_LOG(ERR, "failed to set config vector"); + + return ret; } @@ -1037,7 +1076,6 @@ static int virtio_dev_start(struct rte_eth_dev *dev) { uint16_t nb_queues, i; - uint16_t status; struct virtio_hw *hw = VIRTIO_DEV_PRIVATE_TO_HW(dev->data->dev_private); @@ -1052,18 +1090,22 @@ virtio_dev_start(struct rte_eth_dev *dev) /* Do final configuration before rx/tx engine starts */ virtio_dev_rxtx_start(dev); - /* Check VIRTIO_NET_F_STATUS for link status*/ - if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { - vtpci_read_dev_config(hw, - offsetof(struct virtio_net_config, status), - &status, sizeof(status)); - if ((status & VIRTIO_NET_S_LINK_UP) == 0) - PMD_INIT_LOG(ERR, "Port: %d Link is DOWN", - dev->data->port_id); - else - PMD_INIT_LOG(DEBUG, "Port: %d Link is UP", - dev->data->port_id); + /* check if lsc interrupt feature is enabled */ + if (dev->data->dev_conf.intr_conf.lsc) { + if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { + PMD_DRV_LOG(ERR, "link status not supported by host"); + return -ENOTSUP; + } + + if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0) { + PMD_DRV_LOG(ERR, "interrupt enable failed"); + return -EIO; + } } + + /* Initialize Link state */ + virtio_dev_link_update(dev, 0); + vtpci_reinit_complete(hw); /*Notify the backend @@ -1145,6 +1187,7 @@ virtio_dev_stop(struct rte_eth_dev *dev) VIRTIO_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* reset the NIC */ + vtpci_irq_config(hw, 0); vtpci_reset(hw); virtio_dev_free_mbufs(dev); } @@ -1161,6 +1204,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet old = link; link.link_duplex = FULL_DUPLEX; link.link_speed = SPEED_10G; + if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { PMD_INIT_LOG(DEBUG, "Get link status from hw"); vtpci_read_dev_config(hw, @@ -1179,10 +1223,8 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet link.link_status = 1; /* Link up */ } virtio_dev_atomic_write_link_status(dev, &link); - if (old.link_status == link.link_status) - return -1; - /*changed*/ - return 0; + + return (old.link_status == link.link_status) ? -1 : 0; } static void diff --git a/lib/librte_pmd_virtio/virtio_pci.c b/lib/librte_pmd_virtio/virtio_pci.c index ca9c748..6d51032 100644 --- a/lib/librte_pmd_virtio/virtio_pci.c +++ b/lib/librte_pmd_virtio/virtio_pci.c @@ -127,3 +127,25 @@ vtpci_set_status(struct virtio_hw *hw, uint8_t status) VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status); } + +uint8_t +vtpci_isr(struct virtio_hw *hw) +{ + + return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR); +} + + +/* Enable one vector (0) for Link State Intrerrupt */ +int +vtpci_irq_config(struct virtio_hw *hw, uint16_t vec) +{ + VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec); + vec = VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR); + if (vec == VIRTIO_MSI_NO_VECTOR) { + PMD_DRV_LOG(ERR, "failed to set config vector"); + return -EBUSY; + } + + return 0; +} diff --git a/lib/librte_pmd_virtio/virtio_pci.h b/lib/librte_pmd_virtio/virtio_pci.h index 373f9dc..6998737 100644 --- a/lib/librte_pmd_virtio/virtio_pci.h +++ b/lib/librte_pmd_virtio/virtio_pci.h @@ -263,4 +263,8 @@ void vtpci_write_dev_config(struct virtio_hw *, uint64_t, void *, int); void vtpci_read_dev_config(struct virtio_hw *, uint64_t, void *, int); +uint8_t vtpci_isr(struct virtio_hw *); + +int vtpci_irq_config(struct virtio_hw *, uint16_t); + #endif /* _VIRTIO_PCI_H_ */ -- 1.8.4.2