Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bdd2e715 authored by Christophe Lombard's avatar Christophe Lombard Committed by Michael Ellerman
Browse files

cxl: Update implementation service layer



The service layer API (in cxl.h) lists some low-level functions whose
implementation is different on PSL8, PSL9 and XSL:
- Init implementation for the adapter and the afu.
- Invalidate TLB/SLB.
- Attach process for dedicated/directed models.
- Handle psl interrupts.
- Debug registers for the adapter and the afu.
- Traces.
Each environment implements its own functions, and the common code uses
them through function pointers, defined in cxl_service_layer_ops.

Signed-off-by: default avatarChristophe Lombard <clombard@linux.vnet.ibm.com>
Reviewed-by: default avatarAndrew Donnellan <andrew.donnellan@au1.ibm.com>
Acked-by: default avatarFrederic Barrat <fbarrat@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 6dd2d234
Loading
Loading
Loading
Loading
+28 −12
Original line number Diff line number Diff line
@@ -553,13 +553,23 @@ struct cxl_context {
	struct mm_struct *mm;
};

struct cxl_irq_info;

struct cxl_service_layer_ops {
	int (*adapter_regs_init)(struct cxl *adapter, struct pci_dev *dev);
	int (*invalidate_all)(struct cxl *adapter);
	int (*afu_regs_init)(struct cxl_afu *afu);
	int (*sanitise_afu_regs)(struct cxl_afu *afu);
	int (*register_serr_irq)(struct cxl_afu *afu);
	void (*release_serr_irq)(struct cxl_afu *afu);
	void (*debugfs_add_adapter_sl_regs)(struct cxl *adapter, struct dentry *dir);
	void (*debugfs_add_afu_sl_regs)(struct cxl_afu *afu, struct dentry *dir);
	irqreturn_t (*handle_interrupt)(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info);
	irqreturn_t (*fail_irq)(struct cxl_afu *afu, struct cxl_irq_info *irq_info);
	int (*activate_dedicated_process)(struct cxl_afu *afu);
	int (*attach_afu_directed)(struct cxl_context *ctx, u64 wed, u64 amr);
	int (*attach_dedicated_process)(struct cxl_context *ctx, u64 wed, u64 amr);
	void (*update_dedicated_ivtes)(struct cxl_context *ctx);
	void (*debugfs_add_adapter_regs)(struct cxl *adapter, struct dentry *dir);
	void (*debugfs_add_afu_regs)(struct cxl_afu *afu, struct dentry *dir);
	void (*psl_irq_dump_registers)(struct cxl_context *ctx);
	void (*err_irq_dump_registers)(struct cxl *adapter);
	void (*debugfs_stop_trace)(struct cxl *adapter);
@@ -803,6 +813,11 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count);
void afu_release_irqs(struct cxl_context *ctx, void *cookie);
void afu_irq_name_free(struct cxl_context *ctx);

int cxl_attach_afu_directed_psl(struct cxl_context *ctx, u64 wed, u64 amr);
int cxl_activate_dedicated_process_psl(struct cxl_afu *afu);
int cxl_attach_dedicated_process_psl(struct cxl_context *ctx, u64 wed, u64 amr);
void cxl_update_dedicated_ivtes_psl(struct cxl_context *ctx);

#ifdef CONFIG_DEBUG_FS

int cxl_debugfs_init(void);
@@ -811,10 +826,10 @@ int cxl_debugfs_adapter_add(struct cxl *adapter);
void cxl_debugfs_adapter_remove(struct cxl *adapter);
int cxl_debugfs_afu_add(struct cxl_afu *afu);
void cxl_debugfs_afu_remove(struct cxl_afu *afu);
void cxl_stop_trace(struct cxl *cxl);
void cxl_debugfs_add_adapter_psl_regs(struct cxl *adapter, struct dentry *dir);
void cxl_debugfs_add_adapter_xsl_regs(struct cxl *adapter, struct dentry *dir);
void cxl_debugfs_add_afu_psl_regs(struct cxl_afu *afu, struct dentry *dir);
void cxl_stop_trace_psl(struct cxl *cxl);
void cxl_debugfs_add_adapter_regs_psl(struct cxl *adapter, struct dentry *dir);
void cxl_debugfs_add_adapter_regs_xsl(struct cxl *adapter, struct dentry *dir);
void cxl_debugfs_add_afu_regs_psl(struct cxl_afu *afu, struct dentry *dir);

#else /* CONFIG_DEBUG_FS */

@@ -849,17 +864,17 @@ static inline void cxl_stop_trace(struct cxl *cxl)
{
}

static inline void cxl_debugfs_add_adapter_psl_regs(struct cxl *adapter,
static inline void cxl_debugfs_add_adapter_regs_psl(struct cxl *adapter,
						    struct dentry *dir)
{
}

static inline void cxl_debugfs_add_adapter_xsl_regs(struct cxl *adapter,
static inline void cxl_debugfs_add_adapter_regs_xsl(struct cxl *adapter,
						    struct dentry *dir)
{
}

static inline void cxl_debugfs_add_afu_psl_regs(struct cxl_afu *afu, struct dentry *dir)
static inline void cxl_debugfs_add_afu_regs_psl(struct cxl_afu *afu, struct dentry *dir)
{
}

@@ -904,19 +919,20 @@ struct cxl_irq_info {
};

void cxl_assign_psn_space(struct cxl_context *ctx);
irqreturn_t cxl_irq(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info);
int cxl_invalidate_all_psl(struct cxl *adapter);
irqreturn_t cxl_irq_psl(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info);
irqreturn_t cxl_fail_irq_psl(struct cxl_afu *afu, struct cxl_irq_info *irq_info);
int cxl_register_one_irq(struct cxl *adapter, irq_handler_t handler,
			void *cookie, irq_hw_number_t *dest_hwirq,
			unsigned int *dest_virq, const char *name);

int cxl_check_error(struct cxl_afu *afu);
int cxl_afu_slbia(struct cxl_afu *afu);
int cxl_tlb_slb_invalidate(struct cxl *adapter);
int cxl_data_cache_flush(struct cxl *adapter);
int cxl_afu_disable(struct cxl_afu *afu);
int cxl_psl_purge(struct cxl_afu *afu);

void cxl_native_psl_irq_dump_regs(struct cxl_context *ctx);
void cxl_native_irq_dump_regs_psl(struct cxl_context *ctx);
void cxl_native_err_irq_dump_regs(struct cxl *adapter);
int cxl_pci_vphb_add(struct cxl_afu *afu);
void cxl_pci_vphb_remove(struct cxl_afu *afu);
+8 −8
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@

static struct dentry *cxl_debugfs;

void cxl_stop_trace(struct cxl *adapter)
void cxl_stop_trace_psl(struct cxl *adapter)
{
	int slice;

@@ -53,7 +53,7 @@ static struct dentry *debugfs_create_io_x64(const char *name, umode_t mode,
					  (void __force *)value, &fops_io_x64);
}

void cxl_debugfs_add_adapter_psl_regs(struct cxl *adapter, struct dentry *dir)
void cxl_debugfs_add_adapter_regs_psl(struct cxl *adapter, struct dentry *dir)
{
	debugfs_create_io_x64("fir1", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_FIR1));
	debugfs_create_io_x64("fir2", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_FIR2));
@@ -61,7 +61,7 @@ void cxl_debugfs_add_adapter_psl_regs(struct cxl *adapter, struct dentry *dir)
	debugfs_create_io_x64("trace", S_IRUSR | S_IWUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_TRACE));
}

void cxl_debugfs_add_adapter_xsl_regs(struct cxl *adapter, struct dentry *dir)
void cxl_debugfs_add_adapter_regs_xsl(struct cxl *adapter, struct dentry *dir)
{
	debugfs_create_io_x64("fec", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_XSL_FEC));
}
@@ -82,8 +82,8 @@ int cxl_debugfs_adapter_add(struct cxl *adapter)

	debugfs_create_io_x64("err_ivte", S_IRUSR, dir, _cxl_p1_addr(adapter, CXL_PSL_ErrIVTE));

	if (adapter->native->sl_ops->debugfs_add_adapter_sl_regs)
		adapter->native->sl_ops->debugfs_add_adapter_sl_regs(adapter, dir);
	if (adapter->native->sl_ops->debugfs_add_adapter_regs)
		adapter->native->sl_ops->debugfs_add_adapter_regs(adapter, dir);
	return 0;
}

@@ -92,7 +92,7 @@ void cxl_debugfs_adapter_remove(struct cxl *adapter)
	debugfs_remove_recursive(adapter->debugfs);
}

void cxl_debugfs_add_afu_psl_regs(struct cxl_afu *afu, struct dentry *dir)
void cxl_debugfs_add_afu_regs_psl(struct cxl_afu *afu, struct dentry *dir)
{
	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));
@@ -121,8 +121,8 @@ int cxl_debugfs_afu_add(struct cxl_afu *afu)
	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_sl_regs)
		afu->adapter->native->sl_ops->debugfs_add_afu_sl_regs(afu, dir);
	if (afu->adapter->native->sl_ops->debugfs_add_afu_regs)
		afu->adapter->native->sl_ops->debugfs_add_afu_regs(afu, dir);

	return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -169,7 +169,7 @@ static irqreturn_t guest_psl_irq(int irq, void *data)
		return IRQ_HANDLED;
	}

	rc = cxl_irq(irq, ctx, &irq_info);
	rc = cxl_irq_psl(irq, ctx, &irq_info);
	return rc;
}

+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ static irqreturn_t schedule_cxl_fault(struct cxl_context *ctx, u64 dsisr, u64 da
	return IRQ_HANDLED;
}

irqreturn_t cxl_irq(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info)
irqreturn_t cxl_irq_psl(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info)
{
	u64 dsisr, dar;

+32 −22
Original line number Diff line number Diff line
@@ -258,7 +258,7 @@ void cxl_release_spa(struct cxl_afu *afu)
	}
}

int cxl_tlb_slb_invalidate(struct cxl *adapter)
int cxl_invalidate_all_psl(struct cxl *adapter)
{
	unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT);

@@ -578,7 +578,7 @@ static void update_ivtes_directed(struct cxl_context *ctx)
		WARN_ON(add_process_element(ctx));
}

static int attach_afu_directed(struct cxl_context *ctx, u64 wed, u64 amr)
int cxl_attach_afu_directed_psl(struct cxl_context *ctx, u64 wed, u64 amr)
{
	u32 pid;
	int result;
@@ -671,7 +671,7 @@ static int deactivate_afu_directed(struct cxl_afu *afu)
	return 0;
}

static int activate_dedicated_process(struct cxl_afu *afu)
int cxl_activate_dedicated_process_psl(struct cxl_afu *afu)
{
	dev_info(&afu->dev, "Activating dedicated process mode\n");

@@ -694,7 +694,7 @@ static int activate_dedicated_process(struct cxl_afu *afu)
	return cxl_chardev_d_afu_add(afu);
}

static void update_ivtes_dedicated(struct cxl_context *ctx)
void cxl_update_dedicated_ivtes_psl(struct cxl_context *ctx)
{
	struct cxl_afu *afu = ctx->afu;

@@ -710,7 +710,7 @@ static void update_ivtes_dedicated(struct cxl_context *ctx)
			((u64)ctx->irqs.range[3] & 0xffff));
}

static int attach_dedicated(struct cxl_context *ctx, u64 wed, u64 amr)
int cxl_attach_dedicated_process_psl(struct cxl_context *ctx, u64 wed, u64 amr)
{
	struct cxl_afu *afu = ctx->afu;
	u64 pid;
@@ -728,7 +728,8 @@ static int attach_dedicated(struct cxl_context *ctx, u64 wed, u64 amr)

	cxl_prefault(ctx, wed);

	update_ivtes_dedicated(ctx);
	if (ctx->afu->adapter->native->sl_ops->update_dedicated_ivtes)
		afu->adapter->native->sl_ops->update_dedicated_ivtes(ctx);

	cxl_p2n_write(afu, CXL_PSL_AMR_An, amr);

@@ -778,8 +779,9 @@ static int native_afu_activate_mode(struct cxl_afu *afu, int mode)

	if (mode == CXL_MODE_DIRECTED)
		return activate_afu_directed(afu);
	if (mode == CXL_MODE_DEDICATED)
		return activate_dedicated_process(afu);
	if ((mode == CXL_MODE_DEDICATED) &&
	    (afu->adapter->native->sl_ops->activate_dedicated_process))
		return afu->adapter->native->sl_ops->activate_dedicated_process(afu);

	return -EINVAL;
}
@@ -793,11 +795,13 @@ static int native_attach_process(struct cxl_context *ctx, bool kernel,
	}

	ctx->kernel = kernel;
	if (ctx->afu->current_mode == CXL_MODE_DIRECTED)
		return attach_afu_directed(ctx, wed, amr);
	if ((ctx->afu->current_mode == CXL_MODE_DIRECTED) &&
	    (ctx->afu->adapter->native->sl_ops->attach_afu_directed))
		return ctx->afu->adapter->native->sl_ops->attach_afu_directed(ctx, wed, amr);

	if (ctx->afu->current_mode == CXL_MODE_DEDICATED)
		return attach_dedicated(ctx, wed, amr);
	if ((ctx->afu->current_mode == CXL_MODE_DEDICATED) &&
	    (ctx->afu->adapter->native->sl_ops->attach_dedicated_process))
		return ctx->afu->adapter->native->sl_ops->attach_dedicated_process(ctx, wed, amr);

	return -EINVAL;
}
@@ -830,8 +834,9 @@ static void native_update_ivtes(struct cxl_context *ctx)
{
	if (ctx->afu->current_mode == CXL_MODE_DIRECTED)
		return update_ivtes_directed(ctx);
	if (ctx->afu->current_mode == CXL_MODE_DEDICATED)
		return update_ivtes_dedicated(ctx);
	if ((ctx->afu->current_mode == CXL_MODE_DEDICATED) &&
	    (ctx->afu->adapter->native->sl_ops->update_dedicated_ivtes))
		return ctx->afu->adapter->native->sl_ops->update_dedicated_ivtes(ctx);
	WARN(1, "native_update_ivtes: Bad mode\n");
}

@@ -875,7 +880,7 @@ static int native_get_irq_info(struct cxl_afu *afu, struct cxl_irq_info *info)
	return 0;
}

void cxl_native_psl_irq_dump_regs(struct cxl_context *ctx)
void cxl_native_irq_dump_regs_psl(struct cxl_context *ctx)
{
	u64 fir1, fir2, fir_slice, serr, afu_debug;

@@ -911,7 +916,7 @@ static irqreturn_t native_handle_psl_slice_error(struct cxl_context *ctx,
	return cxl_ops->ack_irq(ctx, 0, errstat);
}

static irqreturn_t fail_psl_irq(struct cxl_afu *afu, struct cxl_irq_info *irq_info)
irqreturn_t cxl_fail_irq_psl(struct cxl_afu *afu, struct cxl_irq_info *irq_info)
{
	if (irq_info->dsisr & CXL_PSL_DSISR_TRANS)
		cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE);
@@ -927,7 +932,7 @@ static irqreturn_t native_irq_multiplexed(int irq, void *data)
	struct cxl_context *ctx;
	struct cxl_irq_info irq_info;
	u64 phreg = cxl_p2n_read(afu, CXL_PSL_PEHandle_An);
	int ph, ret;
	int ph, ret = IRQ_HANDLED, res;

	/* check if eeh kicked in while the interrupt was in flight */
	if (unlikely(phreg == ~0ULL)) {
@@ -938,15 +943,18 @@ static irqreturn_t native_irq_multiplexed(int irq, void *data)
	}
	/* Mask the pe-handle from register value */
	ph = phreg & 0xffff;
	if ((ret = native_get_irq_info(afu, &irq_info))) {
		WARN(1, "Unable to get CXL IRQ Info: %i\n", ret);
		return fail_psl_irq(afu, &irq_info);
	if ((res = native_get_irq_info(afu, &irq_info))) {
		WARN(1, "Unable to get CXL IRQ Info: %i\n", res);
		if (afu->adapter->native->sl_ops->fail_irq)
			return afu->adapter->native->sl_ops->fail_irq(afu, &irq_info);
		return ret;
	}

	rcu_read_lock();
	ctx = idr_find(&afu->contexts_idr, ph);
	if (ctx) {
		ret = cxl_irq(irq, ctx, &irq_info);
		if (afu->adapter->native->sl_ops->handle_interrupt)
			ret = afu->adapter->native->sl_ops->handle_interrupt(irq, ctx, &irq_info);
		rcu_read_unlock();
		return ret;
	}
@@ -956,7 +964,9 @@ static irqreturn_t native_irq_multiplexed(int irq, void *data)
		" %016llx\n(Possible AFU HW issue - was a term/remove acked"
		" with outstanding transactions?)\n", ph, irq_info.dsisr,
		irq_info.dar);
	return fail_psl_irq(afu, &irq_info);
	if (afu->adapter->native->sl_ops->fail_irq)
		ret = afu->adapter->native->sl_ops->fail_irq(afu, &irq_info);
	return ret;
}

static void native_irq_wait(struct cxl_context *ctx)
Loading