[Skiboot] [PATCH skiboot] phb4: Add PHB flags OPAL call
Oliver O'Halloran
oohall at gmail.com
Fri Nov 22 13:36:35 AEDT 2019
On Fri, Nov 22, 2019 at 11:13 AM Alexey Kardashevskiy <aik at ozlabs.ru> wrote:
>
> A new OPAL call to tweak various PHB parameters. The first flag is
> TVT Select 'GTE4GB' Option of the PHB control register to enable use
> of the second TVE for DMA trafic just above 4GB.
>
> Suggested-by: Alistair Popple <alistair at popple.id.au>
> Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
> ---
> include/opal-api.h | 7 ++++++-
> include/pci.h | 3 +++
> core/pci-opal.c | 20 ++++++++++++++++++++
> hw/phb4.c | 24 ++++++++++++++++++++++++
> 4 files changed, 53 insertions(+), 1 deletion(-)
The new opal call should be documented in doc/opal-api/
> diff --git a/include/opal-api.h b/include/opal-api.h
> index b577952ea060..aec3937105a2 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -225,7 +225,8 @@
> #define OPAL_SECVAR_GET 176
> #define OPAL_SECVAR_GET_NEXT 177
> #define OPAL_SECVAR_ENQUEUE_UPDATE 178
> -#define OPAL_LAST 178
> +#define OPAL_PCI_SET_PHB_FLAGS 179
> +#define OPAL_LAST 179
>
> #define QUIESCE_HOLD 1 /* Spin all calls at entry */
> #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
> @@ -524,6 +525,10 @@ enum OpalCheckTokenStatus {
> OPAL_TOKEN_PRESENT = 1
> };
>
> +enum OpalPCIPHBFlags {
> + OPAL_PCI_PHB_FLAG_TVE1_4GB = 0x1,
> +};
> +
> /*
> * Address cycle types for LPC accesses. These also correspond
> * to the content of the first cell of the "reg" property for
> diff --git a/include/pci.h b/include/pci.h
> index fb91d7936ec6..f7725a897bc7 100644
> --- a/include/pci.h
> +++ b/include/pci.h
> @@ -291,6 +291,9 @@ struct phb_ops {
> uint64_t pci_start_addr,
> uint64_t pci_mem_size);
>
> + int64_t (*set_phb_flags)(struct phb *phb, uint64_t setflags,
> + uint64_t clrflags);
> +
> int64_t (*set_mve)(struct phb *phb, uint32_t mve_number,
> uint64_t pe_number);
>
> diff --git a/core/pci-opal.c b/core/pci-opal.c
> index 828ce8a9715b..d3bc31cdb642 100644
> --- a/core/pci-opal.c
> +++ b/core/pci-opal.c
> @@ -461,6 +461,26 @@ static int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id,
> }
> opal_call(OPAL_PCI_MAP_PE_DMA_WINDOW_REAL, opal_pci_map_pe_dma_window_real, 5);
>
> +static int64_t opal_pci_set_phb_flags(uint64_t phb_id, uint64_t setflags,
> + uint64_t clrflags)
I think the flag based interface is kind of goofy and it will probably
wind up being annoying to implement and use. When you first mentioned
this I was thinking that we should do something like:
opal_phb_set_option(uint64_t phb_id, enum OpalPhbOption opt, uint64_t setting);
opal_phb_get_option(uint64_t phb_id, enum OpalPhbOption opt, uint64_t *setting);
The only real use for this is enabling random hacks, like the the 4GB
one, and having more than just a boolean setting would be useful for
that. There are a few nvram options where it would make sense to have
the ability to set them on a per-PHB basis via this interface. Some of
those take numeric arguments (e.g. the max link speed) and the flag
based interface is going to make that a headache.
> +{
> + struct phb *phb = pci_get_phb(phb_id);
> + int64_t rc;
> +
> + if (!phb)
> + return OPAL_PARAMETER;
> +
> + if (!phb->ops->set_phb_flags)
> + return OPAL_UNSUPPORTED;
> +
> + phb_lock(phb);
> + rc = phb->ops->set_phb_flags(phb, setflags, clrflags);
> + phb_unlock(phb);
> +
> + return rc;
> +}
> +opal_call(OPAL_PCI_SET_PHB_FLAGS, opal_pci_set_phb_flags, 3);
> +
> static int64_t opal_pci_reset(uint64_t id, uint8_t reset_scope,
> uint8_t assert_state)
> {
> diff --git a/hw/phb4.c b/hw/phb4.c
> index 4177589b4584..c7e0d4f739f1 100644
> --- a/hw/phb4.c
> +++ b/hw/phb4.c
> @@ -1534,6 +1534,29 @@ static int64_t phb4_map_pe_dma_window_real(struct phb *phb,
> return OPAL_SUCCESS;
> }
>
> +static int64_t phb4_set_phb_flags(struct phb *phb, uint64_t setflags,
> + uint64_t clrflags)
> +{
> + uint64_t data64;
> + struct phb4 *p = phb_to_phb4(phb);
> +
> + if ((setflags | clrflags) & ~OPAL_PCI_PHB_FLAG_TVE1_4GB)
> + return OPAL_PARAMETER;
> +
> + data64 = in_be64(p->regs + PHB_CTRLR);
> + if (setflags & OPAL_PCI_PHB_FLAG_TVE1_4GB) {
> + prlog(PR_WARNING, "PHB4: Enabling 4GB bypass mode\n");
> + data64 |= PPC_BIT(24);
> + }
> + if (clrflags & OPAL_PCI_PHB_FLAG_TVE1_4GB) {
> + prlog(PR_WARNING, "PHB4: Disabling 4GB bypass mode\n");
> + data64 &= ~PPC_BIT(24);
> + }
> + out_be64(p->regs + PHB_CTRLR, data64);
Use phb4_write_reg() instead of using out_be64() directly. Same for
phb4_read_reg() and in_be64(). PR_WARNING is also too loud for
something that's printed per-phb so drop that to PR_DEBUG or PR_TRACE.
Otherwise we'll end up with a lot of spurious prints in the opal log,
similar to what we have for the IMC or slw_set_reg crap.
> + return OPAL_SUCCESS;
> +}
> +
> static int64_t phb4_set_ive_pe(struct phb *phb,
> uint64_t pe_number,
> uint32_t ive_num)
> @@ -4796,6 +4819,7 @@ static const struct phb_ops phb4_ops = {
> .map_pe_mmio_window = phb4_map_pe_mmio_window,
> .map_pe_dma_window = phb4_map_pe_dma_window,
> .map_pe_dma_window_real = phb4_map_pe_dma_window_real,
> + .set_phb_flags = phb4_set_phb_flags,
> .set_xive_pe = phb4_set_ive_pe,
> .get_msi_32 = phb4_get_msi_32,
> .get_msi_64 = phb4_get_msi_64,
> --
> 2.17.1
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
More information about the Skiboot
mailing list