[Skiboot] [PATCH 03/16] core/pci: Use proper phandle during hotplug for PHB slots
Andrew Donnellan
ajd at linux.ibm.com
Wed Sep 25 00:48:55 AEST 2019
On 9/9/19 2:31 pm, Frederic Barrat wrote:
> PHB slots don't have an associated device (slot->pd = NULL). They were
> not used by the PCI hotplug framework so far, but with opencapi
> virtual PHBs, that's changing. With opencapi, devices are directly
> under the PHB (no root complex or intermediate bridge) and the slot
> used for hotplug is the PHB slot.
>
> This patch uses the proper phandle when replying asynchronously to the
> OS when using a PHB slot.
>
> Signed-off-by: Frederic Barrat <fbarrat at linux.ibm.com>
Looks sensible.
I've also had a look through opal_pci_set_power_state() and I don't see
any way that we can trigger a null dereference by trying to call that
API with a virtual PHB in the current code, as an OpenCAPI PHB has
neither a pd or the slot ops required for slot power-on/off.
Reviewed-by: Andrew Donnellan <ajd at linux.ibm.com>
> ---
> core/pci-opal.c | 21 +++++++++++++++------
> 1 file changed, 15 insertions(+), 6 deletions(-)
>
> diff --git a/core/pci-opal.c b/core/pci-opal.c
> index 175810d0..69bd65c6 100644
> --- a/core/pci-opal.c
> +++ b/core/pci-opal.c
> @@ -647,6 +647,17 @@ static int64_t opal_pci_get_power_state(uint64_t id, uint64_t data)
> }
> opal_call(OPAL_PCI_GET_POWER_STATE, opal_pci_get_power_state, 2);
>
> +static u32 get_slot_phandle(struct pci_slot *slot)
> +{
> + struct phb *phb = slot->phb;
> + struct pci_device *pd = slot->pd;
> +
> + if (pd)
> + return pd->dn->phandle;
> + else
> + return phb->dt_node->phandle;
> +}
> +
> static void rescan_slot_devices(struct pci_slot *slot)
> {
> struct phb *phb = slot->phb;
> @@ -671,8 +682,6 @@ static void set_power_timer(struct timer *t __unused, void *data,
> uint64_t now __unused)
> {
> struct pci_slot *slot = data;
> - struct pci_device *pd = slot->pd;
> - struct dt_node *dn = pd->dn;
> uint8_t link;
> struct phb *phb = slot->phb;
>
> @@ -682,7 +691,7 @@ static void set_power_timer(struct timer *t __unused, void *data,
> if (slot->retries-- == 0) {
> pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
> opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL,
> - slot->async_token, dn->phandle,
> + slot->async_token, get_slot_phandle(slot),
> slot->power_state, OPAL_BUSY);
> } else {
> schedule_timer(&slot->timer, msecs_to_tb(10));
> @@ -694,7 +703,7 @@ static void set_power_timer(struct timer *t __unused, void *data,
> remove_slot_devices(slot);
> pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
> opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL,
> - slot->async_token, dn->phandle,
> + slot->async_token, get_slot_phandle(slot),
> OPAL_PCI_SLOT_POWER_OFF, OPAL_SUCCESS);
> break;
> }
> @@ -706,12 +715,12 @@ static void set_power_timer(struct timer *t __unused, void *data,
> rescan_slot_devices(slot);
> pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
> opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL,
> - slot->async_token, dn->phandle,
> + slot->async_token, get_slot_phandle(slot),
> OPAL_PCI_SLOT_POWER_ON, OPAL_SUCCESS);
> } else if (slot->retries-- == 0) {
> pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
> opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL,
> - slot->async_token, dn->phandle,
> + slot->async_token, get_slot_phandle(slot),
> OPAL_PCI_SLOT_POWER_ON, OPAL_BUSY);
> } else {
> schedule_timer(&slot->timer, msecs_to_tb(10));
>
--
Andrew Donnellan OzLabs, ADL Canberra
ajd at linux.ibm.com IBM Australia Limited
More information about the Skiboot
mailing list