Subject: Re: [linuxppc-release][PATCH] powerpc/pci-hotplug: fix init issue of rescanned pci device

From: Benjamin Herrenschmidt <[email-masked]>
Date: Wed, 05 Dec 2012 18:17:58 +1100

On Wed, 2012-12-05 at 10:31 +0800, Yuanquan Chen wrote:
> On powerpc arch, some fixup work of PCI/PCI-e device is just done during the
> first scan at booting time. For the PCI/PCI-e device rescanned after linux OS
> booting up, the fixup work won't be done, which leads to dma_set_mask error or
> irq related issue in rescanned PCI/PCI-e device's driver. So, it does the same
> fixup work for the rescanned device to avoid this issue.

Hrm, the patch is a bit gross. First the code shouldn't be copy/pasted
that way but factored out.

I'm surprised also that is_added is false when pcibios_enable_device()
gets called ... that looks strange to me. At what point is that enable
happening in the hotplug sequence ?

How do you trigger the rescan anyway ?

I think the problem needs to be solve at a higher level, I'm adding
linux-pci & Bjorn to the CC list.

Cheers,
Ben.

> Signed-off-by: Yuanquan Chen <[email-masked]>
> ---
>  arch/powerpc/kernel/pci-common.c |   20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
> diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> index 7f94f76..f0fb070 100644
> --- a/arch/powerpc/kernel/pci-common.c
> +++ b/arch/powerpc/kernel/pci-common.c
> @@ -1496,6 +1496,26 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
>  		if (ppc_md.pcibios_enable_device_hook(dev))
>  			return -EINVAL;
>  
> +	if (!dev->is_added) {
> +		/* 
> +		 * Fixup NUMA node as it may not be setup yet by the generic
> +		 * code and is needed by the DMA init
> +		 */
> +		set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
> +
> +		/* Hook up default DMA ops */
> +		set_dma_ops(&dev->dev, pci_dma_ops);
> +		set_dma_offset(&dev->dev, PCI_DRAM_OFFSET);
> +
> +		/* Additional platform DMA/iommu setup */
> +		if (ppc_md.pci_dma_dev_setup)
> +			ppc_md.pci_dma_dev_setup(dev);
> +
> +		/* Read default IRQs and fixup if necessary */
> +		pci_read_irq_line(dev);
> +		if (ppc_md.pci_irq_fixup)
> +			ppc_md.pci_irq_fixup(dev);
> +	}
>  	return pci_enable_resources(dev, mask);
>  }
>