[Skiboot] [PATCH v11 20/23] core/pci: Power off empty hotpluggable slot
Russell Currey
ruscur at russell.cc
Thu Jun 2 14:20:03 AEST 2016
On Fri, 2016-05-20 at 16:32 +1000, Gavin Shan wrote:
> This powers off the empty hotpluggable slot during PCI enumeration
> for two purpose: power saving and initialize the slot to starting
> (power-off) state.
>
> Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
> ---
Reviewed-by: Russell Currey <ruscur at russell.cc>
> core/pci.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 52 insertions(+), 1 deletion(-)
>
> diff --git a/core/pci.c b/core/pci.c
> index 21fa823..68b6033 100644
> --- a/core/pci.c
> +++ b/core/pci.c
> @@ -476,6 +476,51 @@ void pci_remove_bus(struct phb *phb, struct list_head
> *list)
> }
> }
>
> +/*
> + * Turn off slot's power supply if there are nothing connected for
> + * 2 purposes: power saving obviously and initialize the slot to
> + * to initial power-off state for hotplug.
> + */
> +static void pci_slot_power_off(struct phb *phb, struct pci_device *pd)
> +{
> + struct pci_slot *slot;
> + int32_t wait = 100;
It'd be good to specify units, or just mention that this is an arbitrary amount
of time to wait.
> + int64_t rc;
> +
> + if (!pd || !pd->slot)
> + return;
> +
> + slot = pd->slot;
> + if (!slot->pluggable || !slot->ops.set_power_state)
> + return;
> +
> + /* Bail if there're something connected */
there's
> + if (!list_empty(&pd->children))
> + return;
> +
> + pci_slot_add_flags(slot, PCI_SLOT_FLAG_BOOTUP);
> + rc = slot->ops.set_power_state(slot, PCI_SLOT_POWER_OFF);
> + if (rc != OPAL_ASYNC_COMPLETION) {
> + pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
> + PCINOTICE(phb, pd->bdfn, "Error %lld powering off slot\n",
> rc);
> + return;
> + }
> +
> + do {
> + if (slot->state == PCI_SLOT_STATE_SPOWER_DONE)
> + break;
> +
> + check_timers(false);
> + time_wait(10);
> + } while (--wait >= 0);
> +
> + pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
> + if (wait >= 0)
> + PCIDBG(phb, pd->bdfn, "Power off hotpluggable slot\n");
> + else
> + PCINOTICE(phb, pd->bdfn, "Timeout powering off slot\n");
> +}
> +
> /* Perform a recursive scan of the bus at bus_number populating
> * the list passed as an argument. This also performs the bus
> * numbering, so it returns the largest bus number that was
> @@ -539,8 +584,12 @@ uint8_t pci_scan_bus(struct phb *phb, uint8_t bus,
> uint8_t max_bus,
> * link is down already, which happens for the top level
> * root complex, and avoids a long secondary timeout
> */
> - if (!scan_downstream)
> + if (!scan_downstream) {
> + list_for_each(list, pd, link)
> + pci_slot_power_off(phb, pd);
> +
> return bus;
> + }
>
> next_bus = bus + 1;
> max_sub = bus;
> @@ -626,6 +675,8 @@ uint8_t pci_scan_bus(struct phb *phb, uint8_t bus, uint8_t
> max_bus,
> pd->subordinate_bus = max_sub;
> pci_cfg_write8(phb, pd->bdfn, PCI_CFG_SUBORDINATE_BUS,
> max_sub);
> next_bus = max_sub + 1;
> +
> + pci_slot_power_off(phb, pd);
> }
>
> return max_sub;
More information about the Skiboot
mailing list