diff options
Diffstat (limited to 'drivers/misc/cxl')
| -rw-r--r-- | drivers/misc/cxl/Makefile | 5 | ||||
| -rw-r--r-- | drivers/misc/cxl/cxl.h | 22 | ||||
| -rw-r--r-- | drivers/misc/cxl/fault.c | 11 | ||||
| -rw-r--r-- | drivers/misc/cxl/file.c | 7 | ||||
| -rw-r--r-- | drivers/misc/cxl/irq.c | 7 | ||||
| -rw-r--r-- | drivers/misc/cxl/main.c | 2 | ||||
| -rw-r--r-- | drivers/misc/cxl/native.c | 39 | ||||
| -rw-r--r-- | drivers/misc/cxl/pci.c | 123 | ||||
| -rw-r--r-- | drivers/misc/cxl/sysfs.c | 236 | ||||
| -rw-r--r-- | drivers/misc/cxl/trace.c | 13 | ||||
| -rw-r--r-- | drivers/misc/cxl/trace.h | 459 | 
11 files changed, 898 insertions, 26 deletions
| diff --git a/drivers/misc/cxl/Makefile b/drivers/misc/cxl/Makefile index 165e98fef2c2..edb494d3ff27 100644 --- a/drivers/misc/cxl/Makefile +++ b/drivers/misc/cxl/Makefile @@ -1,3 +1,6 @@ -cxl-y				+= main.o file.o irq.o fault.o native.o context.o sysfs.o debugfs.o pci.o +cxl-y				+= main.o file.o irq.o fault.o native.o context.o sysfs.o debugfs.o pci.o trace.o  obj-$(CONFIG_CXL)		+= cxl.o  obj-$(CONFIG_CXL_BASE)		+= base.o + +# For tracepoints to include our trace.h from tracepoint infrastructure: +CFLAGS_trace.o := -I$(src) diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index 28078f8894a5..a1cee4767ec6 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h @@ -287,6 +287,13 @@ static const cxl_p2n_reg_t CXL_PSL_WED_An     = {0x0A0};  #define CXL_PE_SOFTWARE_STATE_S (1ul << (31 - 30)) /* Suspend */  #define CXL_PE_SOFTWARE_STATE_T (1ul << (31 - 31)) /* Terminate */ +/****** CXL_PSL_RXCTL_An (Implementation Specific) ************************** + * Controls AFU Hang Pulse, which sets the timeout for the AFU to respond to + * the PSL for any response (except MMIO). Timeouts will occur between 1x to 2x + * of the hang pulse frequency. + */ +#define CXL_PSL_RXCTL_AFUHP_4S      0x7000000000000000ULL +  /* SPA->sw_command_status */  #define CXL_SPA_SW_CMD_MASK         0xffff000000000000ULL  #define CXL_SPA_SW_CMD_TERMINATE    0x0001000000000000ULL @@ -375,6 +382,10 @@ struct cxl_afu {  	int slice;  	int modes_supported;  	int current_mode; +	int crs_num; +	u64 crs_len; +	u64 crs_offset; +	struct list_head crs;  	enum prefault_modes prefault_mode;  	bool psa;  	bool pp_psa; @@ -481,6 +492,8 @@ void cxl_release_one_irq(struct cxl *adapter, int hwirq);  int cxl_alloc_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter, unsigned int num);  void cxl_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter);  int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq, unsigned int virq); +int cxl_update_image_control(struct cxl *adapter); +int cxl_reset(struct cxl *adapter);  /* common == phyp + powernv */  struct cxl_process_element_common { @@ -542,6 +555,15 @@ static inline void __iomem *_cxl_p2n_addr(struct cxl_afu *afu, cxl_p2n_reg_t reg  #define cxl_p2n_read(afu, reg) \  	in_be64(_cxl_p2n_addr(afu, reg)) + +#define cxl_afu_cr_read64(afu, cr, off) \ +	in_le64((afu)->afu_desc_mmio + (afu)->crs_offset + ((cr) * (afu)->crs_len) + (off)) +#define cxl_afu_cr_read32(afu, cr, off) \ +	in_le32((afu)->afu_desc_mmio + (afu)->crs_offset + ((cr) * (afu)->crs_len) + (off)) +u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off); +u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off); + +  struct cxl_calls {  	void (*cxl_slbia)(struct mm_struct *mm);  	struct module *owner; diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c index f8684bca2d79..5286b8b704f5 100644 --- a/drivers/misc/cxl/fault.c +++ b/drivers/misc/cxl/fault.c @@ -20,6 +20,7 @@  #include <asm/mmu.h>  #include "cxl.h" +#include "trace.h"  static bool sste_matches(struct cxl_sste *sste, struct copro_slb *slb)  { @@ -75,6 +76,7 @@ static void cxl_load_segment(struct cxl_context *ctx, struct copro_slb *slb)  	pr_devel("CXL Populating SST[%li]: %#llx %#llx\n",  			sste - ctx->sstp, slb->vsid, slb->esid); +	trace_cxl_ste_write(ctx, sste - ctx->sstp, slb->esid, slb->vsid);  	sste->vsid_data = cpu_to_be64(slb->vsid);  	sste->esid_data = cpu_to_be64(slb->esid); @@ -116,6 +118,7 @@ static int cxl_handle_segment_miss(struct cxl_context *ctx,  	int rc;  	pr_devel("CXL interrupt: Segment fault pe: %i ea: %#llx\n", ctx->pe, ea); +	trace_cxl_ste_miss(ctx, ea);  	if ((rc = cxl_fault_segment(ctx, mm, ea)))  		cxl_ack_ae(ctx); @@ -135,6 +138,8 @@ static void cxl_handle_page_fault(struct cxl_context *ctx,  	int result;  	unsigned long access, flags, inv_flags = 0; +	trace_cxl_pte_miss(ctx, dsisr, dar); +  	if ((result = copro_handle_mm_fault(mm, dar, dsisr, &flt))) {  		pr_devel("copro_handle_mm_fault failed: %#x\n", result);  		return cxl_ack_ae(ctx); @@ -180,6 +185,12 @@ void cxl_handle_fault(struct work_struct *fault_work)  		return;  	} +	/* Early return if the context is being / has been detached */ +	if (ctx->status == CLOSED) { +		cxl_ack_ae(ctx); +		return; +	} +  	pr_devel("CXL BOTTOM HALF handling fault for afu pe: %i. "  		"DSISR: %#llx DAR: %#llx\n", ctx->pe, dsisr, dar); diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c index b15d8113877c..2364bcadb9a9 100644 --- a/drivers/misc/cxl/file.c +++ b/drivers/misc/cxl/file.c @@ -23,6 +23,7 @@  #include <asm/copro.h>  #include "cxl.h" +#include "trace.h"  #define CXL_NUM_MINORS 256 /* Total to reserve */  #define CXL_DEV_MINORS 13   /* 1 control + 4 AFUs * 3 (dedicated/master/shared) */ @@ -186,9 +187,13 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,  	 */  	ctx->pid = get_pid(get_task_pid(current, PIDTYPE_PID)); +	trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); +  	if ((rc = cxl_attach_process(ctx, false, work.work_element_descriptor, -				     amr))) +				     amr))) { +		afu_release_irqs(ctx);  		goto out; +	}  	ctx->status = STARTED;  	rc = 0; diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c index c294925f73ee..c8929c526691 100644 --- a/drivers/misc/cxl/irq.c +++ b/drivers/misc/cxl/irq.c @@ -17,6 +17,7 @@  #include <misc/cxl.h>  #include "cxl.h" +#include "trace.h"  /* XXX: This is implementation specific */  static irqreturn_t handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, u64 errstat) @@ -100,6 +101,8 @@ static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)  	dsisr = irq_info->dsisr;  	dar = irq_info->dar; +	trace_cxl_psl_irq(ctx, irq, dsisr, dar); +  	pr_devel("CXL interrupt %i for afu pe: %i DSISR: %#llx DAR: %#llx\n", irq, ctx->pe, dsisr, dar);  	if (dsisr & CXL_PSL_DSISR_An_DS) { @@ -167,6 +170,7 @@ static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)  		}  		cxl_ack_irq(ctx, CXL_PSL_TFC_An_A, 0); +		return IRQ_HANDLED;  	}  	if (dsisr & CXL_PSL_DSISR_An_OC)  		pr_devel("CXL interrupt: OS Context Warning\n"); @@ -237,6 +241,7 @@ static irqreturn_t cxl_irq_afu(int irq, void *data)  		return IRQ_HANDLED;  	} +	trace_cxl_afu_irq(ctx, afu_irq, irq, hwirq);  	pr_devel("Received AFU interrupt %i for pe: %i (virq %i hwirq %lx)\n",  	       afu_irq, ctx->pe, irq, hwirq); @@ -436,7 +441,7 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)  	 */  	INIT_LIST_HEAD(&ctx->irq_names);  	for (r = 1; r < CXL_IRQ_RANGES; r++) { -		for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { +		for (i = 0; i < ctx->irqs.range[r]; i++) {  			irq_name = kmalloc(sizeof(struct cxl_irq_name),  					   GFP_KERNEL);  			if (!irq_name) diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index 4cde9b661642..8ccddceead66 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c @@ -23,6 +23,7 @@  #include <misc/cxl.h>  #include "cxl.h" +#include "trace.h"  static DEFINE_SPINLOCK(adapter_idr_lock);  static DEFINE_IDR(cxl_adapter_idr); @@ -48,6 +49,7 @@ static inline void _cxl_slbia(struct cxl_context *ctx, struct mm_struct *mm)  		 ctx->afu->adapter->adapter_num, ctx->afu->slice, ctx->pe);  	spin_lock_irqsave(&ctx->sste_lock, flags); +	trace_cxl_slbia(ctx);  	memset(ctx->sstp, 0, ctx->sst_size);  	spin_unlock_irqrestore(&ctx->sste_lock, flags);  	mb(); diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index f2b37b41a0da..29185fc61276 100644 --- a/drivers/misc/cxl/native.c +++ b/drivers/misc/cxl/native.c @@ -18,24 +18,28 @@  #include <misc/cxl.h>  #include "cxl.h" +#include "trace.h"  static int afu_control(struct cxl_afu *afu, u64 command,  		       u64 result, u64 mask, bool enabled)  {  	u64 AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An);  	unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); +	int rc = 0;  	spin_lock(&afu->afu_cntl_lock);  	pr_devel("AFU command starting: %llx\n", command); +	trace_cxl_afu_ctrl(afu, command); +  	cxl_p2n_write(afu, CXL_AFU_Cntl_An, AFU_Cntl | command);  	AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An);  	while ((AFU_Cntl & mask) != result) {  		if (time_after_eq(jiffies, timeout)) {  			dev_warn(&afu->dev, "WARNING: AFU control timed out!\n"); -			spin_unlock(&afu->afu_cntl_lock); -			return -EBUSY; +			rc = -EBUSY; +			goto out;  		}  		pr_devel_ratelimited("AFU control... (0x%.16llx)\n",  				     AFU_Cntl | command); @@ -44,9 +48,11 @@ static int afu_control(struct cxl_afu *afu, u64 command,  	};  	pr_devel("AFU command complete: %llx\n", command);  	afu->enabled = enabled; +out: +	trace_cxl_afu_ctrl_done(afu, command, rc);  	spin_unlock(&afu->afu_cntl_lock); -	return 0; +	return rc;  }  static int afu_enable(struct cxl_afu *afu) @@ -91,6 +97,9 @@ int cxl_psl_purge(struct cxl_afu *afu)  	u64 dsisr, dar;  	u64 start, end;  	unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); +	int rc = 0; + +	trace_cxl_psl_ctrl(afu, CXL_PSL_SCNTL_An_Pc);  	pr_devel("PSL purge request\n"); @@ -107,7 +116,8 @@ int cxl_psl_purge(struct cxl_afu *afu)  			== CXL_PSL_SCNTL_An_Ps_Pending) {  		if (time_after_eq(jiffies, timeout)) {  			dev_warn(&afu->dev, "WARNING: PSL Purge timed out!\n"); -			return -EBUSY; +			rc = -EBUSY; +			goto out;  		}  		dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An);  		pr_devel_ratelimited("PSL purging... PSL_CNTL: 0x%.16llx  PSL_DSISR: 0x%.16llx\n", PSL_CNTL, dsisr); @@ -128,7 +138,9 @@ int cxl_psl_purge(struct cxl_afu *afu)  	cxl_p1n_write(afu, CXL_PSL_SCNTL_An,  		       PSL_CNTL & ~CXL_PSL_SCNTL_An_Pc); -	return 0; +out: +	trace_cxl_psl_ctrl_done(afu, CXL_PSL_SCNTL_An_Pc, rc); +	return rc;  }  static int spa_max_procs(int spa_size) @@ -185,6 +197,7 @@ static int alloc_spa(struct cxl_afu *afu)  static void release_spa(struct cxl_afu *afu)  { +	cxl_p1n_write(afu, CXL_PSL_SPAP_An, 0);  	free_pages((unsigned long) afu->spa, afu->spa_order);  } @@ -278,6 +291,9 @@ static int do_process_element_cmd(struct cxl_context *ctx,  {  	u64 state;  	unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT); +	int rc = 0; + +	trace_cxl_llcmd(ctx, cmd);  	WARN_ON(!ctx->afu->enabled); @@ -289,12 +305,14 @@ static int do_process_element_cmd(struct cxl_context *ctx,  	while (1) {  		if (time_after_eq(jiffies, timeout)) {  			dev_warn(&ctx->afu->dev, "WARNING: Process Element Command timed out!\n"); -			return -EBUSY; +			rc = -EBUSY; +			goto out;  		}  		state = be64_to_cpup(ctx->afu->sw_command_status);  		if (state == ~0ULL) {  			pr_err("cxl: Error adding process element to AFU\n"); -			return -1; +			rc = -1; +			goto out;  		}  		if ((state & (CXL_SPA_SW_CMD_MASK | CXL_SPA_SW_STATE_MASK  | CXL_SPA_SW_LINK_MASK)) ==  		    (cmd | (cmd >> 16) | ctx->pe)) @@ -309,7 +327,9 @@ static int do_process_element_cmd(struct cxl_context *ctx,  		schedule();  	} -	return 0; +out: +	trace_cxl_llcmd_done(ctx, cmd, rc); +	return rc;  }  static int add_process_element(struct cxl_context *ctx) @@ -629,6 +649,8 @@ static inline int detach_process_native_afu_directed(struct cxl_context *ctx)  int cxl_detach_process(struct cxl_context *ctx)  { +	trace_cxl_detach(ctx); +  	if (ctx->afu->current_mode == CXL_MODE_DEDICATED)  		return detach_process_native_dedicated(ctx); @@ -667,6 +689,7 @@ static void recover_psl_err(struct cxl_afu *afu, u64 errstat)  int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask)  { +	trace_cxl_psl_irq_ack(ctx, tfc);  	if (tfc)  		cxl_p2n_write(ctx->afu, CXL_PSL_TFC_An, tfc);  	if (psl_reset_mask) diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 0f2cc9f8b4db..1ef01647265f 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -21,6 +21,7 @@  #include <asm/msi_bitmap.h>  #include <asm/pci-bridge.h> /* for struct pci_controller */  #include <asm/pnv-pci.h> +#include <asm/io.h>  #include "cxl.h" @@ -113,6 +114,24 @@  #define   AFUD_EB_LEN(val)		EXTRACT_PPC_BITS(val, 8, 63)  #define AFUD_READ_EB_OFF(afu)		AFUD_READ(afu, 0x48) +u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off) +{ +	u64 aligned_off = off & ~0x3L; +	u32 val; + +	val = cxl_afu_cr_read32(afu, cr, aligned_off); +	return (val >> ((off & 0x2) * 8)) & 0xffff; +} + +u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off) +{ +	u64 aligned_off = off & ~0x3L; +	u32 val; + +	val = cxl_afu_cr_read32(afu, cr, aligned_off); +	return (val >> ((off & 0x3) * 8)) & 0xff; +} +  static DEFINE_PCI_DEVICE_TABLE(cxl_pci_tbl) = {  	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0477), },  	{ PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x044b), }, @@ -316,7 +335,7 @@ static int init_implementation_adapter_regs(struct cxl *adapter, struct pci_dev  	u64 psl_dsnctl;  	u64 chipid; -	if (!(np = pnv_pci_to_phb_node(dev))) +	if (!(np = pnv_pci_get_phb_node(dev)))  		return -ENODEV;  	while (np && !(prop = of_get_property(np, "ibm,chip-id", NULL))) @@ -348,7 +367,7 @@ static int init_implementation_afu_regs(struct cxl_afu *afu)  	cxl_p1n_write(afu, CXL_PSL_COALLOC_A, 0xFF000000FEFEFEFEULL);  	/* for debugging with trace arrays */  	cxl_p1n_write(afu, CXL_PSL_SLICE_TRACE, 0x0000FFFF00000000ULL); -	cxl_p1n_write(afu, CXL_PSL_RXCTL_A, 0xF000000000000000ULL); +	cxl_p1n_write(afu, CXL_PSL_RXCTL_A, CXL_PSL_RXCTL_AFUHP_4S);  	return 0;  } @@ -361,6 +380,41 @@ int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq,  	return pnv_cxl_ioda_msi_setup(dev, hwirq, virq);  } +int cxl_update_image_control(struct cxl *adapter) +{ +	struct pci_dev *dev = to_pci_dev(adapter->dev.parent); +	int rc; +	int vsec; +	u8 image_state; + +	if (!(vsec = find_cxl_vsec(dev))) { +		dev_err(&dev->dev, "ABORTING: CXL VSEC not found!\n"); +		return -ENODEV; +	} + +	if ((rc = CXL_READ_VSEC_IMAGE_STATE(dev, vsec, &image_state))) { +		dev_err(&dev->dev, "failed to read image state: %i\n", rc); +		return rc; +	} + +	if (adapter->perst_loads_image) +		image_state |= CXL_VSEC_PERST_LOADS_IMAGE; +	else +		image_state &= ~CXL_VSEC_PERST_LOADS_IMAGE; + +	if (adapter->perst_select_user) +		image_state |= CXL_VSEC_PERST_SELECT_USER; +	else +		image_state &= ~CXL_VSEC_PERST_SELECT_USER; + +	if ((rc = CXL_WRITE_VSEC_IMAGE_STATE(dev, vsec, image_state))) { +		dev_err(&dev->dev, "failed to update image control: %i\n", rc); +		return rc; +	} + +	return 0; +} +  int cxl_alloc_one_irq(struct cxl *adapter)  {  	struct pci_dev *dev = to_pci_dev(adapter->dev.parent); @@ -520,6 +574,7 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu)  	val = AFUD_READ_INFO(afu);  	afu->pp_irqs = AFUD_NUM_INTS_PER_PROC(val);  	afu->max_procs_virtualised = AFUD_NUM_PROCS(val); +	afu->crs_num = AFUD_NUM_CRS(val);  	if (AFUD_AFU_DIRECTED(val))  		afu->modes_supported |= CXL_MODE_DIRECTED; @@ -534,11 +589,17 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu)  	if ((afu->pp_psa = AFUD_PPPSA_PP(val)))  		afu->pp_offset = AFUD_READ_PPPSA_OFF(afu); +	val = AFUD_READ_CR(afu); +	afu->crs_len = AFUD_CR_LEN(val) * 256; +	afu->crs_offset = AFUD_READ_CR_OFF(afu); +  	return 0;  }  static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu)  { +	int i; +  	if (afu->psa && afu->adapter->ps_size <  			(afu->pp_offset + afu->pp_size*afu->max_procs_virtualised)) {  		dev_err(&afu->dev, "per-process PSA can't fit inside the PSA!\n"); @@ -548,6 +609,13 @@ 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!"); +	for (i = 0; i < afu->crs_num; i++) { +		if ((cxl_afu_cr_read32(afu, i, 0) == 0)) { +			dev_err(&afu->dev, "ABORTING: AFU configuration record %i is invalid\n", i); +			return -EINVAL; +		} +	} +  	return 0;  } @@ -706,6 +774,42 @@ static void cxl_remove_afu(struct cxl_afu *afu)  	device_unregister(&afu->dev);  } +int cxl_reset(struct cxl *adapter) +{ +	struct pci_dev *dev = to_pci_dev(adapter->dev.parent); +	int rc; +	int i; +	u32 val; + +	dev_info(&dev->dev, "CXL reset\n"); + +	for (i = 0; i < adapter->slices; i++) +		cxl_remove_afu(adapter->afu[i]); + +	/* pcie_warm_reset requests a fundamental pci reset which includes a +	 * PERST assert/deassert.  PERST triggers a loading of the image +	 * if "user" or "factory" is selected in sysfs */ +	if ((rc = pci_set_pcie_reset_state(dev, pcie_warm_reset))) { +		dev_err(&dev->dev, "cxl: pcie_warm_reset failed\n"); +		return rc; +	} + +	/* the PERST done above fences the PHB.  So, reset depends on EEH +	 * to unbind the driver, tell Sapphire to reinit the PHB, and rebind +	 * the driver.  Do an mmio read explictly to ensure EEH notices the +	 * fenced PHB.  Retry for a few seconds before giving up. */ +	i = 0; +	while (((val = mmio_read32be(adapter->p1_mmio)) != 0xffffffff) && +		(i < 5)) { +		msleep(500); +		i++; +	} + +	if (val != 0xffffffff) +		dev_err(&dev->dev, "cxl: PERST failed to trigger EEH\n"); + +	return rc; +}  static int cxl_map_adapter_regs(struct cxl *adapter, struct pci_dev *dev)  { @@ -770,8 +874,8 @@ static int cxl_read_vsec(struct cxl *adapter, struct pci_dev *dev)  	CXL_READ_VSEC_BASE_IMAGE(dev, vsec, &adapter->base_image);  	CXL_READ_VSEC_IMAGE_STATE(dev, vsec, &image_state);  	adapter->user_image_loaded = !!(image_state & CXL_VSEC_USER_IMAGE_LOADED); -	adapter->perst_loads_image = !!(image_state & CXL_VSEC_PERST_LOADS_IMAGE); -	adapter->perst_select_user = !!(image_state & CXL_VSEC_PERST_SELECT_USER); +	adapter->perst_loads_image = true; +	adapter->perst_select_user = !!(image_state & CXL_VSEC_USER_IMAGE_LOADED);  	CXL_READ_VSEC_NAFUS(dev, vsec, &adapter->slices);  	CXL_READ_VSEC_AFU_DESC_OFF(dev, vsec, &afu_desc_off); @@ -879,6 +983,9 @@ static struct cxl *cxl_init_adapter(struct pci_dev *dev)  	if ((rc = cxl_vsec_looks_ok(adapter, dev)))  		goto err2; +	if ((rc = cxl_update_image_control(adapter))) +		goto err2; +  	if ((rc = cxl_map_adapter_regs(adapter, dev)))  		goto err2; @@ -888,9 +995,15 @@ static struct cxl *cxl_init_adapter(struct pci_dev *dev)  	if ((rc = init_implementation_adapter_regs(adapter, dev)))  		goto err3; -	if ((rc = pnv_phb_to_cxl(dev))) +	if ((rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_CAPI)))  		goto err3; +	/* If recovery happened, the last step is to turn on snooping. +	 * In the non-recovery case this has no effect */ +	if ((rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_SNOOP_ON))) { +		goto err3; +	} +  	if ((rc = cxl_register_psl_err_irq(adapter)))  		goto err3; diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 461bdbd5d483..d0c38c7bc0c4 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c @@ -10,6 +10,7 @@  #include <linux/kernel.h>  #include <linux/device.h>  #include <linux/sysfs.h> +#include <linux/pci_regs.h>  #include "cxl.h" @@ -56,11 +57,68 @@ static ssize_t image_loaded_show(struct device *device,  	return scnprintf(buf, PAGE_SIZE, "factory\n");  } +static ssize_t reset_adapter_store(struct device *device, +				   struct device_attribute *attr, +				   const char *buf, size_t count) +{ +	struct cxl *adapter = to_cxl_adapter(device); +	int rc; +	int val; + +	rc = sscanf(buf, "%i", &val); +	if ((rc != 1) || (val != 1)) +		return -EINVAL; + +	if ((rc = cxl_reset(adapter))) +		return rc; +	return count; +} + +static ssize_t load_image_on_perst_show(struct device *device, +				 struct device_attribute *attr, +				 char *buf) +{ +	struct cxl *adapter = to_cxl_adapter(device); + +	if (!adapter->perst_loads_image) +		return scnprintf(buf, PAGE_SIZE, "none\n"); + +	if (adapter->perst_select_user) +		return scnprintf(buf, PAGE_SIZE, "user\n"); +	return scnprintf(buf, PAGE_SIZE, "factory\n"); +} + +static ssize_t load_image_on_perst_store(struct device *device, +				 struct device_attribute *attr, +				 const char *buf, size_t count) +{ +	struct cxl *adapter = to_cxl_adapter(device); +	int rc; + +	if (!strncmp(buf, "none", 4)) +		adapter->perst_loads_image = false; +	else if (!strncmp(buf, "user", 4)) { +		adapter->perst_select_user = true; +		adapter->perst_loads_image = true; +	} else if (!strncmp(buf, "factory", 7)) { +		adapter->perst_select_user = false; +		adapter->perst_loads_image = true; +	} else +		return -EINVAL; + +	if ((rc = cxl_update_image_control(adapter))) +		return rc; + +	return count; +} +  static struct device_attribute adapter_attrs[] = {  	__ATTR_RO(caia_version),  	__ATTR_RO(psl_revision),  	__ATTR_RO(base_image),  	__ATTR_RO(image_loaded), +	__ATTR_RW(load_image_on_perst), +	__ATTR(reset, S_IWUSR, NULL, reset_adapter_store),  }; @@ -310,8 +368,6 @@ static struct device_attribute afu_attrs[] = {  	__ATTR(reset, S_IWUSR, NULL, reset_store_afu),  }; - -  int cxl_sysfs_adapter_add(struct cxl *adapter)  {  	int i, rc; @@ -334,31 +390,191 @@ void cxl_sysfs_adapter_remove(struct cxl *adapter)  		device_remove_file(&adapter->dev, &adapter_attrs[i]);  } +struct afu_config_record { +	struct kobject kobj; +	struct bin_attribute config_attr; +	struct list_head list; +	int cr; +	u16 device; +	u16 vendor; +	u32 class; +}; + +#define to_cr(obj) container_of(obj, struct afu_config_record, kobj) + +static ssize_t vendor_show(struct kobject *kobj, +			   struct kobj_attribute *attr, char *buf) +{ +	struct afu_config_record *cr = to_cr(kobj); + +	return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->vendor); +} + +static ssize_t device_show(struct kobject *kobj, +			   struct kobj_attribute *attr, char *buf) +{ +	struct afu_config_record *cr = to_cr(kobj); + +	return scnprintf(buf, PAGE_SIZE, "0x%.4x\n", cr->device); +} + +static ssize_t class_show(struct kobject *kobj, +			  struct kobj_attribute *attr, char *buf) +{ +	struct afu_config_record *cr = to_cr(kobj); + +	return scnprintf(buf, PAGE_SIZE, "0x%.6x\n", cr->class); +} + +static ssize_t afu_read_config(struct file *filp, struct kobject *kobj, +			       struct bin_attribute *bin_attr, char *buf, +			       loff_t off, size_t count) +{ +	struct afu_config_record *cr = to_cr(kobj); +	struct cxl_afu *afu = to_cxl_afu(container_of(kobj->parent, struct device, kobj)); + +	u64 i, j, val, size = afu->crs_len; + +	if (off > size) +		return 0; +	if (off + count > size) +		count = size - off; + +	for (i = 0; i < count;) { +		val = cxl_afu_cr_read64(afu, cr->cr, off & ~0x7); +		for (j = off & 0x7; j < 8 && i < count; i++, j++, off++) +			buf[i] = (val >> (j * 8)) & 0xff; +	} + +	return count; +} + +static struct kobj_attribute vendor_attribute = +	__ATTR_RO(vendor); +static struct kobj_attribute device_attribute = +	__ATTR_RO(device); +static struct kobj_attribute class_attribute = +	__ATTR_RO(class); + +static struct attribute *afu_cr_attrs[] = { +	&vendor_attribute.attr, +	&device_attribute.attr, +	&class_attribute.attr, +	NULL, +}; + +static void release_afu_config_record(struct kobject *kobj) +{ +	struct afu_config_record *cr = to_cr(kobj); + +	kfree(cr); +} + +static struct kobj_type afu_config_record_type = { +	.sysfs_ops = &kobj_sysfs_ops, +	.release = release_afu_config_record, +	.default_attrs = afu_cr_attrs, +}; + +static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int cr_idx) +{ +	struct afu_config_record *cr; +	int rc; + +	cr = kzalloc(sizeof(struct afu_config_record), GFP_KERNEL); +	if (!cr) +		return ERR_PTR(-ENOMEM); + +	cr->cr = cr_idx; +	cr->device = cxl_afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID); +	cr->vendor = cxl_afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID); +	cr->class = cxl_afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION) >> 8; + +	/* +	 * Export raw AFU PCIe like config record. For now this is read only by +	 * root - we can expand that later to be readable by non-root and maybe +	 * even writable provided we have a good use-case. Once we suport +	 * exposing AFUs through a virtual PHB they will get that for free from +	 * Linux' PCI infrastructure, but until then it's not clear that we +	 * need it for anything since the main use case is just identifying +	 * AFUs, which can be done via the vendor, device and class attributes. +	 */ +	sysfs_bin_attr_init(&cr->config_attr); +	cr->config_attr.attr.name = "config"; +	cr->config_attr.attr.mode = S_IRUSR; +	cr->config_attr.size = afu->crs_len; +	cr->config_attr.read = afu_read_config; + +	rc = kobject_init_and_add(&cr->kobj, &afu_config_record_type, +				  &afu->dev.kobj, "cr%i", cr->cr); +	if (rc) +		goto err; + +	rc = sysfs_create_bin_file(&cr->kobj, &cr->config_attr); +	if (rc) +		goto err1; + +	rc = kobject_uevent(&cr->kobj, KOBJ_ADD); +	if (rc) +		goto err2; + +	return cr; +err2: +	sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); +err1: +	kobject_put(&cr->kobj); +	return ERR_PTR(rc); +err: +	kfree(cr); +	return ERR_PTR(rc); +} + +void cxl_sysfs_afu_remove(struct cxl_afu *afu) +{ +	struct afu_config_record *cr, *tmp; +	int i; + +	for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) +		device_remove_file(&afu->dev, &afu_attrs[i]); + +	list_for_each_entry_safe(cr, tmp, &afu->crs, list) { +		sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); +		kobject_put(&cr->kobj); +	} +} +  int cxl_sysfs_afu_add(struct cxl_afu *afu)  { +	struct afu_config_record *cr;  	int i, rc; +	INIT_LIST_HEAD(&afu->crs); +  	for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) {  		if ((rc = device_create_file(&afu->dev, &afu_attrs[i])))  			goto err;  	} +	for (i = 0; i < afu->crs_num; i++) { +		cr = cxl_sysfs_afu_new_cr(afu, i); +		if (IS_ERR(cr)) { +			rc = PTR_ERR(cr); +			goto err1; +		} +		list_add(&cr->list, &afu->crs); +	} +  	return 0; +err1: +	cxl_sysfs_afu_remove(afu); +	return rc;  err:  	for (i--; i >= 0; i--)  		device_remove_file(&afu->dev, &afu_attrs[i]);  	return rc;  } -void cxl_sysfs_afu_remove(struct cxl_afu *afu) -{ -	int i; - -	for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) -		device_remove_file(&afu->dev, &afu_attrs[i]); -} -  int cxl_sysfs_afu_m_add(struct cxl_afu *afu)  {  	int i, rc; diff --git a/drivers/misc/cxl/trace.c b/drivers/misc/cxl/trace.c new file mode 100644 index 000000000000..c2b06d319e6e --- /dev/null +++ b/drivers/misc/cxl/trace.c @@ -0,0 +1,13 @@ +/* + * Copyright 2015 IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "trace.h" +#endif diff --git a/drivers/misc/cxl/trace.h b/drivers/misc/cxl/trace.h new file mode 100644 index 000000000000..ae434d87887e --- /dev/null +++ b/drivers/misc/cxl/trace.h @@ -0,0 +1,459 @@ +/* + * Copyright 2015 IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM cxl + +#if !defined(_CXL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _CXL_TRACE_H + +#include <linux/tracepoint.h> + +#include "cxl.h" + +#define DSISR_FLAGS \ +	{ CXL_PSL_DSISR_An_DS,	"DS" }, \ +	{ CXL_PSL_DSISR_An_DM,	"DM" }, \ +	{ CXL_PSL_DSISR_An_ST,	"ST" }, \ +	{ CXL_PSL_DSISR_An_UR,	"UR" }, \ +	{ CXL_PSL_DSISR_An_PE,	"PE" }, \ +	{ CXL_PSL_DSISR_An_AE,	"AE" }, \ +	{ CXL_PSL_DSISR_An_OC,	"OC" }, \ +	{ CXL_PSL_DSISR_An_M,	"M" }, \ +	{ CXL_PSL_DSISR_An_P,	"P" }, \ +	{ CXL_PSL_DSISR_An_A,	"A" }, \ +	{ CXL_PSL_DSISR_An_S,	"S" }, \ +	{ CXL_PSL_DSISR_An_K,	"K" } + +#define TFC_FLAGS \ +	{ CXL_PSL_TFC_An_A,	"A" }, \ +	{ CXL_PSL_TFC_An_C,	"C" }, \ +	{ CXL_PSL_TFC_An_AE,	"AE" }, \ +	{ CXL_PSL_TFC_An_R,	"R" } + +#define LLCMD_NAMES \ +	{ CXL_SPA_SW_CMD_TERMINATE,	"TERMINATE" }, \ +	{ CXL_SPA_SW_CMD_REMOVE,	"REMOVE" }, \ +	{ CXL_SPA_SW_CMD_SUSPEND,	"SUSPEND" }, \ +	{ CXL_SPA_SW_CMD_RESUME,	"RESUME" }, \ +	{ CXL_SPA_SW_CMD_ADD,		"ADD" }, \ +	{ CXL_SPA_SW_CMD_UPDATE,	"UPDATE" } + +#define AFU_COMMANDS \ +	{ 0,			"DISABLE" }, \ +	{ CXL_AFU_Cntl_An_E,	"ENABLE" }, \ +	{ CXL_AFU_Cntl_An_RA,	"RESET" } + +#define PSL_COMMANDS \ +	{ CXL_PSL_SCNTL_An_Pc,	"PURGE" }, \ +	{ CXL_PSL_SCNTL_An_Sc,	"SUSPEND" } + + +DECLARE_EVENT_CLASS(cxl_pe_class, +	TP_PROTO(struct cxl_context *ctx), + +	TP_ARGS(ctx), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +	), + +	TP_printk("afu%i.%i pe=%i", +		__entry->card, +		__entry->afu, +		__entry->pe +	) +); + + +TRACE_EVENT(cxl_attach, +	TP_PROTO(struct cxl_context *ctx, u64 wed, s16 num_interrupts, u64 amr), + +	TP_ARGS(ctx, wed, num_interrupts, amr), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(pid_t, pid) +		__field(u64, wed) +		__field(u64, amr) +		__field(s16, num_interrupts) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->pid = pid_nr(ctx->pid); +		__entry->wed = wed; +		__entry->amr = amr; +		__entry->num_interrupts = num_interrupts; +	), + +	TP_printk("afu%i.%i pid=%i pe=%i wed=0x%.16llx irqs=%i amr=0x%llx", +		__entry->card, +		__entry->afu, +		__entry->pid, +		__entry->pe, +		__entry->wed, +		__entry->num_interrupts, +		__entry->amr +	) +); + +DEFINE_EVENT(cxl_pe_class, cxl_detach, +	TP_PROTO(struct cxl_context *ctx), +	TP_ARGS(ctx) +); + +TRACE_EVENT(cxl_afu_irq, +	TP_PROTO(struct cxl_context *ctx, int afu_irq, int virq, irq_hw_number_t hwirq), + +	TP_ARGS(ctx, afu_irq, virq, hwirq), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(u16, afu_irq) +		__field(int, virq) +		__field(irq_hw_number_t, hwirq) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->afu_irq = afu_irq; +		__entry->virq = virq; +		__entry->hwirq = hwirq; +	), + +	TP_printk("afu%i.%i pe=%i afu_irq=%i virq=%i hwirq=0x%lx", +		__entry->card, +		__entry->afu, +		__entry->pe, +		__entry->afu_irq, +		__entry->virq, +		__entry->hwirq +	) +); + +TRACE_EVENT(cxl_psl_irq, +	TP_PROTO(struct cxl_context *ctx, int irq, u64 dsisr, u64 dar), + +	TP_ARGS(ctx, irq, dsisr, dar), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(int, irq) +		__field(u64, dsisr) +		__field(u64, dar) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->irq = irq; +		__entry->dsisr = dsisr; +		__entry->dar = dar; +	), + +	TP_printk("afu%i.%i pe=%i irq=%i dsisr=%s dar=0x%.16llx", +		__entry->card, +		__entry->afu, +		__entry->pe, +		__entry->irq, +		__print_flags(__entry->dsisr, "|", DSISR_FLAGS), +		__entry->dar +	) +); + +TRACE_EVENT(cxl_psl_irq_ack, +	TP_PROTO(struct cxl_context *ctx, u64 tfc), + +	TP_ARGS(ctx, tfc), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(u64, tfc) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->tfc = tfc; +	), + +	TP_printk("afu%i.%i pe=%i tfc=%s", +		__entry->card, +		__entry->afu, +		__entry->pe, +		__print_flags(__entry->tfc, "|", TFC_FLAGS) +	) +); + +TRACE_EVENT(cxl_ste_miss, +	TP_PROTO(struct cxl_context *ctx, u64 dar), + +	TP_ARGS(ctx, dar), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(u64, dar) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->dar = dar; +	), + +	TP_printk("afu%i.%i pe=%i dar=0x%.16llx", +		__entry->card, +		__entry->afu, +		__entry->pe, +		__entry->dar +	) +); + +TRACE_EVENT(cxl_ste_write, +	TP_PROTO(struct cxl_context *ctx, unsigned int idx, u64 e, u64 v), + +	TP_ARGS(ctx, idx, e, v), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(unsigned int, idx) +		__field(u64, e) +		__field(u64, v) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->idx = idx; +		__entry->e = e; +		__entry->v = v; +	), + +	TP_printk("afu%i.%i pe=%i SSTE[%i] E=0x%.16llx V=0x%.16llx", +		__entry->card, +		__entry->afu, +		__entry->pe, +		__entry->idx, +		__entry->e, +		__entry->v +	) +); + +TRACE_EVENT(cxl_pte_miss, +	TP_PROTO(struct cxl_context *ctx, u64 dsisr, u64 dar), + +	TP_ARGS(ctx, dsisr, dar), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(u64, dsisr) +		__field(u64, dar) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->dsisr = dsisr; +		__entry->dar = dar; +	), + +	TP_printk("afu%i.%i pe=%i dsisr=%s dar=0x%.16llx", +		__entry->card, +		__entry->afu, +		__entry->pe, +		__print_flags(__entry->dsisr, "|", DSISR_FLAGS), +		__entry->dar +	) +); + +TRACE_EVENT(cxl_llcmd, +	TP_PROTO(struct cxl_context *ctx, u64 cmd), + +	TP_ARGS(ctx, cmd), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(u64, cmd) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->cmd = cmd; +	), + +	TP_printk("afu%i.%i pe=%i cmd=%s", +		__entry->card, +		__entry->afu, +		__entry->pe, +		__print_symbolic_u64(__entry->cmd, LLCMD_NAMES) +	) +); + +TRACE_EVENT(cxl_llcmd_done, +	TP_PROTO(struct cxl_context *ctx, u64 cmd, int rc), + +	TP_ARGS(ctx, cmd, rc), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u16, pe) +		__field(u64, cmd) +		__field(int, rc) +	), + +	TP_fast_assign( +		__entry->card = ctx->afu->adapter->adapter_num; +		__entry->afu = ctx->afu->slice; +		__entry->pe = ctx->pe; +		__entry->rc = rc; +		__entry->cmd = cmd; +	), + +	TP_printk("afu%i.%i pe=%i cmd=%s rc=%i", +		__entry->card, +		__entry->afu, +		__entry->pe, +		__print_symbolic_u64(__entry->cmd, LLCMD_NAMES), +		__entry->rc +	) +); + +DECLARE_EVENT_CLASS(cxl_afu_psl_ctrl, +	TP_PROTO(struct cxl_afu *afu, u64 cmd), + +	TP_ARGS(afu, cmd), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u64, cmd) +	), + +	TP_fast_assign( +		__entry->card = afu->adapter->adapter_num; +		__entry->afu = afu->slice; +		__entry->cmd = cmd; +	), + +	TP_printk("afu%i.%i cmd=%s", +		__entry->card, +		__entry->afu, +		__print_symbolic_u64(__entry->cmd, AFU_COMMANDS) +	) +); + +DECLARE_EVENT_CLASS(cxl_afu_psl_ctrl_done, +	TP_PROTO(struct cxl_afu *afu, u64 cmd, int rc), + +	TP_ARGS(afu, cmd, rc), + +	TP_STRUCT__entry( +		__field(u8, card) +		__field(u8, afu) +		__field(u64, cmd) +		__field(int, rc) +	), + +	TP_fast_assign( +		__entry->card = afu->adapter->adapter_num; +		__entry->afu = afu->slice; +		__entry->rc = rc; +		__entry->cmd = cmd; +	), + +	TP_printk("afu%i.%i cmd=%s rc=%i", +		__entry->card, +		__entry->afu, +		__print_symbolic_u64(__entry->cmd, AFU_COMMANDS), +		__entry->rc +	) +); + +DEFINE_EVENT(cxl_afu_psl_ctrl, cxl_afu_ctrl, +	TP_PROTO(struct cxl_afu *afu, u64 cmd), +	TP_ARGS(afu, cmd) +); + +DEFINE_EVENT(cxl_afu_psl_ctrl_done, cxl_afu_ctrl_done, +	TP_PROTO(struct cxl_afu *afu, u64 cmd, int rc), +	TP_ARGS(afu, cmd, rc) +); + +DEFINE_EVENT_PRINT(cxl_afu_psl_ctrl, cxl_psl_ctrl, +	TP_PROTO(struct cxl_afu *afu, u64 cmd), +	TP_ARGS(afu, cmd), + +	TP_printk("psl%i.%i cmd=%s", +		__entry->card, +		__entry->afu, +		__print_symbolic_u64(__entry->cmd, PSL_COMMANDS) +	) +); + +DEFINE_EVENT_PRINT(cxl_afu_psl_ctrl_done, cxl_psl_ctrl_done, +	TP_PROTO(struct cxl_afu *afu, u64 cmd, int rc), +	TP_ARGS(afu, cmd, rc), + +	TP_printk("psl%i.%i cmd=%s rc=%i", +		__entry->card, +		__entry->afu, +		__print_symbolic_u64(__entry->cmd, PSL_COMMANDS), +		__entry->rc +	) +); + +DEFINE_EVENT(cxl_pe_class, cxl_slbia, +	TP_PROTO(struct cxl_context *ctx), +	TP_ARGS(ctx) +); + +#endif /* _CXL_TRACE_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE trace +#include <trace/define_trace.h> |