From: Ouyang Changchun Date: Mon, 9 Feb 2015 01:14:06 +0000 (+0800) Subject: virtio: use port IO to get PCI resource X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=da978dfdc43;p=dpdk.git virtio: use port IO to get PCI resource Make virtio not require UIO for some security reasons, this is to match 6WIND's virtio-net-pmd. Signed-off-by: Changchun Ouyang Acked-by: Huawei Xie --- diff --git a/lib/librte_pmd_virtio/Makefile b/lib/librte_pmd_virtio/Makefile index 793067f7a2..0baaf468c0 100644 --- a/lib/librte_pmd_virtio/Makefile +++ b/lib/librte_pmd_virtio/Makefile @@ -57,4 +57,6 @@ DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_net lib/librte_malloc +CFLAGS_virtio_ethdev.o += -Wno-cast-qual + include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c index 7556e117e2..9eb02171f8 100644 --- a/lib/librte_pmd_virtio/virtio_ethdev.c +++ b/lib/librte_pmd_virtio/virtio_ethdev.c @@ -38,6 +38,7 @@ #include #ifdef RTE_EXEC_ENV_LINUXAPP #include +#include #endif #include @@ -408,11 +409,13 @@ static void virtio_dev_close(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; + struct rte_pci_device *pci_dev = dev->pci_dev; PMD_INIT_LOG(DEBUG, "virtio_dev_close"); /* reset the NIC */ - vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); + if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) + vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); vtpci_reset(hw); hw->started = 0; virtio_dev_free_mbufs(dev); @@ -846,9 +849,9 @@ parse_sysfs_value(const char *filename, unsigned long *val) return 0; } -static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen) +static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen, + unsigned int *uio_num) { - unsigned int uio_num; struct dirent *e; DIR *dir; char dirname[PATH_MAX]; @@ -885,18 +888,18 @@ static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen) /* first try uio%d */ errno = 0; - uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10); + *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); + 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); + *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); + *uio_num); break; } } @@ -929,13 +932,16 @@ virtio_has_msix(const struct rte_pci_addr *loc) } /* Extract I/O port numbers from sysfs */ -static int virtio_resource_init(struct rte_pci_device *pci_dev) +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; + struct rte_pci_driver *pci_drv = + (struct rte_pci_driver *)pci_dev->driver; - if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname)) < 0) + if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname), &uio_num) < 0) return -1; /* get portio size */ @@ -960,8 +966,100 @@ static int virtio_resource_init(struct rte_pci_device *pci_dev) 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", + devname, strerror(errno)); + return -1; + } + + pci_dev->intr_handle.type = RTE_INTR_HANDLE_UIO; + pci_drv->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; + struct rte_pci_driver *pci_drv = + (struct rte_pci_driver *)pci_dev->driver; + + 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_drv->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) @@ -970,7 +1068,7 @@ virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) return 0; } -static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) +static int virtio_resource_init(struct rte_pci_device *pci_dev) { /* no setup required */ return 0; @@ -1125,7 +1223,8 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv, pci_dev->id.device_id); /* Setup interrupt callback */ - rte_intr_callback_register(&pci_dev->intr_handle, + if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) + rte_intr_callback_register(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); virtio_dev_cq_start(eth_dev); @@ -1137,7 +1236,6 @@ static struct eth_driver rte_virtio_pmd = { { .name = "rte_virtio_pmd", .id_table = pci_id_virtio_map, - .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_hw), @@ -1184,6 +1282,7 @@ virtio_dev_configure(struct rte_eth_dev *dev) { const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; struct virtio_hw *hw = dev->data->dev_private; + struct rte_pci_device *pci_dev = dev->pci_dev; PMD_INIT_LOG(DEBUG, "configure"); @@ -1201,10 +1300,11 @@ virtio_dev_configure(struct rte_eth_dev *dev) return -ENOTSUP; } - if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { - PMD_DRV_LOG(ERR, "failed to set config vector"); - return -EBUSY; - } + if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) + if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { + PMD_DRV_LOG(ERR, "failed to set config vector"); + return -EBUSY; + } return 0; } @@ -1215,9 +1315,11 @@ virtio_dev_start(struct rte_eth_dev *dev) { uint16_t nb_queues, i; struct virtio_hw *hw = dev->data->dev_private; + struct rte_pci_device *pci_dev = dev->pci_dev; /* check if lsc interrupt feature is enabled */ - if (dev->data->dev_conf.intr_conf.lsc) { + if ((dev->data->dev_conf.intr_conf.lsc) && + (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) { if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { PMD_DRV_LOG(ERR, "link status not supported by host"); return -ENOTSUP;