[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