diff options
author | Armen Baloyan <armen.baloyan@qlogic.com> | 2014-02-26 04:15:18 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-15 13:18:53 -0400 |
commit | 4440e46d5db7b445a961a84444849b2a31fa7fd1 (patch) | |
tree | 749aabd6001295df16788f7423351ead583c0b98 /drivers/scsi | |
parent | faef62d134631c1f390006d51d49c76033f9504f (diff) |
[SCSI] qla2xxx: Add IOCB Abort command asynchronous handling.
Send aborts to the firmware via the request/response queue mechanism.
Signed-off-by: Armen Baloyan <armen.baloyan@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 88 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 27 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 21 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mr.c | 88 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 2 |
7 files changed, 140 insertions, 91 deletions
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index dcd084a4e5c1..e665e8109933 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -330,6 +330,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *, | |||
330 | dma_addr_t); | 330 | dma_addr_t); |
331 | 331 | ||
332 | extern int qla24xx_abort_command(srb_t *); | 332 | extern int qla24xx_abort_command(srb_t *); |
333 | extern int qla24xx_async_abort_command(srb_t *); | ||
333 | extern int | 334 | extern int |
334 | qla24xx_abort_target(struct fc_port *, unsigned int, int); | 335 | qla24xx_abort_target(struct fc_port *, unsigned int, int); |
335 | extern int | 336 | extern int |
@@ -604,7 +605,6 @@ extern char *qlafx00_fw_version_str(struct scsi_qla_host *, char *); | |||
604 | extern irqreturn_t qlafx00_intr_handler(int, void *); | 605 | extern irqreturn_t qlafx00_intr_handler(int, void *); |
605 | extern void qlafx00_enable_intrs(struct qla_hw_data *); | 606 | extern void qlafx00_enable_intrs(struct qla_hw_data *); |
606 | extern void qlafx00_disable_intrs(struct qla_hw_data *); | 607 | extern void qlafx00_disable_intrs(struct qla_hw_data *); |
607 | extern int qlafx00_abort_command(srb_t *); | ||
608 | extern int qlafx00_abort_target(fc_port_t *, unsigned int, int); | 608 | extern int qlafx00_abort_target(fc_port_t *, unsigned int, int); |
609 | extern int qlafx00_lun_reset(fc_port_t *, unsigned int, int); | 609 | extern int qlafx00_lun_reset(fc_port_t *, unsigned int, int); |
610 | extern int qlafx00_start_scsi(srb_t *); | 610 | extern int qlafx00_start_scsi(srb_t *); |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 27248425f86c..0a25e8bd8729 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -347,6 +347,94 @@ done: | |||
347 | return rval; | 347 | return rval; |
348 | } | 348 | } |
349 | 349 | ||
350 | static void | ||
351 | qla24xx_abort_iocb_timeout(void *data) | ||
352 | { | ||
353 | srb_t *sp = (srb_t *)data; | ||
354 | struct srb_iocb *abt = &sp->u.iocb_cmd; | ||
355 | |||
356 | abt->u.abt.comp_status = CS_TIMEOUT; | ||
357 | complete(&abt->u.abt.comp); | ||
358 | } | ||
359 | |||
360 | static void | ||
361 | qla24xx_abort_sp_done(void *data, void *ptr, int res) | ||
362 | { | ||
363 | srb_t *sp = (srb_t *)ptr; | ||
364 | struct srb_iocb *abt = &sp->u.iocb_cmd; | ||
365 | |||
366 | complete(&abt->u.abt.comp); | ||
367 | } | ||
368 | |||
369 | static int | ||
370 | qla24xx_async_abort_cmd(srb_t *cmd_sp) | ||
371 | { | ||
372 | scsi_qla_host_t *vha = cmd_sp->fcport->vha; | ||
373 | fc_port_t *fcport = cmd_sp->fcport; | ||
374 | struct srb_iocb *abt_iocb; | ||
375 | srb_t *sp; | ||
376 | int rval = QLA_FUNCTION_FAILED; | ||
377 | |||
378 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); | ||
379 | if (!sp) | ||
380 | goto done; | ||
381 | |||
382 | abt_iocb = &sp->u.iocb_cmd; | ||
383 | sp->type = SRB_ABT_CMD; | ||
384 | sp->name = "abort"; | ||
385 | qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)); | ||
386 | abt_iocb->u.abt.cmd_hndl = cmd_sp->handle; | ||
387 | sp->done = qla24xx_abort_sp_done; | ||
388 | abt_iocb->timeout = qla24xx_abort_iocb_timeout; | ||
389 | init_completion(&abt_iocb->u.abt.comp); | ||
390 | |||
391 | rval = qla2x00_start_sp(sp); | ||
392 | if (rval != QLA_SUCCESS) | ||
393 | goto done_free_sp; | ||
394 | |||
395 | ql_dbg(ql_dbg_async, vha, 0x507c, | ||
396 | "Abort command issued - hdl=%x, target_id=%x\n", | ||
397 | cmd_sp->handle, fcport->tgt_id); | ||
398 | |||
399 | wait_for_completion(&abt_iocb->u.abt.comp); | ||
400 | |||
401 | rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ? | ||
402 | QLA_SUCCESS : QLA_FUNCTION_FAILED; | ||
403 | |||
404 | done_free_sp: | ||
405 | sp->free(vha, sp); | ||
406 | done: | ||
407 | return rval; | ||
408 | } | ||
409 | |||
410 | int | ||
411 | qla24xx_async_abort_command(srb_t *sp) | ||
412 | { | ||
413 | unsigned long flags = 0; | ||
414 | |||
415 | uint32_t handle; | ||
416 | fc_port_t *fcport = sp->fcport; | ||
417 | struct scsi_qla_host *vha = fcport->vha; | ||
418 | struct qla_hw_data *ha = vha->hw; | ||
419 | struct req_que *req = vha->req; | ||
420 | |||
421 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
422 | for (handle = 1; handle < req->num_outstanding_cmds; handle++) { | ||
423 | if (req->outstanding_cmds[handle] == sp) | ||
424 | break; | ||
425 | } | ||
426 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
427 | if (handle == req->num_outstanding_cmds) { | ||
428 | /* Command not found. */ | ||
429 | return QLA_FUNCTION_FAILED; | ||
430 | } | ||
431 | if (sp->type == SRB_FXIOCB_DCMD) | ||
432 | return qlafx00_fx_disc(vha, &vha->hw->mr.fcport, | ||
433 | FXDISC_ABORT_IOCTL); | ||
434 | |||
435 | return qla24xx_async_abort_cmd(sp); | ||
436 | } | ||
437 | |||
350 | void | 438 | void |
351 | qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | 439 | qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, |
352 | uint16_t *data) | 440 | uint16_t *data) |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 0aad5e412aa7..8c5dec2e3b6d 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -2585,6 +2585,29 @@ queuing_error: | |||
2585 | return QLA_FUNCTION_FAILED; | 2585 | return QLA_FUNCTION_FAILED; |
2586 | } | 2586 | } |
2587 | 2587 | ||
2588 | void | ||
2589 | qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) | ||
2590 | { | ||
2591 | struct srb_iocb *aio = &sp->u.iocb_cmd; | ||
2592 | scsi_qla_host_t *vha = sp->fcport->vha; | ||
2593 | struct req_que *req = vha->req; | ||
2594 | |||
2595 | memset(abt_iocb, 0, sizeof(struct abort_entry_24xx)); | ||
2596 | abt_iocb->entry_type = ABORT_IOCB_TYPE; | ||
2597 | abt_iocb->entry_count = 1; | ||
2598 | abt_iocb->handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); | ||
2599 | abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
2600 | abt_iocb->handle_to_abort = | ||
2601 | cpu_to_le32(MAKE_HANDLE(req->id, aio->u.abt.cmd_hndl)); | ||
2602 | abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
2603 | abt_iocb->port_id[1] = sp->fcport->d_id.b.area; | ||
2604 | abt_iocb->port_id[2] = sp->fcport->d_id.b.domain; | ||
2605 | abt_iocb->vp_index = vha->vp_idx; | ||
2606 | abt_iocb->req_que_no = cpu_to_le16(req->id); | ||
2607 | /* Send the command to the firmware */ | ||
2608 | wmb(); | ||
2609 | } | ||
2610 | |||
2588 | int | 2611 | int |
2589 | qla2x00_start_sp(srb_t *sp) | 2612 | qla2x00_start_sp(srb_t *sp) |
2590 | { | 2613 | { |
@@ -2638,7 +2661,9 @@ qla2x00_start_sp(srb_t *sp) | |||
2638 | qlafx00_fxdisc_iocb(sp, pkt); | 2661 | qlafx00_fxdisc_iocb(sp, pkt); |
2639 | break; | 2662 | break; |
2640 | case SRB_ABT_CMD: | 2663 | case SRB_ABT_CMD: |
2641 | qlafx00_abort_iocb(sp, pkt); | 2664 | IS_QLAFX00(ha) ? |
2665 | qlafx00_abort_iocb(sp, pkt) : | ||
2666 | qla24xx_abort_iocb(sp, pkt); | ||
2642 | break; | 2667 | break; |
2643 | default: | 2668 | default: |
2644 | break; | 2669 | break; |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 293dbd565840..95314ef2e505 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -2428,6 +2428,23 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) | |||
2428 | } | 2428 | } |
2429 | } | 2429 | } |
2430 | 2430 | ||
2431 | static void | ||
2432 | qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
2433 | struct abort_entry_24xx *pkt) | ||
2434 | { | ||
2435 | const char func[] = "ABT_IOCB"; | ||
2436 | srb_t *sp; | ||
2437 | struct srb_iocb *abt; | ||
2438 | |||
2439 | sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); | ||
2440 | if (!sp) | ||
2441 | return; | ||
2442 | |||
2443 | abt = &sp->u.iocb_cmd; | ||
2444 | abt->u.abt.comp_status = le32_to_cpu(pkt->nport_handle); | ||
2445 | sp->done(vha, sp, 0); | ||
2446 | } | ||
2447 | |||
2431 | /** | 2448 | /** |
2432 | * qla24xx_process_response_queue() - Process response queue entries. | 2449 | * qla24xx_process_response_queue() - Process response queue entries. |
2433 | * @ha: SCSI driver HA context | 2450 | * @ha: SCSI driver HA context |
@@ -2496,6 +2513,10 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
2496 | * from falling into default case | 2513 | * from falling into default case |
2497 | */ | 2514 | */ |
2498 | break; | 2515 | break; |
2516 | case ABORT_IOCB_TYPE: | ||
2517 | qla24xx_abort_iocb_entry(vha, rsp->req, | ||
2518 | (struct abort_entry_24xx *)pkt); | ||
2519 | break; | ||
2499 | default: | 2520 | default: |
2500 | /* Type Not Supported. */ | 2521 | /* Type Not Supported. */ |
2501 | ql_dbg(ql_dbg_async, vha, 0x5042, | 2522 | ql_dbg(ql_dbg_async, vha, 0x5042, |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index b4f7cd5fa75c..2528709c4add 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -2597,6 +2597,9 @@ qla24xx_abort_command(srb_t *sp) | |||
2597 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c, | 2597 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c, |
2598 | "Entered %s.\n", __func__); | 2598 | "Entered %s.\n", __func__); |
2599 | 2599 | ||
2600 | if (ql2xasynctmfenable) | ||
2601 | return qla24xx_async_abort_command(sp); | ||
2602 | |||
2600 | spin_lock_irqsave(&ha->hardware_lock, flags); | 2603 | spin_lock_irqsave(&ha->hardware_lock, flags); |
2601 | for (handle = 1; handle < req->num_outstanding_cmds; handle++) { | 2604 | for (handle = 1; handle < req->num_outstanding_cmds; handle++) { |
2602 | if (req->outstanding_cmds[handle] == sp) | 2605 | if (req->outstanding_cmds[handle] == sp) |
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 165db12580af..0aaf6a9c87d3 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c | |||
@@ -1962,94 +1962,6 @@ done: | |||
1962 | return rval; | 1962 | return rval; |
1963 | } | 1963 | } |
1964 | 1964 | ||
1965 | static void | ||
1966 | qlafx00_abort_iocb_timeout(void *data) | ||
1967 | { | ||
1968 | srb_t *sp = (srb_t *)data; | ||
1969 | struct srb_iocb *abt = &sp->u.iocb_cmd; | ||
1970 | |||
1971 | abt->u.abt.comp_status = cpu_to_le16((uint16_t)CS_TIMEOUT); | ||
1972 | complete(&abt->u.abt.comp); | ||
1973 | } | ||
1974 | |||
1975 | static void | ||
1976 | qlafx00_abort_sp_done(void *data, void *ptr, int res) | ||
1977 | { | ||
1978 | srb_t *sp = (srb_t *)ptr; | ||
1979 | struct srb_iocb *abt = &sp->u.iocb_cmd; | ||
1980 | |||
1981 | complete(&abt->u.abt.comp); | ||
1982 | } | ||
1983 | |||
1984 | static int | ||
1985 | qlafx00_async_abt_cmd(srb_t *cmd_sp) | ||
1986 | { | ||
1987 | scsi_qla_host_t *vha = cmd_sp->fcport->vha; | ||
1988 | fc_port_t *fcport = cmd_sp->fcport; | ||
1989 | struct srb_iocb *abt_iocb; | ||
1990 | srb_t *sp; | ||
1991 | int rval = QLA_FUNCTION_FAILED; | ||
1992 | |||
1993 | sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); | ||
1994 | if (!sp) | ||
1995 | goto done; | ||
1996 | |||
1997 | abt_iocb = &sp->u.iocb_cmd; | ||
1998 | sp->type = SRB_ABT_CMD; | ||
1999 | sp->name = "abort"; | ||
2000 | qla2x00_init_timer(sp, FXDISC_TIMEOUT); | ||
2001 | abt_iocb->u.abt.cmd_hndl = cmd_sp->handle; | ||
2002 | sp->done = qlafx00_abort_sp_done; | ||
2003 | abt_iocb->timeout = qlafx00_abort_iocb_timeout; | ||
2004 | init_completion(&abt_iocb->u.abt.comp); | ||
2005 | |||
2006 | rval = qla2x00_start_sp(sp); | ||
2007 | if (rval != QLA_SUCCESS) | ||
2008 | goto done_free_sp; | ||
2009 | |||
2010 | ql_dbg(ql_dbg_async, vha, 0x507c, | ||
2011 | "Abort command issued - hdl=%x, target_id=%x\n", | ||
2012 | cmd_sp->handle, fcport->tgt_id); | ||
2013 | |||
2014 | wait_for_completion(&abt_iocb->u.abt.comp); | ||
2015 | |||
2016 | rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ? | ||
2017 | QLA_SUCCESS : QLA_FUNCTION_FAILED; | ||
2018 | |||
2019 | done_free_sp: | ||
2020 | sp->free(vha, sp); | ||
2021 | done: | ||
2022 | return rval; | ||
2023 | } | ||
2024 | |||
2025 | int | ||
2026 | qlafx00_abort_command(srb_t *sp) | ||
2027 | { | ||
2028 | unsigned long flags = 0; | ||
2029 | |||
2030 | uint32_t handle; | ||
2031 | fc_port_t *fcport = sp->fcport; | ||
2032 | struct scsi_qla_host *vha = fcport->vha; | ||
2033 | struct qla_hw_data *ha = vha->hw; | ||
2034 | struct req_que *req = vha->req; | ||
2035 | |||
2036 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2037 | for (handle = 1; handle < DEFAULT_OUTSTANDING_COMMANDS; handle++) { | ||
2038 | if (req->outstanding_cmds[handle] == sp) | ||
2039 | break; | ||
2040 | } | ||
2041 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2042 | if (handle == DEFAULT_OUTSTANDING_COMMANDS) { | ||
2043 | /* Command not found. */ | ||
2044 | return QLA_FUNCTION_FAILED; | ||
2045 | } | ||
2046 | if (sp->type == SRB_FXIOCB_DCMD) | ||
2047 | return qlafx00_fx_disc(vha, &vha->hw->mr.fcport, | ||
2048 | FXDISC_ABORT_IOCTL); | ||
2049 | |||
2050 | return qlafx00_async_abt_cmd(sp); | ||
2051 | } | ||
2052 | |||
2053 | /* | 1965 | /* |
2054 | * qlafx00_initialize_adapter | 1966 | * qlafx00_initialize_adapter |
2055 | * Initialize board. | 1967 | * Initialize board. |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7b54e0acaac7..5feed53459f4 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -2078,7 +2078,7 @@ static struct isp_operations qlafx00_isp_ops = { | |||
2078 | .intr_handler = qlafx00_intr_handler, | 2078 | .intr_handler = qlafx00_intr_handler, |
2079 | .enable_intrs = qlafx00_enable_intrs, | 2079 | .enable_intrs = qlafx00_enable_intrs, |
2080 | .disable_intrs = qlafx00_disable_intrs, | 2080 | .disable_intrs = qlafx00_disable_intrs, |
2081 | .abort_command = qlafx00_abort_command, | 2081 | .abort_command = qla24xx_async_abort_command, |
2082 | .target_reset = qlafx00_abort_target, | 2082 | .target_reset = qlafx00_abort_target, |
2083 | .lun_reset = qlafx00_lun_reset, | 2083 | .lun_reset = qlafx00_lun_reset, |
2084 | .fabric_login = NULL, | 2084 | .fabric_login = NULL, |