From patchwork Tue Aug 26 02:07:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 212 Return-Path: Received: from mail-pa0-f47.google.com (mail-pa0-f47.google.com [209.85.220.47]) by dpdk.org (Postfix) with ESMTP id 981853975 for ; Tue, 26 Aug 2014 04:04:48 +0200 (CEST) Received: by mail-pa0-f47.google.com with SMTP id kx10so22407930pab.20 for ; Mon, 25 Aug 2014 19:08:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:user-agent:date:from:to:cc:subject :references:mime-version:content-type:content-disposition; bh=e/50CcV3ZU5cPvdXefh19EBPhPuvMIDx+u0RldTLSmQ=; b=ZBgRlA+D6JiZmTaYWULollw5V7ndczfq1iWxGIZQ+/dYRXiRVdguY7BQ1lI3RsVfS0 QKdi4QcY/kikh3MoueygpiE21bTQzk0XgGCjyrMaI1eKEGgi6uyT4388Qi5pQEGd8buQ ouoQ+G4kajlt3Brot5EH36z+uzWx0RXBrX2C9gusXgnaNFYiA65WiAmPTiyw63MNHJtG yIeVfK8D20nclBcnimJM2IrInkn8bLcOHhlbGc7UeeTUfwgQbkUj7khF5koWhT81nfPj 3Z97ukvSXZeqsJkkHrhvwDJYdH/nRSJS2+SPcrLLYJRjWwLvWAHOdwC3y0bX0dsvaw8P K1xg== X-Gm-Message-State: ALoCoQmD3fKEV3FGdfA5L/bCzUqtFIQcpc8TlFCrcnoy+/jCz1HLMT+6jKr8I2+SILh/6dTUSROe X-Received: by 10.68.195.228 with SMTP id ih4mr663471pbc.167.1409018925755; Mon, 25 Aug 2014 19:08:45 -0700 (PDT) Received: from localhost (static-50-53-65-80.bvtn.or.frontiernet.net. [50.53.65.80]) by mx.google.com with ESMTPSA id yw4sm1143156pbc.69.2014.08.25.19.08.44 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 25 Aug 2014 19:08:45 -0700 (PDT) Message-Id: <20140826020843.806847742@networkplumber.org> User-Agent: quilt/0.63-1 Date: Mon, 25 Aug 2014 19:07:50 -0700 From: Stephen Hemminger To: Ouyang Changchun References: <20140826020746.062748014@networkplumber.org> MIME-Version: 1.0 Content-Disposition: inline; filename=virtio-lsc.patch Cc: dev@dpdk.org, Stephen Hemminger Subject: [dpdk-dev] [RFC 04/10] 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: Tue, 26 Aug 2014 02:04:49 -0000 Virtio has link state interrupt which can be used. 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(-) --- a/lib/librte_pmd_virtio/virtio_ethdev.c 2014-08-25 19:00:06.342530488 -0700 +++ b/lib/librte_pmd_virtio/virtio_ethdev.c 2014-08-25 19:00:06.342530488 -0700 @@ -757,6 +757,34 @@ static int virtio_resource_init(struct r #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. */ @@ -886,6 +914,10 @@ eth_virtio_dev_init(__rte_unused struct 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; } @@ -893,7 +925,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), @@ -933,6 +965,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"); @@ -941,7 +976,11 @@ virtio_dev_configure(struct rte_eth_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; } @@ -949,7 +988,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); @@ -964,18 +1002,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 @@ -1057,6 +1099,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); } @@ -1073,6 +1116,7 @@ virtio_dev_link_update(struct rte_eth_de 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, @@ -1091,10 +1135,8 @@ virtio_dev_link_update(struct rte_eth_de 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 --- a/lib/librte_pmd_virtio/virtio_pci.c 2014-08-25 19:00:06.342530488 -0700 +++ b/lib/librte_pmd_virtio/virtio_pci.c 2014-08-25 19:00:06.342530488 -0700 @@ -127,3 +127,25 @@ vtpci_set_status(struct virtio_hw *hw, u 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; +} --- a/lib/librte_pmd_virtio/virtio_pci.h 2014-08-25 19:00:06.342530488 -0700 +++ b/lib/librte_pmd_virtio/virtio_pci.h 2014-08-25 19:00:06.342530488 -0700 @@ -263,4 +263,8 @@ void vtpci_write_dev_config(struct virti 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_ */