pnv_phb3.c: add unique chassis and slot for pnv_phb3_root_port

When creating a pnv_phb3_root_port using the command line, the first
root port is created successfully, but the second fails with the
following error:

qemu-system-ppc64: -device pnv-phb3-root-port,bus=phb3-root.0,id=pcie.3:
Can't add chassis slot, error -16

This error comes from the realize() function of its parent type,
rp_realize() from TYPE_PCIE_ROOT_PORT. pcie_chassis_add_slot() fails
with -EBUSY if there's an existing PCIESlot that has the same
chassis/slot value, regardless of being in a different bus.

One way to prevent this error is simply set chassis and slot values in
the command line. However, since phb3 root buses only supports a single
root port, we can just get an unique chassis/slot value by checking
which root bus the pnv_phb3_root_port is going to be attached, get the
equivalent phb3 device and use its chip-id and index values, which are
guaranteed to be unique.

Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Message-Id: <20220105212338.49899-2-danielhb413@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
Daniel Henrique Barboza 2022-01-12 11:28:27 +01:00 committed by Cédric Le Goater
parent 5609400a42
commit 392c278302
1 changed files with 16 additions and 0 deletions

View File

@ -1142,8 +1142,24 @@ static const TypeInfo pnv_phb3_root_bus_info = {
static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp)
{
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
PCIDevice *pci = PCI_DEVICE(dev);
PCIBus *bus = pci_get_bus(pci);
PnvPHB3 *phb = NULL;
Error *local_err = NULL;
phb = (PnvPHB3 *) object_dynamic_cast(OBJECT(bus->qbus.parent),
TYPE_PNV_PHB3);
if (!phb) {
error_setg(errp,
"pnv_phb3_root_port devices must be connected to pnv-phb3 buses");
return;
}
/* Set unique chassis/slot values for the root port */
qdev_prop_set_uint8(&pci->qdev, "chassis", phb->chip_id);
qdev_prop_set_uint16(&pci->qdev, "slot", phb->phb_id);
rpc->parent_realize(dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);