From patchwork Thu Jan 14 07:42:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yuanhan Liu X-Patchwork-Id: 9844 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 114418E8E; Thu, 14 Jan 2016 08:41:45 +0100 (CET) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 3D8938E6A for ; Thu, 14 Jan 2016 08:41:41 +0100 (CET) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga102.jf.intel.com with ESMTP; 13 Jan 2016 23:41:39 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,293,1449561600"; d="scan'208";a="633215271" Received: from yliu-dev.sh.intel.com ([10.239.66.49]) by FMSMGA003.fm.intel.com with ESMTP; 13 Jan 2016 23:41:38 -0800 From: Yuanhan Liu To: dev@dpdk.org Date: Thu, 14 Jan 2016 15:42:47 +0800 Message-Id: <1452757372-686-4-git-send-email-yuanhan.liu@linux.intel.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1452757372-686-1-git-send-email-yuanhan.liu@linux.intel.com> References: <1452581944-24838-1-git-send-email-yuanhan.liu@linux.intel.com> <1452757372-686-1-git-send-email-yuanhan.liu@linux.intel.com> Cc: "Michael S. Tsirkin" Subject: [dpdk-dev] [PATCH v3 3/8] virtio: move left pci stuff to virtio_pci.c 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" virtio_pci.c is a more proper place for pci stuff; virtio_ethdev.c is not. Signed-off-by: Yuanhan Liu --- drivers/net/virtio/virtio_ethdev.c | 265 +----------------------------------- drivers/net/virtio/virtio_pci.c | 270 ++++++++++++++++++++++++++++++++++++- 2 files changed, 270 insertions(+), 265 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 6c1d3a0..b57224d 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -36,10 +36,6 @@ #include #include #include -#ifdef RTE_EXEC_ENV_LINUXAPP -#include -#include -#endif #include #include @@ -955,260 +951,6 @@ virtio_negotiate_features(struct virtio_hw *hw) hw->guest_features); } -#ifdef RTE_EXEC_ENV_LINUXAPP -static int -parse_sysfs_value(const char *filename, unsigned long *val) -{ - FILE *f; - char buf[BUFSIZ]; - char *end = NULL; - - f = fopen(filename, "r"); - if (f == NULL) { - PMD_INIT_LOG(ERR, "%s(): cannot open sysfs value %s", - __func__, filename); - return -1; - } - - if (fgets(buf, sizeof(buf), f) == NULL) { - PMD_INIT_LOG(ERR, "%s(): cannot read sysfs value %s", - __func__, filename); - fclose(f); - return -1; - } - *val = strtoul(buf, &end, 0); - if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { - PMD_INIT_LOG(ERR, "%s(): cannot parse sysfs value %s", - __func__, filename); - fclose(f); - return -1; - } - fclose(f); - return 0; -} - -static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen, - unsigned int *uio_num) -{ - struct dirent *e; - DIR *dir; - char dirname[PATH_MAX]; - - /* depending on kernel version, uio can be located in uio/uioX - * or uio:uioX */ - snprintf(dirname, sizeof(dirname), - SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/uio", - loc->domain, loc->bus, loc->devid, loc->function); - dir = opendir(dirname); - if (dir == NULL) { - /* retry with the parent directory */ - snprintf(dirname, sizeof(dirname), - SYSFS_PCI_DEVICES "/" PCI_PRI_FMT, - loc->domain, loc->bus, loc->devid, loc->function); - dir = opendir(dirname); - - if (dir == NULL) { - PMD_INIT_LOG(ERR, "Cannot opendir %s", dirname); - return -1; - } - } - - /* take the first file starting with "uio" */ - while ((e = readdir(dir)) != NULL) { - /* format could be uio%d ...*/ - int shortprefix_len = sizeof("uio") - 1; - /* ... or uio:uio%d */ - int longprefix_len = sizeof("uio:uio") - 1; - char *endptr; - - if (strncmp(e->d_name, "uio", 3) != 0) - continue; - - /* first try uio%d */ - errno = 0; - *uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10); - if (errno == 0 && endptr != (e->d_name + shortprefix_len)) { - snprintf(buf, buflen, "%s/uio%u", dirname, *uio_num); - break; - } - - /* then try uio:uio%d */ - errno = 0; - *uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10); - if (errno == 0 && endptr != (e->d_name + longprefix_len)) { - snprintf(buf, buflen, "%s/uio:uio%u", dirname, - *uio_num); - break; - } - } - closedir(dir); - - /* No uio resource found */ - if (e == NULL) { - PMD_INIT_LOG(ERR, "Could not find uio resource"); - return -1; - } - - return 0; -} - -static int -virtio_has_msix(const struct rte_pci_addr *loc) -{ - DIR *d; - char dirname[PATH_MAX]; - - snprintf(dirname, sizeof(dirname), - SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/msi_irqs", - loc->domain, loc->bus, loc->devid, loc->function); - - d = opendir(dirname); - if (d) - closedir(d); - - return (d != NULL); -} - -/* Extract I/O port numbers from sysfs */ -static int virtio_resource_init_by_uio(struct rte_pci_device *pci_dev) -{ - char dirname[PATH_MAX]; - char filename[PATH_MAX]; - unsigned long start, size; - unsigned int uio_num; - - if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname), &uio_num) < 0) - return -1; - - /* get portio size */ - snprintf(filename, sizeof(filename), - "%s/portio/port0/size", dirname); - if (parse_sysfs_value(filename, &size) < 0) { - PMD_INIT_LOG(ERR, "%s(): cannot parse size", - __func__); - return -1; - } - - /* get portio start */ - snprintf(filename, sizeof(filename), - "%s/portio/port0/start", dirname); - if (parse_sysfs_value(filename, &start) < 0) { - PMD_INIT_LOG(ERR, "%s(): cannot parse portio start", - __func__); - return -1; - } - pci_dev->mem_resource[0].addr = (void *)(uintptr_t)start; - pci_dev->mem_resource[0].len = (uint64_t)size; - PMD_INIT_LOG(DEBUG, - "PCI Port IO found start=0x%lx with size=0x%lx", - start, size); - - /* save fd */ - memset(dirname, 0, sizeof(dirname)); - snprintf(dirname, sizeof(dirname), "/dev/uio%u", uio_num); - pci_dev->intr_handle.fd = open(dirname, O_RDWR); - if (pci_dev->intr_handle.fd < 0) { - PMD_INIT_LOG(ERR, "Cannot open %s: %s\n", - dirname, strerror(errno)); - return -1; - } - - pci_dev->intr_handle.type = RTE_INTR_HANDLE_UIO; - pci_dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC; - - return 0; -} - -/* Extract port I/O numbers from proc/ioports */ -static int virtio_resource_init_by_ioports(struct rte_pci_device *pci_dev) -{ - uint16_t start, end; - int size; - FILE *fp; - char *line = NULL; - char pci_id[16]; - int found = 0; - size_t linesz; - - snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, - pci_dev->addr.domain, - pci_dev->addr.bus, - pci_dev->addr.devid, - pci_dev->addr.function); - - fp = fopen("/proc/ioports", "r"); - if (fp == NULL) { - PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); - return -1; - } - - while (getdelim(&line, &linesz, '\n', fp) > 0) { - char *ptr = line; - char *left; - int n; - - n = strcspn(ptr, ":"); - ptr[n] = 0; - left = &ptr[n+1]; - - while (*left && isspace(*left)) - left++; - - if (!strncmp(left, pci_id, strlen(pci_id))) { - found = 1; - - while (*ptr && isspace(*ptr)) - ptr++; - - sscanf(ptr, "%04hx-%04hx", &start, &end); - size = end - start + 1; - - break; - } - } - - free(line); - fclose(fp); - - if (!found) - return -1; - - pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_t)start; - pci_dev->mem_resource[0].len = (uint64_t)size; - PMD_INIT_LOG(DEBUG, - "PCI Port IO found start=0x%x with size=0x%x", - start, size); - - /* can't support lsc interrupt without uio */ - pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; - - return 0; -} - -/* Extract I/O port numbers from sysfs */ -static int virtio_resource_init(struct rte_pci_device *pci_dev) -{ - if (virtio_resource_init_by_uio(pci_dev) == 0) - return 0; - else - return virtio_resource_init_by_ioports(pci_dev); -} - -#else -static int -virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) -{ - /* nic_uio does not enable interrupts, return 0 (false). */ - return 0; -} - -static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) -{ - /* no setup required */ - return 0; -} -#endif - /* * Process Virtio Config changed interrupt and call the callback * if link state changed. @@ -1279,14 +1021,9 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) pci_dev = eth_dev->pci_dev; - vtpci_init(pci_dev, hw); - - if (virtio_resource_init(pci_dev) < 0) + if (vtpci_init(pci_dev, hw) < 0) return -1; - hw->use_msix = virtio_has_msix(&pci_dev->addr); - hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr; - /* Reset the device although not necessary at startup */ vtpci_reset(hw); diff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c index 9930efa..03d623b 100644 --- a/drivers/net/virtio/virtio_pci.c +++ b/drivers/net/virtio/virtio_pci.c @@ -32,6 +32,11 @@ */ #include +#ifdef RTE_EXEC_ENV_LINUXAPP + #include + #include +#endif + #include "virtio_pci.h" #include "virtio_logs.h" #include "virtqueue.h" @@ -156,6 +161,264 @@ legacy_notify_queue(struct virtio_hw *hw, struct virtqueue *vq) VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_NOTIFY, vq->vq_queue_index); } +#ifdef RTE_EXEC_ENV_LINUXAPP +static int +parse_sysfs_value(const char *filename, unsigned long *val) +{ + FILE *f; + char buf[BUFSIZ]; + char *end = NULL; + + f = fopen(filename, "r"); + if (f == NULL) { + PMD_INIT_LOG(ERR, "%s(): cannot open sysfs value %s", + __func__, filename); + return -1; + } + + if (fgets(buf, sizeof(buf), f) == NULL) { + PMD_INIT_LOG(ERR, "%s(): cannot read sysfs value %s", + __func__, filename); + fclose(f); + return -1; + } + *val = strtoul(buf, &end, 0); + if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { + PMD_INIT_LOG(ERR, "%s(): cannot parse sysfs value %s", + __func__, filename); + fclose(f); + return -1; + } + fclose(f); + return 0; +} + +static int +get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen, + unsigned int *uio_num) +{ + struct dirent *e; + DIR *dir; + char dirname[PATH_MAX]; + + /* depending on kernel version, uio can be located in uio/uioX + * or uio:uioX */ + snprintf(dirname, sizeof(dirname), + SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/uio", + loc->domain, loc->bus, loc->devid, loc->function); + dir = opendir(dirname); + if (dir == NULL) { + /* retry with the parent directory */ + snprintf(dirname, sizeof(dirname), + SYSFS_PCI_DEVICES "/" PCI_PRI_FMT, + loc->domain, loc->bus, loc->devid, loc->function); + dir = opendir(dirname); + + if (dir == NULL) { + PMD_INIT_LOG(ERR, "Cannot opendir %s", dirname); + return -1; + } + } + + /* take the first file starting with "uio" */ + while ((e = readdir(dir)) != NULL) { + /* format could be uio%d ...*/ + int shortprefix_len = sizeof("uio") - 1; + /* ... or uio:uio%d */ + int longprefix_len = sizeof("uio:uio") - 1; + char *endptr; + + if (strncmp(e->d_name, "uio", 3) != 0) + continue; + + /* first try uio%d */ + errno = 0; + *uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10); + if (errno == 0 && endptr != (e->d_name + shortprefix_len)) { + snprintf(buf, buflen, "%s/uio%u", dirname, *uio_num); + break; + } + + /* then try uio:uio%d */ + errno = 0; + *uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10); + if (errno == 0 && endptr != (e->d_name + longprefix_len)) { + snprintf(buf, buflen, "%s/uio:uio%u", dirname, + *uio_num); + break; + } + } + closedir(dir); + + /* No uio resource found */ + if (e == NULL) { + PMD_INIT_LOG(ERR, "Could not find uio resource"); + return -1; + } + + return 0; +} + +static int +legacy_virtio_has_msix(const struct rte_pci_addr *loc) +{ + DIR *d; + char dirname[PATH_MAX]; + + snprintf(dirname, sizeof(dirname), + SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/msi_irqs", + loc->domain, loc->bus, loc->devid, loc->function); + + d = opendir(dirname); + if (d) + closedir(d); + + return (d != NULL); +} + +/* Extract I/O port numbers from sysfs */ +static int +virtio_resource_init_by_uio(struct rte_pci_device *pci_dev) +{ + char dirname[PATH_MAX]; + char filename[PATH_MAX]; + unsigned long start, size; + unsigned int uio_num; + + if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname), &uio_num) < 0) + return -1; + + /* get portio size */ + snprintf(filename, sizeof(filename), + "%s/portio/port0/size", dirname); + if (parse_sysfs_value(filename, &size) < 0) { + PMD_INIT_LOG(ERR, "%s(): cannot parse size", + __func__); + return -1; + } + + /* get portio start */ + snprintf(filename, sizeof(filename), + "%s/portio/port0/start", dirname); + if (parse_sysfs_value(filename, &start) < 0) { + PMD_INIT_LOG(ERR, "%s(): cannot parse portio start", + __func__); + return -1; + } + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)start; + pci_dev->mem_resource[0].len = (uint64_t)size; + PMD_INIT_LOG(DEBUG, + "PCI Port IO found start=0x%lx with size=0x%lx", + start, size); + + /* save fd */ + memset(dirname, 0, sizeof(dirname)); + snprintf(dirname, sizeof(dirname), "/dev/uio%u", uio_num); + pci_dev->intr_handle.fd = open(dirname, O_RDWR); + if (pci_dev->intr_handle.fd < 0) { + PMD_INIT_LOG(ERR, "Cannot open %s: %s\n", + dirname, strerror(errno)); + return -1; + } + + pci_dev->intr_handle.type = RTE_INTR_HANDLE_UIO; + pci_dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC; + + return 0; +} + +/* Extract port I/O numbers from proc/ioports */ +static int +virtio_resource_init_by_ioports(struct rte_pci_device *pci_dev) +{ + uint16_t start, end; + int size; + FILE *fp; + char *line = NULL; + char pci_id[16]; + int found = 0; + size_t linesz; + + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, + pci_dev->addr.domain, + pci_dev->addr.bus, + pci_dev->addr.devid, + pci_dev->addr.function); + + fp = fopen("/proc/ioports", "r"); + if (fp == NULL) { + PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); + return -1; + } + + while (getdelim(&line, &linesz, '\n', fp) > 0) { + char *ptr = line; + char *left; + int n; + + n = strcspn(ptr, ":"); + ptr[n] = 0; + left = &ptr[n+1]; + + while (*left && isspace(*left)) + left++; + + if (!strncmp(left, pci_id, strlen(pci_id))) { + found = 1; + + while (*ptr && isspace(*ptr)) + ptr++; + + sscanf(ptr, "%04hx-%04hx", &start, &end); + size = end - start + 1; + + break; + } + } + + free(line); + fclose(fp); + + if (!found) + return -1; + + pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_t)start; + pci_dev->mem_resource[0].len = (uint64_t)size; + PMD_INIT_LOG(DEBUG, + "PCI Port IO found start=0x%x with size=0x%x", + start, size); + + /* can't support lsc interrupt without uio */ + pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; + + return 0; +} + +/* Extract I/O port numbers from sysfs */ +static int +legacy_virtio_resource_init(struct rte_pci_device *pci_dev) +{ + if (virtio_resource_init_by_uio(pci_dev) == 0) + return 0; + else + return virtio_resource_init_by_ioports(pci_dev); +} + +#else +static int +legayc_virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) +{ + /* nic_uio does not enable interrupts, return 0 (false). */ + return 0; +} + +static int +legacy_virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) +{ + /* no setup required */ + return 0; +} +#endif static const struct virtio_pci_ops legacy_ops = { .read_dev_cfg = legacy_read_dev_config, @@ -241,9 +504,14 @@ vtpci_irq_config(struct virtio_hw *hw, uint16_t vec) } int -vtpci_init(struct rte_pci_device *dev __rte_unused, struct virtio_hw *hw) +vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw) { hw->vtpci_ops = &legacy_ops; + if (legacy_virtio_resource_init(dev) < 0) + return -1; + hw->use_msix = legacy_virtio_has_msix(&dev->addr); + hw->io_base = (uint32_t)(uintptr_t)dev->mem_resource[0].addr; + return 0; }