From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 0AA1E8D97 for ; Sun, 10 Jan 2016 19:43:23 +0100 (CET) Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP; 10 Jan 2016 10:43:23 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,548,1444719600"; d="scan'208";a="26927906" Received: from dpdk06.sh.intel.com ([10.239.128.225]) by fmsmga004.fm.intel.com with ESMTP; 10 Jan 2016 10:43:21 -0800 From: Jianfeng Tan To: dev@dpdk.org Date: Sun, 10 Jan 2016 19:43:02 +0800 Message-Id: <1452426182-86851-5-git-send-email-jianfeng.tan@intel.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1452426182-86851-1-git-send-email-jianfeng.tan@intel.com> References: <1446748276-132087-1-git-send-email-jianfeng.tan@intel.com> <1452426182-86851-1-git-send-email-jianfeng.tan@intel.com> Cc: nakajima.yoshihiro@lab.ntt.co.jp, mst@redhat.com, ann.zhuangyanying@huawei.com Subject: [dpdk-dev] [PATCH 4/4] virtio/vdev: add a new vdev named eth_cvio 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: Sun, 10 Jan 2016 18:43:25 -0000 Add a new virtual device named eth_cvio, it can be used just like eth_ring, eth_null, etc. Configured parameters include: - rx (optional, 1 by default): number of rx, only allowed to be 1 for now. - tx (optional, 1 by default): number of tx, only allowed to be 1 for now. - cq (optional, 0 by default): if ctrl queue is enabled, not supported for now. - mac (optional): mac address, random value will be given if not specified. - queue_num (optional, 256 by default): size of virtqueue. - path (madatory): path of vhost, depends on the file type: vhost-user is used if the given path points to a unix socket; vhost-net is used if the given path points to a char device. The major difference with original virtio for vm is that, here we use virtual address instead of physical address for vhost to calculate relative address. When enable CONFIG_RTE_VIRTIO_VDEV (enabled by default), the compiled library can be used in both VM and container environment. Examples: a. Use vhost-net as a backend sudo numactl -N 1 -m 1 ./examples/l2fwd/build/l2fwd -c 0x100000 -n 4 \ -m 1024 --no-pci --single-file --file-prefix=l2fwd \ --vdev=eth_cvio0,mac=00:01:02:03:04:05,path=/dev/vhost-net \ -- -p 0x1 b. Use vhost-user as a backend numactl -N 1 -m 1 ./examples/l2fwd/build/l2fwd -c 0x100000 -n 4 -m 1024 \ --no-pci --single-file --file-prefix=l2fwd \ --vdev=eth_cvio0,mac=00:01:02:03:04:05,path= \ -- -p 0x1 Signed-off-by: Huawei Xie Signed-off-by: Jianfeng Tan --- drivers/net/virtio/virtio_ethdev.c | 338 +++++++++++++++++++++++++------- drivers/net/virtio/virtio_ethdev.h | 1 + drivers/net/virtio/virtio_pci.h | 24 +-- drivers/net/virtio/virtio_rxtx.c | 11 +- drivers/net/virtio/virtio_rxtx_simple.c | 14 +- drivers/net/virtio/virtqueue.h | 13 +- 6 files changed, 302 insertions(+), 99 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index d928339..6e46060 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -56,6 +56,7 @@ #include #include #include +#include #include "virtio_ethdev.h" #include "virtio_pci.h" @@ -174,14 +175,14 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, * One RX packet for ACK. */ vq->vq_ring.desc[head].flags = VRING_DESC_F_NEXT; - vq->vq_ring.desc[head].addr = vq->virtio_net_hdr_mz->phys_addr; + vq->vq_ring.desc[head].addr = vq->virtio_net_hdr_mem; vq->vq_ring.desc[head].len = sizeof(struct virtio_net_ctrl_hdr); vq->vq_free_cnt--; i = vq->vq_ring.desc[head].next; for (k = 0; k < pkt_num; k++) { vq->vq_ring.desc[i].flags = VRING_DESC_F_NEXT; - vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mz->phys_addr + vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mem + sizeof(struct virtio_net_ctrl_hdr) + sizeof(ctrl->status) + sizeof(uint8_t)*sum; vq->vq_ring.desc[i].len = dlen[k]; @@ -191,7 +192,7 @@ virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, } vq->vq_ring.desc[i].flags = VRING_DESC_F_WRITE; - vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mz->phys_addr + vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mem + sizeof(struct virtio_net_ctrl_hdr); vq->vq_ring.desc[i].len = sizeof(ctrl->status); vq->vq_free_cnt--; @@ -374,68 +375,85 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, } } - /* - * Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit, - * and only accepts 32 bit page frame number. - * Check if the allocated physical memory exceeds 16TB. - */ - if ((mz->phys_addr + vq->vq_ring_size - 1) >> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) { - PMD_INIT_LOG(ERR, "vring address shouldn't be above 16TB!"); - rte_free(vq); - return -ENOMEM; - } - memset(mz->addr, 0, sizeof(mz->len)); vq->mz = mz; - vq->vq_ring_mem = mz->phys_addr; vq->vq_ring_virt_mem = mz->addr; - PMD_INIT_LOG(DEBUG, "vq->vq_ring_mem: 0x%"PRIx64, (uint64_t)mz->phys_addr); - PMD_INIT_LOG(DEBUG, "vq->vq_ring_virt_mem: 0x%"PRIx64, (uint64_t)(uintptr_t)mz->addr); + + if (dev->dev_type == RTE_ETH_DEV_PCI) { + vq->vq_ring_mem = mz->phys_addr; + + /* Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit, + * and only accepts 32 bit page frame number. + * Check if the allocated physical memory exceeds 16TB. + */ + uint64_t last_physaddr = vq->vq_ring_mem + vq->vq_ring_size - 1; + if (last_physaddr >> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) { + PMD_INIT_LOG(ERR, "vring address shouldn't be above 16TB!"); + rte_free(vq); + return -ENOMEM; + } + } +#ifdef RTE_VIRTIO_VDEV + else + vq->vq_ring_mem = (phys_addr_t)mz->addr; /* Use vaddr!!! */ +#endif + + PMD_INIT_LOG(DEBUG, "vq->vq_ring_mem: 0x%"PRIx64, + (uint64_t)vq->vq_ring_mem); + PMD_INIT_LOG(DEBUG, "vq->vq_ring_virt_mem: 0x%"PRIx64, + (uint64_t)(uintptr_t)vq->vq_ring_virt_mem); vq->virtio_net_hdr_mz = NULL; vq->virtio_net_hdr_mem = 0; + uint64_t hdr_size = 0; if (queue_type == VTNET_TQ) { /* * For each xmit packet, allocate a virtio_net_hdr */ snprintf(vq_name, sizeof(vq_name), "port%d_tvq%d_hdrzone", dev->data->port_id, queue_idx); - vq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name, - vq_size * hw->vtnet_hdr_size, - socket_id, 0, RTE_CACHE_LINE_SIZE); - if (vq->virtio_net_hdr_mz == NULL) { - if (rte_errno == EEXIST) - vq->virtio_net_hdr_mz = - rte_memzone_lookup(vq_name); - if (vq->virtio_net_hdr_mz == NULL) { - rte_free(vq); - return -ENOMEM; - } - } - vq->virtio_net_hdr_mem = - vq->virtio_net_hdr_mz->phys_addr; - memset(vq->virtio_net_hdr_mz->addr, 0, - vq_size * hw->vtnet_hdr_size); + hdr_size = vq_size * hw->vtnet_hdr_size; } else if (queue_type == VTNET_CQ) { /* Allocate a page for control vq command, data and status */ snprintf(vq_name, sizeof(vq_name), "port%d_cvq_hdrzone", dev->data->port_id); - vq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name, - PAGE_SIZE, socket_id, 0, RTE_CACHE_LINE_SIZE); - if (vq->virtio_net_hdr_mz == NULL) { + hdr_size = PAGE_SIZE; + } + + if (hdr_size) { /* queue_type is VTNET_TQ or VTNET_CQ */ + mz = rte_memzone_reserve_aligned(vq_name, + hdr_size, socket_id, 0, RTE_CACHE_LINE_SIZE); + if (mz == NULL) { if (rte_errno == EEXIST) - vq->virtio_net_hdr_mz = - rte_memzone_lookup(vq_name); - if (vq->virtio_net_hdr_mz == NULL) { + mz = rte_memzone_lookup(vq_name); + if (mz == NULL) { rte_free(vq); return -ENOMEM; } } - vq->virtio_net_hdr_mem = - vq->virtio_net_hdr_mz->phys_addr; - memset(vq->virtio_net_hdr_mz->addr, 0, PAGE_SIZE); + vq->virtio_net_hdr_mz = mz; + vq->virtio_net_hdr_vaddr = mz->addr; + memset(vq->virtio_net_hdr_vaddr, 0, hdr_size); + + if (dev->dev_type == RTE_ETH_DEV_PCI) + vq->virtio_net_hdr_mem = mz->phys_addr; +#ifdef RTE_VIRTIO_VDEV + else + vq->virtio_net_hdr_mem = (phys_addr_t)mz->addr; /* Use vaddr!!! */ +#endif } + struct rte_mbuf *m = NULL; + if (dev->dev_type == RTE_ETH_DEV_PCI) + vq->offset = (uintptr_t)&m->buf_addr; +#ifdef RTE_VIRTIO_VDEV + else { + vq->offset = (uintptr_t)&m->buf_physaddr; +#if (RTE_BYTE_ORDER == RTE_BIG_ENDIAN) && (__WORDSIZE == 32) + vq->offset += 4; +#endif + } +#endif /* * Set guest physical address of the virtqueue * in VIRTIO_PCI_QUEUE_PFN config register of device @@ -491,8 +509,10 @@ virtio_dev_close(struct rte_eth_dev *dev) PMD_INIT_LOG(DEBUG, "virtio_dev_close"); /* reset the NIC */ - if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) - vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); + if (dev->dev_type == RTE_ETH_DEV_PCI) { + 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); @@ -1233,8 +1253,9 @@ virtio_interrupt_handler(__rte_unused struct rte_intr_handle *handle, 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 (dev->dev_type == RTE_ETH_DEV_PCI) + 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) @@ -1287,11 +1308,18 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) pci_dev = eth_dev->pci_dev; - if (virtio_resource_init(pci_dev) < 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; + if (eth_dev->dev_type == RTE_ETH_DEV_PCI) { + if (virtio_resource_init(pci_dev) < 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; + } +#ifdef RTE_VIRTIO_VDEV + else { + hw->use_msix = 0; + hw->io_base = VIRTIO_VDEV_IO_BASE; + } +#endif /* Reset the device although not necessary at startup */ vtpci_reset(hw); @@ -1304,10 +1332,12 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) virtio_negotiate_features(hw); /* If host does not support status then disable LSC */ - if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) - pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; + if (eth_dev->dev_type == RTE_ETH_DEV_PCI) { + if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) + pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; - rte_eth_copy_pci_info(eth_dev, pci_dev); + rte_eth_copy_pci_info(eth_dev, pci_dev); + } rx_func_get(eth_dev); @@ -1383,15 +1413,16 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) PMD_INIT_LOG(DEBUG, "hw->max_rx_queues=%d hw->max_tx_queues=%d", hw->max_rx_queues, hw->max_tx_queues); - 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 */ - if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) - rte_intr_callback_register(&pci_dev->intr_handle, - virtio_interrupt_handler, eth_dev); - + if (eth_dev->dev_type == RTE_ETH_DEV_PCI) { + 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 */ + 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); return 0; @@ -1424,10 +1455,12 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev) eth_dev->data->mac_addrs = NULL; /* reset interrupt callback */ - if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) - rte_intr_callback_unregister(&pci_dev->intr_handle, - virtio_interrupt_handler, - eth_dev); + if (eth_dev->dev_type == RTE_ETH_DEV_PCI) { + if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) + rte_intr_callback_unregister(&pci_dev->intr_handle, + virtio_interrupt_handler, + eth_dev); + } PMD_INIT_LOG(DEBUG, "dev_uninit completed"); @@ -1491,11 +1524,13 @@ virtio_dev_configure(struct rte_eth_dev *dev) return -ENOTSUP; } - 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; - } + if (dev->dev_type == RTE_ETH_DEV_PCI) { + 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; } @@ -1689,3 +1724,162 @@ static struct rte_driver rte_virtio_driver = { }; PMD_REGISTER_DRIVER(rte_virtio_driver); + +#ifdef RTE_VIRTIO_VDEV + +static const char *valid_args[] = { +#define ETH_CVIO_ARG_RX_NUM "rx" + ETH_CVIO_ARG_RX_NUM, +#define ETH_CVIO_ARG_TX_NUM "tx" + ETH_CVIO_ARG_TX_NUM, +#define ETH_CVIO_ARG_CQ_NUM "cq" + ETH_CVIO_ARG_CQ_NUM, +#define ETH_CVIO_ARG_MAC "mac" + ETH_CVIO_ARG_MAC, +#define ETH_CVIO_ARG_PATH "path" + ETH_CVIO_ARG_PATH, +#define ETH_CVIO_ARG_QUEUE_SIZE "queue_num" + ETH_CVIO_ARG_QUEUE_SIZE, + NULL +}; + +static int +get_string_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + if ((value == NULL) || (extra_args == NULL)) + return -EINVAL; + + strcpy(extra_args, value); + + return 0; +} + +static int +get_integer_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + uint64_t *p_u64 = extra_args; + + if ((value == NULL) || (extra_args == NULL)) + return -EINVAL; + + *p_u64 = (uint64_t)strtoull(value, NULL, 0); + + return 0; +} + +static struct rte_eth_dev * +cvio_eth_dev_alloc(const char *name) +{ + struct rte_eth_dev *eth_dev; + struct rte_eth_dev_data *data; + struct virtio_hw *hw; + + eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); + if (eth_dev == NULL) + rte_panic("cannot alloc rte_eth_dev\n"); + + data = eth_dev->data; + + hw = rte_zmalloc(NULL, sizeof(*hw), 0); + if (!hw) + rte_panic("malloc virtio_hw failed\n"); + + data->dev_private = hw; + data->numa_node = SOCKET_ID_ANY; + eth_dev->pci_dev = NULL; + /* will be used in virtio_dev_info_get() */ + eth_dev->driver = &rte_virtio_pmd; + /* TODO: eth_dev->link_intr_cbs */ + return eth_dev; +} + +#define CVIO_DEF_CQ_EN 0 +#define CVIO_DEF_Q_NUM 1 +#define CVIO_DEF_Q_SZ 256 +/* + * Dev initialization routine. Invoked once for each virtio vdev at + * EAL init time, see rte_eal_dev_init(). + * Returns 0 on success. + */ +static int +rte_cvio_pmd_devinit(const char *name, const char *params) +{ + struct rte_kvargs *kvlist = NULL; + struct rte_eth_dev *eth_dev = NULL; + uint64_t nb_rx = CVIO_DEF_Q_NUM; + uint64_t nb_tx = CVIO_DEF_Q_NUM; + uint64_t nb_cq = CVIO_DEF_CQ_EN; + uint64_t queue_num = CVIO_DEF_Q_SZ; + char sock_path[256]; + char mac_addr[32]; + int flag_mac = 0; + + if (params == NULL || params[0] == '\0') + rte_panic("arg %s is mandatory for eth_cvio\n", + ETH_CVIO_ARG_QUEUE_SIZE); + + kvlist = rte_kvargs_parse(params, valid_args); + if (!kvlist) + rte_panic("error when parsing param\n"); + + if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_PATH) == 1) + rte_kvargs_process(kvlist, ETH_CVIO_ARG_PATH, + &get_string_arg, sock_path); + else + rte_panic("arg %s is mandatory for eth_cvio\n", + ETH_CVIO_ARG_QUEUE_SIZE); + + if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_MAC) == 1) { + rte_kvargs_process(kvlist, ETH_CVIO_ARG_MAC, + &get_string_arg, mac_addr); + flag_mac = 1; + } + + if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_QUEUE_SIZE) == 1) + rte_kvargs_process(kvlist, ETH_CVIO_ARG_QUEUE_SIZE, + &get_integer_arg, &queue_num); + + if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_RX_NUM) == 1) + rte_kvargs_process(kvlist, ETH_CVIO_ARG_RX_NUM, + &get_integer_arg, &nb_rx); + + if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_TX_NUM) == 1) + rte_kvargs_process(kvlist, ETH_CVIO_ARG_TX_NUM, + &get_integer_arg, &nb_tx); + + if (rte_kvargs_count(kvlist, ETH_CVIO_ARG_CQ_NUM) == 1) + rte_kvargs_process(kvlist, ETH_CVIO_ARG_CQ_NUM, + &get_integer_arg, &nb_cq); + + eth_dev = cvio_eth_dev_alloc(name); + + virtio_vdev_init(eth_dev->data, sock_path, + nb_rx, nb_tx, nb_cq, queue_num, + (flag_mac) ? mac_addr : NULL); + + /* originally, this will be called in rte_eal_pci_probe() */ + eth_virtio_dev_init(eth_dev); + + return 0; +} + +static int +rte_cvio_pmd_devuninit(const char *name) +{ + /* TODO: if it's last one, memory init, free memory */ + rte_panic("%s: %s", __func__, name); + return 0; +} + +static struct rte_driver rte_cvio_driver = { + .name = "eth_cvio", + .type = PMD_VDEV, + .init = rte_cvio_pmd_devinit, + .uninit = rte_cvio_pmd_devuninit, +}; + +PMD_REGISTER_DRIVER(rte_cvio_driver); + +#endif diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index 9e1ecb3..90890b4 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -126,4 +126,5 @@ uint16_t virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, void virtio_vdev_init(struct rte_eth_dev_data *data, const char *path, int nb_rx, int nb_tx, int nb_cq, int queue_num, char *mac); #endif + #endif /* _VIRTIO_ETHDEV_H_ */ diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h index af05ae2..d79bd05 100644 --- a/drivers/net/virtio/virtio_pci.h +++ b/drivers/net/virtio/virtio_pci.h @@ -249,31 +249,31 @@ uint32_t virtio_ioport_read(struct virtio_hw *, uint64_t); void virtio_ioport_write(struct virtio_hw *, uint64_t, uint32_t); #define VIRTIO_READ_REG_1(hw, reg) \ - (hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ + ((hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ inb((VIRTIO_PCI_REG_ADDR((hw), (reg)))) \ - :virtio_ioport_read(hw, reg) + :virtio_ioport_read(hw, reg)) #define VIRTIO_WRITE_REG_1(hw, reg, value) \ - (hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ + ((hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ outb_p((unsigned char)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) \ - :virtio_ioport_write(hw, reg, value) + :virtio_ioport_write(hw, reg, value)) #define VIRTIO_READ_REG_2(hw, reg) \ - (hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ + ((hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ inw((VIRTIO_PCI_REG_ADDR((hw), (reg)))) \ - :virtio_ioport_read(hw, reg) + :virtio_ioport_read(hw, reg)) #define VIRTIO_WRITE_REG_2(hw, reg, value) \ - (hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ + ((hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ outw_p((unsigned short)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) \ - :virtio_ioport_write(hw, reg, value) + :virtio_ioport_write(hw, reg, value)) #define VIRTIO_READ_REG_4(hw, reg) \ - (hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ + ((hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ inl((VIRTIO_PCI_REG_ADDR((hw), (reg)))) \ - :virtio_ioport_read(hw, reg) + :virtio_ioport_read(hw, reg)) #define VIRTIO_WRITE_REG_4(hw, reg, value) \ - (hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ + ((hw->io_base != VIRTIO_VDEV_IO_BASE) ? \ outl_p((unsigned int)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) \ - :virtio_ioport_write(hw, reg, value) + :virtio_ioport_write(hw, reg, value)) #else /* RTE_VIRTIO_VDEV */ diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 74b39ef..dd07ba7 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -191,8 +191,7 @@ virtqueue_enqueue_recv_refill(struct virtqueue *vq, struct rte_mbuf *cookie) start_dp = vq->vq_ring.desc; start_dp[idx].addr = - (uint64_t)(cookie->buf_physaddr + RTE_PKTMBUF_HEADROOM - - hw->vtnet_hdr_size); + RTE_MBUF_DATA_DMA_ADDR(cookie, vq->offset) - hw->vtnet_hdr_size; start_dp[idx].len = cookie->buf_len - RTE_PKTMBUF_HEADROOM + hw->vtnet_hdr_size; start_dp[idx].flags = VRING_DESC_F_WRITE; @@ -237,7 +236,7 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie) for (; ((seg_num > 0) && (cookie != NULL)); seg_num--) { idx = start_dp[idx].next; - start_dp[idx].addr = RTE_MBUF_DATA_DMA_ADDR(cookie); + start_dp[idx].addr = RTE_MBUF_DATA_DMA_ADDR(cookie, txvq->offset); start_dp[idx].len = cookie->data_len; start_dp[idx].flags = VRING_DESC_F_NEXT; cookie = cookie->next; @@ -343,7 +342,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) VIRTIO_WRITE_REG_2(vq->hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); VIRTIO_WRITE_REG_4(vq->hw, VIRTIO_PCI_QUEUE_PFN, - vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + vq->vq_ring_mem >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } else if (queue_type == VTNET_TQ) { if (use_simple_rxtx) { int mid_idx = vq->vq_nentries >> 1; @@ -366,12 +365,12 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) VIRTIO_WRITE_REG_2(vq->hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); VIRTIO_WRITE_REG_4(vq->hw, VIRTIO_PCI_QUEUE_PFN, - vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + vq->vq_ring_mem >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } else { VIRTIO_WRITE_REG_2(vq->hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); VIRTIO_WRITE_REG_4(vq->hw, VIRTIO_PCI_QUEUE_PFN, - vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + vq->vq_ring_mem >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } } diff --git a/drivers/net/virtio/virtio_rxtx_simple.c b/drivers/net/virtio/virtio_rxtx_simple.c index ff3c11a..3a14a4e 100644 --- a/drivers/net/virtio/virtio_rxtx_simple.c +++ b/drivers/net/virtio/virtio_rxtx_simple.c @@ -80,8 +80,8 @@ virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, vq->sw_ring[desc_idx] = cookie; start_dp = vq->vq_ring.desc; - start_dp[desc_idx].addr = (uint64_t)((uintptr_t)cookie->buf_physaddr + - RTE_PKTMBUF_HEADROOM - sizeof(struct virtio_net_hdr)); + start_dp[desc_idx].addr = RTE_MBUF_DATA_DMA_ADDR(cookie, vq->offset) + - sizeof(struct virtio_net_hdr); start_dp[desc_idx].len = cookie->buf_len - RTE_PKTMBUF_HEADROOM + sizeof(struct virtio_net_hdr); @@ -118,9 +118,8 @@ virtio_rxq_rearm_vec(struct virtqueue *rxvq) p = (uintptr_t)&sw_ring[i]->rearm_data; *(uint64_t *)p = rxvq->mbuf_initializer; - start_dp[i].addr = - (uint64_t)((uintptr_t)sw_ring[i]->buf_physaddr + - RTE_PKTMBUF_HEADROOM - sizeof(struct virtio_net_hdr)); + start_dp[i].addr = RTE_MBUF_DATA_DMA_ADDR(sw_ring[i], rxvq->offset) + - sizeof(struct virtio_net_hdr); start_dp[i].len = sw_ring[i]->buf_len - RTE_PKTMBUF_HEADROOM + sizeof(struct virtio_net_hdr); } @@ -366,7 +365,7 @@ virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, txvq->vq_descx[desc_idx + i].cookie = tx_pkts[i]; for (i = 0; i < nb_tail; i++) { start_dp[desc_idx].addr = - RTE_MBUF_DATA_DMA_ADDR(*tx_pkts); + RTE_MBUF_DATA_DMA_ADDR(*tx_pkts, txvq->offset); start_dp[desc_idx].len = (*tx_pkts)->pkt_len; tx_pkts++; desc_idx++; @@ -377,7 +376,8 @@ virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, for (i = 0; i < nb_commit; i++) txvq->vq_descx[desc_idx + i].cookie = tx_pkts[i]; for (i = 0; i < nb_commit; i++) { - start_dp[desc_idx].addr = RTE_MBUF_DATA_DMA_ADDR(*tx_pkts); + start_dp[desc_idx].addr = RTE_MBUF_DATA_DMA_ADDR(*tx_pkts, + txvq->offset); start_dp[desc_idx].len = (*tx_pkts)->pkt_len; tx_pkts++; desc_idx++; diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h index 61b3137..dc0b656 100644 --- a/drivers/net/virtio/virtqueue.h +++ b/drivers/net/virtio/virtqueue.h @@ -66,8 +66,14 @@ struct rte_mbuf; #define VIRTQUEUE_MAX_NAME_SZ 32 -#define RTE_MBUF_DATA_DMA_ADDR(mb) \ +#ifdef RTE_VIRTIO_VDEV +#define RTE_MBUF_DATA_DMA_ADDR(mb, offset) \ + (uint64_t)((uintptr_t)(*(void **)((uintptr_t)mb + offset)) \ + + (mb)->data_off) +#else +#define RTE_MBUF_DATA_DMA_ADDR(mb, offset) \ (uint64_t) ((mb)->buf_physaddr + (mb)->data_off) +#endif /* RTE_VIRTIO_VDEV */ #define VTNET_SQ_RQ_QUEUE_IDX 0 #define VTNET_SQ_TQ_QUEUE_IDX 1 @@ -167,7 +173,8 @@ struct virtqueue { void *vq_ring_virt_mem; /**< linear address of vring*/ unsigned int vq_ring_size; - phys_addr_t vq_ring_mem; /**< physical address of vring */ + phys_addr_t vq_ring_mem; /**< phys address of vring for pci dev, + virt addr of vring for vdev */ struct vring vq_ring; /**< vring keeping desc, used and avail */ uint16_t vq_free_cnt; /**< num of desc available */ @@ -186,8 +193,10 @@ struct virtqueue { */ uint16_t vq_used_cons_idx; uint16_t vq_avail_idx; + uint16_t offset; /**< relative offset to obtain addr in mbuf */ uint64_t mbuf_initializer; /**< value to init mbufs. */ phys_addr_t virtio_net_hdr_mem; /**< hdr for each xmit packet */ + void *virtio_net_hdr_vaddr; /**< linear address of vring*/ struct rte_mbuf **sw_ring; /**< RX software ring. */ /* dummy mbuf, for wraparound when processing RX ring. */ -- 2.1.4