[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