浏览代码

powerpc/powernv: Skip check on PE if necessary

While the device driver or PCI core tries to enable PCI device, the
platform dependent callback "ppc_md.pcibios_enable_device_hook" will
be called to check if there has one associated PE for the PCI device.
If we don't have the associated PE for the PCI device, it's not allowed
to enable the PCI device. Unfortunately, there might have some cases
we have to enable the PCI device (e.g. P2P bridge), but the PEs have
not been created yet.

The patch handles the unfortunate cases. Each PHB (struct pnv_phb)
has one field "initialized" to trace if the PEs have been created
and configured or not. When the PEs are not available, we won't check
the associated PE for the PCI device to be enabled.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Reviewed-by: Ram Pai <linuxram@us.ibm.com>
Reviewed-by: Richard Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Gavin Shan 13 年之前
父节点
当前提交
db1266c852
共有 2 个文件被更改,包括 19 次插入1 次删除
  1. 18 1
      arch/powerpc/platforms/powernv/pci-ioda.c
  2. 1 0
      arch/powerpc/platforms/powernv/pci.h

+ 18 - 1
arch/powerpc/platforms/powernv/pci-ioda.c

@@ -1244,9 +1244,14 @@ static void __devinit pnv_pci_ioda_setup_seg(void)
 static void __devinit pnv_pci_ioda_setup_DMA(void)
 static void __devinit pnv_pci_ioda_setup_DMA(void)
 {
 {
 	struct pci_controller *hose, *tmp;
 	struct pci_controller *hose, *tmp;
+	struct pnv_phb *phb;
 
 
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		pnv_ioda_setup_dma(hose->private_data);
 		pnv_ioda_setup_dma(hose->private_data);
+
+		/* Mark the PHB initialization done */
+		phb = hose->private_data;
+		phb->initialized = 1;
 	}
 	}
 }
 }
 
 
@@ -1300,10 +1305,22 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
  */
  */
 static int __devinit pnv_pci_enable_device_hook(struct pci_dev *dev)
 static int __devinit pnv_pci_enable_device_hook(struct pci_dev *dev)
 {
 {
-	struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	struct pnv_phb *phb = hose->private_data;
+	struct pci_dn *pdn;
 
 
+	/* The function is probably called while the PEs have
+	 * not be created yet. For example, resource reassignment
+	 * during PCI probe period. We just skip the check if
+	 * PEs isn't ready.
+	 */
+	if (!phb->initialized)
+		return 0;
+
+	pdn = pnv_ioda_get_pdn(dev);
 	if (!pdn || pdn->pe_number == IODA_INVALID_PE)
 	if (!pdn || pdn->pe_number == IODA_INVALID_PE)
 		return -EINVAL;
 		return -EINVAL;
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 0
arch/powerpc/platforms/powernv/pci.h

@@ -69,6 +69,7 @@ struct pnv_phb {
 	enum pnv_phb_model	model;
 	enum pnv_phb_model	model;
 	u64			opal_id;
 	u64			opal_id;
 	void __iomem		*regs;
 	void __iomem		*regs;
+	int			initialized;
 	spinlock_t		lock;
 	spinlock_t		lock;
 
 
 #ifdef CONFIG_PCI_MSI
 #ifdef CONFIG_PCI_MSI