Commit 3047766b authored by Niklas Schnelle's avatar Niklas Schnelle Committed by Heiko Carstens

s390/pci: fix enabling a reserved PCI function

In usual IPL or hot plug scenarios a zPCI function transitions directly
from reserved (invisible to Linux) to configured state or is configured
by Linux itself using an SCLP, however it can also first go from
reserved to standby and then from standby to configured without
Linux initiative.
In this scenario we first get a PEC event 0x302 and then 0x301.  This may
happen for example when the device is deconfigured at another LPAR and
made available for this LPAR. It may also happen under z/VM when
a device is attached while in some inconsistent state.

However when we get the 0x301 the device is already known to zPCI
so calling zpci_create() will add it twice resulting in the below
BUG. Instead we should only enable the existing device and finally
scan it through the PCI subsystem.

list_add double add: new=00000000ed5a9008, prev=00000000ed5a9008, next=0000000083502300.
kernel BUG at lib/list_debug.c:31!
Krnl PSW : 0704c00180000000 0000000082dc2db8 (__list_add_valid+0x70/0xa8)
Call Trace:
 [<0000000082dc2db8>] __list_add_valid+0x70/0xa8
([<0000000082dc2db4>] __list_add_valid+0x6c/0xa8)
 [<00000000828ea920>] zpci_create_device+0x60/0x1b0
 [<00000000828ef04a>] zpci_event_availability+0x282/0x2f0
 [<000000008315f848>] chsc_process_crw+0x2b8/0xa18
 [<000000008316735c>] crw_collect_info+0x254/0x348
 [<00000000829226ea>] kthread+0x14a/0x168
 [<000000008319d5c0>] ret_from_fork+0x24/0x2c

Fixes: f606b3ef ("s390/pci: adapt events for zbus")
Reported-by: default avatarAlexander Egorenkov <egorenar@linux.ibm.com>
Tested-by: default avatarAlexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
parent 9ebcfadb
...@@ -94,7 +94,18 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) ...@@ -94,7 +94,18 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
} }
zdev->fh = ccdf->fh; zdev->fh = ccdf->fh;
zdev->state = ZPCI_FN_STATE_CONFIGURED; zdev->state = ZPCI_FN_STATE_CONFIGURED;
zpci_create_device(zdev); ret = zpci_enable_device(zdev);
if (ret)
break;
pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
if (!pdev)
break;
pci_bus_add_device(pdev);
pci_lock_rescan_remove();
pci_bus_add_devices(zdev->zbus->bus);
pci_unlock_rescan_remove();
break; break;
case 0x0302: /* Reserved -> Standby */ case 0x0302: /* Reserved -> Standby */
if (!zdev) { if (!zdev) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment