summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/cxlflash
diff options
context:
space:
mode:
authorUma Krishnan <ukrishn@linux.vnet.ibm.com>2018-03-26 12:33:48 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2018-04-18 19:32:49 -0400
commita06b1cfc0400a699374e9c41d0ca46de2cb4d0d7 (patch)
tree75238d882c2f5eed0e1478cf6e9de2fc1aa99349 /drivers/scsi/cxlflash
parentbc65c1c7bfb34a6eeea99eb725b467ff64eda3d8 (diff)
scsi: cxlflash: Support AFU interrupt mapping and registration
Add support to map and unmap the irq space and manage irq registrations with the kernel for each allocated AFU interrupt. Also support mapping the physical trigger page to obtain an effective address that will be provided to the cxlflash core in a future commit. 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>
Diffstat (limited to 'drivers/scsi/cxlflash')
-rw-r--r--drivers/scsi/cxlflash/ocxl_hw.c120
-rw-r--r--drivers/scsi/cxlflash/ocxl_hw.h2
2 files changed, 122 insertions, 0 deletions
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 75351c3ca9bd..c53405e7190e 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -186,6 +186,124 @@ static int ocxlflash_process_element(void *ctx_cookie)
186} 186}
187 187
188/** 188/**
189 * afu_map_irq() - map the interrupt of the adapter context
190 * @flags: Flags.
191 * @ctx: Adapter context.
192 * @num: Per-context AFU interrupt number.
193 * @handler: Interrupt handler to register.
194 * @cookie: Interrupt handler private data.
195 * @name: Name of the interrupt.
196 *
197 * Return: 0 on success, -errno on failure
198 */
199static int afu_map_irq(u64 flags, struct ocxlflash_context *ctx, int num,
200 irq_handler_t handler, void *cookie, char *name)
201{
202 struct ocxl_hw_afu *afu = ctx->hw_afu;
203 struct device *dev = afu->dev;
204 struct ocxlflash_irqs *irq;
205 void __iomem *vtrig;
206 u32 virq;
207 int rc = 0;
208
209 if (num < 0 || num >= ctx->num_irqs) {
210 dev_err(dev, "%s: Interrupt %d not allocated\n", __func__, num);
211 rc = -ENOENT;
212 goto out;
213 }
214
215 irq = &ctx->irqs[num];
216 virq = irq_create_mapping(NULL, irq->hwirq);
217 if (unlikely(!virq)) {
218 dev_err(dev, "%s: irq_create_mapping failed\n", __func__);
219 rc = -ENOMEM;
220 goto out;
221 }
222
223 rc = request_irq(virq, handler, 0, name, cookie);
224 if (unlikely(rc)) {
225 dev_err(dev, "%s: request_irq failed rc=%d\n", __func__, rc);
226 goto err1;
227 }
228
229 vtrig = ioremap(irq->ptrig, PAGE_SIZE);
230 if (unlikely(!vtrig)) {
231 dev_err(dev, "%s: Trigger page mapping failed\n", __func__);
232 rc = -ENOMEM;
233 goto err2;
234 }
235
236 irq->virq = virq;
237 irq->vtrig = vtrig;
238out:
239 return rc;
240err2:
241 free_irq(virq, cookie);
242err1:
243 irq_dispose_mapping(virq);
244 goto out;
245}
246
247/**
248 * ocxlflash_map_afu_irq() - map the interrupt of the adapter context
249 * @ctx_cookie: Adapter context.
250 * @num: Per-context AFU interrupt number.
251 * @handler: Interrupt handler to register.
252 * @cookie: Interrupt handler private data.
253 * @name: Name of the interrupt.
254 *
255 * Return: 0 on success, -errno on failure
256 */
257static int ocxlflash_map_afu_irq(void *ctx_cookie, int num,
258 irq_handler_t handler, void *cookie,
259 char *name)
260{
261 return afu_map_irq(0, ctx_cookie, num, handler, cookie, name);
262}
263
264/**
265 * afu_unmap_irq() - unmap the interrupt
266 * @flags: Flags.
267 * @ctx: Adapter context.
268 * @num: Per-context AFU interrupt number.
269 * @cookie: Interrupt handler private data.
270 */
271static void afu_unmap_irq(u64 flags, struct ocxlflash_context *ctx, int num,
272 void *cookie)
273{
274 struct ocxl_hw_afu *afu = ctx->hw_afu;
275 struct device *dev = afu->dev;
276 struct ocxlflash_irqs *irq;
277
278 if (num < 0 || num >= ctx->num_irqs) {
279 dev_err(dev, "%s: Interrupt %d not allocated\n", __func__, num);
280 return;
281 }
282
283 irq = &ctx->irqs[num];
284 if (irq->vtrig)
285 iounmap(irq->vtrig);
286
287 if (irq_find_mapping(NULL, irq->hwirq)) {
288 free_irq(irq->virq, cookie);
289 irq_dispose_mapping(irq->virq);
290 }
291
292 memset(irq, 0, sizeof(*irq));
293}
294
295/**
296 * ocxlflash_unmap_afu_irq() - unmap the interrupt
297 * @ctx_cookie: Adapter context.
298 * @num: Per-context AFU interrupt number.
299 * @cookie: Interrupt handler private data.
300 */
301static void ocxlflash_unmap_afu_irq(void *ctx_cookie, int num, void *cookie)
302{
303 return afu_unmap_irq(0, ctx_cookie, num, cookie);
304}
305
306/**
189 * start_context() - local routine to start a context 307 * start_context() - local routine to start a context
190 * @ctx: Adapter context to be started. 308 * @ctx: Adapter context to be started.
191 * 309 *
@@ -844,6 +962,8 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
844 .psa_map = ocxlflash_psa_map, 962 .psa_map = ocxlflash_psa_map,
845 .psa_unmap = ocxlflash_psa_unmap, 963 .psa_unmap = ocxlflash_psa_unmap,
846 .process_element = ocxlflash_process_element, 964 .process_element = ocxlflash_process_element,
965 .map_afu_irq = ocxlflash_map_afu_irq,
966 .unmap_afu_irq = ocxlflash_unmap_afu_irq,
847 .start_context = ocxlflash_start_context, 967 .start_context = ocxlflash_start_context,
848 .stop_context = ocxlflash_stop_context, 968 .stop_context = ocxlflash_stop_context,
849 .set_master = ocxlflash_set_master, 969 .set_master = ocxlflash_set_master,
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 85b3fad24263..9011af08a957 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -16,7 +16,9 @@
16 16
17struct ocxlflash_irqs { 17struct ocxlflash_irqs {
18 int hwirq; 18 int hwirq;
19 u32 virq;
19 u64 ptrig; 20 u64 ptrig;
21 void __iomem *vtrig;
20}; 22};
21 23
22/* OCXL hardware AFU associated with the host */ 24/* OCXL hardware AFU associated with the host */