Commit 998fb7ba authored by Diana Craciun's avatar Diana Craciun Committed by Catalin Marinas
Browse files

bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver



The DPRC driver is not taking into account the msi-map property
and assumes that the icid is the same as the stream ID. Although
this assumption is correct, generalize the code to include a
translation between icid and streamID.

Furthermore do not just copy the MSI domain from parent (for child
containers), but use the information provided by the msi-map property.

If the msi-map property is missing from the device tree retain the old
behaviour for backward compatibility ie the child DPRC objects
inherit the MSI domain from the parent.

Signed-off-by: default avatarDiana Craciun <diana.craciun@oss.nxp.com>
Acked-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20200619082013.13661-12-lorenzo.pieralisi@arm.com


Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 2bcdd8f2
Loading
Loading
Loading
Loading
+8 −23
Original line number Diff line number Diff line
@@ -592,6 +592,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
	bool mc_io_created = false;
	bool msi_domain_set = false;
	u16 major_ver, minor_ver;
	struct irq_domain *mc_msi_domain;

	if (!is_fsl_mc_bus_dprc(mc_dev))
		return -EINVAL;
@@ -621,32 +622,16 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
			return error;

		mc_io_created = true;
	}

		/*
		 * Inherit parent MSI domain:
		 */
		dev_set_msi_domain(&mc_dev->dev,
				   dev_get_msi_domain(parent_dev));
		msi_domain_set = true;
	} else {
		/*
		 * This is a root DPRC
		 */
		struct irq_domain *mc_msi_domain;

		if (dev_is_fsl_mc(parent_dev))
			return -EINVAL;

		error = fsl_mc_find_msi_domain(parent_dev,
					       &mc_msi_domain);
		if (error < 0) {
	mc_msi_domain = fsl_mc_find_msi_domain(&mc_dev->dev);
	if (!mc_msi_domain) {
		dev_warn(&mc_dev->dev,
			 "WARNING: MC bus without interrupt support\n");
	} else {
		dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
		msi_domain_set = true;
	}
	}

	error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
			  &mc_dev->mc_handle);
+2 −2
Original line number Diff line number Diff line
@@ -370,7 +370,7 @@ EXPORT_SYMBOL_GPL(fsl_mc_get_version);
/**
 * fsl_mc_get_root_dprc - function to traverse to the root dprc
 */
static void fsl_mc_get_root_dprc(struct device *dev,
void fsl_mc_get_root_dprc(struct device *dev,
			 struct device **root_dprc_dev)
{
	if (!dev) {
+19 −12
Original line number Diff line number Diff line
@@ -177,23 +177,30 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
	return domain;
}

int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
			   struct irq_domain **mc_msi_domain)
struct irq_domain *fsl_mc_find_msi_domain(struct device *dev)
{
	struct irq_domain *msi_domain;
	struct device_node *mc_of_node = mc_platform_dev->of_node;
	struct irq_domain *msi_domain = NULL;
	struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);

	msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
	msi_domain = of_msi_map_get_device_domain(dev, mc_dev->icid,
						  DOMAIN_BUS_FSL_MC_MSI);

	/*
	 * if the msi-map property is missing assume that all the
	 * child containers inherit the domain from the parent
	 */
	if (!msi_domain) {
		pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
		       mc_of_node);
		struct device *root_dprc_dev;
		struct device *bus_dev;

		return -ENOENT;
		fsl_mc_get_root_dprc(dev, &root_dprc_dev);
		bus_dev = root_dprc_dev->parent;
		msi_domain = of_msi_get_domain(bus_dev,
					       bus_dev->of_node,
					       DOMAIN_BUS_FSL_MC_MSI);
	}

	*mc_msi_domain = msi_domain;
	return 0;
	return msi_domain;
}

static void fsl_mc_msi_free_descs(struct device *dev)
+4 −2
Original line number Diff line number Diff line
@@ -595,8 +595,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev,

void fsl_mc_msi_domain_free_irqs(struct device *dev);

int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
			   struct irq_domain **mc_msi_domain);
struct irq_domain *fsl_mc_find_msi_domain(struct device *dev);

int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
			     unsigned int irq_count);
@@ -613,6 +612,9 @@ void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);

bool fsl_mc_is_root_dprc(struct device *dev);

void fsl_mc_get_root_dprc(struct device *dev,
			 struct device **root_dprc_dev);

struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc *obj_desc,
					   struct fsl_mc_device *mc_bus_dev);

+14 −1
Original line number Diff line number Diff line
@@ -23,6 +23,18 @@ static struct irq_chip its_msi_irq_chip = {
	.irq_set_affinity = msi_domain_set_affinity
};

static u32 fsl_mc_msi_domain_get_msi_id(struct irq_domain *domain,
					struct fsl_mc_device *mc_dev)
{
	struct device_node *of_node;
	u32 out_id;

	of_node = irq_domain_get_of_node(domain);
	out_id = of_msi_map_id(&mc_dev->dev, of_node, mc_dev->icid);

	return out_id;
}

static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
				  struct device *dev,
				  int nvec, msi_alloc_info_t *info)
@@ -43,7 +55,8 @@ static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
	 * NOTE: This device id corresponds to the IOMMU stream ID
	 * associated with the DPRC object (ICID).
	 */
	info->scratchpad[0].ul = mc_bus_dev->icid;
	info->scratchpad[0].ul = fsl_mc_msi_domain_get_msi_id(msi_domain,
							      mc_bus_dev);
	msi_info = msi_get_domain_info(msi_domain->parent);

	/* Allocate at least 32 MSIs, and always as a power of 2 */