[PATCH v2] Bugfix: powerpc/eeh: Wrong place to call pci_get_slot()
Mike Qiu
qiudayu at linux.vnet.ibm.com
Tue Jul 15 15:15:58 EST 2014
On 07/15/2014 01:07 PM, Gavin Shan wrote:
> On Mon, Jul 14, 2014 at 10:33:48PM -0400, Mike Qiu wrote:
>> pci_get_slot() is called with hold of PCI bus semaphore and it's not
>> safe to be called in interrupt context. However, we possibly checks
>> EEH error and calls the function in interrupt context. To avoid using
>> pci_get_slot(), we turn into device tree for fetching location code.
>> Otherwise, we might run into WARN_ON() as following messages indicate:
>>
>> WARNING: at drivers/pci/search.c:223
>> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.16.0-rc3+ #72
>> task: c000000001367af0 ti: c000000001444000 task.ti: c000000001444000
>> NIP: c000000000497b70 LR: c000000000037530 CTR: 000000003003d114
>> REGS: c000000001446fa0 TRAP: 0700 Not tainted (3.16.0-rc3+)
>> MSR: 9000000000029032 <SF,HV,EE,ME,IR,DR,RI> CR: 48002422 XER: 20000000
>> CFAR: c00000000003752c SOFTE: 0
>> :
>> NIP [c000000000497b70] .pci_get_slot+0x40/0x110
>> LR [c000000000037530] .eeh_pe_loc_get+0x150/0x190
>> Call Trace:
>> .of_get_property+0x30/0x60 (unreliable)
>> .eeh_pe_loc_get+0x150/0x190
>> .eeh_dev_check_failure+0x1b4/0x550
>> .eeh_check_failure+0x90/0xf0
>> .lpfc_sli_check_eratt+0x504/0x7c0 [lpfc]
>> .lpfc_poll_eratt+0x64/0x100 [lpfc]
>> .call_timer_fn+0x64/0x190
>> .run_timer_softirq+0x2cc/0x3e0
>>
>> Signed-off-by: Mike Qiu <qiudayu at linux.vnet.ibm.com>
>> ---
>> Changelog[v2]:
>> Check the child device_node of root bus for root port
>> directly instead of search pdev from device-tree and
>> then translate it to device-node
>>
> I run into following warning with your patch. Please test the attached
> one. If no problem found, send that one please.
>
> arch/powerpc/kernel/eeh_pe.c: In function 'eeh_pe_loc_get':
> arch/powerpc/kernel/eeh_pe.c:806:18: warning: unused variable 'pdev'
OK, I will remove unused variable.
Thanks,
Mike
> Thanks,
> Gavin
>
>> arch/powerpc/kernel/eeh_pe.c | 24 ++++++------------------
>> 1 file changed, 6 insertions(+), 18 deletions(-)
>>
>> diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
>> index fbd01eb..f96c10f 100644
>> --- a/arch/powerpc/kernel/eeh_pe.c
>> +++ b/arch/powerpc/kernel/eeh_pe.c
>> @@ -802,7 +802,6 @@ void eeh_pe_restore_bars(struct eeh_pe *pe)
>> */
>> const char *eeh_pe_loc_get(struct eeh_pe *pe)
>> {
>> - struct pci_controller *hose;
>> struct pci_bus *bus = eeh_pe_bus_get(pe);
>> struct pci_dev *pdev;
>> struct device_node *dn;
>> @@ -811,29 +810,20 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe)
>> if (!bus)
>> return "N/A";
>>
>> + dn = pci_bus_to_OF_node(bus);
>> /* PHB PE or root PE ? */
>> - if (pci_is_root_bus(bus)) {
>> - hose = pci_bus_to_host(bus);
>> - loc = of_get_property(hose->dn,
>> - "ibm,loc-code", NULL);
>> + if (dn && pci_is_root_bus(bus)) {
>> + loc = of_get_property(dn, "ibm,loc-code", NULL);
>> if (loc)
>> return loc;
>> - loc = of_get_property(hose->dn,
>> - "ibm,io-base-loc-code", NULL);
>> + loc = of_get_property(dn, "ibm,io-base-loc-code", NULL);
>> if (loc)
>> return loc;
>>
>> - pdev = pci_get_slot(bus, 0x0);
>> - } else {
>> - pdev = bus->self;
>> - }
>> -
>> - if (!pdev) {
>> - loc = "N/A";
>> - goto out;
>> + /* Check the root port */
>> + dn = dn->child;
>> }
>>
>> - dn = pci_device_to_OF_node(pdev);
>> if (!dn) {
>> loc = "N/A";
>> goto out;
>> @@ -846,8 +836,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;
>> }
>>
>> --
>> 1.8.1.4
>>
More information about the Linuxppc-dev
mailing list