diff options
Diffstat (limited to 'kernel/irq/msi.c')
| -rw-r--r-- | kernel/irq/msi.c | 95 | 
1 files changed, 20 insertions, 75 deletions
| diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 2024f89baea4..5fa0547ece0c 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -8,18 +8,34 @@   * This file contains common code to support Message Signaled Interrupts for   * PCI compatible and non PCI compatible devices.   */ -#include <linux/types.h>  #include <linux/device.h>  #include <linux/irq.h>  #include <linux/irqdomain.h>  #include <linux/msi.h> +#include <linux/mutex.h> +#include <linux/pci.h>  #include <linux/slab.h>  #include <linux/sysfs.h> -#include <linux/pci.h> +#include <linux/types.h> +#include <linux/xarray.h>  #include "internals.h"  /** + * struct msi_device_data - MSI per device data + * @properties:		MSI properties which are interesting to drivers + * @mutex:		Mutex protecting the MSI descriptor store + * @__domains:		Internal data for per device MSI domains + * @__iter_idx:		Index to search the next entry for iterators + */ +struct msi_device_data { +	unsigned long			properties; +	struct mutex			mutex; +	struct msi_dev_domain		__domains[MSI_MAX_DEVICE_IRQDOMAINS]; +	unsigned long			__iter_idx; +}; + +/**   * struct msi_ctrl - MSI internal management control structure   * @domid:	ID of the domain on which management operations should be done   * @first:	First (hardware) slot index to operate on @@ -1088,8 +1104,8 @@ bool msi_match_device_irq_domain(struct device *dev, unsigned int domid,  	return ret;  } -int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, -			    int nvec, msi_alloc_info_t *arg) +static int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, +				   int nvec, msi_alloc_info_t *arg)  {  	struct msi_domain_info *info = domain->host_data;  	struct msi_domain_ops *ops = info->ops; @@ -1097,77 +1113,6 @@ int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,  	return ops->msi_prepare(domain, dev, nvec, arg);  } -int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev, -			     int virq_base, int nvec, msi_alloc_info_t *arg) -{ -	struct msi_domain_info *info = domain->host_data; -	struct msi_domain_ops *ops = info->ops; -	struct msi_ctrl ctrl = { -		.domid	= MSI_DEFAULT_DOMAIN, -		.first  = virq_base, -		.last	= virq_base + nvec - 1, -	}; -	struct msi_desc *desc; -	struct xarray *xa; -	int ret, virq; - -	msi_lock_descs(dev); - -	if (!msi_ctrl_valid(dev, &ctrl)) { -		ret = -EINVAL; -		goto unlock; -	} - -	ret = msi_domain_add_simple_msi_descs(dev, &ctrl); -	if (ret) -		goto unlock; - -	xa = &dev->msi.data->__domains[ctrl.domid].store; - -	for (virq = virq_base; virq < virq_base + nvec; virq++) { -		desc = xa_load(xa, virq); -		desc->irq = virq; - -		ops->set_desc(arg, desc); -		ret = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg); -		if (ret) -			goto fail; - -		irq_set_msi_desc(virq, desc); -	} -	msi_unlock_descs(dev); -	return 0; - -fail: -	for (--virq; virq >= virq_base; virq--) { -		msi_domain_depopulate_descs(dev, virq, 1); -		irq_domain_free_irqs_common(domain, virq, 1); -	} -	msi_domain_free_descs(dev, &ctrl); -unlock: -	msi_unlock_descs(dev); -	return ret; -} - -void msi_domain_depopulate_descs(struct device *dev, int virq_base, int nvec) -{ -	struct msi_ctrl ctrl = { -		.domid	= MSI_DEFAULT_DOMAIN, -		.first  = virq_base, -		.last	= virq_base + nvec - 1, -	}; -	struct msi_desc *desc; -	struct xarray *xa; -	unsigned long idx; - -	if (!msi_ctrl_valid(dev, &ctrl)) -		return; - -	xa = &dev->msi.data->__domains[ctrl.domid].store; -	xa_for_each_range(xa, idx, desc, ctrl.first, ctrl.last) -		desc->irq = 0; -} -  /*   * Carefully check whether the device can use reservation mode. If   * reservation mode is enabled then the early activation will assign a |