[Skiboot] [PATCH 14/16] npu2-opencapi: Activate PCI hotplug on opencapi slot

christophe lombard clombard at linux.vnet.ibm.com
Tue Sep 17 23:37:59 AEST 2019


On 09/09/2019 14:31, Frederic Barrat wrote:
> Implement the get_power_state() and set_power_state() callbacks for
> the opencapi slot and add properties in the device tree to mark the
> opencapi slot as hot-pluggable.
> 
> We don't really power off/on the opencapi adapter. The slot at play
> here is the virtual slot associated to the virtual opencapi PHB. The
> real PCIe slot where the card is drawing its power from is
> untouched (skiboot is not even aware which PCIe slot the card is
> seated on). So the 'fake' power off is fencing the card and set it in
> reset so that the FPGA image can be updated. The 'fake' power on is
> not doing much, as the unfencing happens on the subsequent link
> training.
> 
> Opencapi slots are named 'OPENCAPI-xxxx' where xxxx is the opal ID of
> the PHB/slot. This is meant to easily identify the slot used by an AFU
> device, as the AFU device names are also built around that ID.
> For example, the device /dev/ocxl/AFP3.0006:00:00.1.0 uses the slot
> OPENCAPI-0006.
> 
> Signed-off-by: Frederic Barrat <fbarrat at linux.ibm.com>
> ---
>   hw/npu2-opencapi.c | 69 +++++++++++++++++++++++++++++++++++++++++++---
>   1 file changed, 65 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/npu2-opencapi.c b/hw/npu2-opencapi.c
> index c8bc64d1..af309362 100644
> --- a/hw/npu2-opencapi.c
> +++ b/hw/npu2-opencapi.c
> @@ -1032,9 +1032,10 @@ static int64_t npu2_opencapi_get_presence_state(struct pci_slot __unused *slot,
>   	 * As such we will never be asked to get the presence of a slot that's
>   	 * empty.
>   	 *
> -	 * This may change if we ever support hotplug down the track.
> +	 * This may change if we ever support surprise hotplug down
> +	 * the track.
>   	 */
> -	*val = true;
> +	*val = OPAL_PCI_SLOT_PRESENT;
>   	return OPAL_SUCCESS;
>   }
>   
> @@ -1092,6 +1093,38 @@ static int64_t npu2_opencapi_get_link_state(struct pci_slot *slot, uint8_t *val)
>   	return OPAL_SUCCESS;
>   }
>   
> +static int64_t npu2_opencapi_get_power_state(struct pci_slot *slot,
> +					     uint8_t *val)
> +{
> +	*val = slot->power_state;
> +	return OPAL_SUCCESS;
> +}
> +
> +static int64_t npu2_opencapi_set_power_state(struct pci_slot *slot, uint8_t val)
> +{
> +	struct npu2_dev *dev = phb_to_npu2_dev_ocapi(slot->phb);
> +
> +	switch (val) {
> +	case PCI_SLOT_POWER_OFF:
> +		OCAPIDBG(dev, "Fake power off\n");
> +		fence_brick(dev);
> +		assert_adapter_reset(dev);
> +		slot->power_state = PCI_SLOT_POWER_OFF;
> +		return OPAL_SUCCESS;
> +
> +	case PCI_SLOT_POWER_ON:
> +		if (slot->power_state != PCI_SLOT_POWER_OFF)
> +			return OPAL_SUCCESS;
> +		OCAPIDBG(dev, "Fake power on\n");
> +		slot->power_state = PCI_SLOT_POWER_ON;
> +		slot->state = OCAPI_SLOT_NORMAL;
> +		return OPAL_SUCCESS;
> +
> +	default:
> +		return OPAL_UNSUPPORTED;
> +	}
> +}
> +
>   static void check_trained_link(struct npu2_dev *dev, uint64_t odl_status)
>   {
>   	if (get_link_width(odl_status) != OPAL_SHPC_LINK_UP_x8) {
> @@ -1132,6 +1165,14 @@ static int64_t npu2_opencapi_retry_state(struct pci_slot *slot,
>   	return pci_slot_set_sm_timeout(slot, msecs_to_tb(1));
>   }
>   
> +static void npu2_opencapi_prepare_link_change(struct pci_slot *slot __unused,
> +					      bool up __unused)
> +{
> +	/*
> +	 * PCI hotplug wants it defined, but we don't need to do anything
> +	 */
> +}
> +
>   static int64_t npu2_opencapi_poll_link(struct pci_slot *slot)
>   {
>   	struct npu2_dev *dev = phb_to_npu2_dev_ocapi(slot->phb);
> @@ -1259,6 +1300,24 @@ static int64_t npu2_opencapi_hreset(struct pci_slot *slot __unused)
>   	return OPAL_UNSUPPORTED;
>   }
>   
> +static void make_slot_hotpluggable(struct pci_slot *slot, struct phb *phb)
> +{
> +	char label[40];
> +
> +	/*
> +	 * Add a few definitions to the DT so that the linux PCI
> +	 * hotplug framework can find the slot and identify it as
> +	 * hot-pluggable.
> +	 *
> +	 * The "ibm,slot-label" property is used by linux as the slot name
> +	 */
> +	slot->pluggable = 1;
> +	pci_slot_add_dt_properties(slot, phb->dt_node);
> +	snprintf(label, sizeof(label), "OPENCAPI-%04x",
> +		 (int)PCI_SLOT_PHB_INDEX(slot->id));
> +	dt_add_property_string(phb->dt_node, "ibm,slot-label", label);

most of dt definitions were added in setup_device(). May be you should 
move this one ?
Otherwise

Reviewed-by: Christophe Lombard <clombard at linux.vnet.ibm.com>

> +}
> +
>   static struct pci_slot *npu2_opencapi_slot_create(struct phb *phb)
>   {
>   	struct pci_slot *slot;
> @@ -1270,17 +1329,19 @@ static struct pci_slot *npu2_opencapi_slot_create(struct phb *phb)
>   	/* TODO: Figure out other slot functions */
>   	slot->ops.get_presence_state  = npu2_opencapi_get_presence_state;
>   	slot->ops.get_link_state      = npu2_opencapi_get_link_state;
> -	slot->ops.get_power_state     = NULL;
> +	slot->ops.get_power_state     = npu2_opencapi_get_power_state;
>   	slot->ops.get_attention_state = NULL;
>   	slot->ops.get_latch_state     = NULL;
> -	slot->ops.set_power_state     = NULL;
> +	slot->ops.set_power_state     = npu2_opencapi_set_power_state;
>   	slot->ops.set_attention_state = NULL;
>   
> +	slot->ops.prepare_link_change = npu2_opencapi_prepare_link_change;
>   	slot->ops.poll_link           = npu2_opencapi_poll_link;
>   	slot->ops.creset              = npu2_opencapi_creset;
>   	slot->ops.freset              = npu2_opencapi_freset;
>   	slot->ops.hreset              = npu2_opencapi_hreset;
>   
> +	make_slot_hotpluggable(slot, phb);
>   	return slot;
>   }
>   
> 



More information about the Skiboot mailing list