Skip to content

Commit

Permalink
cxl: Isolate few psl8 specific calls
Browse files Browse the repository at this point in the history
Point out the specific Coherent Accelerator Interface Architecture,
level 1, registers.
Code and functions specific to PSL8 (CAIA1) must be framed.

Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
Acked-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
[mpe: Don't split long strings, it makes them hard to grep for]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
  • Loading branch information
Christophe Lombard authored and Michael Ellerman committed Apr 13, 2017
1 parent 64663f3 commit abd1d99
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 56 deletions.
28 changes: 16 additions & 12 deletions drivers/misc/cxl/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,26 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
{
int i;

spin_lock_init(&ctx->sste_lock);
ctx->afu = afu;
ctx->master = master;
ctx->pid = NULL; /* Set in start work ioctl */
mutex_init(&ctx->mapping_lock);
ctx->mapping = NULL;

/*
* Allocate the segment table before we put it in the IDR so that we
* can always access it when dereferenced from IDR. For the same
* reason, the segment table is only destroyed after the context is
* removed from the IDR. Access to this in the IOCTL is protected by
* Linux filesytem symantics (can't IOCTL until open is complete).
*/
i = cxl_alloc_sst(ctx);
if (i)
return i;
if (cxl_is_psl8(afu)) {
spin_lock_init(&ctx->sste_lock);

/*
* Allocate the segment table before we put it in the IDR so that we
* can always access it when dereferenced from IDR. For the same
* reason, the segment table is only destroyed after the context is
* removed from the IDR. Access to this in the IOCTL is protected by
* Linux filesytem symantics (can't IOCTL until open is complete).
*/
i = cxl_alloc_sst(ctx);
if (i)
return i;
}

INIT_WORK(&ctx->fault_work, cxl_handle_fault);

Expand Down Expand Up @@ -308,7 +311,8 @@ static void reclaim_ctx(struct rcu_head *rcu)
{
struct cxl_context *ctx = container_of(rcu, struct cxl_context, rcu);

free_page((u64)ctx->sstp);
if (cxl_is_psl8(ctx->afu))
free_page((u64)ctx->sstp);
if (ctx->ff_page)
__free_page(ctx->ff_page);
ctx->sstp = NULL;
Expand Down
35 changes: 27 additions & 8 deletions drivers/misc/cxl/cxl.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static const cxl_p1_reg_t CXL_PSL_Control = {0x0020};
static const cxl_p1_reg_t CXL_PSL_DLCNTL = {0x0060};
static const cxl_p1_reg_t CXL_PSL_DLADDR = {0x0068};

/* PSL Lookaside Buffer Management Area */
/* PSL Lookaside Buffer Management Area - CAIA 1 */
static const cxl_p1_reg_t CXL_PSL_LBISEL = {0x0080};
static const cxl_p1_reg_t CXL_PSL_SLBIE = {0x0088};
static const cxl_p1_reg_t CXL_PSL_SLBIA = {0x0090};
Expand All @@ -82,7 +82,7 @@ static const cxl_p1_reg_t CXL_PSL_TLBIA = {0x00A8};
static const cxl_p1_reg_t CXL_PSL_AFUSEL = {0x00B0};

/* 0x00C0:7EFF Implementation dependent area */
/* PSL registers */
/* PSL registers - CAIA 1 */
static const cxl_p1_reg_t CXL_PSL_FIR1 = {0x0100};
static const cxl_p1_reg_t CXL_PSL_FIR2 = {0x0108};
static const cxl_p1_reg_t CXL_PSL_Timebase = {0x0110};
Expand All @@ -109,7 +109,7 @@ static const cxl_p1n_reg_t CXL_PSL_AMBAR_An = {0x10};
static const cxl_p1n_reg_t CXL_PSL_SPOffset_An = {0x18};
static const cxl_p1n_reg_t CXL_PSL_ID_An = {0x20};
static const cxl_p1n_reg_t CXL_PSL_SERR_An = {0x28};
/* Memory Management and Lookaside Buffer Management */
/* Memory Management and Lookaside Buffer Management - CAIA 1*/
static const cxl_p1n_reg_t CXL_PSL_SDR_An = {0x30};
static const cxl_p1n_reg_t CXL_PSL_AMOR_An = {0x38};
/* Pointer Area */
Expand All @@ -124,6 +124,7 @@ static const cxl_p1n_reg_t CXL_PSL_IVTE_Limit_An = {0xB8};
/* 0xC0:FF Implementation Dependent Area */
static const cxl_p1n_reg_t CXL_PSL_FIR_SLICE_An = {0xC0};
static const cxl_p1n_reg_t CXL_AFU_DEBUG_An = {0xC8};
/* 0xC0:FF Implementation Dependent Area - CAIA 1 */
static const cxl_p1n_reg_t CXL_PSL_APCALLOC_A = {0xD0};
static const cxl_p1n_reg_t CXL_PSL_COALLOC_A = {0xD8};
static const cxl_p1n_reg_t CXL_PSL_RXCTL_A = {0xE0};
Expand All @@ -133,12 +134,14 @@ static const cxl_p1n_reg_t CXL_PSL_SLICE_TRACE = {0xE8};
/* Configuration and Control Area */
static const cxl_p2n_reg_t CXL_PSL_PID_TID_An = {0x000};
static const cxl_p2n_reg_t CXL_CSRP_An = {0x008};
/* Configuration and Control Area - CAIA 1 */
static const cxl_p2n_reg_t CXL_AURP0_An = {0x010};
static const cxl_p2n_reg_t CXL_AURP1_An = {0x018};
static const cxl_p2n_reg_t CXL_SSTP0_An = {0x020};
static const cxl_p2n_reg_t CXL_SSTP1_An = {0x028};
/* Configuration and Control Area - CAIA 1 */
static const cxl_p2n_reg_t CXL_PSL_AMR_An = {0x030};
/* Segment Lookaside Buffer Management */
/* Segment Lookaside Buffer Management - CAIA 1 */
static const cxl_p2n_reg_t CXL_SLBIE_An = {0x040};
static const cxl_p2n_reg_t CXL_SLBIA_An = {0x048};
static const cxl_p2n_reg_t CXL_SLBI_Select_An = {0x050};
Expand Down Expand Up @@ -257,7 +260,7 @@ static const cxl_p2n_reg_t CXL_PSL_WED_An = {0x0A0};
#define CXL_SSTP1_An_STVA_L_MASK (~((1ull << (63-55))-1))
#define CXL_SSTP1_An_V (1ull << (63-63))

/****** CXL_PSL_SLBIE_[An] **************************************************/
/****** CXL_PSL_SLBIE_[An] - CAIA 1 **************************************************/
/* write: */
#define CXL_SLBIE_C PPC_BIT(36) /* Class */
#define CXL_SLBIE_SS PPC_BITMASK(37, 38) /* Segment Size */
Expand All @@ -267,18 +270,18 @@ static const cxl_p2n_reg_t CXL_PSL_WED_An = {0x0A0};
#define CXL_SLBIE_MAX PPC_BITMASK(24, 31)
#define CXL_SLBIE_PENDING PPC_BITMASK(56, 63)

/****** Common to all CXL_TLBIA/SLBIA_[An] **********************************/
/****** Common to all CXL_TLBIA/SLBIA_[An] - CAIA 1 **********************************/
#define CXL_TLB_SLB_P (1ull) /* Pending (read) */

/****** Common to all CXL_TLB/SLB_IA/IE_[An] registers **********************/
/****** Common to all CXL_TLB/SLB_IA/IE_[An] registers - CAIA 1 **********************/
#define CXL_TLB_SLB_IQ_ALL (0ull) /* Inv qualifier */
#define CXL_TLB_SLB_IQ_LPID (1ull) /* Inv qualifier */
#define CXL_TLB_SLB_IQ_LPIDPID (3ull) /* Inv qualifier */

/****** CXL_PSL_AFUSEL ******************************************************/
#define CXL_PSL_AFUSEL_A (1ull << (63-55)) /* Adapter wide invalidates affect all AFUs */

/****** CXL_PSL_DSISR_An ****************************************************/
/****** CXL_PSL_DSISR_An - CAIA 1 ****************************************************/
#define CXL_PSL_DSISR_An_DS (1ull << (63-0)) /* Segment not found */
#define CXL_PSL_DSISR_An_DM (1ull << (63-1)) /* PTE not found (See also: M) or protection fault */
#define CXL_PSL_DSISR_An_ST (1ull << (63-2)) /* Segment Table PTE not found */
Expand Down Expand Up @@ -749,6 +752,22 @@ static inline u64 cxl_p2n_read(struct cxl_afu *afu, cxl_p2n_reg_t reg)
return ~0ULL;
}

static inline bool cxl_is_power8(void)
{
if ((pvr_version_is(PVR_POWER8E)) ||
(pvr_version_is(PVR_POWER8NVL)) ||
(pvr_version_is(PVR_POWER8)))
return true;
return false;
}

static inline bool cxl_is_psl8(struct cxl_afu *afu)
{
if (afu->adapter->caia_major == 1)
return true;
return false;
}

ssize_t cxl_pci_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
loff_t off, size_t count);

Expand Down
6 changes: 4 additions & 2 deletions drivers/misc/cxl/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ void cxl_debugfs_adapter_remove(struct cxl *adapter)

void cxl_debugfs_add_afu_regs_psl8(struct cxl_afu *afu, struct dentry *dir)
{
debugfs_create_io_x64("sstp0", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_SSTP0_An));
debugfs_create_io_x64("sstp1", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_SSTP1_An));

debugfs_create_io_x64("fir", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_FIR_SLICE_An));
debugfs_create_io_x64("serr", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SERR_An));
debugfs_create_io_x64("afu_debug", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_AFU_DEBUG_An));
Expand All @@ -117,8 +120,7 @@ int cxl_debugfs_afu_add(struct cxl_afu *afu)
debugfs_create_io_x64("sr", S_IRUSR, dir, _cxl_p1n_addr(afu, CXL_PSL_SR_An));
debugfs_create_io_x64("dsisr", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_PSL_DSISR_An));
debugfs_create_io_x64("dar", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_PSL_DAR_An));
debugfs_create_io_x64("sstp0", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_SSTP0_An));
debugfs_create_io_x64("sstp1", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_SSTP1_An));

debugfs_create_io_x64("err_status", S_IRUSR, dir, _cxl_p2n_addr(afu, CXL_PSL_ErrStat_An));

if (afu->adapter->native->sl_ops->debugfs_add_afu_regs)
Expand Down
39 changes: 26 additions & 13 deletions drivers/misc/cxl/native.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,17 @@ int cxl_psl_purge(struct cxl_afu *afu)
}

dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An);
pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%016llx PSL_DSISR: 0x%016llx\n", PSL_CNTL, dsisr);
pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%016llx PSL_DSISR: 0x%016llx\n",
PSL_CNTL, dsisr);

if (dsisr & CXL_PSL_DSISR_TRANS) {
dar = cxl_p2n_read(afu, CXL_PSL_DAR_An);
dev_notice(&afu->dev, "PSL purge terminating pending translation, DSISR: 0x%016llx, DAR: 0x%016llx\n", dsisr, dar);
dev_notice(&afu->dev, "PSL purge terminating pending translation, DSISR: 0x%016llx, DAR: 0x%016llx\n",
dsisr, dar);
cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE);
} else if (dsisr) {
dev_notice(&afu->dev, "PSL purge acknowledging pending non-translation fault, DSISR: 0x%016llx\n", dsisr);
dev_notice(&afu->dev, "PSL purge acknowledging pending non-translation fault, DSISR: 0x%016llx\n",
dsisr);
cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A);
} else {
cpu_relax();
Expand Down Expand Up @@ -466,7 +470,8 @@ static int remove_process_element(struct cxl_context *ctx)

if (!rc)
ctx->pe_inserted = false;
slb_invalid(ctx);
if (cxl_is_power8())
slb_invalid(ctx);
pr_devel("%s Remove pe: %i finished\n", __func__, ctx->pe);
mutex_unlock(&ctx->afu->native->spa_mutex);

Expand Down Expand Up @@ -499,7 +504,8 @@ static int activate_afu_directed(struct cxl_afu *afu)
attach_spa(afu);

cxl_p1n_write(afu, CXL_PSL_SCNTL_An, CXL_PSL_SCNTL_An_PM_AFU);
cxl_p1n_write(afu, CXL_PSL_AMOR_An, 0xFFFFFFFFFFFFFFFFULL);
if (cxl_is_power8())
cxl_p1n_write(afu, CXL_PSL_AMOR_An, 0xFFFFFFFFFFFFFFFFULL);
cxl_p1n_write(afu, CXL_PSL_ID_An, CXL_PSL_ID_An_F | CXL_PSL_ID_An_L);

afu->current_mode = CXL_MODE_DIRECTED;
Expand Down Expand Up @@ -872,7 +878,8 @@ static int native_get_irq_info(struct cxl_afu *afu, struct cxl_irq_info *info)

info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An);
info->dar = cxl_p2n_read(afu, CXL_PSL_DAR_An);
info->dsr = cxl_p2n_read(afu, CXL_PSL_DSR_An);
if (cxl_is_power8())
info->dsr = cxl_p2n_read(afu, CXL_PSL_DSR_An);
info->afu_err = cxl_p2n_read(afu, CXL_AFU_ERR_An);
info->errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An);
info->proc_handle = 0;
Expand Down Expand Up @@ -984,7 +991,8 @@ static void native_irq_wait(struct cxl_context *ctx)
if (ph != ctx->pe)
return;
dsisr = cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An);
if ((dsisr & CXL_PSL_DSISR_PENDING) == 0)
if (cxl_is_psl8(ctx->afu) &&
((dsisr & CXL_PSL_DSISR_PENDING) == 0))
return;
/*
* We are waiting for the workqueue to process our
Expand All @@ -1001,21 +1009,25 @@ static void native_irq_wait(struct cxl_context *ctx)
static irqreturn_t native_slice_irq_err(int irq, void *data)
{
struct cxl_afu *afu = data;
u64 fir_slice, errstat, serr, afu_debug, afu_error, dsisr;
u64 errstat, serr, afu_error, dsisr;
u64 fir_slice, afu_debug;

/*
* slice err interrupt is only used with full PSL (no XSL)
*/
serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
fir_slice = cxl_p1n_read(afu, CXL_PSL_FIR_SLICE_An);
errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An);
afu_debug = cxl_p1n_read(afu, CXL_AFU_DEBUG_An);
afu_error = cxl_p2n_read(afu, CXL_AFU_ERR_An);
dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An);
cxl_afu_decode_psl_serr(afu, serr);
dev_crit(&afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);

if (cxl_is_power8()) {
fir_slice = cxl_p1n_read(afu, CXL_PSL_FIR_SLICE_An);
afu_debug = cxl_p1n_read(afu, CXL_AFU_DEBUG_An);
dev_crit(&afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
dev_crit(&afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
}
dev_crit(&afu->dev, "CXL_PSL_ErrStat_An: 0x%016llx\n", errstat);
dev_crit(&afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
dev_crit(&afu->dev, "AFU_ERR_An: 0x%.16llx\n", afu_error);
dev_crit(&afu->dev, "PSL_DSISR_An: 0x%.16llx\n", dsisr);

Expand Down Expand Up @@ -1108,7 +1120,8 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu)
}

serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff);
if (cxl_is_power8())
serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff);
cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);

return 0;
Expand Down
64 changes: 43 additions & 21 deletions drivers/misc/cxl/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,32 +324,33 @@ static void dump_afu_descriptor(struct cxl_afu *afu)
#undef show_reg
}

#define CAPP_UNIT0_ID 0xBA
#define CAPP_UNIT1_ID 0XBE
#define P8_CAPP_UNIT0_ID 0xBA
#define P8_CAPP_UNIT1_ID 0XBE

static u64 get_capp_unit_id(struct device_node *np)
{
u32 phb_index;

/*
* For chips other than POWER8NVL, we only have CAPP 0,
* irrespective of which PHB is used.
*/
if (!pvr_version_is(PVR_POWER8NVL))
return CAPP_UNIT0_ID;
if (of_property_read_u32(np, "ibm,phb-index", &phb_index))
return 0;

/*
* For POWER8NVL, assume CAPP 0 is attached to PHB0 and
* CAPP 1 is attached to PHB1.
* POWER 8:
* - For chips other than POWER8NVL, we only have CAPP 0,
* irrespective of which PHB is used.
* - For POWER8NVL, assume CAPP 0 is attached to PHB0 and
* CAPP 1 is attached to PHB1.
*/
if (of_property_read_u32(np, "ibm,phb-index", &phb_index))
return 0;
if (cxl_is_power8()) {
if (!pvr_version_is(PVR_POWER8NVL))
return P8_CAPP_UNIT0_ID;

if (phb_index == 0)
return CAPP_UNIT0_ID;
if (phb_index == 0)
return P8_CAPP_UNIT0_ID;

if (phb_index == 1)
return CAPP_UNIT1_ID;
if (phb_index == 1)
return P8_CAPP_UNIT1_ID;
}

return 0;
}
Expand Down Expand Up @@ -968,7 +969,7 @@ static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu)
}

if (afu->pp_psa && (afu->pp_size < PAGE_SIZE))
dev_warn(&afu->dev, "AFU uses < PAGE_SIZE per-process PSA!");
dev_warn(&afu->dev, "AFU uses pp_size(%#016llx) < PAGE_SIZE per-process PSA!\n", afu->pp_size);

for (i = 0; i < afu->crs_num; i++) {
rc = cxl_ops->afu_cr_read32(afu, i, 0, &val);
Expand Down Expand Up @@ -1251,8 +1252,13 @@ int cxl_pci_reset(struct cxl *adapter)

dev_info(&dev->dev, "CXL reset\n");

/* the adapter is about to be reset, so ignore errors */
cxl_data_cache_flush(adapter);
/*
* The adapter is about to be reset, so ignore errors.
* Not supported on P9 DD1 but don't forget to enable it
* on P9 DD2
*/
if (cxl_is_power8())
cxl_data_cache_flush(adapter);

/* pcie_warm_reset requests a fundamental pci reset which includes a
* PERST assert/deassert. PERST triggers a loading of the image
Expand Down Expand Up @@ -1382,6 +1388,14 @@ static void cxl_fixup_malformed_tlp(struct cxl *adapter, struct pci_dev *dev)
pci_write_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, data);
}

static bool cxl_compatible_caia_version(struct cxl *adapter)
{
if (cxl_is_power8() && (adapter->caia_major == 1))
return true;

return false;
}

static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev)
{
if (adapter->vsec_status & CXL_STATUS_SECOND_PORT)
Expand All @@ -1392,6 +1406,12 @@ static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev)
return -EINVAL;
}

if (!cxl_compatible_caia_version(adapter)) {
dev_info(&dev->dev, "Ignoring card. PSL type is not supported (caia version: %d)\n",
adapter->caia_major);
return -ENODEV;
}

if (!adapter->slices) {
/* Once we support dynamic reprogramming we can use the card if
* it supports loadable AFUs */
Expand Down Expand Up @@ -1574,8 +1594,10 @@ static void set_sl_ops(struct cxl *adapter, struct pci_dev *dev)
adapter->native->sl_ops = &xsl_ops;
adapter->min_pe = 1; /* Workaround for CX-4 hardware bug */
} else {
dev_info(&dev->dev, "Device uses a PSL8\n");
adapter->native->sl_ops = &psl8_ops;
if (cxl_is_power8()) {
dev_info(&dev->dev, "Device uses a PSL8\n");
adapter->native->sl_ops = &psl8_ops;
}
}
}

Expand Down

0 comments on commit abd1d99

Please sign in to comment.