Skip to content

Commit d6a90bb

Browse files
Philippe Bergheaudmpe
authored andcommitted
powerpc/powernv: Enable tunneled operations
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@linux.vnet.ibm.com> Reviewed-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com> Reviewed-by: Christophe Lombard <clombard@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
1 parent 2b74e2a commit d6a90bb

File tree

6 files changed

+148
-9
lines changed

6 files changed

+148
-9
lines changed

arch/powerpc/include/asm/opal-api.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,9 @@
204204
#define OPAL_NPU_SPA_SETUP 159
205205
#define OPAL_NPU_SPA_CLEAR_CACHE 160
206206
#define OPAL_NPU_TL_SET 161
207-
#define OPAL_LAST 161
207+
#define OPAL_PCI_GET_PBCQ_TUNNEL_BAR 164
208+
#define OPAL_PCI_SET_PBCQ_TUNNEL_BAR 165
209+
#define OPAL_LAST 165
208210

209211
/* Device tree flags */
210212

arch/powerpc/include/asm/opal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ int64_t opal_unregister_dump_region(uint32_t id);
204204
int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
205205
int64_t opal_config_cpu_idle_state(uint64_t state, uint64_t flag);
206206
int64_t opal_pci_set_phb_cxl_mode(uint64_t phb_id, uint64_t mode, uint64_t pe_number);
207+
int64_t opal_pci_get_pbcq_tunnel_bar(uint64_t phb_id, uint64_t *addr);
208+
int64_t opal_pci_set_pbcq_tunnel_bar(uint64_t phb_id, uint64_t addr);
207209
int64_t opal_ipmi_send(uint64_t interface, struct opal_ipmi_msg *msg,
208210
uint64_t msg_len);
209211
int64_t opal_ipmi_recv(uint64_t interface, struct opal_ipmi_msg *msg,

arch/powerpc/include/asm/pnv-pci.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ extern int pnv_pci_set_power_state(uint64_t id, uint8_t state,
2929
extern int pnv_pci_set_p2p(struct pci_dev *initiator, struct pci_dev *target,
3030
u64 desc);
3131

32+
extern int pnv_pci_enable_tunnel(struct pci_dev *dev, uint64_t *asnind);
33+
extern int pnv_pci_disable_tunnel(struct pci_dev *dev);
34+
extern int pnv_pci_set_tunnel_bar(struct pci_dev *dev, uint64_t addr,
35+
int enable);
36+
extern int pnv_pci_get_as_notify_info(struct task_struct *task, u32 *lpid,
37+
u32 *pid, u32 *tid);
3238
int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode);
3339
int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq,
3440
unsigned int virq);

arch/powerpc/platforms/powernv/opal-wrappers.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,5 @@ OPAL_CALL(opal_sensor_group_clear, OPAL_SENSOR_GROUP_CLEAR);
323323
OPAL_CALL(opal_npu_spa_setup, OPAL_NPU_SPA_SETUP);
324324
OPAL_CALL(opal_npu_spa_clear_cache, OPAL_NPU_SPA_CLEAR_CACHE);
325325
OPAL_CALL(opal_npu_tl_set, OPAL_NPU_TL_SET);
326+
OPAL_CALL(opal_pci_get_pbcq_tunnel_bar, OPAL_PCI_GET_PBCQ_TUNNEL_BAR);
327+
OPAL_CALL(opal_pci_set_pbcq_tunnel_bar, OPAL_PCI_SET_PBCQ_TUNNEL_BAR);

arch/powerpc/platforms/powernv/pci-cxl.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@
1616

1717
#include "pci.h"
1818

19-
struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev)
20-
{
21-
struct pci_controller *hose = pci_bus_to_host(dev->bus);
22-
23-
return of_node_get(hose->dn);
24-
}
25-
EXPORT_SYMBOL(pnv_pci_get_phb_node);
26-
2719
int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode)
2820
{
2921
struct pci_controller *hose = pci_bus_to_host(dev->bus);

arch/powerpc/platforms/powernv/pci.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/io.h>
1919
#include <linux/msi.h>
2020
#include <linux/iommu.h>
21+
#include <linux/sched/mm.h>
2122

2223
#include <asm/sections.h>
2324
#include <asm/io.h>
@@ -38,6 +39,7 @@
3839
#include "pci.h"
3940

4041
static DEFINE_MUTEX(p2p_mutex);
42+
static DEFINE_MUTEX(tunnel_mutex);
4143

4244
int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id)
4345
{
@@ -1092,6 +1094,139 @@ int pnv_pci_set_p2p(struct pci_dev *initiator, struct pci_dev *target, u64 desc)
10921094
}
10931095
EXPORT_SYMBOL_GPL(pnv_pci_set_p2p);
10941096

1097+
struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev)
1098+
{
1099+
struct pci_controller *hose = pci_bus_to_host(dev->bus);
1100+
1101+
return of_node_get(hose->dn);
1102+
}
1103+
EXPORT_SYMBOL(pnv_pci_get_phb_node);
1104+
1105+
int pnv_pci_enable_tunnel(struct pci_dev *dev, u64 *asnind)
1106+
{
1107+
struct device_node *np;
1108+
const __be32 *prop;
1109+
struct pnv_ioda_pe *pe;
1110+
uint16_t window_id;
1111+
int rc;
1112+
1113+
if (!radix_enabled())
1114+
return -ENXIO;
1115+
1116+
if (!(np = pnv_pci_get_phb_node(dev)))
1117+
return -ENXIO;
1118+
1119+
prop = of_get_property(np, "ibm,phb-indications", NULL);
1120+
of_node_put(np);
1121+
1122+
if (!prop || !prop[1])
1123+
return -ENXIO;
1124+
1125+
*asnind = (u64)be32_to_cpu(prop[1]);
1126+
pe = pnv_ioda_get_pe(dev);
1127+
if (!pe)
1128+
return -ENODEV;
1129+
1130+
/* Increase real window size to accept as_notify messages. */
1131+
window_id = (pe->pe_number << 1 ) + 1;
1132+
rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id, pe->pe_number,
1133+
window_id, pe->tce_bypass_base,
1134+
(uint64_t)1 << 48);
1135+
return opal_error_code(rc);
1136+
}
1137+
EXPORT_SYMBOL_GPL(pnv_pci_enable_tunnel);
1138+
1139+
int pnv_pci_disable_tunnel(struct pci_dev *dev)
1140+
{
1141+
struct pnv_ioda_pe *pe;
1142+
1143+
pe = pnv_ioda_get_pe(dev);
1144+
if (!pe)
1145+
return -ENODEV;
1146+
1147+
/* Restore default real window size. */
1148+
pnv_pci_ioda2_set_bypass(pe, true);
1149+
return 0;
1150+
}
1151+
EXPORT_SYMBOL_GPL(pnv_pci_disable_tunnel);
1152+
1153+
int pnv_pci_set_tunnel_bar(struct pci_dev *dev, u64 addr, int enable)
1154+
{
1155+
__be64 val;
1156+
struct pci_controller *hose;
1157+
struct pnv_phb *phb;
1158+
u64 tunnel_bar;
1159+
int rc;
1160+
1161+
if (!opal_check_token(OPAL_PCI_GET_PBCQ_TUNNEL_BAR))
1162+
return -ENXIO;
1163+
if (!opal_check_token(OPAL_PCI_SET_PBCQ_TUNNEL_BAR))
1164+
return -ENXIO;
1165+
1166+
hose = pci_bus_to_host(dev->bus);
1167+
phb = hose->private_data;
1168+
1169+
mutex_lock(&tunnel_mutex);
1170+
rc = opal_pci_get_pbcq_tunnel_bar(phb->opal_id, &val);
1171+
if (rc != OPAL_SUCCESS) {
1172+
rc = -EIO;
1173+
goto out;
1174+
}
1175+
tunnel_bar = be64_to_cpu(val);
1176+
if (enable) {
1177+
/*
1178+
* Only one device per PHB can use atomics.
1179+
* Our policy is first-come, first-served.
1180+
*/
1181+
if (tunnel_bar) {
1182+
if (tunnel_bar != addr)
1183+
rc = -EBUSY;
1184+
else
1185+
rc = 0; /* Setting same address twice is ok */
1186+
goto out;
1187+
}
1188+
} else {
1189+
/*
1190+
* The device that owns atomics and wants to release
1191+
* them must pass the same address with enable == 0.
1192+
*/
1193+
if (tunnel_bar != addr) {
1194+
rc = -EPERM;
1195+
goto out;
1196+
}
1197+
addr = 0x0ULL;
1198+
}
1199+
rc = opal_pci_set_pbcq_tunnel_bar(phb->opal_id, addr);
1200+
rc = opal_error_code(rc);
1201+
out:
1202+
mutex_unlock(&tunnel_mutex);
1203+
return rc;
1204+
}
1205+
EXPORT_SYMBOL_GPL(pnv_pci_set_tunnel_bar);
1206+
1207+
#ifdef CONFIG_PPC64 /* for thread.tidr */
1208+
int pnv_pci_get_as_notify_info(struct task_struct *task, u32 *lpid, u32 *pid,
1209+
u32 *tid)
1210+
{
1211+
struct mm_struct *mm = NULL;
1212+
1213+
if (task == NULL)
1214+
return -EINVAL;
1215+
1216+
mm = get_task_mm(task);
1217+
if (mm == NULL)
1218+
return -EINVAL;
1219+
1220+
*pid = mm->context.id;
1221+
mmput(mm);
1222+
1223+
*tid = task->thread.tidr;
1224+
*lpid = mfspr(SPRN_LPID);
1225+
return 0;
1226+
}
1227+
EXPORT_SYMBOL_GPL(pnv_pci_get_as_notify_info);
1228+
#endif
1229+
10951230
void pnv_pci_shutdown(void)
10961231
{
10971232
struct pci_controller *hose;

0 commit comments

Comments
 (0)