forked from Minki/linux
vfio: Introduce common function to add capabilities
Vendor driver using mediated device framework should use vfio_info_add_capability() to add capabilities. Introduced this function to reduce code duplication in vendor drivers. vfio_info_cap_shift() manipulated a data buffer to add an offset to each element in a chain. This data buffer is documented in a uapi header. Changing vfio_info_cap_shift symbol to be available to all drivers. Signed-off-by: Kirti Wankhede <kwankhede@nvidia.com> Signed-off-by: Neo Jia <cjia@nvidia.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
c086de818d
commit
b3c0a866f1
@ -1797,8 +1797,66 @@ void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset)
|
||||
for (tmp = caps->buf; tmp->next; tmp = (void *)tmp + tmp->next - offset)
|
||||
tmp->next += offset;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfio_info_cap_shift);
|
||||
EXPORT_SYMBOL(vfio_info_cap_shift);
|
||||
|
||||
static int sparse_mmap_cap(struct vfio_info_cap *caps, void *cap_type)
|
||||
{
|
||||
struct vfio_info_cap_header *header;
|
||||
struct vfio_region_info_cap_sparse_mmap *sparse_cap, *sparse = cap_type;
|
||||
size_t size;
|
||||
|
||||
size = sizeof(*sparse) + sparse->nr_areas * sizeof(*sparse->areas);
|
||||
header = vfio_info_cap_add(caps, size,
|
||||
VFIO_REGION_INFO_CAP_SPARSE_MMAP, 1);
|
||||
if (IS_ERR(header))
|
||||
return PTR_ERR(header);
|
||||
|
||||
sparse_cap = container_of(header,
|
||||
struct vfio_region_info_cap_sparse_mmap, header);
|
||||
sparse_cap->nr_areas = sparse->nr_areas;
|
||||
memcpy(sparse_cap->areas, sparse->areas,
|
||||
sparse->nr_areas * sizeof(*sparse->areas));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int region_type_cap(struct vfio_info_cap *caps, void *cap_type)
|
||||
{
|
||||
struct vfio_info_cap_header *header;
|
||||
struct vfio_region_info_cap_type *type_cap, *cap = cap_type;
|
||||
|
||||
header = vfio_info_cap_add(caps, sizeof(*cap),
|
||||
VFIO_REGION_INFO_CAP_TYPE, 1);
|
||||
if (IS_ERR(header))
|
||||
return PTR_ERR(header);
|
||||
|
||||
type_cap = container_of(header, struct vfio_region_info_cap_type,
|
||||
header);
|
||||
type_cap->type = cap->type;
|
||||
type_cap->subtype = cap->subtype;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfio_info_add_capability(struct vfio_info_cap *caps, int cap_type_id,
|
||||
void *cap_type)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!cap_type)
|
||||
return 0;
|
||||
|
||||
switch (cap_type_id) {
|
||||
case VFIO_REGION_INFO_CAP_SPARSE_MMAP:
|
||||
ret = sparse_mmap_cap(caps, cap_type);
|
||||
break;
|
||||
|
||||
case VFIO_REGION_INFO_CAP_TYPE:
|
||||
ret = region_type_cap(caps, cap_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vfio_info_add_capability);
|
||||
|
||||
/*
|
||||
* Pin a set of guest PFNs and return their associated host PFNs for local
|
||||
|
@ -126,6 +126,9 @@ extern struct vfio_info_cap_header *vfio_info_cap_add(
|
||||
struct vfio_info_cap *caps, size_t size, u16 id, u16 version);
|
||||
extern void vfio_info_cap_shift(struct vfio_info_cap *caps, size_t offset);
|
||||
|
||||
extern int vfio_info_add_capability(struct vfio_info_cap *caps,
|
||||
int cap_type_id, void *cap_type);
|
||||
|
||||
struct pci_dev;
|
||||
#ifdef CONFIG_EEH
|
||||
extern void vfio_spapr_pci_eeh_open(struct pci_dev *pdev);
|
||||
|
Loading…
Reference in New Issue
Block a user