vdpa/octeon_ep: read vendor-specific PCI capability

Added support to read the vendor-specific PCI capability to identify the
type of device being emulated.

Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Shijith Thotton <sthotton@marvell.com>
Message-Id: <20250103153226.1933479-4-sthotton@marvell.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Shijith Thotton 2025-01-03 21:01:37 +05:30 committed by Michael S. Tsirkin
parent 1629ee1078
commit 5abfb2208b
3 changed files with 58 additions and 2 deletions

View File

@ -8,6 +8,7 @@
#include <linux/pci_regs.h>
#include <linux/vdpa.h>
#include <linux/virtio_pci_modern.h>
#include <uapi/linux/virtio_crypto.h>
#include <uapi/linux/virtio_net.h>
#include <uapi/linux/virtio_blk.h>
#include <uapi/linux/virtio_config.h>
@ -52,6 +53,24 @@ struct octep_vring_info {
phys_addr_t notify_pa;
};
enum octep_pci_vndr_cfg_type {
OCTEP_PCI_VNDR_CFG_TYPE_VIRTIO_ID,
OCTEP_PCI_VNDR_CFG_TYPE_MAX,
};
struct octep_pci_vndr_data {
struct virtio_pci_vndr_data hdr;
u8 id;
u8 bar;
union {
u64 data;
struct {
u32 offset;
u32 length;
};
};
};
struct octep_hw {
struct pci_dev *pdev;
u8 __iomem *base[PCI_STD_NUM_BARS];
@ -69,6 +88,7 @@ struct octep_hw {
u32 config_size;
int nb_irqs;
int *irqs;
u8 dev_id;
};
u8 octep_hw_get_status(struct octep_hw *oct_hw);

View File

@ -2,6 +2,7 @@
/* Copyright (C) 2024 Marvell. */
#include <linux/iopoll.h>
#include <linux/build_bug.h>
#include "octep_vdpa.h"
@ -358,7 +359,14 @@ u16 octep_get_vq_size(struct octep_hw *oct_hw)
static u32 octep_get_config_size(struct octep_hw *oct_hw)
{
return sizeof(struct virtio_net_config);
switch (oct_hw->dev_id) {
case VIRTIO_ID_NET:
return sizeof(struct virtio_net_config);
case VIRTIO_ID_CRYPTO:
return sizeof(struct virtio_crypto_config);
default:
return 0;
}
}
static void __iomem *octep_get_cap_addr(struct octep_hw *oct_hw, struct virtio_pci_cap *cap)
@ -416,8 +424,25 @@ static int octep_pci_signature_verify(struct octep_hw *oct_hw)
return 0;
}
static void octep_vndr_data_process(struct octep_hw *oct_hw,
struct octep_pci_vndr_data *vndr_data)
{
BUILD_BUG_ON(sizeof(struct octep_pci_vndr_data) % 4 != 0);
switch (vndr_data->id) {
case OCTEP_PCI_VNDR_CFG_TYPE_VIRTIO_ID:
oct_hw->dev_id = (u8)vndr_data->data;
break;
default:
dev_err(&oct_hw->pdev->dev, "Invalid vendor data id %u\n",
vndr_data->id);
break;
}
}
int octep_hw_caps_read(struct octep_hw *oct_hw, struct pci_dev *pdev)
{
struct octep_pci_vndr_data vndr_data;
struct octep_mbox __iomem *mbox;
struct device *dev = &pdev->dev;
struct virtio_pci_cap cap;
@ -466,6 +491,15 @@ int octep_hw_caps_read(struct octep_hw *oct_hw, struct pci_dev *pdev)
case VIRTIO_PCI_CAP_ISR_CFG:
oct_hw->isr = octep_get_cap_addr(oct_hw, &cap);
break;
case VIRTIO_PCI_CAP_VENDOR_CFG:
octep_pci_caps_read(oct_hw, &vndr_data, sizeof(vndr_data), pos);
if (vndr_data.hdr.vendor_id != PCI_VENDOR_ID_CAVIUM) {
dev_err(dev, "Invalid vendor data\n");
return -EINVAL;
}
octep_vndr_data_process(oct_hw, &vndr_data);
break;
}
pos = cap.cap_next;

View File

@ -302,7 +302,9 @@ static u32 octep_vdpa_get_generation(struct vdpa_device *vdpa_dev)
static u32 octep_vdpa_get_device_id(struct vdpa_device *vdpa_dev)
{
return VIRTIO_ID_NET;
struct octep_hw *oct_hw = vdpa_to_octep_hw(vdpa_dev);
return oct_hw->dev_id;
}
static u32 octep_vdpa_get_vendor_id(struct vdpa_device *vdpa_dev)