[Skiboot] [PATCH v4] phb4: Activate shared PCI slot on witherspoon

Frederic Barrat fbarrat at linux.vnet.ibm.com
Thu Jun 8 02:22:32 AEST 2017



Le 07/06/2017 à 12:28, Stewart Smith a écrit :
> From: Frederic Barrat <fbarrat at linux.vnet.ibm.com>
> 
> Witherspoon systems come with a 'shared' PCI slot: physically, it
> looks like a x16 slot, but it's actually two x8 slots connected to two
> PHBs of two different chips. Taking advantage of it requires some
> logic on the PCI adapter. Only the Mellanox CX5 adapter is known to
> support it at the time of this writing.
> 
> This patch enables support for the shared slot on witherspoon if a x16
> adapter is detected. Each x8 slot has a presence bit, so both bits
> need to be set for the activation to take place. Slot sharing is
> activated through a gpio.
> 
> Note that there's no easy way to be sure that the card is indeed a
> shared-slot compatible PCI adapter and not a normal x16 card. Plugging
> a normal x16 adapter on the shared slot should be avoided on
> witherspoon, as the link won't train on the second slot, resulting in
> a timeout and a longer boot time. Only the first slot is usable and
> the x16 adapter will end up using only half the lines.
> 
> If the PCI card plugged on the physical slot is only x8 (or less),
> then the presence bit of the second slot is not set, so this patch
> does nothing. The x8 (or less) adapter should work like on any other
> physical slot.
> 
> Signed-off-by: Frederic Barrat <fbarrat at linux.vnet.ibm.com>
> [stewart at linux.vnet.ibm.com: re-org code, move into platform file]
> Signed-off-by: Stewart Smith <stewart at linux.vnet.ibm.com>
> ---


code reorg looks ok to me. I had the _witherspoon suffix on the 
functions to show the context, so it could be removed now that they are 
in withersoon.c
I guess it's debatable where that code belongs, but 1) I don't feel 
strongly about it and 2) it would be better done around a beer and 3) 
you're the boss anyway :-)

   Fred


>   core/pci.c                     |  3 ++
>   hw/phb4.c                      |  2 +-
>   include/phb4.h                 |  7 ++++
>   include/platform.h             |  5 +++
>   include/xscom-p9-regs.h        |  3 ++
>   platforms/astbmc/witherspoon.c | 94 ++++++++++++++++++++++++++++++++++++++++++
>   6 files changed, 113 insertions(+), 1 deletion(-)
> 
> diff --git a/core/pci.c b/core/pci.c
> index ec2416701015..f71482aafb28 100644
> --- a/core/pci.c
> +++ b/core/pci.c
> @@ -1651,6 +1651,9 @@ void pci_init_slots(void)
>   		}
>   	}
> 
> +	if (platform.pre_pci_fixup)
> +		platform.pre_pci_fixup();
> +
>   	prlog(PR_NOTICE, "PCI: Resetting PHBs...\n");
>   	pci_do_jobs(pci_reset_phb);
> 
> diff --git a/hw/phb4.c b/hw/phb4.c
> index b53dadfb7b67..3843456fbc4a 100644
> --- a/hw/phb4.c
> +++ b/hw/phb4.c
> @@ -3290,7 +3290,7 @@ static void phb4_create(struct dt_node *np)
>   	/* We register the PHB before we initialize it so we
>   	 * get a useful OPAL ID for it
>   	 */
> -	pci_register_phb(&p->phb, p->chip_id * 6 + p->index); //6 PHBs per chip?
> +	pci_register_phb(&p->phb, phb4_get_opal_id(p->chip_id, p->index));
> 
>   	/* Create slot structure */
>   	slot = phb4_slot_create(&p->phb);
> diff --git a/include/phb4.h b/include/phb4.h
> index bed6eef09279..3ec8a5b8cc46 100644
> --- a/include/phb4.h
> +++ b/include/phb4.h
> @@ -306,4 +306,11 @@ static inline void phb4_set_err_pending(struct phb4 *p, bool pending)
>   	p->err_pending = pending;
>   }
> 
> +#define PHB4_PER_CHIP                        6 /* Max 6 PHBs per chip on p9 */
> +
> +static inline int phb4_get_opal_id(unsigned int chip_id, unsigned int index)
> +{
> +	return chip_id * PHB4_PER_CHIP + index;
> +}
> +
>   #endif /* __PHB4_H */
> diff --git a/include/platform.h b/include/platform.h
> index 9133204207d6..4dcdb3350364 100644
> --- a/include/platform.h
> +++ b/include/platform.h
> @@ -101,6 +101,11 @@ struct platform {
>   	void		(*pci_setup_phb)(struct phb *phb, unsigned int index);
> 
>   	/*
> +	 * This is called before resetting the PHBs (lift PERST) and
> +	 * probing the devices. The PHBs have already been initialized.
> +	 */
> +	void		(*pre_pci_fixup)(void);
> +	/*
>   	 * Called during PCI scan for each device. For bridges, this is
>   	 * called before its children are probed. This is called for
>   	 * every device and for the PHB itself with a NULL pd though
> diff --git a/include/xscom-p9-regs.h b/include/xscom-p9-regs.h
> index 7da404baed10..4738e812c8c2 100644
> --- a/include/xscom-p9-regs.h
> +++ b/include/xscom-p9-regs.h
> @@ -18,4 +18,7 @@
>   #define P9X_EX_NCU_DARN_BAR			0x11011
>   #define  P9X_EX_NCU_DARN_BAR_EN			PPC_BIT(0)
> 
> +#define P9_GPIO_DATA_OUT_ENABLE			0x00000000000B0054ull
> +#define P9_GPIO_DATA_OUT			0x00000000000B0051ull
> +
>   #endif /* __XSCOM_P9_REGS_H__ */
> diff --git a/platforms/astbmc/witherspoon.c b/platforms/astbmc/witherspoon.c
> index abaa7c9bc15c..460498608627 100644
> --- a/platforms/astbmc/witherspoon.c
> +++ b/platforms/astbmc/witherspoon.c
> @@ -21,9 +21,17 @@
>   #include <ipmi.h>
>   #include <psi.h>
>   #include <npu-regs.h>
> +#include <xscom.h>
> +#include <xscom-p9-regs.h>
> +#include <timebase.h>
> +#include <pci.h>
> +#include <pci-slot.h>
> +#include <phb4.h>
> 
>   #include "astbmc.h"
> 
> +#define PHB4_SHARED_SLOT_IDX_WITHERSPOON     3
> +
>   static bool witherspoon_probe(void)
>   {
>   	if (!dt_node_is_compatible(dt_root, "ibm,witherspoon"))
> @@ -38,10 +46,96 @@ static bool witherspoon_probe(void)
>   	return true;
>   }
> 
> +static void phb4_activate_shared_slot_witherspoon(struct proc_chip *chip)
> +{
> +	uint64_t val;
> +
> +	/*
> +	 * Shared slot activation is done by raising a GPIO line on the
> +	 * chip with the secondary slot. It will somehow activate the
> +	 * sideband signals between the slots.
> +	 * Need to wait 100us for stability.
> +	 */
> +	xscom_read(chip->id, P9_GPIO_DATA_OUT_ENABLE, &val);
> +	val |= PPC_BIT(2);
> +	xscom_write(chip->id, P9_GPIO_DATA_OUT_ENABLE, val);
> +
> +	xscom_read(chip->id, P9_GPIO_DATA_OUT, &val);
> +	val |= PPC_BIT(2);
> +	xscom_write(chip->id, P9_GPIO_DATA_OUT, val);
> +	time_wait_us(100);
> +	prlog(PR_INFO, "Shared PCI slot activated\n");
> +}
> +
> +static void phb4_pre_pci_fixup_witherspoon(void)
> +{
> +	struct pci_slot *slot0, *slot1;
> +	struct proc_chip *chip0, *chip1;
> +	uint8_t p0 = 0, p1 = 0;
> +
> +	/*
> +	 * Detect if a x16 card is present on the shared slot and
> +	 * do some extra configuration if it is.
> +	 *
> +	 * The shared slot, a.k.a "Slot 2" in the documentation, is
> +	 * connected to PEC2 phb index 3 on both chips. From skiboot,
> +	 * it looks like two x8 slots, each with its own presence bit.
> +	 *
> +	 * Here is the matrix of possibilities for the presence bits:
> +	 *
> +	 * slot0 presence     slot1 presence
> +	 *    0                  0               => no card
> +	 *    1                  0               => x8 or less card detected
> +	 *    1                  1               => x16 card detected
> +	 *    0                  1               => invalid combination
> +	 *
> +	 * We only act if a x16 card is detected ('1 1' combination above).
> +	 *
> +	 * One issue is that we don't really know if it is a
> +	 * shared-slot-compatible card (such as Mellanox CX5) or
> +	 * a 'normal' x16 PCI card. We activate the shared slot in both cases,
> +	 * as it doesn't seem to hurt.
> +	 *
> +	 * If the card is a normal x16 PCI card, the link won't train on the
> +	 * second slot (nothing to do with the shared slot activation), the
> +	 * procedure will timeout, thus adding some delay to the boot time.
> +	 * Therefore the recommendation is that we shouldn't use a normal
> +	 * x16 card on the shared slot of a witherspoon.
> +	 *
> +	 * Plugging a x8 or less adapter on the shared slot should work
> +	 * like any other physical slot.
> +	 */
> +	chip0 = next_chip(NULL);
> +	chip1 = next_chip(chip0);
> +	if (!chip1 || next_chip(chip1)) {
> +		prlog(PR_WARNING,
> +			"Unexpected number of chips, skipping shared slot detection\n");
> +		return;
> +	}
> +	slot0 = pci_slot_find(phb4_get_opal_id(chip0->id,
> +					PHB4_SHARED_SLOT_IDX_WITHERSPOON));
> +	slot1 = pci_slot_find(phb4_get_opal_id(chip1->id,
> +					PHB4_SHARED_SLOT_IDX_WITHERSPOON));
> +	if (slot0 && slot1) {
> +		if (slot0->ops.get_presence_state)
> +			slot0->ops.get_presence_state(slot0, &p0);
> +		if (slot1->ops.get_presence_state)
> +			slot1->ops.get_presence_state(slot1, &p1);
> +		if (p0 == 1 && p1 == 1)
> +			phb4_activate_shared_slot_witherspoon(chip1);
> +	}
> +}
> +
> +static void witherspoon_pre_pci_fixup(void)
> +{
> +	phb4_pre_pci_fixup_witherspoon();
> +}
> +
>   DECLARE_PLATFORM(witherspoon_platform) = {
>   	.name			= "Witherspoon",
>   	.probe			= witherspoon_probe,
>   	.init			= astbmc_init,
> +	.pre_pci_fixup		= witherspoon_pre_pci_fixup,
>   	.start_preload_resource	= flash_start_preload_resource,
>   	.resource_loaded	= flash_resource_loaded,
>   	.bmc			= NULL, /* FIXME: Add openBMC */
> 



More information about the Skiboot mailing list