Skip to content

Commit c88f911

Browse files
committed
platform-msi: Prepare for real per device domains
Provide functions to create and remove per device MSI domains which replace the platform-MSI domains. The new model is that each of the devices which utilize platform-MSI gets now its private MSI domain which is "customized" in size and with a device specific function to write the MSI message into the device. This is the same functionality as platform-MSI but it avoids all the down sides of platform MSI, i.e. the extra ID book keeping, the special data structure in the msi descriptor. Further the domains are only created when the devices are really in use, so the burden is on the usage and not on the infrastructure. Fill in the domain template and provide two functions to init/allocate and remove a per device MSI domain. Until all users and parent domain providers are converted, the init/alloc function invokes the original platform-MSI code when the irqdomain which is associated to the device does not provide MSI parent functionality yet. Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Anup Patel <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 6516d5a commit c88f911

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

drivers/base/platform-msi.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <linux/msi.h>
1414
#include <linux/slab.h>
1515

16+
/* Begin of removal area. Once everything is converted over. Cleanup the includes too! */
17+
1618
#define DEV_ID_SHIFT 21
1719
#define MAX_DEV_MSIS (1 << (32 - DEV_ID_SHIFT))
1820

@@ -350,3 +352,104 @@ int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int vir
350352

351353
return msi_domain_populate_irqs(domain->parent, dev, virq, nr_irqs, &data->arg);
352354
}
355+
356+
/* End of removal area */
357+
358+
/* Real per device domain interfaces */
359+
360+
/*
361+
* This indirection can go when platform_device_msi_init_and_alloc_irqs()
362+
* is switched to a proper irq_chip::irq_write_msi_msg() callback. Keep it
363+
* simple for now.
364+
*/
365+
static void platform_msi_write_msi_msg(struct irq_data *d, struct msi_msg *msg)
366+
{
367+
irq_write_msi_msg_t cb = d->chip_data;
368+
369+
cb(irq_data_get_msi_desc(d), msg);
370+
}
371+
372+
static void platform_msi_set_desc_byindex(msi_alloc_info_t *arg, struct msi_desc *desc)
373+
{
374+
arg->desc = desc;
375+
arg->hwirq = desc->msi_index;
376+
}
377+
378+
static const struct msi_domain_template platform_msi_template = {
379+
.chip = {
380+
.name = "pMSI",
381+
.irq_mask = irq_chip_mask_parent,
382+
.irq_unmask = irq_chip_unmask_parent,
383+
.irq_write_msi_msg = platform_msi_write_msi_msg,
384+
/* The rest is filled in by the platform MSI parent */
385+
},
386+
387+
.ops = {
388+
.set_desc = platform_msi_set_desc_byindex,
389+
},
390+
391+
.info = {
392+
.bus_token = DOMAIN_BUS_DEVICE_MSI,
393+
},
394+
};
395+
396+
/**
397+
* platform_device_msi_init_and_alloc_irqs - Initialize platform device MSI
398+
* and allocate interrupts for @dev
399+
* @dev: The device for which to allocate interrupts
400+
* @nvec: The number of interrupts to allocate
401+
* @write_msi_msg: Callback to write an interrupt message for @dev
402+
*
403+
* Returns:
404+
* Zero for success, or an error code in case of failure
405+
*
406+
* This creates a MSI domain on @dev which has @dev->msi.domain as
407+
* parent. The parent domain sets up the new domain. The domain has
408+
* a fixed size of @nvec. The domain is managed by devres and will
409+
* be removed when the device is removed.
410+
*
411+
* Note: For migration purposes this falls back to the original platform_msi code
412+
* up to the point where all platforms have been converted to the MSI
413+
* parent model.
414+
*/
415+
int platform_device_msi_init_and_alloc_irqs(struct device *dev, unsigned int nvec,
416+
irq_write_msi_msg_t write_msi_msg)
417+
{
418+
struct irq_domain *domain = dev->msi.domain;
419+
420+
if (!domain || !write_msi_msg)
421+
return -EINVAL;
422+
423+
/* Migration support. Will go away once everything is converted */
424+
if (!irq_domain_is_msi_parent(domain))
425+
return platform_msi_domain_alloc_irqs(dev, nvec, write_msi_msg);
426+
427+
/*
428+
* @write_msi_msg is stored in the resulting msi_domain_info::data.
429+
* The underlying domain creation mechanism will assign that
430+
* callback to the resulting irq chip.
431+
*/
432+
if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN,
433+
&platform_msi_template,
434+
nvec, NULL, write_msi_msg))
435+
return -ENODEV;
436+
437+
return msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, nvec - 1);
438+
}
439+
EXPORT_SYMBOL_GPL(platform_device_msi_init_and_alloc_irqs);
440+
441+
/**
442+
* platform_device_msi_free_irqs_all - Free all interrupts for @dev
443+
* @dev: The device for which to free interrupts
444+
*/
445+
void platform_device_msi_free_irqs_all(struct device *dev)
446+
{
447+
struct irq_domain *domain = dev->msi.domain;
448+
449+
msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
450+
451+
/* Migration support. Will go away once everything is converted */
452+
if (!irq_domain_is_msi_parent(domain))
453+
platform_msi_free_priv_data(dev);
454+
}
455+
EXPORT_SYMBOL_GPL(platform_device_msi_free_irqs_all);

include/linux/msi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,10 @@ int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int vir
664664
void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int virq,
665665
unsigned int nvec);
666666
void *platform_msi_get_host_data(struct irq_domain *domain);
667+
/* Per device platform MSI */
668+
int platform_device_msi_init_and_alloc_irqs(struct device *dev, unsigned int nvec,
669+
irq_write_msi_msg_t write_msi_msg);
670+
void platform_device_msi_free_irqs_all(struct device *dev);
667671

668672
bool msi_device_has_isolated_msi(struct device *dev);
669673
#else /* CONFIG_GENERIC_MSI_IRQ */

0 commit comments

Comments
 (0)