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

Frederic Barrat fbarrat at linux.ibm.com
Wed Sep 18 01:23:25 AEST 2019



Le 17/09/2019 à 15:37, christophe lombard a écrit :
> 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

mmm, ok. I need the slot to be created first, but we do that at the end 
of setup_device(). Maybe I should call make_slot_hotpluggable() one call 
higher, in setup_device() instead of within npu2_opencapi_slot_create().

   Fred



> 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