Re: [PATCH V2 1/7] PCI: dwc: Move MSI functionality related code to separate file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jul 15, 2024 at 11:13:29AM -0700, Mayank Rana wrote:
> This change moves dwc PCIe controller specific MSI functionality
> into separate file in preparation to allow MSI functionality with
> PCIe ECAM driver. Update existing drivers to accommodate this change.
> 

Could you please add more info on how the move is happening? For sure you are
not just copy pasting stuff...

> Signed-off-by: Mayank Rana <quic_mrana@xxxxxxxxxxx>
> ---
>  drivers/pci/controller/dwc/Makefile               |   2 +-
>  drivers/pci/controller/dwc/pci-keystone.c         |  12 +-
>  drivers/pci/controller/dwc/pcie-designware-host.c | 420 +---------------------
>  drivers/pci/controller/dwc/pcie-designware-msi.c  | 409 +++++++++++++++++++++
>  drivers/pci/controller/dwc/pcie-designware-msi.h  |  43 +++
>  drivers/pci/controller/dwc/pcie-designware.c      |   1 +
>  drivers/pci/controller/dwc/pcie-designware.h      |  26 +-
>  drivers/pci/controller/dwc/pcie-rcar-gen4.c       |   1 +
>  drivers/pci/controller/dwc/pcie-tegra194.c        |   5 +-
>  9 files changed, 484 insertions(+), 435 deletions(-)
>  create mode 100644 drivers/pci/controller/dwc/pcie-designware-msi.c
>  create mode 100644 drivers/pci/controller/dwc/pcie-designware-msi.h
> 
> diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
> index bac103f..2ecc603 100644
> --- a/drivers/pci/controller/dwc/Makefile
> +++ b/drivers/pci/controller/dwc/Makefile
> @@ -1,6 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0
>  obj-$(CONFIG_PCIE_DW) += pcie-designware.o
> -obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o
> +obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o pcie-designware-msi.o
>  obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
>  obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
>  obj-$(CONFIG_PCIE_BT1) += pcie-bt1.o
> diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
> index cd0e002..b95d319 100644
> --- a/drivers/pci/controller/dwc/pci-keystone.c
> +++ b/drivers/pci/controller/dwc/pci-keystone.c
> @@ -307,8 +307,14 @@ static int ks_pcie_msi_host_init(struct dw_pcie_rp *pp)
>  	 */
>  	dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, ks_pcie->app.start);
>  
> -	pp->msi_irq_chip = &ks_pcie_msi_irq_chip;
> -	return dw_pcie_allocate_domains(pp);
> +	pp->msi = devm_kzalloc(pci->dev, sizeof(struct dw_msi *), GFP_KERNEL);
> +	if (pp->msi == NULL)
> +		return -ENOMEM;
> +
> +	pp->msi->msi_irq_chip = &ks_pcie_msi_irq_chip;
> +	pp->msi->dev =  pci->dev;
> +	pp->msi->private_data = pp;

It'd be better to have an API to allocate 'struct dw_msi' and populate these
parameters, like:

pp->msi = dw_pcie_alloc_msi(dev, &ks_pcie_msi_irq_chip, pp);

This API could then be used in dw_pcie_msi_host_init() also.

Rest LGTM!

- Mani

> +	return dw_pcie_allocate_domains(pp->msi);
>  }
>  
>  static void ks_pcie_handle_intx_irq(struct keystone_pcie *ks_pcie,
> @@ -322,7 +328,7 @@ static void ks_pcie_handle_intx_irq(struct keystone_pcie *ks_pcie,
>  
>  	if (BIT(0) & pending) {
>  		dev_dbg(dev, ": irq: irq_offset %d", offset);
> -		generic_handle_domain_irq(ks_pcie->intx_irq_domain, offset);
> +		generic_handle_domain_irq(ks_pcie->msi->intx_irq_domain, offset);
>  	}
>  
>  	/* EOI the INTx interrupt */
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index a0822d5..3dcf88a 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -9,9 +9,6 @@
>   */
>  
>  #include <linux/iopoll.h>
> -#include <linux/irqchip/chained_irq.h>
> -#include <linux/irqdomain.h>
> -#include <linux/msi.h>
>  #include <linux/of_address.h>
>  #include <linux/of_pci.h>
>  #include <linux/pci_regs.h>
> @@ -19,385 +16,11 @@
>  
>  #include "../../pci.h"
>  #include "pcie-designware.h"
> +#include "pcie-designware-msi.h"
>  
>  static struct pci_ops dw_pcie_ops;
>  static struct pci_ops dw_child_pcie_ops;
>  
> -static void dw_msi_ack_irq(struct irq_data *d)
> -{
> -	irq_chip_ack_parent(d);
> -}
> -
> -static void dw_msi_mask_irq(struct irq_data *d)
> -{
> -	pci_msi_mask_irq(d);
> -	irq_chip_mask_parent(d);
> -}
> -
> -static void dw_msi_unmask_irq(struct irq_data *d)
> -{
> -	pci_msi_unmask_irq(d);
> -	irq_chip_unmask_parent(d);
> -}
> -
> -static struct irq_chip dw_pcie_msi_irq_chip = {
> -	.name = "PCI-MSI",
> -	.irq_ack = dw_msi_ack_irq,
> -	.irq_mask = dw_msi_mask_irq,
> -	.irq_unmask = dw_msi_unmask_irq,
> -};
> -
> -static struct msi_domain_info dw_pcie_msi_domain_info = {
> -	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
> -		   MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI),
> -	.chip	= &dw_pcie_msi_irq_chip,
> -};
> -
> -/* MSI int handler */
> -irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp)
> -{
> -	int i, pos;
> -	unsigned long val;
> -	u32 status, num_ctrls;
> -	irqreturn_t ret = IRQ_NONE;
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -
> -	num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
> -
> -	for (i = 0; i < num_ctrls; i++) {
> -		status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS +
> -					   (i * MSI_REG_CTRL_BLOCK_SIZE));
> -		if (!status)
> -			continue;
> -
> -		ret = IRQ_HANDLED;
> -		val = status;
> -		pos = 0;
> -		while ((pos = find_next_bit(&val, MAX_MSI_IRQS_PER_CTRL,
> -					    pos)) != MAX_MSI_IRQS_PER_CTRL) {
> -			generic_handle_domain_irq(pp->irq_domain,
> -						  (i * MAX_MSI_IRQS_PER_CTRL) +
> -						  pos);
> -			pos++;
> -		}
> -	}
> -
> -	return ret;
> -}
> -
> -/* Chained MSI interrupt service routine */
> -static void dw_chained_msi_isr(struct irq_desc *desc)
> -{
> -	struct irq_chip *chip = irq_desc_get_chip(desc);
> -	struct dw_pcie_rp *pp;
> -
> -	chained_irq_enter(chip, desc);
> -
> -	pp = irq_desc_get_handler_data(desc);
> -	dw_handle_msi_irq(pp);
> -
> -	chained_irq_exit(chip, desc);
> -}
> -
> -static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)
> -{
> -	struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	u64 msi_target;
> -
> -	msi_target = (u64)pp->msi_data;
> -
> -	msg->address_lo = lower_32_bits(msi_target);
> -	msg->address_hi = upper_32_bits(msi_target);
> -
> -	msg->data = d->hwirq;
> -
> -	dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",
> -		(int)d->hwirq, msg->address_hi, msg->address_lo);
> -}
> -
> -static int dw_pci_msi_set_affinity(struct irq_data *d,
> -				   const struct cpumask *mask, bool force)
> -{
> -	return -EINVAL;
> -}
> -
> -static void dw_pci_bottom_mask(struct irq_data *d)
> -{
> -	struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	unsigned int res, bit, ctrl;
> -	unsigned long flags;
> -
> -	raw_spin_lock_irqsave(&pp->lock, flags);
> -
> -	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
> -	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
> -	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
> -
> -	pp->irq_mask[ctrl] |= BIT(bit);
> -	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);
> -
> -	raw_spin_unlock_irqrestore(&pp->lock, flags);
> -}
> -
> -static void dw_pci_bottom_unmask(struct irq_data *d)
> -{
> -	struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	unsigned int res, bit, ctrl;
> -	unsigned long flags;
> -
> -	raw_spin_lock_irqsave(&pp->lock, flags);
> -
> -	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
> -	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
> -	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
> -
> -	pp->irq_mask[ctrl] &= ~BIT(bit);
> -	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);
> -
> -	raw_spin_unlock_irqrestore(&pp->lock, flags);
> -}
> -
> -static void dw_pci_bottom_ack(struct irq_data *d)
> -{
> -	struct dw_pcie_rp *pp  = irq_data_get_irq_chip_data(d);
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	unsigned int res, bit, ctrl;
> -
> -	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
> -	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
> -	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
> -
> -	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_STATUS + res, BIT(bit));
> -}
> -
> -static struct irq_chip dw_pci_msi_bottom_irq_chip = {
> -	.name = "DWPCI-MSI",
> -	.irq_ack = dw_pci_bottom_ack,
> -	.irq_compose_msi_msg = dw_pci_setup_msi_msg,
> -	.irq_set_affinity = dw_pci_msi_set_affinity,
> -	.irq_mask = dw_pci_bottom_mask,
> -	.irq_unmask = dw_pci_bottom_unmask,
> -};
> -
> -static int dw_pcie_irq_domain_alloc(struct irq_domain *domain,
> -				    unsigned int virq, unsigned int nr_irqs,
> -				    void *args)
> -{
> -	struct dw_pcie_rp *pp = domain->host_data;
> -	unsigned long flags;
> -	u32 i;
> -	int bit;
> -
> -	raw_spin_lock_irqsave(&pp->lock, flags);
> -
> -	bit = bitmap_find_free_region(pp->msi_irq_in_use, pp->num_vectors,
> -				      order_base_2(nr_irqs));
> -
> -	raw_spin_unlock_irqrestore(&pp->lock, flags);
> -
> -	if (bit < 0)
> -		return -ENOSPC;
> -
> -	for (i = 0; i < nr_irqs; i++)
> -		irq_domain_set_info(domain, virq + i, bit + i,
> -				    pp->msi_irq_chip,
> -				    pp, handle_edge_irq,
> -				    NULL, NULL);
> -
> -	return 0;
> -}
> -
> -static void dw_pcie_irq_domain_free(struct irq_domain *domain,
> -				    unsigned int virq, unsigned int nr_irqs)
> -{
> -	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
> -	struct dw_pcie_rp *pp = domain->host_data;
> -	unsigned long flags;
> -
> -	raw_spin_lock_irqsave(&pp->lock, flags);
> -
> -	bitmap_release_region(pp->msi_irq_in_use, d->hwirq,
> -			      order_base_2(nr_irqs));
> -
> -	raw_spin_unlock_irqrestore(&pp->lock, flags);
> -}
> -
> -static const struct irq_domain_ops dw_pcie_msi_domain_ops = {
> -	.alloc	= dw_pcie_irq_domain_alloc,
> -	.free	= dw_pcie_irq_domain_free,
> -};
> -
> -int dw_pcie_allocate_domains(struct dw_pcie_rp *pp)
> -{
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	struct fwnode_handle *fwnode = of_node_to_fwnode(pci->dev->of_node);
> -
> -	pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors,
> -					       &dw_pcie_msi_domain_ops, pp);
> -	if (!pp->irq_domain) {
> -		dev_err(pci->dev, "Failed to create IRQ domain\n");
> -		return -ENOMEM;
> -	}
> -
> -	irq_domain_update_bus_token(pp->irq_domain, DOMAIN_BUS_NEXUS);
> -
> -	pp->msi_domain = pci_msi_create_irq_domain(fwnode,
> -						   &dw_pcie_msi_domain_info,
> -						   pp->irq_domain);
> -	if (!pp->msi_domain) {
> -		dev_err(pci->dev, "Failed to create MSI domain\n");
> -		irq_domain_remove(pp->irq_domain);
> -		return -ENOMEM;
> -	}
> -
> -	return 0;
> -}
> -
> -static void dw_pcie_free_msi(struct dw_pcie_rp *pp)
> -{
> -	u32 ctrl;
> -
> -	for (ctrl = 0; ctrl < MAX_MSI_CTRLS; ctrl++) {
> -		if (pp->msi_irq[ctrl] > 0)
> -			irq_set_chained_handler_and_data(pp->msi_irq[ctrl],
> -							 NULL, NULL);
> -	}
> -
> -	irq_domain_remove(pp->msi_domain);
> -	irq_domain_remove(pp->irq_domain);
> -}
> -
> -static void dw_pcie_msi_init(struct dw_pcie_rp *pp)
> -{
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	u64 msi_target = (u64)pp->msi_data;
> -
> -	if (!pci_msi_enabled() || !pp->has_msi_ctrl)
> -		return;
> -
> -	/* Program the msi_data */
> -	dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target));
> -	dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));
> -}
> -
> -static int dw_pcie_parse_split_msi_irq(struct dw_pcie_rp *pp)
> -{
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	struct device *dev = pci->dev;
> -	struct platform_device *pdev = to_platform_device(dev);
> -	u32 ctrl, max_vectors;
> -	int irq;
> -
> -	/* Parse any "msiX" IRQs described in the devicetree */
> -	for (ctrl = 0; ctrl < MAX_MSI_CTRLS; ctrl++) {
> -		char msi_name[] = "msiX";
> -
> -		msi_name[3] = '0' + ctrl;
> -		irq = platform_get_irq_byname_optional(pdev, msi_name);
> -		if (irq == -ENXIO)
> -			break;
> -		if (irq < 0)
> -			return dev_err_probe(dev, irq,
> -					     "Failed to parse MSI IRQ '%s'\n",
> -					     msi_name);
> -
> -		pp->msi_irq[ctrl] = irq;
> -	}
> -
> -	/* If no "msiX" IRQs, caller should fallback to "msi" IRQ */
> -	if (ctrl == 0)
> -		return -ENXIO;
> -
> -	max_vectors = ctrl * MAX_MSI_IRQS_PER_CTRL;
> -	if (pp->num_vectors > max_vectors) {
> -		dev_warn(dev, "Exceeding number of MSI vectors, limiting to %u\n",
> -			 max_vectors);
> -		pp->num_vectors = max_vectors;
> -	}
> -	if (!pp->num_vectors)
> -		pp->num_vectors = max_vectors;
> -
> -	return 0;
> -}
> -
> -static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
> -{
> -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	struct device *dev = pci->dev;
> -	struct platform_device *pdev = to_platform_device(dev);
> -	u64 *msi_vaddr = NULL;
> -	int ret;
> -	u32 ctrl, num_ctrls;
> -
> -	for (ctrl = 0; ctrl < MAX_MSI_CTRLS; ctrl++)
> -		pp->irq_mask[ctrl] = ~0;
> -
> -	if (!pp->msi_irq[0]) {
> -		ret = dw_pcie_parse_split_msi_irq(pp);
> -		if (ret < 0 && ret != -ENXIO)
> -			return ret;
> -	}
> -
> -	if (!pp->num_vectors)
> -		pp->num_vectors = MSI_DEF_NUM_VECTORS;
> -	num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
> -
> -	if (!pp->msi_irq[0]) {
> -		pp->msi_irq[0] = platform_get_irq_byname_optional(pdev, "msi");
> -		if (pp->msi_irq[0] < 0) {
> -			pp->msi_irq[0] = platform_get_irq(pdev, 0);
> -			if (pp->msi_irq[0] < 0)
> -				return pp->msi_irq[0];
> -		}
> -	}
> -
> -	dev_dbg(dev, "Using %d MSI vectors\n", pp->num_vectors);
> -
> -	pp->msi_irq_chip = &dw_pci_msi_bottom_irq_chip;
> -
> -	ret = dw_pcie_allocate_domains(pp);
> -	if (ret)
> -		return ret;
> -
> -	for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
> -		if (pp->msi_irq[ctrl] > 0)
> -			irq_set_chained_handler_and_data(pp->msi_irq[ctrl],
> -						    dw_chained_msi_isr, pp);
> -	}
> -
> -	/*
> -	 * Even though the iMSI-RX Module supports 64-bit addresses some
> -	 * peripheral PCIe devices may lack 64-bit message support. In
> -	 * order not to miss MSI TLPs from those devices the MSI target
> -	 * address has to be within the lowest 4GB.
> -	 *
> -	 * Note until there is a better alternative found the reservation is
> -	 * done by allocating from the artificially limited DMA-coherent
> -	 * memory.
> -	 */
> -	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
> -	if (!ret)
> -		msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data,
> -						GFP_KERNEL);
> -
> -	if (!msi_vaddr) {
> -		dev_warn(dev, "Failed to allocate 32-bit MSI address\n");
> -		dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
> -		msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data,
> -						GFP_KERNEL);
> -		if (!msi_vaddr) {
> -			dev_err(dev, "Failed to allocate MSI address\n");
> -			dw_pcie_free_msi(pp);
> -			return -ENOMEM;
> -		}
> -	}
> -
> -	return 0;
> -}
> -
>  static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
>  {
>  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> @@ -433,6 +56,7 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  	struct resource_entry *win;
>  	struct pci_host_bridge *bridge;
>  	struct resource *res;
> +	bool has_msi_ctrl;
>  	int ret;
>  
>  	raw_spin_lock_init(&pp->lock);
> @@ -479,15 +103,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  	}
>  
>  	if (pci_msi_enabled()) {
> -		pp->has_msi_ctrl = !(pp->ops->msi_init ||
> -				     of_property_read_bool(np, "msi-parent") ||
> -				     of_property_read_bool(np, "msi-map"));
> +		has_msi_ctrl = !(pp->ops->msi_init ||
> +					of_property_read_bool(np, "msi-parent") ||
> +					of_property_read_bool(np, "msi-map"));
>  
>  		/*
>  		 * For the has_msi_ctrl case the default assignment is handled
>  		 * in the dw_pcie_msi_host_init().
>  		 */
> -		if (!pp->has_msi_ctrl && !pp->num_vectors) {
> +		if (!has_msi_ctrl && !pp->num_vectors) {
>  			pp->num_vectors = MSI_DEF_NUM_VECTORS;
>  		} else if (pp->num_vectors > MAX_MSI_IRQS) {
>  			dev_err(dev, "Invalid number of vectors\n");
> @@ -499,10 +123,12 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  			ret = pp->ops->msi_init(pp);
>  			if (ret < 0)
>  				goto err_deinit_host;
> -		} else if (pp->has_msi_ctrl) {
> -			ret = dw_pcie_msi_host_init(pp);
> -			if (ret < 0)
> +		} else if (has_msi_ctrl) {
> +			pp->msi = dw_pcie_msi_host_init(pdev, pp, pp->num_vectors);
> +			if (IS_ERR(pp->msi)) {
> +				ret = PTR_ERR(pp->msi);
>  				goto err_deinit_host;
> +			}
>  		}
>  	}
>  
> @@ -557,8 +183,7 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  	dw_pcie_edma_remove(pci);
>  
>  err_free_msi:
> -	if (pp->has_msi_ctrl)
> -		dw_pcie_free_msi(pp);
> +	dw_pcie_free_msi(pp->msi);
>  
>  err_deinit_host:
>  	if (pp->ops->deinit)
> @@ -579,8 +204,7 @@ void dw_pcie_host_deinit(struct dw_pcie_rp *pp)
>  
>  	dw_pcie_edma_remove(pci);
>  
> -	if (pp->has_msi_ctrl)
> -		dw_pcie_free_msi(pp);
> +	dw_pcie_free_msi(pp->msi);
>  
>  	if (pp->ops->deinit)
>  		pp->ops->deinit(pp);
> @@ -808,7 +432,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
>  int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
>  {
>  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> -	u32 val, ctrl, num_ctrls;
> +	u32 val;
>  	int ret;
>  
>  	/*
> @@ -819,21 +443,7 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
>  
>  	dw_pcie_setup(pci);
>  
> -	if (pp->has_msi_ctrl) {
> -		num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
> -
> -		/* Initialize IRQ Status array */
> -		for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
> -			dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK +
> -					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
> -					    pp->irq_mask[ctrl]);
> -			dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE +
> -					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE),
> -					    ~0);
> -		}
> -	}
> -
> -	dw_pcie_msi_init(pp);
> +	dw_pcie_msi_init(pp->msi);
>  
>  	/* Setup RC BARs */
>  	dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);
> diff --git a/drivers/pci/controller/dwc/pcie-designware-msi.c b/drivers/pci/controller/dwc/pcie-designware-msi.c
> new file mode 100644
> index 0000000..39fe5be
> --- /dev/null
> +++ b/drivers/pci/controller/dwc/pcie-designware-msi.c
> @@ -0,0 +1,409 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + *		https://www.samsung.com
> + *
> + * Author: Jingoo Han <jg1.han@xxxxxxxxxxx>
> + */
> +
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/msi.h>
> +#include <linux/platform_device.h>
> +
> +#include "pcie-designware.h"
> +#include "pcie-designware-msi.h"
> +
> +static void dw_msi_ack_irq(struct irq_data *d)
> +{
> +	irq_chip_ack_parent(d);
> +}
> +
> +static void dw_msi_mask_irq(struct irq_data *d)
> +{
> +	pci_msi_mask_irq(d);
> +	irq_chip_mask_parent(d);
> +}
> +
> +static void dw_msi_unmask_irq(struct irq_data *d)
> +{
> +	pci_msi_unmask_irq(d);
> +	irq_chip_unmask_parent(d);
> +}
> +
> +static struct irq_chip dw_pcie_msi_irq_chip = {
> +	.name = "PCI-MSI",
> +	.irq_ack = dw_msi_ack_irq,
> +	.irq_mask = dw_msi_mask_irq,
> +	.irq_unmask = dw_msi_unmask_irq,
> +};
> +
> +static struct msi_domain_info dw_pcie_msi_domain_info = {
> +	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
> +		   MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI),
> +	.chip	= &dw_pcie_msi_irq_chip,
> +};
> +
> +/* MSI int handler */
> +irqreturn_t dw_handle_msi_irq(struct dw_msi *msi)
> +{
> +	int i, pos;
> +	unsigned long val;
> +	u32 status, num_ctrls;
> +	irqreturn_t ret = IRQ_NONE;
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
> +
> +	num_ctrls = msi->num_vectors / MAX_MSI_IRQS_PER_CTRL;
> +
> +	for (i = 0; i < num_ctrls; i++) {
> +		status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS +
> +					   (i * MSI_REG_CTRL_BLOCK_SIZE));
> +		if (!status)
> +			continue;
> +
> +		ret = IRQ_HANDLED;
> +		val = status;
> +		pos = 0;
> +		while ((pos = find_next_bit(&val, MAX_MSI_IRQS_PER_CTRL,
> +					    pos)) != MAX_MSI_IRQS_PER_CTRL) {
> +			generic_handle_domain_irq(msi->irq_domain,
> +						  (i * MAX_MSI_IRQS_PER_CTRL) +
> +						  pos);
> +			pos++;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +/* Chained MSI interrupt service routine */
> +static void dw_chained_msi_isr(struct irq_desc *desc)
> +{
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	struct dw_msi *msi;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	msi = irq_desc_get_handler_data(desc);
> +	dw_handle_msi_irq(msi);
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
> +static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)
> +{
> +	struct dw_msi *msi = irq_data_get_irq_chip_data(d);
> +	u64 msi_target;
> +
> +	msi_target = (u64)msi->msi_data;
> +
> +	msg->address_lo = lower_32_bits(msi_target);
> +	msg->address_hi = upper_32_bits(msi_target);
> +
> +	msg->data = d->hwirq;
> +
> +	dev_dbg(msi->dev, "msi#%d address_hi %#x address_lo %#x\n",
> +		(int)d->hwirq, msg->address_hi, msg->address_lo);
> +}
> +
> +static int dw_pci_msi_set_affinity(struct irq_data *d,
> +				   const struct cpumask *mask, bool force)
> +{
> +	return -EINVAL;
> +}
> +
> +static void dw_pci_bottom_mask(struct irq_data *d)
> +{
> +	struct dw_msi *msi = irq_data_get_irq_chip_data(d);
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
> +	unsigned int res, bit, ctrl;
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&msi->lock, flags);
> +
> +	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
> +	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
> +	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
> +
> +	msi->irq_mask[ctrl] |= BIT(bit);
> +	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, msi->irq_mask[ctrl]);
> +
> +	raw_spin_unlock_irqrestore(&msi->lock, flags);
> +}
> +
> +static void dw_pci_bottom_unmask(struct irq_data *d)
> +{
> +	struct dw_msi *msi = irq_data_get_irq_chip_data(d);
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
> +	unsigned int res, bit, ctrl;
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&msi->lock, flags);
> +
> +	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
> +	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
> +	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
> +
> +	msi->irq_mask[ctrl] &= ~BIT(bit);
> +	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, msi->irq_mask[ctrl]);
> +
> +	raw_spin_unlock_irqrestore(&msi->lock, flags);
> +}
> +
> +static void dw_pci_bottom_ack(struct irq_data *d)
> +{
> +	struct dw_msi *msi  = irq_data_get_irq_chip_data(d);
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
> +	unsigned int res, bit, ctrl;
> +
> +	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
> +	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
> +	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
> +
> +	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_STATUS + res, BIT(bit));
> +}
> +
> +static struct irq_chip dw_pci_msi_bottom_irq_chip = {
> +	.name = "DWPCI-MSI",
> +	.irq_ack = dw_pci_bottom_ack,
> +	.irq_compose_msi_msg = dw_pci_setup_msi_msg,
> +	.irq_set_affinity = dw_pci_msi_set_affinity,
> +	.irq_mask = dw_pci_bottom_mask,
> +	.irq_unmask = dw_pci_bottom_unmask,
> +};
> +
> +static int dw_pcie_irq_domain_alloc(struct irq_domain *domain,
> +				    unsigned int virq, unsigned int nr_irqs,
> +				    void *args)
> +{
> +	struct dw_msi *msi = domain->host_data;
> +	unsigned long flags;
> +	u32 i;
> +	int bit;
> +
> +	raw_spin_lock_irqsave(&msi->lock, flags);
> +
> +	bit = bitmap_find_free_region(msi->msi_irq_in_use, msi->num_vectors,
> +				      order_base_2(nr_irqs));
> +
> +	raw_spin_unlock_irqrestore(&msi->lock, flags);
> +
> +	if (bit < 0)
> +		return -ENOSPC;
> +
> +	for (i = 0; i < nr_irqs; i++)
> +		irq_domain_set_info(domain, virq + i, bit + i,
> +				    msi->msi_irq_chip,
> +				    msi, handle_edge_irq,
> +				    NULL, NULL);
> +
> +	return 0;
> +}
> +
> +static void dw_pcie_irq_domain_free(struct irq_domain *domain,
> +				    unsigned int virq, unsigned int nr_irqs)
> +{
> +	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
> +	struct dw_msi *msi = domain->host_data;
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&msi->lock, flags);
> +
> +	bitmap_release_region(msi->msi_irq_in_use, d->hwirq,
> +			      order_base_2(nr_irqs));
> +
> +	raw_spin_unlock_irqrestore(&msi->lock, flags);
> +}
> +
> +static const struct irq_domain_ops dw_pcie_msi_domain_ops = {
> +	.alloc	= dw_pcie_irq_domain_alloc,
> +	.free	= dw_pcie_irq_domain_free,
> +};
> +
> +int dw_pcie_allocate_domains(struct dw_msi *msi)
> +{
> +	struct fwnode_handle *fwnode = of_node_to_fwnode(msi->dev->of_node);
> +
> +	msi->irq_domain = irq_domain_create_linear(fwnode, msi->num_vectors,
> +				&dw_pcie_msi_domain_ops,
> +				msi->private_data ? msi->private_data : msi);
> +	if (!msi->irq_domain) {
> +		dev_err(msi->dev, "Failed to create IRQ domain\n");
> +		return -ENOMEM;
> +	}
> +
> +	irq_domain_update_bus_token(msi->irq_domain, DOMAIN_BUS_NEXUS);
> +
> +	msi->msi_domain = pci_msi_create_irq_domain(fwnode,
> +						   &dw_pcie_msi_domain_info,
> +						   msi->irq_domain);
> +	if (!msi->msi_domain) {
> +		dev_err(msi->dev, "Failed to create MSI domain\n");
> +		irq_domain_remove(msi->irq_domain);
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +void dw_pcie_free_msi(struct dw_msi *msi)
> +{
> +	u32 ctrl;
> +
> +	for (ctrl = 0; ctrl < MAX_MSI_CTRLS; ctrl++) {
> +		if (msi->msi_irq[ctrl] > 0)
> +			irq_set_chained_handler_and_data(msi->msi_irq[ctrl],
> +							 NULL, NULL);
> +	}
> +
> +	irq_domain_remove(msi->msi_domain);
> +	irq_domain_remove(msi->irq_domain);
> +}
> +
> +void dw_pcie_msi_init(struct dw_msi *msi)
> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(msi->pp);
> +	u32 ctrl, num_ctrls;
> +	u64 msi_target;
> +
> +	if (!pci_msi_enabled() || !msi->has_msi_ctrl)
> +		return;
> +
> +	msi_target = (u64)msi->msi_data;
> +	num_ctrls = msi->num_vectors / MAX_MSI_IRQS_PER_CTRL;
> +	/* Initialize IRQ Status array */
> +	for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
> +		dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK +
> +				(ctrl * MSI_REG_CTRL_BLOCK_SIZE),
> +				msi->irq_mask[ctrl]);
> +		dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE +
> +				(ctrl * MSI_REG_CTRL_BLOCK_SIZE), ~0);
> +	}
> +
> +	/* Program the msi_data */
> +	dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target));
> +	dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));
> +}
> +
> +static int dw_pcie_parse_split_msi_irq(struct dw_msi *msi, struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	u32 ctrl, max_vectors;
> +	int irq;
> +
> +	/* Parse any "msiX" IRQs described in the devicetree */
> +	for (ctrl = 0; ctrl < MAX_MSI_CTRLS; ctrl++) {
> +		char msi_name[] = "msiX";
> +
> +		msi_name[3] = '0' + ctrl;
> +		irq = platform_get_irq_byname_optional(pdev, msi_name);
> +		if (irq == -ENXIO)
> +			break;
> +		if (irq < 0)
> +			return dev_err_probe(dev, irq,
> +					     "Failed to parse MSI IRQ '%s'\n",
> +					     msi_name);
> +
> +		msi->msi_irq[ctrl] = irq;
> +	}
> +
> +	/* If no "msiX" IRQs, caller should fallback to "msi" IRQ */
> +	if (ctrl == 0)
> +		return -ENXIO;
> +
> +	max_vectors = ctrl * MAX_MSI_IRQS_PER_CTRL;
> +	if (msi->num_vectors > max_vectors) {
> +		dev_warn(dev, "Exceeding number of MSI vectors, limiting to %u\n",
> +			 max_vectors);
> +		msi->num_vectors = max_vectors;
> +	}
> +	if (!msi->num_vectors)
> +		msi->num_vectors = max_vectors;
> +
> +	return 0;
> +}
> +
> +struct dw_msi *dw_pcie_msi_host_init(struct platform_device *pdev,
> +				void *pp, u32 num_vectors)
> +{
> +	struct device *dev = &pdev->dev;
> +	u64 *msi_vaddr = NULL;
> +	u32 ctrl, num_ctrls;
> +	struct dw_msi *msi;
> +	int ret;
> +
> +	msi = devm_kzalloc(dev, sizeof(*msi), GFP_KERNEL);
> +	if (msi == NULL)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (ctrl = 0; ctrl < MAX_MSI_CTRLS; ctrl++)
> +		msi->irq_mask[ctrl] = ~0;
> +
> +	raw_spin_lock_init(&msi->lock);
> +	msi->dev = dev;
> +	msi->pp = pp;
> +	msi->has_msi_ctrl = true;
> +	msi->num_vectors = num_vectors;
> +
> +	if (!msi->msi_irq[0]) {
> +		ret = dw_pcie_parse_split_msi_irq(msi, pdev);
> +		if (ret < 0 && ret != -ENXIO)
> +			return ERR_PTR(ret);
> +	}
> +
> +	if (!msi->num_vectors)
> +		msi->num_vectors = MSI_DEF_NUM_VECTORS;
> +	num_ctrls = msi->num_vectors / MAX_MSI_IRQS_PER_CTRL;
> +
> +	if (!msi->msi_irq[0]) {
> +		msi->msi_irq[0] = platform_get_irq_byname_optional(pdev, "msi");
> +		if (msi->msi_irq[0] < 0) {
> +			msi->msi_irq[0] = platform_get_irq(pdev, 0);
> +			if (msi->msi_irq[0] < 0)
> +				return ERR_PTR(msi->msi_irq[0]);
> +		}
> +	}
> +
> +	dev_dbg(dev, "Using %d MSI vectors\n", msi->num_vectors);
> +
> +	msi->msi_irq_chip = &dw_pci_msi_bottom_irq_chip;
> +
> +	ret = dw_pcie_allocate_domains(msi);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
> +		if (msi->msi_irq[ctrl] > 0)
> +			irq_set_chained_handler_and_data(msi->msi_irq[ctrl],
> +						    dw_chained_msi_isr, msi);
> +	}
> +
> +	/*
> +	 * Even though the iMSI-RX Module supports 64-bit addresses some
> +	 * peripheral PCIe devices may lack 64-bit message support. In
> +	 * order not to miss MSI TLPs from those devices the MSI target
> +	 * address has to be within the lowest 4GB.
> +	 *
> +	 * Note until there is a better alternative found the reservation is
> +	 * done by allocating from the artificially limited DMA-coherent
> +	 * memory.
> +	 */
> +	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
> +	if (!ret)
> +		msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &msi->msi_data,
> +						GFP_KERNEL);
> +
> +	if (!msi_vaddr) {
> +		dev_warn(dev, "Failed to allocate 32-bit MSI address\n");
> +		dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
> +		msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &msi->msi_data,
> +						GFP_KERNEL);
> +		if (!msi_vaddr) {
> +			dev_err(dev, "Failed to allocate MSI address\n");
> +			dw_pcie_free_msi(msi);
> +			return ERR_PTR(-ENOMEM);
> +		}
> +	}
> +
> +	return msi;
> +}
> diff --git a/drivers/pci/controller/dwc/pcie-designware-msi.h b/drivers/pci/controller/dwc/pcie-designware-msi.h
> new file mode 100644
> index 0000000..633156e
> --- /dev/null
> +++ b/drivers/pci/controller/dwc/pcie-designware-msi.h
> @@ -0,0 +1,43 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Synopsys DesignWare PCIe host controller driver
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + *		https://www.samsung.com
> + *
> + * Author: Jingoo Han <jg1.han@xxxxxxxxxxx>
> + */
> +#ifndef _PCIE_DESIGNWARE_MSI_H
> +#define _PCIE_DESIGNWARE_MSI_H
> +
> +#include "../../pci.h"
> +
> +#define MAX_MSI_IRQS			256
> +#define MAX_MSI_IRQS_PER_CTRL		32
> +#define MAX_MSI_CTRLS			(MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL)
> +#define MSI_REG_CTRL_BLOCK_SIZE		12
> +#define MSI_DEF_NUM_VECTORS		32
> +
> +struct dw_msi {
> +	struct device		*dev;
> +	struct irq_domain	*irq_domain;
> +	struct irq_domain	*msi_domain;
> +	struct irq_chip		*msi_irq_chip;
> +	int			msi_irq[MAX_MSI_CTRLS];
> +	dma_addr_t		msi_data;
> +	u32			num_vectors;
> +	u32			irq_mask[MAX_MSI_CTRLS];
> +	raw_spinlock_t		lock;
> +	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
> +	bool                    has_msi_ctrl;
> +	void			*private_data;
> +	void			*pp;
> +};
> +
> +struct dw_msi *dw_pcie_msi_host_init(struct platform_device *pdev,
> +			void *pp, u32 num_vectors);
> +int dw_pcie_allocate_domains(struct dw_msi *msi);
> +void dw_pcie_msi_init(struct dw_msi *msi);
> +void dw_pcie_free_msi(struct dw_msi *msi);
> +irqreturn_t dw_handle_msi_irq(struct dw_msi *msi);
> +#endif /* _PCIE_DESIGNWARE_MSI_H */
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index 1b5aba1..e84298e 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -22,6 +22,7 @@
>  
>  #include "../../pci.h"
>  #include "pcie-designware.h"
> +#include "pcie-designware-msi.h"
>  
>  static const char * const dw_pcie_app_clks[DW_PCIE_NUM_APP_CLKS] = {
>  	[DW_PCIE_DBI_CLK] = "dbi",
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index ef84931..8b7fddf 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -232,12 +232,6 @@
>  #define DEFAULT_DBI_ATU_OFFSET (0x3 << 20)
>  #define DEFAULT_DBI_DMA_OFFSET PCIE_DMA_UNROLL_BASE
>  
> -#define MAX_MSI_IRQS			256
> -#define MAX_MSI_IRQS_PER_CTRL		32
> -#define MAX_MSI_CTRLS			(MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL)
> -#define MSI_REG_CTRL_BLOCK_SIZE		12
> -#define MSI_DEF_NUM_VECTORS		32
> -
>  /* Maximum number of inbound/outbound iATUs */
>  #define MAX_IATU_IN			256
>  #define MAX_IATU_OUT			256
> @@ -319,7 +313,6 @@ struct dw_pcie_host_ops {
>  };
>  
>  struct dw_pcie_rp {
> -	bool			has_msi_ctrl:1;
>  	bool			cfg0_io_shared:1;
>  	u64			cfg0_base;
>  	void __iomem		*va_cfg0_base;
> @@ -329,16 +322,10 @@ struct dw_pcie_rp {
>  	u32			io_size;
>  	int			irq;
>  	const struct dw_pcie_host_ops *ops;
> -	int			msi_irq[MAX_MSI_CTRLS];
> -	struct irq_domain	*irq_domain;
> -	struct irq_domain	*msi_domain;
> -	dma_addr_t		msi_data;
> -	struct irq_chip		*msi_irq_chip;
>  	u32			num_vectors;
> -	u32			irq_mask[MAX_MSI_CTRLS];
> +	struct dw_msi		*msi;
>  	struct pci_host_bridge  *bridge;
>  	raw_spinlock_t		lock;
> -	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
>  	bool			use_atu_msg;
>  	int			msg_atu_index;
>  	struct resource		*msg_res;
> @@ -639,19 +626,12 @@ static inline enum dw_pcie_ltssm dw_pcie_get_ltssm(struct dw_pcie *pci)
>  }
>  
>  #ifdef CONFIG_PCIE_DW_HOST
> -irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp);
>  int dw_pcie_setup_rc(struct dw_pcie_rp *pp);
>  int dw_pcie_host_init(struct dw_pcie_rp *pp);
>  void dw_pcie_host_deinit(struct dw_pcie_rp *pp);
> -int dw_pcie_allocate_domains(struct dw_pcie_rp *pp);
>  void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn,
>  				       int where);
>  #else
> -static inline irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp)
> -{
> -	return IRQ_NONE;
> -}
> -
>  static inline int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
>  {
>  	return 0;
> @@ -666,10 +646,6 @@ static inline void dw_pcie_host_deinit(struct dw_pcie_rp *pp)
>  {
>  }
>  
> -static inline int dw_pcie_allocate_domains(struct dw_pcie_rp *pp)
> -{
> -	return 0;
> -}
>  static inline void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus,
>  						     unsigned int devfn,
>  						     int where)
> diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> index d99e12f..6139330 100644
> --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> @@ -16,6 +16,7 @@
>  
>  #include "../../pci.h"
>  #include "pcie-designware.h"
> +#include "pcie-designware-msi.h"
>  
>  /* Renesas-specific */
>  /* PCIe Mode Setting Register 0 */
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 804341b..f415fa1 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -34,6 +34,7 @@
>  #include <soc/tegra/bpmp.h>
>  #include <soc/tegra/bpmp-abi.h>
>  #include "../../pci.h"
> +#include "pcie-designware-msi.h"
>  
>  #define TEGRA194_DWC_IP_VER			0x490A
>  #define TEGRA234_DWC_IP_VER			0x562A
> @@ -2407,6 +2408,7 @@ static int tegra_pcie_dw_resume_early(struct device *dev)
>  static void tegra_pcie_dw_shutdown(struct platform_device *pdev)
>  {
>  	struct tegra_pcie_dw *pcie = platform_get_drvdata(pdev);
> +	struct dw_msi *msi;
>  
>  	if (pcie->of_data->mode == DW_PCIE_RC_TYPE) {
>  		if (!pcie->link_state)
> @@ -2415,9 +2417,10 @@ static void tegra_pcie_dw_shutdown(struct platform_device *pdev)
>  		debugfs_remove_recursive(pcie->debugfs);
>  		tegra_pcie_downstream_dev_to_D0(pcie);
>  
> +		msi = pcie->pci.pp.msi;
>  		disable_irq(pcie->pci.pp.irq);
>  		if (IS_ENABLED(CONFIG_PCI_MSI))
> -			disable_irq(pcie->pci.pp.msi_irq[0]);
> +			disable_irq(msi->msi_irq[0]);
>  
>  		tegra_pcie_dw_pme_turnoff(pcie);
>  		tegra_pcie_unconfig_controller(pcie);
> -- 
> 2.7.4
> 

-- 
மணிவண்ணன் சதாசிவம்




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux