Re: [RFC v3 1/2] vfio/platform: add support for msi
Hi Vikas, On 1/15/21 7:26 AM, Vikas Gupta wrote: > Hi Eric, > > On Tue, Jan 12, 2021 at 2:30 PM Auger Eric wrote: >> >> Hi Vikas, >> >> On 1/5/21 6:53 AM, Vikas Gupta wrote: >>> On Tue, Dec 22, 2020 at 10:57 PM Auger Eric wrote: Hi Vikas, On 12/14/20 6:45 PM, Vikas Gupta wrote: > MSI support for platform devices.The MSI block > is added as an extended IRQ which exports caps > VFIO_IRQ_INFO_CAP_TYPE and VFIO_IRQ_INFO_CAP_MSI_DESCS. > > Signed-off-by: Vikas Gupta > --- > drivers/vfio/platform/vfio_platform_common.c | 179 +++- > drivers/vfio/platform/vfio_platform_irq.c | 260 +- > drivers/vfio/platform/vfio_platform_private.h | 32 +++ > include/uapi/linux/vfio.h | 44 +++ > 4 files changed, 496 insertions(+), 19 deletions(-) > > diff --git a/drivers/vfio/platform/vfio_platform_common.c > b/drivers/vfio/platform/vfio_platform_common.c > index fb4b385191f2..c936852f35d7 100644 > --- a/drivers/vfio/platform/vfio_platform_common.c > +++ b/drivers/vfio/platform/vfio_platform_common.c > @@ -16,6 +16,7 @@ > #include > #include > #include > +#include > > #include "vfio_platform_private.h" > > @@ -26,6 +27,8 @@ > #define VFIO_PLATFORM_IS_ACPI(vdev) ((vdev)->acpihid != NULL) > > static LIST_HEAD(reset_list); > +/* devices having MSI support */ nit: for devices using MSIs? > +static LIST_HEAD(msi_list); > static DEFINE_MUTEX(driver_lock); > > static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char > *compat, > @@ -47,6 +50,25 @@ static vfio_platform_reset_fn_t > vfio_platform_lookup_reset(const char *compat, > return reset_fn; > } > > +static bool vfio_platform_lookup_msi(struct vfio_platform_device *vdev) > +{ > + bool has_msi = false; > + struct vfio_platform_msi_node *iter; > + > + mutex_lock(_lock); > + list_for_each_entry(iter, _list, link) { > + if (!strcmp(iter->compat, vdev->compat) && > + try_module_get(iter->owner)) { > + vdev->msi_module = iter->owner; > + vdev->of_get_msi = iter->of_get_msi; > + has_msi = true; > + break; > + } > + } > + mutex_unlock(_lock); > + return has_msi; > +} > + > static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev, > struct device *dev) > { > @@ -126,6 +148,19 @@ static int vfio_platform_get_reset(struct > vfio_platform_device *vdev) > return vdev->of_reset ? 0 : -ENOENT; > } > > +static int vfio_platform_get_msi(struct vfio_platform_device *vdev) > +{ > + bool has_msi; > + > + has_msi = vfio_platform_lookup_msi(vdev); > + if (!has_msi) { > + request_module("vfio-msi:%s", vdev->compat); > + has_msi = vfio_platform_lookup_msi(vdev); > + } > + > + return has_msi ? 0 : -ENOENT; > +} > + > static void vfio_platform_put_reset(struct vfio_platform_device *vdev) > { > if (VFIO_PLATFORM_IS_ACPI(vdev)) > @@ -135,6 +170,12 @@ static void vfio_platform_put_reset(struct > vfio_platform_device *vdev) > module_put(vdev->reset_module); > } > > +static void vfio_platform_put_msi(struct vfio_platform_device *vdev) > +{ > + if (vdev->of_get_msi) > + module_put(vdev->msi_module); > +} > + > static int vfio_platform_regions_init(struct vfio_platform_device *vdev) > { > int cnt = 0, i; > @@ -343,9 +384,17 @@ static long vfio_platform_ioctl(void *device_data, > > } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { > struct vfio_irq_info info; > + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; > + struct vfio_irq_info_cap_msi *msi_info = NULL; > + int ext_irq_index = vdev->num_irqs - vdev->num_ext_irqs; > + unsigned long capsz; > + u32 index; > > minsz = offsetofend(struct vfio_irq_info, count); > > + /* For backward compatibility, cannot require this */ > + capsz = offsetofend(struct vfio_irq_info, cap_offset); > + > if (copy_from_user(, (void __user *)arg, minsz)) > return -EFAULT; > > @@ -355,8 +404,94 @@ static long vfio_platform_ioctl(void *device_data, > if (info.index >= vdev->num_irqs) > return -EINVAL; > > - info.flags = vdev->irqs[info.index].flags; > - info.count =
Re: [RFC v3 1/2] vfio/platform: add support for msi
Hi Eric, On Tue, Jan 12, 2021 at 2:30 PM Auger Eric wrote: > > Hi Vikas, > > On 1/5/21 6:53 AM, Vikas Gupta wrote: > > On Tue, Dec 22, 2020 at 10:57 PM Auger Eric wrote: > >> > >> Hi Vikas, > >> > >> On 12/14/20 6:45 PM, Vikas Gupta wrote: > >>> MSI support for platform devices.The MSI block > >>> is added as an extended IRQ which exports caps > >>> VFIO_IRQ_INFO_CAP_TYPE and VFIO_IRQ_INFO_CAP_MSI_DESCS. > >>> > >>> Signed-off-by: Vikas Gupta > >>> --- > >>> drivers/vfio/platform/vfio_platform_common.c | 179 +++- > >>> drivers/vfio/platform/vfio_platform_irq.c | 260 +- > >>> drivers/vfio/platform/vfio_platform_private.h | 32 +++ > >>> include/uapi/linux/vfio.h | 44 +++ > >>> 4 files changed, 496 insertions(+), 19 deletions(-) > >>> > >>> diff --git a/drivers/vfio/platform/vfio_platform_common.c > >>> b/drivers/vfio/platform/vfio_platform_common.c > >>> index fb4b385191f2..c936852f35d7 100644 > >>> --- a/drivers/vfio/platform/vfio_platform_common.c > >>> +++ b/drivers/vfio/platform/vfio_platform_common.c > >>> @@ -16,6 +16,7 @@ > >>> #include > >>> #include > >>> #include > >>> +#include > >>> > >>> #include "vfio_platform_private.h" > >>> > >>> @@ -26,6 +27,8 @@ > >>> #define VFIO_PLATFORM_IS_ACPI(vdev) ((vdev)->acpihid != NULL) > >>> > >>> static LIST_HEAD(reset_list); > >>> +/* devices having MSI support */ > >> nit: for devices using MSIs? > >>> +static LIST_HEAD(msi_list); > >>> static DEFINE_MUTEX(driver_lock); > >>> > >>> static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char > >>> *compat, > >>> @@ -47,6 +50,25 @@ static vfio_platform_reset_fn_t > >>> vfio_platform_lookup_reset(const char *compat, > >>> return reset_fn; > >>> } > >>> > >>> +static bool vfio_platform_lookup_msi(struct vfio_platform_device *vdev) > >>> +{ > >>> + bool has_msi = false; > >>> + struct vfio_platform_msi_node *iter; > >>> + > >>> + mutex_lock(_lock); > >>> + list_for_each_entry(iter, _list, link) { > >>> + if (!strcmp(iter->compat, vdev->compat) && > >>> + try_module_get(iter->owner)) { > >>> + vdev->msi_module = iter->owner; > >>> + vdev->of_get_msi = iter->of_get_msi; > >>> + has_msi = true; > >>> + break; > >>> + } > >>> + } > >>> + mutex_unlock(_lock); > >>> + return has_msi; > >>> +} > >>> + > >>> static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev, > >>> struct device *dev) > >>> { > >>> @@ -126,6 +148,19 @@ static int vfio_platform_get_reset(struct > >>> vfio_platform_device *vdev) > >>> return vdev->of_reset ? 0 : -ENOENT; > >>> } > >>> > >>> +static int vfio_platform_get_msi(struct vfio_platform_device *vdev) > >>> +{ > >>> + bool has_msi; > >>> + > >>> + has_msi = vfio_platform_lookup_msi(vdev); > >>> + if (!has_msi) { > >>> + request_module("vfio-msi:%s", vdev->compat); > >>> + has_msi = vfio_platform_lookup_msi(vdev); > >>> + } > >>> + > >>> + return has_msi ? 0 : -ENOENT; > >>> +} > >>> + > >>> static void vfio_platform_put_reset(struct vfio_platform_device *vdev) > >>> { > >>> if (VFIO_PLATFORM_IS_ACPI(vdev)) > >>> @@ -135,6 +170,12 @@ static void vfio_platform_put_reset(struct > >>> vfio_platform_device *vdev) > >>> module_put(vdev->reset_module); > >>> } > >>> > >>> +static void vfio_platform_put_msi(struct vfio_platform_device *vdev) > >>> +{ > >>> + if (vdev->of_get_msi) > >>> + module_put(vdev->msi_module); > >>> +} > >>> + > >>> static int vfio_platform_regions_init(struct vfio_platform_device *vdev) > >>> { > >>> int cnt = 0, i; > >>> @@ -343,9 +384,17 @@ static long vfio_platform_ioctl(void *device_data, > >>> > >>> } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { > >>> struct vfio_irq_info info; > >>> + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; > >>> + struct vfio_irq_info_cap_msi *msi_info = NULL; > >>> + int ext_irq_index = vdev->num_irqs - vdev->num_ext_irqs; > >>> + unsigned long capsz; > >>> + u32 index; > >>> > >>> minsz = offsetofend(struct vfio_irq_info, count); > >>> > >>> + /* For backward compatibility, cannot require this */ > >>> + capsz = offsetofend(struct vfio_irq_info, cap_offset); > >>> + > >>> if (copy_from_user(, (void __user *)arg, minsz)) > >>> return -EFAULT; > >>> > >>> @@ -355,8 +404,94 @@ static long vfio_platform_ioctl(void *device_data, > >>> if (info.index >= vdev->num_irqs) > >>> return -EINVAL; > >>> > >>> - info.flags = vdev->irqs[info.index].flags; > >>> - info.count = vdev->irqs[info.index].count; > >>> + if (info.argsz >= capsz) > >>> +
Re: [RFC v3 1/2] vfio/platform: add support for msi
Hi Vikas, On 1/5/21 6:53 AM, Vikas Gupta wrote: > On Tue, Dec 22, 2020 at 10:57 PM Auger Eric wrote: >> >> Hi Vikas, >> >> On 12/14/20 6:45 PM, Vikas Gupta wrote: >>> MSI support for platform devices.The MSI block >>> is added as an extended IRQ which exports caps >>> VFIO_IRQ_INFO_CAP_TYPE and VFIO_IRQ_INFO_CAP_MSI_DESCS. >>> >>> Signed-off-by: Vikas Gupta >>> --- >>> drivers/vfio/platform/vfio_platform_common.c | 179 +++- >>> drivers/vfio/platform/vfio_platform_irq.c | 260 +- >>> drivers/vfio/platform/vfio_platform_private.h | 32 +++ >>> include/uapi/linux/vfio.h | 44 +++ >>> 4 files changed, 496 insertions(+), 19 deletions(-) >>> >>> diff --git a/drivers/vfio/platform/vfio_platform_common.c >>> b/drivers/vfio/platform/vfio_platform_common.c >>> index fb4b385191f2..c936852f35d7 100644 >>> --- a/drivers/vfio/platform/vfio_platform_common.c >>> +++ b/drivers/vfio/platform/vfio_platform_common.c >>> @@ -16,6 +16,7 @@ >>> #include >>> #include >>> #include >>> +#include >>> >>> #include "vfio_platform_private.h" >>> >>> @@ -26,6 +27,8 @@ >>> #define VFIO_PLATFORM_IS_ACPI(vdev) ((vdev)->acpihid != NULL) >>> >>> static LIST_HEAD(reset_list); >>> +/* devices having MSI support */ >> nit: for devices using MSIs? >>> +static LIST_HEAD(msi_list); >>> static DEFINE_MUTEX(driver_lock); >>> >>> static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char >>> *compat, >>> @@ -47,6 +50,25 @@ static vfio_platform_reset_fn_t >>> vfio_platform_lookup_reset(const char *compat, >>> return reset_fn; >>> } >>> >>> +static bool vfio_platform_lookup_msi(struct vfio_platform_device *vdev) >>> +{ >>> + bool has_msi = false; >>> + struct vfio_platform_msi_node *iter; >>> + >>> + mutex_lock(_lock); >>> + list_for_each_entry(iter, _list, link) { >>> + if (!strcmp(iter->compat, vdev->compat) && >>> + try_module_get(iter->owner)) { >>> + vdev->msi_module = iter->owner; >>> + vdev->of_get_msi = iter->of_get_msi; >>> + has_msi = true; >>> + break; >>> + } >>> + } >>> + mutex_unlock(_lock); >>> + return has_msi; >>> +} >>> + >>> static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev, >>> struct device *dev) >>> { >>> @@ -126,6 +148,19 @@ static int vfio_platform_get_reset(struct >>> vfio_platform_device *vdev) >>> return vdev->of_reset ? 0 : -ENOENT; >>> } >>> >>> +static int vfio_platform_get_msi(struct vfio_platform_device *vdev) >>> +{ >>> + bool has_msi; >>> + >>> + has_msi = vfio_platform_lookup_msi(vdev); >>> + if (!has_msi) { >>> + request_module("vfio-msi:%s", vdev->compat); >>> + has_msi = vfio_platform_lookup_msi(vdev); >>> + } >>> + >>> + return has_msi ? 0 : -ENOENT; >>> +} >>> + >>> static void vfio_platform_put_reset(struct vfio_platform_device *vdev) >>> { >>> if (VFIO_PLATFORM_IS_ACPI(vdev)) >>> @@ -135,6 +170,12 @@ static void vfio_platform_put_reset(struct >>> vfio_platform_device *vdev) >>> module_put(vdev->reset_module); >>> } >>> >>> +static void vfio_platform_put_msi(struct vfio_platform_device *vdev) >>> +{ >>> + if (vdev->of_get_msi) >>> + module_put(vdev->msi_module); >>> +} >>> + >>> static int vfio_platform_regions_init(struct vfio_platform_device *vdev) >>> { >>> int cnt = 0, i; >>> @@ -343,9 +384,17 @@ static long vfio_platform_ioctl(void *device_data, >>> >>> } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { >>> struct vfio_irq_info info; >>> + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; >>> + struct vfio_irq_info_cap_msi *msi_info = NULL; >>> + int ext_irq_index = vdev->num_irqs - vdev->num_ext_irqs; >>> + unsigned long capsz; >>> + u32 index; >>> >>> minsz = offsetofend(struct vfio_irq_info, count); >>> >>> + /* For backward compatibility, cannot require this */ >>> + capsz = offsetofend(struct vfio_irq_info, cap_offset); >>> + >>> if (copy_from_user(, (void __user *)arg, minsz)) >>> return -EFAULT; >>> >>> @@ -355,8 +404,94 @@ static long vfio_platform_ioctl(void *device_data, >>> if (info.index >= vdev->num_irqs) >>> return -EINVAL; >>> >>> - info.flags = vdev->irqs[info.index].flags; >>> - info.count = vdev->irqs[info.index].count; >>> + if (info.argsz >= capsz) >>> + minsz = capsz; >>> + >>> + index = info.index; >>> + >>> + info.flags = vdev->irqs[index].flags; >>> + info.count = vdev->irqs[index].count; >>> + >>> + if (ext_irq_index - index == VFIO_EXT_IRQ_MSI) { >>> + struct vfio_irq_info_cap_type
Re: [RFC v3 1/2] vfio/platform: add support for msi
On Tue, Dec 22, 2020 at 10:57 PM Auger Eric wrote: > > Hi Vikas, > > On 12/14/20 6:45 PM, Vikas Gupta wrote: > > MSI support for platform devices.The MSI block > > is added as an extended IRQ which exports caps > > VFIO_IRQ_INFO_CAP_TYPE and VFIO_IRQ_INFO_CAP_MSI_DESCS. > > > > Signed-off-by: Vikas Gupta > > --- > > drivers/vfio/platform/vfio_platform_common.c | 179 +++- > > drivers/vfio/platform/vfio_platform_irq.c | 260 +- > > drivers/vfio/platform/vfio_platform_private.h | 32 +++ > > include/uapi/linux/vfio.h | 44 +++ > > 4 files changed, 496 insertions(+), 19 deletions(-) > > > > diff --git a/drivers/vfio/platform/vfio_platform_common.c > > b/drivers/vfio/platform/vfio_platform_common.c > > index fb4b385191f2..c936852f35d7 100644 > > --- a/drivers/vfio/platform/vfio_platform_common.c > > +++ b/drivers/vfio/platform/vfio_platform_common.c > > @@ -16,6 +16,7 @@ > > #include > > #include > > #include > > +#include > > > > #include "vfio_platform_private.h" > > > > @@ -26,6 +27,8 @@ > > #define VFIO_PLATFORM_IS_ACPI(vdev) ((vdev)->acpihid != NULL) > > > > static LIST_HEAD(reset_list); > > +/* devices having MSI support */ > nit: for devices using MSIs? > > +static LIST_HEAD(msi_list); > > static DEFINE_MUTEX(driver_lock); > > > > static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char > > *compat, > > @@ -47,6 +50,25 @@ static vfio_platform_reset_fn_t > > vfio_platform_lookup_reset(const char *compat, > > return reset_fn; > > } > > > > +static bool vfio_platform_lookup_msi(struct vfio_platform_device *vdev) > > +{ > > + bool has_msi = false; > > + struct vfio_platform_msi_node *iter; > > + > > + mutex_lock(_lock); > > + list_for_each_entry(iter, _list, link) { > > + if (!strcmp(iter->compat, vdev->compat) && > > + try_module_get(iter->owner)) { > > + vdev->msi_module = iter->owner; > > + vdev->of_get_msi = iter->of_get_msi; > > + has_msi = true; > > + break; > > + } > > + } > > + mutex_unlock(_lock); > > + return has_msi; > > +} > > + > > static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev, > > struct device *dev) > > { > > @@ -126,6 +148,19 @@ static int vfio_platform_get_reset(struct > > vfio_platform_device *vdev) > > return vdev->of_reset ? 0 : -ENOENT; > > } > > > > +static int vfio_platform_get_msi(struct vfio_platform_device *vdev) > > +{ > > + bool has_msi; > > + > > + has_msi = vfio_platform_lookup_msi(vdev); > > + if (!has_msi) { > > + request_module("vfio-msi:%s", vdev->compat); > > + has_msi = vfio_platform_lookup_msi(vdev); > > + } > > + > > + return has_msi ? 0 : -ENOENT; > > +} > > + > > static void vfio_platform_put_reset(struct vfio_platform_device *vdev) > > { > > if (VFIO_PLATFORM_IS_ACPI(vdev)) > > @@ -135,6 +170,12 @@ static void vfio_platform_put_reset(struct > > vfio_platform_device *vdev) > > module_put(vdev->reset_module); > > } > > > > +static void vfio_platform_put_msi(struct vfio_platform_device *vdev) > > +{ > > + if (vdev->of_get_msi) > > + module_put(vdev->msi_module); > > +} > > + > > static int vfio_platform_regions_init(struct vfio_platform_device *vdev) > > { > > int cnt = 0, i; > > @@ -343,9 +384,17 @@ static long vfio_platform_ioctl(void *device_data, > > > > } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { > > struct vfio_irq_info info; > > + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; > > + struct vfio_irq_info_cap_msi *msi_info = NULL; > > + int ext_irq_index = vdev->num_irqs - vdev->num_ext_irqs; > > + unsigned long capsz; > > + u32 index; > > > > minsz = offsetofend(struct vfio_irq_info, count); > > > > + /* For backward compatibility, cannot require this */ > > + capsz = offsetofend(struct vfio_irq_info, cap_offset); > > + > > if (copy_from_user(, (void __user *)arg, minsz)) > > return -EFAULT; > > > > @@ -355,8 +404,94 @@ static long vfio_platform_ioctl(void *device_data, > > if (info.index >= vdev->num_irqs) > > return -EINVAL; > > > > - info.flags = vdev->irqs[info.index].flags; > > - info.count = vdev->irqs[info.index].count; > > + if (info.argsz >= capsz) > > + minsz = capsz; > > + > > + index = info.index; > > + > > + info.flags = vdev->irqs[index].flags; > > + info.count = vdev->irqs[index].count; > > + > > + if (ext_irq_index - index == VFIO_EXT_IRQ_MSI) { > > + struct vfio_irq_info_cap_type cap_type = { > > + .header.id =
Re: [RFC v3 1/2] vfio/platform: add support for msi
Hi Vikas, On 12/14/20 6:45 PM, Vikas Gupta wrote: > MSI support for platform devices.The MSI block > is added as an extended IRQ which exports caps > VFIO_IRQ_INFO_CAP_TYPE and VFIO_IRQ_INFO_CAP_MSI_DESCS. > > Signed-off-by: Vikas Gupta > --- > drivers/vfio/platform/vfio_platform_common.c | 179 +++- > drivers/vfio/platform/vfio_platform_irq.c | 260 +- > drivers/vfio/platform/vfio_platform_private.h | 32 +++ > include/uapi/linux/vfio.h | 44 +++ > 4 files changed, 496 insertions(+), 19 deletions(-) > > diff --git a/drivers/vfio/platform/vfio_platform_common.c > b/drivers/vfio/platform/vfio_platform_common.c > index fb4b385191f2..c936852f35d7 100644 > --- a/drivers/vfio/platform/vfio_platform_common.c > +++ b/drivers/vfio/platform/vfio_platform_common.c > @@ -16,6 +16,7 @@ > #include > #include > #include > +#include > > #include "vfio_platform_private.h" > > @@ -26,6 +27,8 @@ > #define VFIO_PLATFORM_IS_ACPI(vdev) ((vdev)->acpihid != NULL) > > static LIST_HEAD(reset_list); > +/* devices having MSI support */ nit: for devices using MSIs? > +static LIST_HEAD(msi_list); > static DEFINE_MUTEX(driver_lock); > > static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char > *compat, > @@ -47,6 +50,25 @@ static vfio_platform_reset_fn_t > vfio_platform_lookup_reset(const char *compat, > return reset_fn; > } > > +static bool vfio_platform_lookup_msi(struct vfio_platform_device *vdev) > +{ > + bool has_msi = false; > + struct vfio_platform_msi_node *iter; > + > + mutex_lock(_lock); > + list_for_each_entry(iter, _list, link) { > + if (!strcmp(iter->compat, vdev->compat) && > + try_module_get(iter->owner)) { > + vdev->msi_module = iter->owner; > + vdev->of_get_msi = iter->of_get_msi; > + has_msi = true; > + break; > + } > + } > + mutex_unlock(_lock); > + return has_msi; > +} > + > static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev, > struct device *dev) > { > @@ -126,6 +148,19 @@ static int vfio_platform_get_reset(struct > vfio_platform_device *vdev) > return vdev->of_reset ? 0 : -ENOENT; > } > > +static int vfio_platform_get_msi(struct vfio_platform_device *vdev) > +{ > + bool has_msi; > + > + has_msi = vfio_platform_lookup_msi(vdev); > + if (!has_msi) { > + request_module("vfio-msi:%s", vdev->compat); > + has_msi = vfio_platform_lookup_msi(vdev); > + } > + > + return has_msi ? 0 : -ENOENT; > +} > + > static void vfio_platform_put_reset(struct vfio_platform_device *vdev) > { > if (VFIO_PLATFORM_IS_ACPI(vdev)) > @@ -135,6 +170,12 @@ static void vfio_platform_put_reset(struct > vfio_platform_device *vdev) > module_put(vdev->reset_module); > } > > +static void vfio_platform_put_msi(struct vfio_platform_device *vdev) > +{ > + if (vdev->of_get_msi) > + module_put(vdev->msi_module); > +} > + > static int vfio_platform_regions_init(struct vfio_platform_device *vdev) > { > int cnt = 0, i; > @@ -343,9 +384,17 @@ static long vfio_platform_ioctl(void *device_data, > > } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) { > struct vfio_irq_info info; > + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; > + struct vfio_irq_info_cap_msi *msi_info = NULL; > + int ext_irq_index = vdev->num_irqs - vdev->num_ext_irqs; > + unsigned long capsz; > + u32 index; > > minsz = offsetofend(struct vfio_irq_info, count); > > + /* For backward compatibility, cannot require this */ > + capsz = offsetofend(struct vfio_irq_info, cap_offset); > + > if (copy_from_user(, (void __user *)arg, minsz)) > return -EFAULT; > > @@ -355,8 +404,94 @@ static long vfio_platform_ioctl(void *device_data, > if (info.index >= vdev->num_irqs) > return -EINVAL; > > - info.flags = vdev->irqs[info.index].flags; > - info.count = vdev->irqs[info.index].count; > + if (info.argsz >= capsz) > + minsz = capsz; > + > + index = info.index; > + > + info.flags = vdev->irqs[index].flags; > + info.count = vdev->irqs[index].count; > + > + if (ext_irq_index - index == VFIO_EXT_IRQ_MSI) { > + struct vfio_irq_info_cap_type cap_type = { > + .header.id = VFIO_IRQ_INFO_CAP_TYPE, > + .header.version = 1 }; > + struct vfio_platform_irq *irq; > + size_t msi_info_size; > + int num_msgs; > + int ret; > + int i; > + > +