[PATCH v9 1/2] powerpc/powernv: Enable tunneled operations
Frederic Barrat
fbarrat at linux.vnet.ibm.com
Wed Feb 21 20:46:41 AEDT 2018
Le 20/02/2018 à 16:51, Philippe Bergheaud a écrit :
> P9 supports PCI tunneled operations (atomics and as_notify). This
> patch adds support for tunneled operations on powernv, with a new
> API, to be called by device drivers:
>
> pnv_pci_enable_tunnel()
> Enable tunnel operations, tell driver the 16-bit ASN indication
> used by kernel.
>
> pnv_pci_disable_tunnel()
> Disable tunnel operations.
>
> pnv_pci_set_tunnel_bar()
> Tell kernel the Tunnel BAR Response address used by driver.
> This function uses two new OPAL calls, as the PBCQ Tunnel BAR
> register is configured by skiboot.
>
> pnv_pci_get_as_notify_info()
> Return the ASN info of the thread to be woken up.
>
> Signed-off-by: Philippe Bergheaud <felix at linux.vnet.ibm.com>
> ---
Reviewed-by: Frederic Barrat <fbarrat at linux.vnet.ibm.com>
> Changelog:
>
> v2: Do not set the ASN indication. Get it from the device tree.
>
> v3: Make pnv_pci_get_phb_node() available when compiling without cxl.
>
> v4: Add pnv_pci_get_as_notify_info().
> Rebase opal call numbers on skiboot 5.9.6.
>
> v5: pnv_pci_get_tunnel_ind():
> - fix node reference count
> pnv_pci_get_as_notify_info():
> - fail if task == NULL
> - read pid from mm->context.id
> - explain that thread.tidr require CONFIG_PPC64
>
> v6: pnv_pci_get_tunnel_ind():
> - check if radix is enabled, or else return an error
> pnv_pci_get_as_notify_info():
> - remove a capi-specific comment, irrelevant for pci
>
> v7: pnv_pci_set_tunnel_bar():
> - setting the tunnel bar more than once with the same value
> is not an error
>
> v8: No change
>
> v9: Rename pnv_pci_get_tunnel_ind() into pnv_pci_enable_tunnel():
> - Increase real window size to accept as_notify messages.
> New api pnv_pci_disable_tunnel():
> - Restore real window size to its default value.
> Adjust opal call numbers.
>
> This patch depends on the following skiboot patches:
> https://patchwork.ozlabs.org/patch/874415/
> https://patchwork.ozlabs.org/patch/874416/
> ---
> arch/powerpc/include/asm/opal-api.h | 4 +-
> arch/powerpc/include/asm/opal.h | 2 +
> arch/powerpc/include/asm/pnv-pci.h | 6 ++
> arch/powerpc/platforms/powernv/opal-wrappers.S | 2 +
> arch/powerpc/platforms/powernv/pci-cxl.c | 8 --
> arch/powerpc/platforms/powernv/pci.c | 135 +++++++++++++++++++++++++
> 6 files changed, 148 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
> index 94bd1bf2c873..07b5e2240ecc 100644
> --- a/arch/powerpc/include/asm/opal-api.h
> +++ b/arch/powerpc/include/asm/opal-api.h
> @@ -204,7 +204,9 @@
> #define OPAL_NPU_SPA_SETUP 159
> #define OPAL_NPU_SPA_CLEAR_CACHE 160
> #define OPAL_NPU_TL_SET 161
> -#define OPAL_LAST 161
> +#define OPAL_PCI_GET_PBCQ_TUNNEL_BAR 162
> +#define OPAL_PCI_SET_PBCQ_TUNNEL_BAR 163
> +#define OPAL_LAST 163
>
> /* Device tree flags */
>
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index 12e70fb58700..dde60089d0d4 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -204,6 +204,8 @@ int64_t opal_unregister_dump_region(uint32_t id);
> int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
> int64_t opal_config_cpu_idle_state(uint64_t state, uint64_t flag);
> int64_t opal_pci_set_phb_cxl_mode(uint64_t phb_id, uint64_t mode, uint64_t pe_number);
> +int64_t opal_pci_get_pbcq_tunnel_bar(uint64_t phb_id, uint64_t *addr);
> +int64_t opal_pci_set_pbcq_tunnel_bar(uint64_t phb_id, uint64_t addr);
> int64_t opal_ipmi_send(uint64_t interface, struct opal_ipmi_msg *msg,
> uint64_t msg_len);
> int64_t opal_ipmi_recv(uint64_t interface, struct opal_ipmi_msg *msg,
> diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h
> index 3e5cf251ad9a..d2d8c28db336 100644
> --- a/arch/powerpc/include/asm/pnv-pci.h
> +++ b/arch/powerpc/include/asm/pnv-pci.h
> @@ -29,6 +29,12 @@ extern int pnv_pci_set_power_state(uint64_t id, uint8_t state,
> extern int pnv_pci_set_p2p(struct pci_dev *initiator, struct pci_dev *target,
> u64 desc);
>
> +extern int pnv_pci_enable_tunnel(struct pci_dev *dev, uint64_t *asnind);
> +extern int pnv_pci_disable_tunnel(struct pci_dev *dev);
> +extern int pnv_pci_set_tunnel_bar(struct pci_dev *dev, uint64_t addr,
> + int enable);
> +extern int pnv_pci_get_as_notify_info(struct task_struct *task, u32 *lpid,
> + u32 *pid, u32 *tid);
> int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode);
> int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq,
> unsigned int virq);
> diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
> index 1b2936ba6040..3da30c2f26b4 100644
> --- a/arch/powerpc/platforms/powernv/opal-wrappers.S
> +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
> @@ -323,3 +323,5 @@ OPAL_CALL(opal_sensor_group_clear, OPAL_SENSOR_GROUP_CLEAR);
> OPAL_CALL(opal_npu_spa_setup, OPAL_NPU_SPA_SETUP);
> OPAL_CALL(opal_npu_spa_clear_cache, OPAL_NPU_SPA_CLEAR_CACHE);
> OPAL_CALL(opal_npu_tl_set, OPAL_NPU_TL_SET);
> +OPAL_CALL(opal_pci_get_pbcq_tunnel_bar, OPAL_PCI_GET_PBCQ_TUNNEL_BAR);
> +OPAL_CALL(opal_pci_set_pbcq_tunnel_bar, OPAL_PCI_SET_PBCQ_TUNNEL_BAR);
> diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c
> index 94498a04558b..cee003de63af 100644
> --- a/arch/powerpc/platforms/powernv/pci-cxl.c
> +++ b/arch/powerpc/platforms/powernv/pci-cxl.c
> @@ -16,14 +16,6 @@
>
> #include "pci.h"
>
> -struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev)
> -{
> - struct pci_controller *hose = pci_bus_to_host(dev->bus);
> -
> - return of_node_get(hose->dn);
> -}
> -EXPORT_SYMBOL(pnv_pci_get_phb_node);
> -
> int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode)
> {
> struct pci_controller *hose = pci_bus_to_host(dev->bus);
> diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
> index 69d102cbf48f..b265ecc0836a 100644
> --- a/arch/powerpc/platforms/powernv/pci.c
> +++ b/arch/powerpc/platforms/powernv/pci.c
> @@ -18,6 +18,7 @@
> #include <linux/io.h>
> #include <linux/msi.h>
> #include <linux/iommu.h>
> +#include <linux/sched/mm.h>
>
> #include <asm/sections.h>
> #include <asm/io.h>
> @@ -38,6 +39,7 @@
> #include "pci.h"
>
> static DEFINE_MUTEX(p2p_mutex);
> +static DEFINE_MUTEX(tunnel_mutex);
>
> int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id)
> {
> @@ -1092,6 +1094,139 @@ int pnv_pci_set_p2p(struct pci_dev *initiator, struct pci_dev *target, u64 desc)
> }
> EXPORT_SYMBOL_GPL(pnv_pci_set_p2p);
>
> +struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev)
> +{
> + struct pci_controller *hose = pci_bus_to_host(dev->bus);
> +
> + return of_node_get(hose->dn);
> +}
> +EXPORT_SYMBOL(pnv_pci_get_phb_node);
> +
> +int pnv_pci_enable_tunnel(struct pci_dev *dev, u64 *asnind)
> +{
> + struct device_node *np;
> + const __be32 *prop;
> + struct pnv_ioda_pe *pe;
> + uint16_t window_id;
> + int rc;
> +
> + if (!radix_enabled())
> + return -ENXIO;
> +
> + if (!(np = pnv_pci_get_phb_node(dev)))
> + return -ENXIO;
> +
> + prop = of_get_property(np, "ibm,phb-indications", NULL);
> + of_node_put(np);
> +
> + if (!prop || !prop[1])
> + return -ENXIO;
> +
> + *asnind = (u64)be32_to_cpu(prop[1]);
> + pe = pnv_ioda_get_pe(dev);
> + if (!pe)
> + return -ENODEV;
> +
> + /* Increase real window size to accept as_notify messages. */
> + window_id = (pe->pe_number << 1 ) + 1;
> + rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id, pe->pe_number,
> + window_id, pe->tce_bypass_base,
> + (uint64_t)1 << 48);
> + return opal_error_code(rc);
> +}
> +EXPORT_SYMBOL_GPL(pnv_pci_enable_tunnel);
> +
> +int pnv_pci_disable_tunnel(struct pci_dev *dev)
> +{
> + struct pnv_ioda_pe *pe;
> +
> + pe = pnv_ioda_get_pe(dev);
> + if (!pe)
> + return -ENODEV;
> +
> + /* Restore default real window size. */
> + pnv_pci_ioda2_set_bypass(pe, true);
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(pnv_pci_disable_tunnel);
> +
> +int pnv_pci_set_tunnel_bar(struct pci_dev *dev, u64 addr, int enable)
> +{
> + __be64 val;
> + struct pci_controller *hose;
> + struct pnv_phb *phb;
> + u64 tunnel_bar;
> + int rc;
> +
> + if (!opal_check_token(OPAL_PCI_GET_PBCQ_TUNNEL_BAR))
> + return -ENXIO;
> + if (!opal_check_token(OPAL_PCI_SET_PBCQ_TUNNEL_BAR))
> + return -ENXIO;
> +
> + hose = pci_bus_to_host(dev->bus);
> + phb = hose->private_data;
> +
> + mutex_lock(&tunnel_mutex);
> + rc = opal_pci_get_pbcq_tunnel_bar(phb->opal_id, &val);
> + if (rc != OPAL_SUCCESS) {
> + rc = -EIO;
> + goto out;
> + }
> + tunnel_bar = be64_to_cpu(val);
> + if (enable) {
> + /*
> + * Only one device per PHB can use atomics.
> + * Our policy is first-come, first-served.
> + */
> + if (tunnel_bar) {
> + if (tunnel_bar != addr)
> + rc = -EBUSY;
> + else
> + rc = 0; /* Setting same address twice is ok */
> + goto out;
> + }
> + } else {
> + /*
> + * The device that owns atomics and wants to release
> + * them must pass the same address with enable == 0.
> + */
> + if (tunnel_bar != addr) {
> + rc = -EPERM;
> + goto out;
> + }
> + addr = 0x0ULL;
> + }
> + rc = opal_pci_set_pbcq_tunnel_bar(phb->opal_id, addr);
> + rc = opal_error_code(rc);
> +out:
> + mutex_unlock(&tunnel_mutex);
> + return rc;
> +}
> +EXPORT_SYMBOL_GPL(pnv_pci_set_tunnel_bar);
> +
> +#ifdef CONFIG_PPC64 /* for thread.tidr */
> +int pnv_pci_get_as_notify_info(struct task_struct *task, u32 *lpid, u32 *pid,
> + u32 *tid)
> +{
> + struct mm_struct *mm = NULL;
> +
> + if (task == NULL)
> + return -EINVAL;
> +
> + mm = get_task_mm(task);
> + if (mm == NULL)
> + return -EINVAL;
> +
> + *pid = mm->context.id;
> + mmput(mm);
> +
> + *tid = task->thread.tidr;
> + *lpid = mfspr(SPRN_LPID);
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(pnv_pci_get_as_notify_info);
> +#endif
> +
> void pnv_pci_shutdown(void)
> {
> struct pci_controller *hose;
>
More information about the Linuxppc-dev
mailing list