diff options
author | Uma Krishnan <ukrishn@linux.vnet.ibm.com> | 2018-03-26 11:35:07 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-04-18 19:32:50 -0400 |
commit | 66ae644b922abcbf6d3303a4e69f658b02165b31 (patch) | |
tree | 32a58398f8fcf225d27e531c82bb5729e7e70f39 | |
parent | f81face7256339c584ee9baba3240ddac74a0293 (diff) | |
download | linux-stable-66ae644b922abcbf6d3303a4e69f658b02165b31.tar.gz linux-stable-66ae644b922abcbf6d3303a4e69f658b02165b31.tar.bz2 linux-stable-66ae644b922abcbf6d3303a4e69f658b02165b31.zip |
scsi: cxlflash: Register for translation errors
While enabling a context on the link, a predefined callback can be registered
with the OCXL provider services to be notified on translation errors. These
errors can in turn be passed back to the user on a read operation.
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/cxlflash/ocxl_hw.c | 31 | ||||
-rw-r--r-- | drivers/scsi/cxlflash/ocxl_hw.h | 4 |
2 files changed, 33 insertions, 2 deletions
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c index 89d3d89f22ed..5b5565d6572e 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.c +++ b/drivers/scsi/cxlflash/ocxl_hw.c @@ -335,6 +335,25 @@ static u64 ocxlflash_get_irq_objhndl(void *ctx_cookie, int irq) } /** + * ocxlflash_xsl_fault() - callback when translation error is triggered + * @data: Private data provided at callback registration, the context. + * @addr: Address that triggered the error. + * @dsisr: Value of dsisr register. + */ +static void ocxlflash_xsl_fault(void *data, u64 addr, u64 dsisr) +{ + struct ocxlflash_context *ctx = data; + + spin_lock(&ctx->slock); + ctx->fault_addr = addr; + ctx->fault_dsisr = dsisr; + ctx->pending_fault = true; + spin_unlock(&ctx->slock); + + wake_up_all(&ctx->wq); +} + +/** * start_context() - local routine to start a context * @ctx: Adapter context to be started. * @@ -378,7 +397,8 @@ static int start_context(struct ocxlflash_context *ctx) mm = current->mm; } - rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0, mm, NULL, NULL); + rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0, mm, + ocxlflash_xsl_fault, ctx); if (unlikely(rc)) { dev_err(dev, "%s: ocxl_link_add_pe failed rc=%d\n", __func__, rc); @@ -512,6 +532,7 @@ static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie) ctx->hw_afu = afu; ctx->irq_bitmap = 0; ctx->pending_irq = false; + ctx->pending_fault = false; out: return ctx; err2: @@ -965,7 +986,7 @@ err1: */ static inline bool ctx_event_pending(struct ocxlflash_context *ctx) { - if (ctx->pending_irq) + if (ctx->pending_irq || ctx->pending_fault) return true; return false; @@ -1070,6 +1091,12 @@ static ssize_t afu_read(struct file *file, char __user *buf, size_t count, event.irq.irq = bit + 1; if (bitmap_empty(&ctx->irq_bitmap, ctx->num_irqs)) ctx->pending_irq = false; + } else if (ctx->pending_fault) { + event.header.size += sizeof(struct cxl_event_data_storage); + event.header.type = CXL_EVENT_DATA_STORAGE; + event.fault.addr = ctx->fault_addr; + event.fault.dsisr = ctx->fault_dsisr; + ctx->pending_fault = false; } spin_unlock_irqrestore(&ctx->slock, lock_flags); diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h index 1829e55c974a..9270d35c4620 100644 --- a/drivers/scsi/cxlflash/ocxl_hw.h +++ b/drivers/scsi/cxlflash/ocxl_hw.h @@ -70,4 +70,8 @@ struct ocxlflash_context { int num_irqs; /* Number of interrupts */ bool pending_irq; /* Pending interrupt on the context */ ulong irq_bitmap; /* Bits indicating pending irq num */ + + u64 fault_addr; /* Address that triggered the fault */ + u64 fault_dsisr; /* Value of dsisr register at fault */ + bool pending_fault; /* Pending translation fault */ }; |