[PATCH] Bugfix: powerpc/eeh: Wrong place to call pci_get_slot()
Gavin Shan
gwshan at linux.vnet.ibm.com
Tue Jul 15 09:24:49 EST 2014
On Mon, Jul 14, 2014 at 09:35:18PM +0800, Mike Qiu wrote:
>On 07/14/2014 09:01 PM, Gavin Shan wrote:
>>On Mon, Jul 14, 2014 at 04:19:23AM -0400, Mike Qiu wrote:
.../...
>>>Signed-off-by: Mike Qiu <qiudayu at linux.vnet.ibm.com>
>>>---
>>>arch/powerpc/kernel/eeh_pe.c | 29 ++++++++++++++++++++++++++---
>>>1 file changed, 26 insertions(+), 3 deletions(-)
>>>
>>>diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
>>>index fbd01eb..6f4bfee 100644
>>>--- a/arch/powerpc/kernel/eeh_pe.c
>>>+++ b/arch/powerpc/kernel/eeh_pe.c
>>>@@ -792,6 +792,28 @@ void eeh_pe_restore_bars(struct eeh_pe *pe)
>>>}
>>>
>>>/**
>>>+ * __dn_get_pdev - Retrieve the pci_dev from device_node by bus/devfn
>>>+ * @dn: device_node of the pci_dev
>>>+ * @data: the pci device's bus/devfn
>>>+ *
>>>+ * Retrieve the pci_dev using the given device_node and bus/devfn.
>>>+ */
>>>+void *__dn_get_pdev(struct device_node *dn, void *data)
>>>+{
>>The function isn't necessarily public. "static" is enough, I think.
>>I don't think we need this actually. Please refer to more comments
>>below.
>>
>>>+ struct pci_dn *pdn = PCI_DN(dn);
>>>+ int busno = *((int *)data) >> 8;
>>>+ int devfn = *((int *)data) & 0xff;
>>>+
>>>+ if (!pdn)
>>>+ return NULL;
>>>+
>>>+ if (pdn->busno == busno && pdn->devfn == devfn)
>>>+ return pdn->pcidev;
>>>+
>>>+ return NULL;
>>>+}
>>>+
>>>+/**
>>> * eeh_pe_loc_get - Retrieve location code binding to the given PE
>>> * @pe: EEH PE
>>> *
>>>@@ -807,6 +829,7 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe)
>>> struct pci_dev *pdev;
>>> struct device_node *dn;
>>> const char *loc;
>>>+ int bdevfn;
>>>
>>> if (!bus)
>>> return "N/A";
>>>@@ -823,7 +846,9 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe)
>>> if (loc)
>>> return loc;
>>>
>>>- pdev = pci_get_slot(bus, 0x0);
>>>+ /* Get the root port */
>>>+ bdevfn = (bus->number) << 8 || 0x0;
>>>+ pdev = traverse_pci_devices(hose->dn, __dn_get_pdev, &bdevfn);
>>We needn't search pdev from device-tree and then translate it to
>>device-node. Root port is the only child hooked to root bus's
>>device node (it's also PHB's device-node). So I guess you can
>
>So here you mean, child hooked device node(root port) can be
>hose->dn->child?
>
Yes, I think so.
>>just have something:
>>
>> /* Check PHB's device node */
>> dn = pci_bus_to_OF_node(bus);
>> if (unlikely(!dn)) {
>> loc = "N/A";
>> goto out;
>> }
>> loc = of_get_property(hose->dn,
>> "ibm,loc-code", NULL);
>> if (loc)
>> return loc;
>> loc = of_get_property(hose->dn,
>> "ibm,io-base-loc-code", NULL);
>> if (loc)
>> return loc;
>>
>> /* Check root port */
>> dn = dn->child;
>>> } else {
>>> pdev = bus->self;
>>Here, we needn't grab the bridge as well:
>>
>> dn = pci_bus_to_OF_node(bus);
>>> }
>>Then check the device-node of bridge (or root port):
>>
>> if (unlikely(!dn)) {
>> loc = "N/A";
>> goto out;
>> }
>>
>> loc = of_get_property(dn, "ibm,loc-code", NULL);
>> if (!loc)
>> loc = of_get_property(dn, "ibm,slot-location-code", NULL);
>> if (!loc)
>> loc = "N/A";
>>
>>>@@ -846,8 +871,6 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe)
>>> loc = "N/A";
>>>
>>>out:
>>>- if (pci_is_root_bus(bus) && pdev)
>>>- pci_dev_put(pdev);
>>> return loc;
>>>}
>
>I will make a new patch, after tested, I will resend it out
>
Thanks, Mike.
Thanks,
Gavin
More information about the Linuxppc-dev
mailing list