Hello!

 See inline

> -----Original Message-----
> From: Jianfeng Tan [mailto:jianfeng.tan at intel.com]
> Sent: Sunday, January 10, 2016 2:43 PM
> To: dev at dpdk.org
> Cc: rich.lane at bigswitch.com; yuanhan.liu at linux.intel.com; mst at 
> redhat.com;
> nakajima.yoshihiro at lab.ntt.co.jp; huawei.xie at intel.com; mukawa at 
> igel.co.jp;
> p.fedin at samsung.com; michael.qiu at intel.com; ann.zhuangyanying at 
> huawei.com; Jianfeng Tan
> Subject: [PATCH 4/4] virtio/vdev: add a new vdev named eth_cvio
> 
> 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=<path_to_vhost_user> \
>     -- -p 0x1
> 
> Signed-off-by: Huawei Xie <huawei.xie at intel.com>
> Signed-off-by: Jianfeng Tan <jianfeng.tan at intel.com>
> ---
>  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 <rte_memory.h>
>  #include <rte_eal.h>
>  #include <rte_dev.h>
> +#include <rte_kvargs.h>
> 
>  #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;

 Not sure, but shouldn't these be swapped? Originally, for PCI devices, we used 
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))

 These bracket fixups should be squashed into #3

> 
>  #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

Kind regards,
Pavel Fedin
Senior Engineer
Samsung Electronics Research center Russia

Reply via email to