All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Wang <jasowang@redhat.com>
To: Wu Zongyong <wuzongyong@linux.alibaba.com>,
	virtualization@lists.linux-foundation.org,
	linux-kernel@vger.kernel.org, mst@redhat.com
Cc: wei.yang1@linux.alibaba.com
Subject: Re: [PATCH v4 7/7] eni_vdpa: add vDPA driver for Alibaba ENI
Date: Mon, 11 Oct 2021 11:18:42 +0800	[thread overview]
Message-ID: <7872513b-6cf5-704e-8807-43dc7b563d96@redhat.com> (raw)
In-Reply-To: <68d4ffac2ed9c21f352c272efbdf21e567d7d48e.1632882380.git.wuzongyong@linux.alibaba.com>


在 2021/9/29 下午2:11, Wu Zongyong 写道:
> This patch adds a new vDPA driver for Alibaba ENI(Elastic Network
> Interface) which is build upon virtio 0.9.5 specification.
> And this driver doesn't support to run on BE host.


If this is true, I think it's still better to exclude this driver via 
Kconfig.


>
> Signed-off-by: Wu Zongyong <wuzongyong@linux.alibaba.com>
> ---
>   drivers/vdpa/Kconfig            |   8 +
>   drivers/vdpa/Makefile           |   1 +
>   drivers/vdpa/alibaba/Makefile   |   3 +
>   drivers/vdpa/alibaba/eni_vdpa.c | 553 ++++++++++++++++++++++++++++++++
>   4 files changed, 565 insertions(+)
>   create mode 100644 drivers/vdpa/alibaba/Makefile
>   create mode 100644 drivers/vdpa/alibaba/eni_vdpa.c
>
> diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig
> index 3d91982d8371..9587b9177b05 100644
> --- a/drivers/vdpa/Kconfig
> +++ b/drivers/vdpa/Kconfig
> @@ -78,4 +78,12 @@ config VP_VDPA
>   	help
>   	  This kernel module bridges virtio PCI device to vDPA bus.
>   
> +config ALIBABA_ENI_VDPA
> +	tristate "vDPA driver for Alibaba ENI"
> +	select VIRTIO_PCI_LEGACY_LIB
> +	depends on PCI_MSI
> +	help
> +	  VDPA driver for Alibaba ENI(Elastic Network Interface) which is build upon
> +	  virtio 0.9.5 specification.
> +
>   endif # VDPA
> diff --git a/drivers/vdpa/Makefile b/drivers/vdpa/Makefile
> index f02ebed33f19..15665563a7f4 100644
> --- a/drivers/vdpa/Makefile
> +++ b/drivers/vdpa/Makefile
> @@ -5,3 +5,4 @@ obj-$(CONFIG_VDPA_USER) += vdpa_user/
>   obj-$(CONFIG_IFCVF)    += ifcvf/
>   obj-$(CONFIG_MLX5_VDPA) += mlx5/
>   obj-$(CONFIG_VP_VDPA)    += virtio_pci/
> +obj-$(CONFIG_ALIBABA_ENI_VDPA) += alibaba/
> diff --git a/drivers/vdpa/alibaba/Makefile b/drivers/vdpa/alibaba/Makefile
> new file mode 100644
> index 000000000000..ef4aae69f87a
> --- /dev/null
> +++ b/drivers/vdpa/alibaba/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_ALIBABA_ENI_VDPA) += eni_vdpa.o
> +
> diff --git a/drivers/vdpa/alibaba/eni_vdpa.c b/drivers/vdpa/alibaba/eni_vdpa.c
> new file mode 100644
> index 000000000000..6a09f157d810
> --- /dev/null
> +++ b/drivers/vdpa/alibaba/eni_vdpa.c
> @@ -0,0 +1,553 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * vDPA bridge driver for Alibaba ENI(Elastic Network Interface)
> + *
> + * Copyright (c) 2021, Alibaba Inc. All rights reserved.
> + * Author: Wu Zongyong <wuzongyong@linux.alibaba.com>
> + *
> + */
> +
> +#include "linux/bits.h"
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/vdpa.h>
> +#include <linux/virtio.h>
> +#include <linux/virtio_config.h>
> +#include <linux/virtio_ring.h>
> +#include <linux/virtio_pci.h>
> +#include <linux/virtio_pci_legacy.h>
> +#include <uapi/linux/virtio_net.h>
> +
> +#define ENI_MSIX_NAME_SIZE 256
> +
> +#define ENI_ERR(pdev, fmt, ...)	\
> +	dev_err(&pdev->dev, "%s"fmt, "eni_vdpa: ", ##__VA_ARGS__)
> +#define ENI_DBG(pdev, fmt, ...)	\
> +	dev_dbg(&pdev->dev, "%s"fmt, "eni_vdpa: ", ##__VA_ARGS__)
> +#define ENI_INFO(pdev, fmt, ...) \
> +	dev_info(&pdev->dev, "%s"fmt, "eni_vdpa: ", ##__VA_ARGS__)
> +
> +struct eni_vring {
> +	void __iomem *notify;
> +	char msix_name[ENI_MSIX_NAME_SIZE];
> +	struct vdpa_callback cb;
> +	int irq;
> +};
> +
> +struct eni_vdpa {
> +	struct vdpa_device vdpa;
> +	struct virtio_pci_legacy_device ldev;
> +	struct eni_vring *vring;
> +	struct vdpa_callback config_cb;
> +	char msix_name[ENI_MSIX_NAME_SIZE];
> +	int config_irq;
> +	int queues;
> +	int vectors;
> +};
> +
> +static struct eni_vdpa *vdpa_to_eni(struct vdpa_device *vdpa)
> +{
> +	return container_of(vdpa, struct eni_vdpa, vdpa);
> +}
> +
> +static struct virtio_pci_legacy_device *vdpa_to_ldev(struct vdpa_device *vdpa)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +
> +	return &eni_vdpa->ldev;
> +}
> +
> +static u64 eni_vdpa_get_features(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +	u64 features = vp_legacy_get_features(ldev);
> +
> +	features |= BIT_ULL(VIRTIO_F_ACCESS_PLATFORM);
> +	features |= BIT_ULL(VIRTIO_F_ORDER_PLATFORM);


VERSION_1 is also needed?


> +
> +	return features;
> +}
> +
> +static int eni_vdpa_set_features(struct vdpa_device *vdpa, u64 features)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	if (!(features & BIT_ULL(VIRTIO_NET_F_MRG_RXBUF)) && features) {
> +		ENI_ERR(ldev->pci_dev,
> +			"VIRTIO_NET_F_MRG_RXBUF is not negotiated\n");
> +		return -EINVAL;


Do we need to make sure FEATURE_OK is not set in this case or the ENI 
can do this for us?

Other looks good.

Thanks


> +	}
> +
> +	vp_legacy_set_features(ldev, (u32)features);
> +
> +	return 0;
> +}
> +
> +static u8 eni_vdpa_get_status(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return vp_legacy_get_status(ldev);
> +}
> +
> +static int eni_vdpa_get_vq_irq(struct vdpa_device *vdpa, u16 idx)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	int irq = eni_vdpa->vring[idx].irq;
> +
> +	if (irq == VIRTIO_MSI_NO_VECTOR)
> +		return -EINVAL;
> +
> +	return irq;
> +}
> +
> +static void eni_vdpa_free_irq(struct eni_vdpa *eni_vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	struct pci_dev *pdev = ldev->pci_dev;
> +	int i;
> +
> +	for (i = 0; i < eni_vdpa->queues; i++) {
> +		if (eni_vdpa->vring[i].irq != VIRTIO_MSI_NO_VECTOR) {
> +			vp_legacy_queue_vector(ldev, i, VIRTIO_MSI_NO_VECTOR);
> +			devm_free_irq(&pdev->dev, eni_vdpa->vring[i].irq,
> +				      &eni_vdpa->vring[i]);
> +			eni_vdpa->vring[i].irq = VIRTIO_MSI_NO_VECTOR;
> +		}
> +	}
> +
> +	if (eni_vdpa->config_irq != VIRTIO_MSI_NO_VECTOR) {
> +		vp_legacy_config_vector(ldev, VIRTIO_MSI_NO_VECTOR);
> +		devm_free_irq(&pdev->dev, eni_vdpa->config_irq, eni_vdpa);
> +		eni_vdpa->config_irq = VIRTIO_MSI_NO_VECTOR;
> +	}
> +
> +	if (eni_vdpa->vectors) {
> +		pci_free_irq_vectors(pdev);
> +		eni_vdpa->vectors = 0;
> +	}
> +}
> +
> +static irqreturn_t eni_vdpa_vq_handler(int irq, void *arg)
> +{
> +	struct eni_vring *vring = arg;
> +
> +	if (vring->cb.callback)
> +		return vring->cb.callback(vring->cb.private);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t eni_vdpa_config_handler(int irq, void *arg)
> +{
> +	struct eni_vdpa *eni_vdpa = arg;
> +
> +	if (eni_vdpa->config_cb.callback)
> +		return eni_vdpa->config_cb.callback(eni_vdpa->config_cb.private);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int eni_vdpa_request_irq(struct eni_vdpa *eni_vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	struct pci_dev *pdev = ldev->pci_dev;
> +	int i, ret, irq;
> +	int queues = eni_vdpa->queues;
> +	int vectors = queues + 1;
> +
> +	ret = pci_alloc_irq_vectors(pdev, vectors, vectors, PCI_IRQ_MSIX);
> +	if (ret != vectors) {
> +		ENI_ERR(pdev,
> +			"failed to allocate irq vectors want %d but %d\n",
> +			vectors, ret);
> +		return ret;
> +	}
> +
> +	eni_vdpa->vectors = vectors;
> +
> +	for (i = 0; i < queues; i++) {
> +		snprintf(eni_vdpa->vring[i].msix_name, ENI_MSIX_NAME_SIZE,
> +			 "eni-vdpa[%s]-%d\n", pci_name(pdev), i);
> +		irq = pci_irq_vector(pdev, i);
> +		ret = devm_request_irq(&pdev->dev, irq,
> +				       eni_vdpa_vq_handler,
> +				       0, eni_vdpa->vring[i].msix_name,
> +				       &eni_vdpa->vring[i]);
> +		if (ret) {
> +			ENI_ERR(pdev, "failed to request irq for vq %d\n", i);
> +			goto err;
> +		}
> +		vp_legacy_queue_vector(ldev, i, i);
> +		eni_vdpa->vring[i].irq = irq;
> +	}
> +
> +	snprintf(eni_vdpa->msix_name, ENI_MSIX_NAME_SIZE, "eni-vdpa[%s]-config\n",
> +		 pci_name(pdev));
> +	irq = pci_irq_vector(pdev, queues);
> +	ret = devm_request_irq(&pdev->dev, irq, eni_vdpa_config_handler, 0,
> +			       eni_vdpa->msix_name, eni_vdpa);
> +	if (ret) {
> +		ENI_ERR(pdev, "failed to request irq for config vq %d\n", i);
> +		goto err;
> +	}
> +	vp_legacy_config_vector(ldev, queues);
> +	eni_vdpa->config_irq = irq;
> +
> +	return 0;
> +err:
> +	eni_vdpa_free_irq(eni_vdpa);
> +	return ret;
> +}
> +
> +static void eni_vdpa_set_status(struct vdpa_device *vdpa, u8 status)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	u8 s = eni_vdpa_get_status(vdpa);
> +
> +	if (status & VIRTIO_CONFIG_S_DRIVER_OK &&
> +	    !(s & VIRTIO_CONFIG_S_DRIVER_OK)) {
> +		eni_vdpa_request_irq(eni_vdpa);
> +	}
> +
> +	vp_legacy_set_status(ldev, status);
> +
> +	if (!(status & VIRTIO_CONFIG_S_DRIVER_OK) &&
> +	    (s & VIRTIO_CONFIG_S_DRIVER_OK))
> +		eni_vdpa_free_irq(eni_vdpa);
> +}
> +
> +static int eni_vdpa_reset(struct vdpa_device *vdpa)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	u8 s = eni_vdpa_get_status(vdpa);
> +
> +	vp_legacy_set_status(ldev, 0);
> +
> +	if (s & VIRTIO_CONFIG_S_DRIVER_OK)
> +		eni_vdpa_free_irq(eni_vdpa);
> +
> +	return 0;
> +}
> +
> +static u16 eni_vdpa_get_vq_num_max(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return vp_legacy_get_queue_size(ldev, 0);
> +}
> +
> +static u16 eni_vdpa_get_vq_num_min(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return vp_legacy_get_queue_size(ldev, 0);
> +}
> +
> +static int eni_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 qid,
> +				struct vdpa_vq_state *state)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
> +static int eni_vdpa_set_vq_state(struct vdpa_device *vdpa, u16 qid,
> +				 const struct vdpa_vq_state *state)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +	const struct vdpa_vq_state_split *split = &state->split;
> +
> +	/* ENI is build upon virtio-pci specfication which not support
> +	 * to set state of virtqueue. But if the state is equal to the
> +	 * device initial state by chance, we can let it go.
> +	 */
> +	if (!vp_legacy_get_queue_enable(ldev, qid)
> +	    && split->avail_index == 0)
> +		return 0;
> +
> +	return -EOPNOTSUPP;
> +}
> +
> +
> +static void eni_vdpa_set_vq_cb(struct vdpa_device *vdpa, u16 qid,
> +			       struct vdpa_callback *cb)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +
> +	eni_vdpa->vring[qid].cb = *cb;
> +}
> +
> +static void eni_vdpa_set_vq_ready(struct vdpa_device *vdpa, u16 qid,
> +				  bool ready)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	/* ENI is a legacy virtio-pci device. This is not supported
> +	 * by specification. But we can disable virtqueue by setting
> +	 * address to 0.
> +	 */
> +	if (!ready)
> +		vp_legacy_set_queue_address(ldev, qid, 0);
> +}
> +
> +static bool eni_vdpa_get_vq_ready(struct vdpa_device *vdpa, u16 qid)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return vp_legacy_get_queue_enable(ldev, qid);
> +}
> +
> +static void eni_vdpa_set_vq_num(struct vdpa_device *vdpa, u16 qid,
> +			       u32 num)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +	struct pci_dev *pdev = ldev->pci_dev;
> +	u16 n = vp_legacy_get_queue_size(ldev, qid);
> +
> +	/* ENI is a legacy virtio-pci device which not allow to change
> +	 * virtqueue size. Just report a error if someone tries to
> +	 * change it.
> +	 */
> +	if (num != n)
> +		ENI_ERR(pdev,
> +			"not support to set vq %u fixed num %u to %u\n",
> +			qid, n, num);
> +}
> +
> +static int eni_vdpa_set_vq_address(struct vdpa_device *vdpa, u16 qid,
> +				   u64 desc_area, u64 driver_area,
> +				   u64 device_area)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +	u32 pfn = desc_area >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
> +
> +	vp_legacy_set_queue_address(ldev, qid, pfn);
> +
> +	return 0;
> +}
> +
> +static void eni_vdpa_kick_vq(struct vdpa_device *vdpa, u16 qid)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +
> +	iowrite16(qid, eni_vdpa->vring[qid].notify);
> +}
> +
> +static u32 eni_vdpa_get_device_id(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return ldev->id.device;
> +}
> +
> +static u32 eni_vdpa_get_vendor_id(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return ldev->id.vendor;
> +}
> +
> +static u32 eni_vdpa_get_vq_align(struct vdpa_device *vdpa)
> +{
> +	return PAGE_SIZE;
> +}
> +
> +static size_t eni_vdpa_get_config_size(struct vdpa_device *vdpa)
> +{
> +	return sizeof(struct virtio_net_config);
> +}
> +
> +
> +static void eni_vdpa_get_config(struct vdpa_device *vdpa,
> +				unsigned int offset,
> +				void *buf, unsigned int len)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	void __iomem *ioaddr = ldev->ioaddr +
> +		VIRTIO_PCI_CONFIG_OFF(eni_vdpa->vectors) +
> +		offset;
> +	u8 *p = buf;
> +	int i;
> +
> +	for (i = 0; i < len; i++)
> +		*p++ = ioread8(ioaddr + i);
> +}
> +
> +static void eni_vdpa_set_config(struct vdpa_device *vdpa,
> +				unsigned int offset, const void *buf,
> +				unsigned int len)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	void __iomem *ioaddr = ldev->ioaddr +
> +		VIRTIO_PCI_CONFIG_OFF(eni_vdpa->vectors) +
> +		offset;
> +	const u8 *p = buf;
> +	int i;
> +
> +	for (i = 0; i < len; i++)
> +		iowrite8(*p++, ioaddr + i);
> +}
> +
> +static void eni_vdpa_set_config_cb(struct vdpa_device *vdpa,
> +				   struct vdpa_callback *cb)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +
> +	eni_vdpa->config_cb = *cb;
> +}
> +
> +static const struct vdpa_config_ops eni_vdpa_ops = {
> +	.get_features	= eni_vdpa_get_features,
> +	.set_features	= eni_vdpa_set_features,
> +	.get_status	= eni_vdpa_get_status,
> +	.set_status	= eni_vdpa_set_status,
> +	.reset		= eni_vdpa_reset,
> +	.get_vq_num_max	= eni_vdpa_get_vq_num_max,
> +	.get_vq_num_min	= eni_vdpa_get_vq_num_min,
> +	.get_vq_state	= eni_vdpa_get_vq_state,
> +	.set_vq_state	= eni_vdpa_set_vq_state,
> +	.set_vq_cb	= eni_vdpa_set_vq_cb,
> +	.set_vq_ready	= eni_vdpa_set_vq_ready,
> +	.get_vq_ready	= eni_vdpa_get_vq_ready,
> +	.set_vq_num	= eni_vdpa_set_vq_num,
> +	.set_vq_address	= eni_vdpa_set_vq_address,
> +	.kick_vq	= eni_vdpa_kick_vq,
> +	.get_device_id	= eni_vdpa_get_device_id,
> +	.get_vendor_id	= eni_vdpa_get_vendor_id,
> +	.get_vq_align	= eni_vdpa_get_vq_align,
> +	.get_config_size = eni_vdpa_get_config_size,
> +	.get_config	= eni_vdpa_get_config,
> +	.set_config	= eni_vdpa_set_config,
> +	.set_config_cb  = eni_vdpa_set_config_cb,
> +	.get_vq_irq	= eni_vdpa_get_vq_irq,
> +};
> +
> +
> +static u16 eni_vdpa_get_num_queues(struct eni_vdpa *eni_vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	u32 features = vp_legacy_get_features(ldev);
> +	u16 num = 2;
> +
> +	if (features & BIT_ULL(VIRTIO_NET_F_MQ)) {
> +		__virtio16 max_virtqueue_pairs;
> +
> +		eni_vdpa_get_config(&eni_vdpa->vdpa,
> +			offsetof(struct virtio_net_config, max_virtqueue_pairs),
> +			&max_virtqueue_pairs,
> +			sizeof(max_virtqueue_pairs));
> +		num = 2 * __virtio16_to_cpu(virtio_legacy_is_little_endian(),
> +				max_virtqueue_pairs);
> +	}
> +
> +	if (features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))
> +		num += 1;
> +
> +	return num;
> +}
> +
> +static void eni_vdpa_free_irq_vectors(void *data)
> +{
> +	pci_free_irq_vectors(data);
> +}
> +
> +static int eni_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct eni_vdpa *eni_vdpa;
> +	struct virtio_pci_legacy_device *ldev;
> +	int ret, i;
> +
> +	ret = pcim_enable_device(pdev);
> +	if (ret)
> +		return ret;
> +
> +	eni_vdpa = vdpa_alloc_device(struct eni_vdpa, vdpa,
> +				     dev, &eni_vdpa_ops, NULL, false);
> +	if (IS_ERR(eni_vdpa)) {
> +		ENI_ERR(pdev, "failed to allocate vDPA structure\n");
> +		return PTR_ERR(eni_vdpa);
> +	}
> +
> +	ldev = &eni_vdpa->ldev;
> +	ldev->pci_dev = pdev;
> +
> +	ret = vp_legacy_probe(ldev);
> +	if (ret) {
> +		ENI_ERR(pdev, "failed to probe legacy PCI device\n");
> +		goto err;
> +	}
> +
> +	pci_set_master(pdev);
> +	pci_set_drvdata(pdev, eni_vdpa);
> +
> +	eni_vdpa->vdpa.dma_dev = &pdev->dev;
> +	eni_vdpa->queues = eni_vdpa_get_num_queues(eni_vdpa);
> +
> +	ret = devm_add_action_or_reset(dev, eni_vdpa_free_irq_vectors, pdev);
> +	if (ret) {
> +		ENI_ERR(pdev,
> +			"failed for adding devres for freeing irq vectors\n");
> +		goto err;
> +	}
> +
> +	eni_vdpa->vring = devm_kcalloc(&pdev->dev, eni_vdpa->queues,
> +				      sizeof(*eni_vdpa->vring),
> +				      GFP_KERNEL);
> +	if (!eni_vdpa->vring) {
> +		ret = -ENOMEM;
> +		ENI_ERR(pdev, "failed to allocate virtqueues\n");
> +		goto err;
> +	}
> +
> +	for (i = 0; i < eni_vdpa->queues; i++) {
> +		eni_vdpa->vring[i].irq = VIRTIO_MSI_NO_VECTOR;
> +		eni_vdpa->vring[i].notify = ldev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY;
> +	}
> +	eni_vdpa->config_irq = VIRTIO_MSI_NO_VECTOR;
> +
> +	ret = vdpa_register_device(&eni_vdpa->vdpa, eni_vdpa->queues);
> +	if (ret) {
> +		ENI_ERR(pdev, "failed to register to vdpa bus\n");
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	put_device(&eni_vdpa->vdpa.dev);
> +	return ret;
> +}
> +
> +static void eni_vdpa_remove(struct pci_dev *pdev)
> +{
> +	struct eni_vdpa *eni_vdpa = pci_get_drvdata(pdev);
> +
> +	vdpa_unregister_device(&eni_vdpa->vdpa);
> +	vp_legacy_remove(&eni_vdpa->ldev);
> +}
> +
> +static struct pci_device_id eni_pci_ids[] = {
> +	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_REDHAT_QUMRANET,
> +			 VIRTIO_TRANS_ID_NET,
> +			 PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
> +			 VIRTIO_ID_NET) },
> +	{ 0 },
> +};
> +
> +static struct pci_driver eni_vdpa_driver = {
> +	.name		= "alibaba-eni-vdpa",
> +	.id_table	= eni_pci_ids,
> +	.probe		= eni_vdpa_probe,
> +	.remove		= eni_vdpa_remove,
> +};
> +
> +module_pci_driver(eni_vdpa_driver);
> +
> +MODULE_AUTHOR("Wu Zongyong <wuzongyong@linux.alibaba.com>");
> +MODULE_DESCRIPTION("Alibaba ENI vDPA driver");
> +MODULE_LICENSE("GPL v2");


WARNING: multiple messages have this Message-ID (diff)
From: Jason Wang <jasowang@redhat.com>
To: Wu Zongyong <wuzongyong@linux.alibaba.com>,
	virtualization@lists.linux-foundation.org,
	linux-kernel@vger.kernel.org, mst@redhat.com
Cc: wei.yang1@linux.alibaba.com
Subject: Re: [PATCH v4 7/7] eni_vdpa: add vDPA driver for Alibaba ENI
Date: Mon, 11 Oct 2021 11:18:42 +0800	[thread overview]
Message-ID: <7872513b-6cf5-704e-8807-43dc7b563d96@redhat.com> (raw)
In-Reply-To: <68d4ffac2ed9c21f352c272efbdf21e567d7d48e.1632882380.git.wuzongyong@linux.alibaba.com>


在 2021/9/29 下午2:11, Wu Zongyong 写道:
> This patch adds a new vDPA driver for Alibaba ENI(Elastic Network
> Interface) which is build upon virtio 0.9.5 specification.
> And this driver doesn't support to run on BE host.


If this is true, I think it's still better to exclude this driver via 
Kconfig.


>
> Signed-off-by: Wu Zongyong <wuzongyong@linux.alibaba.com>
> ---
>   drivers/vdpa/Kconfig            |   8 +
>   drivers/vdpa/Makefile           |   1 +
>   drivers/vdpa/alibaba/Makefile   |   3 +
>   drivers/vdpa/alibaba/eni_vdpa.c | 553 ++++++++++++++++++++++++++++++++
>   4 files changed, 565 insertions(+)
>   create mode 100644 drivers/vdpa/alibaba/Makefile
>   create mode 100644 drivers/vdpa/alibaba/eni_vdpa.c
>
> diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig
> index 3d91982d8371..9587b9177b05 100644
> --- a/drivers/vdpa/Kconfig
> +++ b/drivers/vdpa/Kconfig
> @@ -78,4 +78,12 @@ config VP_VDPA
>   	help
>   	  This kernel module bridges virtio PCI device to vDPA bus.
>   
> +config ALIBABA_ENI_VDPA
> +	tristate "vDPA driver for Alibaba ENI"
> +	select VIRTIO_PCI_LEGACY_LIB
> +	depends on PCI_MSI
> +	help
> +	  VDPA driver for Alibaba ENI(Elastic Network Interface) which is build upon
> +	  virtio 0.9.5 specification.
> +
>   endif # VDPA
> diff --git a/drivers/vdpa/Makefile b/drivers/vdpa/Makefile
> index f02ebed33f19..15665563a7f4 100644
> --- a/drivers/vdpa/Makefile
> +++ b/drivers/vdpa/Makefile
> @@ -5,3 +5,4 @@ obj-$(CONFIG_VDPA_USER) += vdpa_user/
>   obj-$(CONFIG_IFCVF)    += ifcvf/
>   obj-$(CONFIG_MLX5_VDPA) += mlx5/
>   obj-$(CONFIG_VP_VDPA)    += virtio_pci/
> +obj-$(CONFIG_ALIBABA_ENI_VDPA) += alibaba/
> diff --git a/drivers/vdpa/alibaba/Makefile b/drivers/vdpa/alibaba/Makefile
> new file mode 100644
> index 000000000000..ef4aae69f87a
> --- /dev/null
> +++ b/drivers/vdpa/alibaba/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_ALIBABA_ENI_VDPA) += eni_vdpa.o
> +
> diff --git a/drivers/vdpa/alibaba/eni_vdpa.c b/drivers/vdpa/alibaba/eni_vdpa.c
> new file mode 100644
> index 000000000000..6a09f157d810
> --- /dev/null
> +++ b/drivers/vdpa/alibaba/eni_vdpa.c
> @@ -0,0 +1,553 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * vDPA bridge driver for Alibaba ENI(Elastic Network Interface)
> + *
> + * Copyright (c) 2021, Alibaba Inc. All rights reserved.
> + * Author: Wu Zongyong <wuzongyong@linux.alibaba.com>
> + *
> + */
> +
> +#include "linux/bits.h"
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/vdpa.h>
> +#include <linux/virtio.h>
> +#include <linux/virtio_config.h>
> +#include <linux/virtio_ring.h>
> +#include <linux/virtio_pci.h>
> +#include <linux/virtio_pci_legacy.h>
> +#include <uapi/linux/virtio_net.h>
> +
> +#define ENI_MSIX_NAME_SIZE 256
> +
> +#define ENI_ERR(pdev, fmt, ...)	\
> +	dev_err(&pdev->dev, "%s"fmt, "eni_vdpa: ", ##__VA_ARGS__)
> +#define ENI_DBG(pdev, fmt, ...)	\
> +	dev_dbg(&pdev->dev, "%s"fmt, "eni_vdpa: ", ##__VA_ARGS__)
> +#define ENI_INFO(pdev, fmt, ...) \
> +	dev_info(&pdev->dev, "%s"fmt, "eni_vdpa: ", ##__VA_ARGS__)
> +
> +struct eni_vring {
> +	void __iomem *notify;
> +	char msix_name[ENI_MSIX_NAME_SIZE];
> +	struct vdpa_callback cb;
> +	int irq;
> +};
> +
> +struct eni_vdpa {
> +	struct vdpa_device vdpa;
> +	struct virtio_pci_legacy_device ldev;
> +	struct eni_vring *vring;
> +	struct vdpa_callback config_cb;
> +	char msix_name[ENI_MSIX_NAME_SIZE];
> +	int config_irq;
> +	int queues;
> +	int vectors;
> +};
> +
> +static struct eni_vdpa *vdpa_to_eni(struct vdpa_device *vdpa)
> +{
> +	return container_of(vdpa, struct eni_vdpa, vdpa);
> +}
> +
> +static struct virtio_pci_legacy_device *vdpa_to_ldev(struct vdpa_device *vdpa)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +
> +	return &eni_vdpa->ldev;
> +}
> +
> +static u64 eni_vdpa_get_features(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +	u64 features = vp_legacy_get_features(ldev);
> +
> +	features |= BIT_ULL(VIRTIO_F_ACCESS_PLATFORM);
> +	features |= BIT_ULL(VIRTIO_F_ORDER_PLATFORM);


VERSION_1 is also needed?


> +
> +	return features;
> +}
> +
> +static int eni_vdpa_set_features(struct vdpa_device *vdpa, u64 features)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	if (!(features & BIT_ULL(VIRTIO_NET_F_MRG_RXBUF)) && features) {
> +		ENI_ERR(ldev->pci_dev,
> +			"VIRTIO_NET_F_MRG_RXBUF is not negotiated\n");
> +		return -EINVAL;


Do we need to make sure FEATURE_OK is not set in this case or the ENI 
can do this for us?

Other looks good.

Thanks


> +	}
> +
> +	vp_legacy_set_features(ldev, (u32)features);
> +
> +	return 0;
> +}
> +
> +static u8 eni_vdpa_get_status(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return vp_legacy_get_status(ldev);
> +}
> +
> +static int eni_vdpa_get_vq_irq(struct vdpa_device *vdpa, u16 idx)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	int irq = eni_vdpa->vring[idx].irq;
> +
> +	if (irq == VIRTIO_MSI_NO_VECTOR)
> +		return -EINVAL;
> +
> +	return irq;
> +}
> +
> +static void eni_vdpa_free_irq(struct eni_vdpa *eni_vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	struct pci_dev *pdev = ldev->pci_dev;
> +	int i;
> +
> +	for (i = 0; i < eni_vdpa->queues; i++) {
> +		if (eni_vdpa->vring[i].irq != VIRTIO_MSI_NO_VECTOR) {
> +			vp_legacy_queue_vector(ldev, i, VIRTIO_MSI_NO_VECTOR);
> +			devm_free_irq(&pdev->dev, eni_vdpa->vring[i].irq,
> +				      &eni_vdpa->vring[i]);
> +			eni_vdpa->vring[i].irq = VIRTIO_MSI_NO_VECTOR;
> +		}
> +	}
> +
> +	if (eni_vdpa->config_irq != VIRTIO_MSI_NO_VECTOR) {
> +		vp_legacy_config_vector(ldev, VIRTIO_MSI_NO_VECTOR);
> +		devm_free_irq(&pdev->dev, eni_vdpa->config_irq, eni_vdpa);
> +		eni_vdpa->config_irq = VIRTIO_MSI_NO_VECTOR;
> +	}
> +
> +	if (eni_vdpa->vectors) {
> +		pci_free_irq_vectors(pdev);
> +		eni_vdpa->vectors = 0;
> +	}
> +}
> +
> +static irqreturn_t eni_vdpa_vq_handler(int irq, void *arg)
> +{
> +	struct eni_vring *vring = arg;
> +
> +	if (vring->cb.callback)
> +		return vring->cb.callback(vring->cb.private);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t eni_vdpa_config_handler(int irq, void *arg)
> +{
> +	struct eni_vdpa *eni_vdpa = arg;
> +
> +	if (eni_vdpa->config_cb.callback)
> +		return eni_vdpa->config_cb.callback(eni_vdpa->config_cb.private);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int eni_vdpa_request_irq(struct eni_vdpa *eni_vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	struct pci_dev *pdev = ldev->pci_dev;
> +	int i, ret, irq;
> +	int queues = eni_vdpa->queues;
> +	int vectors = queues + 1;
> +
> +	ret = pci_alloc_irq_vectors(pdev, vectors, vectors, PCI_IRQ_MSIX);
> +	if (ret != vectors) {
> +		ENI_ERR(pdev,
> +			"failed to allocate irq vectors want %d but %d\n",
> +			vectors, ret);
> +		return ret;
> +	}
> +
> +	eni_vdpa->vectors = vectors;
> +
> +	for (i = 0; i < queues; i++) {
> +		snprintf(eni_vdpa->vring[i].msix_name, ENI_MSIX_NAME_SIZE,
> +			 "eni-vdpa[%s]-%d\n", pci_name(pdev), i);
> +		irq = pci_irq_vector(pdev, i);
> +		ret = devm_request_irq(&pdev->dev, irq,
> +				       eni_vdpa_vq_handler,
> +				       0, eni_vdpa->vring[i].msix_name,
> +				       &eni_vdpa->vring[i]);
> +		if (ret) {
> +			ENI_ERR(pdev, "failed to request irq for vq %d\n", i);
> +			goto err;
> +		}
> +		vp_legacy_queue_vector(ldev, i, i);
> +		eni_vdpa->vring[i].irq = irq;
> +	}
> +
> +	snprintf(eni_vdpa->msix_name, ENI_MSIX_NAME_SIZE, "eni-vdpa[%s]-config\n",
> +		 pci_name(pdev));
> +	irq = pci_irq_vector(pdev, queues);
> +	ret = devm_request_irq(&pdev->dev, irq, eni_vdpa_config_handler, 0,
> +			       eni_vdpa->msix_name, eni_vdpa);
> +	if (ret) {
> +		ENI_ERR(pdev, "failed to request irq for config vq %d\n", i);
> +		goto err;
> +	}
> +	vp_legacy_config_vector(ldev, queues);
> +	eni_vdpa->config_irq = irq;
> +
> +	return 0;
> +err:
> +	eni_vdpa_free_irq(eni_vdpa);
> +	return ret;
> +}
> +
> +static void eni_vdpa_set_status(struct vdpa_device *vdpa, u8 status)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	u8 s = eni_vdpa_get_status(vdpa);
> +
> +	if (status & VIRTIO_CONFIG_S_DRIVER_OK &&
> +	    !(s & VIRTIO_CONFIG_S_DRIVER_OK)) {
> +		eni_vdpa_request_irq(eni_vdpa);
> +	}
> +
> +	vp_legacy_set_status(ldev, status);
> +
> +	if (!(status & VIRTIO_CONFIG_S_DRIVER_OK) &&
> +	    (s & VIRTIO_CONFIG_S_DRIVER_OK))
> +		eni_vdpa_free_irq(eni_vdpa);
> +}
> +
> +static int eni_vdpa_reset(struct vdpa_device *vdpa)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	u8 s = eni_vdpa_get_status(vdpa);
> +
> +	vp_legacy_set_status(ldev, 0);
> +
> +	if (s & VIRTIO_CONFIG_S_DRIVER_OK)
> +		eni_vdpa_free_irq(eni_vdpa);
> +
> +	return 0;
> +}
> +
> +static u16 eni_vdpa_get_vq_num_max(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return vp_legacy_get_queue_size(ldev, 0);
> +}
> +
> +static u16 eni_vdpa_get_vq_num_min(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return vp_legacy_get_queue_size(ldev, 0);
> +}
> +
> +static int eni_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 qid,
> +				struct vdpa_vq_state *state)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
> +static int eni_vdpa_set_vq_state(struct vdpa_device *vdpa, u16 qid,
> +				 const struct vdpa_vq_state *state)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +	const struct vdpa_vq_state_split *split = &state->split;
> +
> +	/* ENI is build upon virtio-pci specfication which not support
> +	 * to set state of virtqueue. But if the state is equal to the
> +	 * device initial state by chance, we can let it go.
> +	 */
> +	if (!vp_legacy_get_queue_enable(ldev, qid)
> +	    && split->avail_index == 0)
> +		return 0;
> +
> +	return -EOPNOTSUPP;
> +}
> +
> +
> +static void eni_vdpa_set_vq_cb(struct vdpa_device *vdpa, u16 qid,
> +			       struct vdpa_callback *cb)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +
> +	eni_vdpa->vring[qid].cb = *cb;
> +}
> +
> +static void eni_vdpa_set_vq_ready(struct vdpa_device *vdpa, u16 qid,
> +				  bool ready)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	/* ENI is a legacy virtio-pci device. This is not supported
> +	 * by specification. But we can disable virtqueue by setting
> +	 * address to 0.
> +	 */
> +	if (!ready)
> +		vp_legacy_set_queue_address(ldev, qid, 0);
> +}
> +
> +static bool eni_vdpa_get_vq_ready(struct vdpa_device *vdpa, u16 qid)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return vp_legacy_get_queue_enable(ldev, qid);
> +}
> +
> +static void eni_vdpa_set_vq_num(struct vdpa_device *vdpa, u16 qid,
> +			       u32 num)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +	struct pci_dev *pdev = ldev->pci_dev;
> +	u16 n = vp_legacy_get_queue_size(ldev, qid);
> +
> +	/* ENI is a legacy virtio-pci device which not allow to change
> +	 * virtqueue size. Just report a error if someone tries to
> +	 * change it.
> +	 */
> +	if (num != n)
> +		ENI_ERR(pdev,
> +			"not support to set vq %u fixed num %u to %u\n",
> +			qid, n, num);
> +}
> +
> +static int eni_vdpa_set_vq_address(struct vdpa_device *vdpa, u16 qid,
> +				   u64 desc_area, u64 driver_area,
> +				   u64 device_area)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +	u32 pfn = desc_area >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
> +
> +	vp_legacy_set_queue_address(ldev, qid, pfn);
> +
> +	return 0;
> +}
> +
> +static void eni_vdpa_kick_vq(struct vdpa_device *vdpa, u16 qid)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +
> +	iowrite16(qid, eni_vdpa->vring[qid].notify);
> +}
> +
> +static u32 eni_vdpa_get_device_id(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return ldev->id.device;
> +}
> +
> +static u32 eni_vdpa_get_vendor_id(struct vdpa_device *vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
> +
> +	return ldev->id.vendor;
> +}
> +
> +static u32 eni_vdpa_get_vq_align(struct vdpa_device *vdpa)
> +{
> +	return PAGE_SIZE;
> +}
> +
> +static size_t eni_vdpa_get_config_size(struct vdpa_device *vdpa)
> +{
> +	return sizeof(struct virtio_net_config);
> +}
> +
> +
> +static void eni_vdpa_get_config(struct vdpa_device *vdpa,
> +				unsigned int offset,
> +				void *buf, unsigned int len)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	void __iomem *ioaddr = ldev->ioaddr +
> +		VIRTIO_PCI_CONFIG_OFF(eni_vdpa->vectors) +
> +		offset;
> +	u8 *p = buf;
> +	int i;
> +
> +	for (i = 0; i < len; i++)
> +		*p++ = ioread8(ioaddr + i);
> +}
> +
> +static void eni_vdpa_set_config(struct vdpa_device *vdpa,
> +				unsigned int offset, const void *buf,
> +				unsigned int len)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	void __iomem *ioaddr = ldev->ioaddr +
> +		VIRTIO_PCI_CONFIG_OFF(eni_vdpa->vectors) +
> +		offset;
> +	const u8 *p = buf;
> +	int i;
> +
> +	for (i = 0; i < len; i++)
> +		iowrite8(*p++, ioaddr + i);
> +}
> +
> +static void eni_vdpa_set_config_cb(struct vdpa_device *vdpa,
> +				   struct vdpa_callback *cb)
> +{
> +	struct eni_vdpa *eni_vdpa = vdpa_to_eni(vdpa);
> +
> +	eni_vdpa->config_cb = *cb;
> +}
> +
> +static const struct vdpa_config_ops eni_vdpa_ops = {
> +	.get_features	= eni_vdpa_get_features,
> +	.set_features	= eni_vdpa_set_features,
> +	.get_status	= eni_vdpa_get_status,
> +	.set_status	= eni_vdpa_set_status,
> +	.reset		= eni_vdpa_reset,
> +	.get_vq_num_max	= eni_vdpa_get_vq_num_max,
> +	.get_vq_num_min	= eni_vdpa_get_vq_num_min,
> +	.get_vq_state	= eni_vdpa_get_vq_state,
> +	.set_vq_state	= eni_vdpa_set_vq_state,
> +	.set_vq_cb	= eni_vdpa_set_vq_cb,
> +	.set_vq_ready	= eni_vdpa_set_vq_ready,
> +	.get_vq_ready	= eni_vdpa_get_vq_ready,
> +	.set_vq_num	= eni_vdpa_set_vq_num,
> +	.set_vq_address	= eni_vdpa_set_vq_address,
> +	.kick_vq	= eni_vdpa_kick_vq,
> +	.get_device_id	= eni_vdpa_get_device_id,
> +	.get_vendor_id	= eni_vdpa_get_vendor_id,
> +	.get_vq_align	= eni_vdpa_get_vq_align,
> +	.get_config_size = eni_vdpa_get_config_size,
> +	.get_config	= eni_vdpa_get_config,
> +	.set_config	= eni_vdpa_set_config,
> +	.set_config_cb  = eni_vdpa_set_config_cb,
> +	.get_vq_irq	= eni_vdpa_get_vq_irq,
> +};
> +
> +
> +static u16 eni_vdpa_get_num_queues(struct eni_vdpa *eni_vdpa)
> +{
> +	struct virtio_pci_legacy_device *ldev = &eni_vdpa->ldev;
> +	u32 features = vp_legacy_get_features(ldev);
> +	u16 num = 2;
> +
> +	if (features & BIT_ULL(VIRTIO_NET_F_MQ)) {
> +		__virtio16 max_virtqueue_pairs;
> +
> +		eni_vdpa_get_config(&eni_vdpa->vdpa,
> +			offsetof(struct virtio_net_config, max_virtqueue_pairs),
> +			&max_virtqueue_pairs,
> +			sizeof(max_virtqueue_pairs));
> +		num = 2 * __virtio16_to_cpu(virtio_legacy_is_little_endian(),
> +				max_virtqueue_pairs);
> +	}
> +
> +	if (features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))
> +		num += 1;
> +
> +	return num;
> +}
> +
> +static void eni_vdpa_free_irq_vectors(void *data)
> +{
> +	pci_free_irq_vectors(data);
> +}
> +
> +static int eni_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct eni_vdpa *eni_vdpa;
> +	struct virtio_pci_legacy_device *ldev;
> +	int ret, i;
> +
> +	ret = pcim_enable_device(pdev);
> +	if (ret)
> +		return ret;
> +
> +	eni_vdpa = vdpa_alloc_device(struct eni_vdpa, vdpa,
> +				     dev, &eni_vdpa_ops, NULL, false);
> +	if (IS_ERR(eni_vdpa)) {
> +		ENI_ERR(pdev, "failed to allocate vDPA structure\n");
> +		return PTR_ERR(eni_vdpa);
> +	}
> +
> +	ldev = &eni_vdpa->ldev;
> +	ldev->pci_dev = pdev;
> +
> +	ret = vp_legacy_probe(ldev);
> +	if (ret) {
> +		ENI_ERR(pdev, "failed to probe legacy PCI device\n");
> +		goto err;
> +	}
> +
> +	pci_set_master(pdev);
> +	pci_set_drvdata(pdev, eni_vdpa);
> +
> +	eni_vdpa->vdpa.dma_dev = &pdev->dev;
> +	eni_vdpa->queues = eni_vdpa_get_num_queues(eni_vdpa);
> +
> +	ret = devm_add_action_or_reset(dev, eni_vdpa_free_irq_vectors, pdev);
> +	if (ret) {
> +		ENI_ERR(pdev,
> +			"failed for adding devres for freeing irq vectors\n");
> +		goto err;
> +	}
> +
> +	eni_vdpa->vring = devm_kcalloc(&pdev->dev, eni_vdpa->queues,
> +				      sizeof(*eni_vdpa->vring),
> +				      GFP_KERNEL);
> +	if (!eni_vdpa->vring) {
> +		ret = -ENOMEM;
> +		ENI_ERR(pdev, "failed to allocate virtqueues\n");
> +		goto err;
> +	}
> +
> +	for (i = 0; i < eni_vdpa->queues; i++) {
> +		eni_vdpa->vring[i].irq = VIRTIO_MSI_NO_VECTOR;
> +		eni_vdpa->vring[i].notify = ldev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY;
> +	}
> +	eni_vdpa->config_irq = VIRTIO_MSI_NO_VECTOR;
> +
> +	ret = vdpa_register_device(&eni_vdpa->vdpa, eni_vdpa->queues);
> +	if (ret) {
> +		ENI_ERR(pdev, "failed to register to vdpa bus\n");
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	put_device(&eni_vdpa->vdpa.dev);
> +	return ret;
> +}
> +
> +static void eni_vdpa_remove(struct pci_dev *pdev)
> +{
> +	struct eni_vdpa *eni_vdpa = pci_get_drvdata(pdev);
> +
> +	vdpa_unregister_device(&eni_vdpa->vdpa);
> +	vp_legacy_remove(&eni_vdpa->ldev);
> +}
> +
> +static struct pci_device_id eni_pci_ids[] = {
> +	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_REDHAT_QUMRANET,
> +			 VIRTIO_TRANS_ID_NET,
> +			 PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
> +			 VIRTIO_ID_NET) },
> +	{ 0 },
> +};
> +
> +static struct pci_driver eni_vdpa_driver = {
> +	.name		= "alibaba-eni-vdpa",
> +	.id_table	= eni_pci_ids,
> +	.probe		= eni_vdpa_probe,
> +	.remove		= eni_vdpa_remove,
> +};
> +
> +module_pci_driver(eni_vdpa_driver);
> +
> +MODULE_AUTHOR("Wu Zongyong <wuzongyong@linux.alibaba.com>");
> +MODULE_DESCRIPTION("Alibaba ENI vDPA driver");
> +MODULE_LICENSE("GPL v2");

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

  reply	other threads:[~2021-10-11  3:18 UTC|newest]

Thread overview: 223+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-08 12:20 [PATCH 0/6] vDPA driver for legacy virtio-pci device Wu Zongyong
2021-09-08 12:20 ` [PATCH 1/6] virtio-pci: introduce legacy device module Wu Zongyong
2021-09-08 12:20 ` [PATCH 2/6] vdpa: fix typo Wu Zongyong
2021-09-08 12:20 ` [PATCH 3/6] vp_vdpa: add vq irq offloading support Wu Zongyong
2021-09-09  2:53   ` Jason Wang
2021-09-09  2:53     ` Jason Wang
2021-09-08 12:20 ` [PATCH 4/6] vp_vdpa: split out reusable and device specific codes to separate file Wu Zongyong
2021-09-08 12:20 ` [PATCH 5/6] vdpa: add get_vq_num_unchangeable callback in vdpa_config_ops Wu Zongyong
2021-09-09  2:55   ` Jason Wang
2021-09-09  2:55     ` Jason Wang
2021-09-09  8:01     ` Wu Zongyong
2021-09-09  9:28       ` Jason Wang
2021-09-09  9:28         ` Jason Wang
2021-09-09  9:57         ` Wu Zongyong
2021-09-10  1:45           ` Jason Wang
2021-09-10  1:45             ` Jason Wang
2021-09-10  7:32             ` Wu Zongyong
2021-09-10  8:25               ` Cindy Lu
2021-09-10  9:20                 ` Wu Zongyong
2021-09-10 15:10                   ` Cindy Lu
2021-09-13  1:43                     ` Jason Wang
2021-09-13  1:43                       ` Jason Wang
2021-09-13  2:59                       ` Wu Zongyong
2021-09-13  3:13                         ` Jason Wang
2021-09-13  3:13                           ` Jason Wang
2021-09-13  6:22                           ` Cindy Lu
2021-09-09  9:18     ` Michael S. Tsirkin
2021-09-09  9:18       ` Michael S. Tsirkin
2021-09-09  9:32       ` Jason Wang
2021-09-09  9:32         ` Jason Wang
2021-09-08 12:20 ` [PATCH 6/6] vp_vdpa: introduce legacy virtio pci driver Wu Zongyong
2021-09-09 13:57   ` Michael S. Tsirkin
2021-09-09 13:57     ` Michael S. Tsirkin
2021-09-10  2:28     ` Wu Zongyong
2021-09-10  9:57       ` Michael S. Tsirkin
2021-09-10  9:57         ` Michael S. Tsirkin
2021-09-10 10:01         ` Wu Zongyong
2021-10-22  9:37         ` Michael S. Tsirkin
2021-10-22  9:37           ` Michael S. Tsirkin
2021-09-09  3:05 ` [PATCH 0/6] vDPA driver for legacy virtio-pci device Jason Wang
2021-09-09  3:05   ` Jason Wang
2021-09-09  3:20   ` Jason Wang
2021-09-09  3:20     ` Jason Wang
2021-09-09  8:12   ` Wu Zongyong
2021-09-09  9:29     ` Jason Wang
2021-09-09  9:29       ` Jason Wang
2021-09-09  9:21   ` Michael S. Tsirkin
2021-09-09  9:21     ` Michael S. Tsirkin
2021-09-09  9:31     ` Jason Wang
2021-09-09  9:31       ` Jason Wang
2021-09-09 12:53   ` Wu Zongyong
2021-09-10  1:44     ` Jason Wang
2021-09-10  1:44       ` Jason Wang
2021-09-14 12:24 ` [PATCH v2 0/5] vDPA driver for Alibaba ENI Wu Zongyong
2021-09-14 12:24   ` Wu Zongyong
2021-09-14 12:24   ` [PATCH v2 1/5] virtio-pci: introduce legacy device module Wu Zongyong
2021-09-14 22:37     ` Randy Dunlap
2021-09-14 22:37       ` Randy Dunlap
2021-09-14 12:24   ` [PATCH v2 2/5] vdpa: fix typo Wu Zongyong
2021-09-15  3:15     ` Jason Wang
2021-09-15  3:15       ` Jason Wang
2021-09-14 12:24   ` [PATCH v2 3/5] vp_vdpa: add vq irq offloading support Wu Zongyong
2021-09-15  3:16     ` Jason Wang
2021-09-15  3:16       ` Jason Wang
2021-09-15  3:31       ` Wu Zongyong
2021-09-15  4:13         ` Jason Wang
2021-09-15  4:13           ` Jason Wang
2021-09-14 12:24   ` [PATCH v2 4/5] vdpa: add new vdpa attribute VDPA_ATTR_DEV_F_VERSION_1 Wu Zongyong
2021-09-14 12:58     ` Michael S. Tsirkin
2021-09-14 12:58       ` Michael S. Tsirkin
2021-09-15  3:18       ` Jason Wang
2021-09-15  3:18         ` Jason Wang
2021-09-15  7:38         ` Michael S. Tsirkin
2021-09-15  7:38           ` Michael S. Tsirkin
2021-09-15  8:06           ` Jason Wang
2021-09-15  8:06             ` Jason Wang
2021-09-15 11:08             ` Michael S. Tsirkin
2021-09-15 11:08               ` Michael S. Tsirkin
2021-09-15 12:12               ` Wu Zongyong
2021-09-16  1:11                 ` Jason Wang
2021-09-16  1:11                   ` Jason Wang
2021-09-16  1:05               ` Jason Wang
2021-09-16  1:05                 ` Jason Wang
2021-09-17  2:34                 ` Wu Zongyong
2021-09-17  7:51                   ` Jason Wang
2021-09-17  7:51                     ` Jason Wang
2021-09-15  3:24       ` Wu Zongyong
2021-09-15  7:30         ` Michael S. Tsirkin
2021-09-15  7:30           ` Michael S. Tsirkin
2021-09-15  8:05           ` Jason Wang
2021-09-15  8:05             ` Jason Wang
2021-09-15 11:10             ` Michael S. Tsirkin
2021-09-15 11:10               ` Michael S. Tsirkin
2021-09-14 12:24   ` [PATCH v2 5/5] eni_vdpa: add vDPA driver for Alibaba ENI Wu Zongyong
2021-09-14 22:35     ` Randy Dunlap
2021-09-14 22:35       ` Randy Dunlap
2021-09-15  3:14     ` Jason Wang
2021-09-15  3:14       ` Jason Wang
2021-09-15  3:47       ` Wu Zongyong
2021-09-15 13:36     ` kernel test robot
2021-09-15 13:36       ` kernel test robot
2021-09-15 13:36       ` kernel test robot
2021-09-22 12:46   ` [PATCH v3 0/7] " Wu Zongyong
2021-09-22 12:46     ` [PATCH v3 1/7] virtio-pci: introduce legacy device module Wu Zongyong
2021-09-22 12:46     ` [PATCH v3 2/7] vdpa: fix typo Wu Zongyong
2021-09-22 12:46     ` [PATCH v3 3/7] vp_vdpa: add vq irq offloading support Wu Zongyong
2021-09-22 12:46     ` [PATCH v3 4/7] vdpa: add new callback get_vq_num_min in vdpa_config_ops Wu Zongyong
2021-09-22 12:46     ` [PATCH v3 5/7] virtio_vdpa: setup correct vq size with callbacks get_vq_num_{max,min} Wu Zongyong
2021-09-22 12:46     ` [PATCH v3 6/7] vdpa: add new attribute VDPA_ATTR_DEV_MIN_VQ_SIZE Wu Zongyong
2021-09-22 12:46     ` [PATCH v3 7/7] eni_vdpa: add vDPA driver for Alibaba ENI Wu Zongyong
2021-09-26  2:24       ` Jason Wang
2021-09-26  2:24         ` Jason Wang
2021-09-26  3:24         ` Wu Zongyong
2021-09-26  4:18           ` Jason Wang
2021-09-26  4:18             ` Jason Wang
2021-09-27 10:36             ` Michael S. Tsirkin
2021-09-27 10:36               ` Michael S. Tsirkin
2021-09-28  2:17               ` Jason Wang
2021-09-28  2:17                 ` Jason Wang
2021-09-26  2:26       ` Jason Wang
2021-09-26  2:26         ` Jason Wang
2021-09-26  3:27         ` Wu Zongyong
2021-09-26  4:19           ` Jason Wang
2021-09-26  4:19             ` Jason Wang
2021-09-29 12:54       ` kernel test robot
2021-09-29 12:54         ` kernel test robot
2021-09-29 12:54         ` kernel test robot
2021-09-29  6:11     ` [PATCH v4 0/7] " Wu Zongyong
2021-09-29  6:11       ` [PATCH v4 1/7] virtio-pci: introduce legacy device module Wu Zongyong
2021-10-11  3:00         ` Jason Wang
2021-10-11  3:00           ` Jason Wang
2021-10-11  3:02         ` Jason Wang
2021-10-11  3:02           ` Jason Wang
2021-09-29  6:11       ` [PATCH v4 2/7] vdpa: fix typo Wu Zongyong
2021-10-11  3:03         ` Jason Wang
2021-10-11  3:03           ` Jason Wang
2021-09-29  6:11       ` [PATCH v4 3/7] vp_vdpa: add vq irq offloading support Wu Zongyong
2021-09-29  6:11       ` [PATCH v4 4/7] vdpa: add new callback get_vq_num_min in vdpa_config_ops Wu Zongyong
2021-10-11  3:04         ` Jason Wang
2021-10-11  3:04           ` Jason Wang
2021-09-29  6:11       ` [PATCH v4 5/7] virtio_vdpa: setup correct vq size with callbacks get_vq_num_{max,min} Wu Zongyong
2021-10-11  3:06         ` Jason Wang
2021-10-11  3:06           ` Jason Wang
2021-09-29  6:11       ` [PATCH v4 6/7] vdpa: add new attribute VDPA_ATTR_DEV_MIN_VQ_SIZE Wu Zongyong
2021-10-11  3:10         ` Jason Wang
2021-10-11  3:10           ` Jason Wang
2021-09-29  6:11       ` [PATCH v4 7/7] eni_vdpa: add vDPA driver for Alibaba ENI Wu Zongyong
2021-10-11  3:18         ` Jason Wang [this message]
2021-10-11  3:18           ` Jason Wang
2021-10-15  7:14       ` [PATCH v5 0/8] " Wu Zongyong
2021-10-15  7:14         ` [PATCH v5 1/8] virtio-pci: introduce legacy device module Wu Zongyong
2021-10-15  8:22           ` Jason Wang
2021-10-15  8:22             ` Jason Wang
2021-10-15  7:14         ` [PATCH v5 2/8] vdpa: fix typo Wu Zongyong
2021-10-15  7:14         ` [PATCH v5 3/8] vp_vdpa: add vq irq offloading support Wu Zongyong
2021-10-15  7:14         ` [PATCH v5 4/8] vdpa: add new callback get_vq_num_min in vdpa_config_ops Wu Zongyong
2021-10-15  8:22           ` Jason Wang
2021-10-15  8:22             ` Jason Wang
2021-10-15  7:14         ` [PATCH v5 5/8] vdpa: min vq num of vdpa device cannot be greater than max vq num Wu Zongyong
2021-10-15  8:24           ` Jason Wang
2021-10-15  8:24             ` Jason Wang
2021-10-15  7:14         ` [PATCH v5 6/8] virtio_vdpa: setup correct vq size with callbacks get_vq_num_{max,min} Wu Zongyong
2021-10-15  8:30           ` Jason Wang
2021-10-15  8:30             ` Jason Wang
2021-10-15  7:15         ` [PATCH v5 7/8] vdpa: add new attribute VDPA_ATTR_DEV_MIN_VQ_SIZE Wu Zongyong
2021-10-15  7:15         ` [PATCH v5 8/8] eni_vdpa: add vDPA driver for Alibaba ENI Wu Zongyong
2021-10-15  8:18           ` Jason Wang
2021-10-15  8:18             ` Jason Wang
2021-10-15 19:13           ` Randy Dunlap
2021-10-15 19:13             ` Randy Dunlap
2021-10-22  2:44         ` [PATCH v6 0/8] " Wu Zongyong
2021-10-22  2:44           ` [PATCH v6 1/8] virtio-pci: introduce legacy device module Wu Zongyong
2021-10-25  1:30             ` Jason Wang
2021-10-25  1:30               ` Jason Wang
2021-10-22  2:44           ` [PATCH v6 2/8] vdpa: fix typo Wu Zongyong
2021-10-22  2:44           ` [PATCH v6 3/8] vp_vdpa: add vq irq offloading support Wu Zongyong
2021-10-22  2:44           ` [PATCH v6 4/8] vdpa: add new callback get_vq_num_min in vdpa_config_ops Wu Zongyong
2021-10-25  2:17             ` Jason Wang
2021-10-25  2:17               ` Jason Wang
2021-10-22  2:44           ` [PATCH v6 5/8] vdpa: min vq num of vdpa device cannot be greater than max vq num Wu Zongyong
2021-10-25  2:18             ` Jason Wang
2021-10-25  2:18               ` Jason Wang
2021-10-22  2:44           ` [PATCH v6 6/8] virtio_vdpa: setup correct vq size with callbacks get_vq_num_{max,min} Wu Zongyong
2021-10-25  2:22             ` Jason Wang
2021-10-25  2:22               ` [PATCH v6 6/8] virtio_vdpa: setup correct vq size with callbacks get_vq_num_{max, min} Jason Wang
     [not found]               ` <20211025024403.GA3684@L-PF27918B-1352.localdomain>
2021-10-25  4:45                 ` [PATCH v6 6/8] virtio_vdpa: setup correct vq size with callbacks get_vq_num_{max,min} Jason Wang
2021-10-25  4:45                   ` Jason Wang
     [not found]                   ` <20211025062454.GA4832@L-PF27918B-1352.localdomain>
2021-10-26  4:46                     ` Jason Wang
2021-10-26  4:46                       ` [PATCH v6 6/8] virtio_vdpa: setup correct vq size with callbacks get_vq_num_{max, min} Jason Wang
2021-10-22  2:44           ` [PATCH v6 7/8] vdpa: add new attribute VDPA_ATTR_DEV_MIN_VQ_SIZE Wu Zongyong
2021-10-25  2:23             ` Jason Wang
2021-10-25  2:23               ` Jason Wang
2021-10-22  2:44           ` [PATCH v6 8/8] eni_vdpa: add vDPA driver for Alibaba ENI Wu Zongyong
2021-10-25  2:27             ` Jason Wang
2021-10-25  2:27               ` Jason Wang
     [not found]               ` <20211025032146.GC3684@L-PF27918B-1352.localdomain>
2021-10-25  4:40                 ` Jason Wang
2021-10-25  4:40                   ` Jason Wang
2021-10-27  2:47                   ` Wu Zongyong
2021-10-27  3:55                     ` Jason Wang
2021-10-27  3:55                       ` Jason Wang
2021-10-27  7:04                       ` Wu Zongyong
2021-10-29  9:14           ` [PATCH v7 0/9] " Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 1/9] virtio-pci: introduce legacy device module Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 2/9] vdpa: fix typo Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 3/9] vp_vdpa: add vq irq offloading support Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 4/9] vdpa: add new callback get_vq_num_min in vdpa_config_ops Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 5/9] vdpa: min vq num of vdpa device cannot be greater than max vq num Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 6/9] virtio_vdpa: setup correct vq size with callbacks get_vq_num_{max,min} Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 7/9] vdpa: add new attribute VDPA_ATTR_DEV_MIN_VQ_SIZE Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 8/9] eni_vdpa: add vDPA driver for Alibaba ENI Wu Zongyong
2021-10-29  9:14             ` [PATCH v7 9/9] eni_vdpa: alibaba: fix Kconfig typo Wu Zongyong
2021-11-01  8:18               ` Michael S. Tsirkin
2021-11-01  8:18                 ` Michael S. Tsirkin
2021-11-01  3:31             ` [PATCH v7 0/9] vDPA driver for Alibaba ENI Jason Wang
2021-11-01  3:31               ` Jason Wang
2021-11-01  6:22               ` Wu Zongyong
2021-11-01  7:02                 ` Jason Wang
2021-11-01  7:02                   ` Jason Wang
2021-11-01  8:11                   ` Wu Zongyong
2021-11-01 11:12                     ` Michael S. Tsirkin
2021-11-01 11:12                       ` Michael S. Tsirkin
2021-11-01  8:19             ` Michael S. Tsirkin
2021-11-01  8:19               ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7872513b-6cf5-704e-8807-43dc7b563d96@redhat.com \
    --to=jasowang@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=virtualization@lists.linux-foundation.org \
    --cc=wei.yang1@linux.alibaba.com \
    --cc=wuzongyong@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.