spapr: Adjust firmware path of PCI devices
It is currently not possible to perform a strict boot from USB storage: $ qemu-system-ppc64 -accel kvm -nodefaults -nographic -serial stdio \ -boot strict=on \ -device qemu-xhci \ -device usb-storage,drive=disk,bootindex=0 \ -blockdev driver=file,node-name=disk,filename=fedora-ppc64le.qcow2 SLOF ********************************************************************** QEMU Starting Build Date = Jul 17 2020 11:15:24 FW Version = git-e18ddad8516ff2cf Press "s" to enter Open Firmware. Populating /vdevice methods Populating /vdevice/vty@71000000 Populating /vdevice/nvram@71000001 Populating /pci@800000020000000 00 0000 (D) : 1b36 000d serial bus [ usb-xhci ] No NVRAM common partition, re-initializing... Scanning USB XHCI: Initializing USB Storage SCSI: Looking for devices 101000000000000 DISK : "QEMU QEMU HARDDISK 2.5+" Using default console: /vdevice/vty@71000000 Welcome to Open Firmware Copyright (c) 2004, 2017 IBM Corporation All rights reserved. This program and the accompanying materials are made available under the terms of the BSD License available at http://www.opensource.org/licenses/bsd-license.php Trying to load: from: /pci@800000020000000/usb@0/storage@1/disk@101000000000000 ... E3405: No such device E3407: Load failed Type 'boot' and press return to continue booting the system. Type 'reset-all' and press return to reboot the system. Ready! 0 > The device tree handed over by QEMU to SLOF indeed contains: qemu,boot-list = "/pci@800000020000000/usb@0/storage@1/disk@101000000000000 HALT"; but the device node is named usb-xhci@0, not usb@0. This happens because the firmware names of PCI devices returned by get_boot_devices_list() come from pcibus_get_fw_dev_path(), while the sPAPR PHB code uses a different naming scheme for device nodes. This inconsistency has always been there but it was hidden for a long time because SLOF used to rename USB device nodes, until this commit, merged in QEMU 4.2.0 : commit85164ad4ed
Author: Alexey Kardashevskiy <aik@ozlabs.ru> Date: Wed Sep 11 16:24:32 2019 +1000 pseries: Update SLOF firmware image This fixes USB host bus adapter name in the device tree to match QEMU's one. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Fortunately, sPAPR implements the firmware path provider interface. This provides a way to override the default firmware paths. Just factor out the sPAPR PHB naming logic from spapr_dt_pci_device() to a helper, and use it in the sPAPR firmware path provider hook. Fixes:85164ad4ed
("pseries: Update SLOF firmware image") Signed-off-by: Greg Kurz <groug@kaod.org> Message-Id: <20210122170157.246374-1-groug@kaod.org> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
a85bb34e1c
commit
040bdafce1
@ -3054,6 +3054,7 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
|
||||
SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE);
|
||||
SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
|
||||
VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON);
|
||||
PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE);
|
||||
|
||||
if (d) {
|
||||
void *spapr = CAST(void, bus->parent, "spapr-vscsi");
|
||||
@ -3127,6 +3128,10 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
|
||||
return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn));
|
||||
}
|
||||
|
||||
if (pcidev) {
|
||||
return spapr_pci_fw_dev_name(pcidev);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1344,15 +1344,29 @@ static int spapr_dt_pci_bus(SpaprPhbState *sphb, PCIBus *bus,
|
||||
return offset;
|
||||
}
|
||||
|
||||
char *spapr_pci_fw_dev_name(PCIDevice *dev)
|
||||
{
|
||||
const gchar *basename;
|
||||
int slot = PCI_SLOT(dev->devfn);
|
||||
int func = PCI_FUNC(dev->devfn);
|
||||
uint32_t ccode = pci_default_read_config(dev, PCI_CLASS_PROG, 3);
|
||||
|
||||
basename = dt_name_from_class((ccode >> 16) & 0xff, (ccode >> 8) & 0xff,
|
||||
ccode & 0xff);
|
||||
|
||||
if (func != 0) {
|
||||
return g_strdup_printf("%s@%x,%x", basename, slot, func);
|
||||
} else {
|
||||
return g_strdup_printf("%s@%x", basename, slot);
|
||||
}
|
||||
}
|
||||
|
||||
/* create OF node for pci device and required OF DT properties */
|
||||
static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev,
|
||||
void *fdt, int parent_offset)
|
||||
{
|
||||
int offset;
|
||||
const gchar *basename;
|
||||
gchar *nodename;
|
||||
int slot = PCI_SLOT(dev->devfn);
|
||||
int func = PCI_FUNC(dev->devfn);
|
||||
g_autofree gchar *nodename = spapr_pci_fw_dev_name(dev);
|
||||
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
|
||||
ResourceProps rp;
|
||||
SpaprDrc *drc = drc_from_dev(sphb, dev);
|
||||
@ -1369,19 +1383,8 @@ static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev,
|
||||
uint32_t pci_status = pci_default_read_config(dev, PCI_STATUS, 2);
|
||||
gchar *loc_code;
|
||||
|
||||
basename = dt_name_from_class((ccode >> 16) & 0xff, (ccode >> 8) & 0xff,
|
||||
ccode & 0xff);
|
||||
|
||||
if (func != 0) {
|
||||
nodename = g_strdup_printf("%s@%x,%x", basename, slot, func);
|
||||
} else {
|
||||
nodename = g_strdup_printf("%s@%x", basename, slot);
|
||||
}
|
||||
|
||||
_FDT(offset = fdt_add_subnode(fdt, parent_offset, nodename));
|
||||
|
||||
g_free(nodename);
|
||||
|
||||
/* in accordance with PAPR+ v2.7 13.6.3, Table 181 */
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "vendor-id", vendor_id));
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "device-id", device_id));
|
||||
|
@ -210,4 +210,6 @@ static inline unsigned spapr_phb_windows_supported(SpaprPhbState *sphb)
|
||||
return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
|
||||
}
|
||||
|
||||
char *spapr_pci_fw_dev_name(PCIDevice *dev);
|
||||
|
||||
#endif /* PCI_HOST_SPAPR_H */
|
||||
|
Loading…
Reference in New Issue
Block a user