diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2010-05-28 18:08:19 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-27 13:01:21 -0400 |
commit | 6ac5260850841eb4055811a68ff47d658ebe9a59 (patch) | |
tree | 00e6bc407c4732ffb709ba9de7d8c743b9520194 /drivers/scsi/qla2xxx/qla_init.c | |
parent | 083a469db4ecf3b286a96b5b722c37fc1affe0be (diff) |
[SCSI] qla2xxx: Correct async-srb issues.
* hold the hardware_lock throughout the duration of ctx-sp
timeout handling -- could result in use-after-free oops.
* retry a timed-out login-request.
* done() routines are called with the hardware-lock held, issue
qla2x00_mark_device_lost() with proper 'defer' flag.
* FCP2 capabilities are only relevant to target devices.
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 4bf973483818..cc7352545081 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -60,9 +60,8 @@ qla2x00_ctx_sp_timeout(unsigned long __data) | |||
60 | ctx = sp->ctx; | 60 | ctx = sp->ctx; |
61 | iocb = ctx->u.iocb_cmd; | 61 | iocb = ctx->u.iocb_cmd; |
62 | iocb->timeout(sp); | 62 | iocb->timeout(sp); |
63 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
64 | |||
65 | iocb->free(sp); | 63 | iocb->free(sp); |
64 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
66 | } | 65 | } |
67 | 66 | ||
68 | void | 67 | void |
@@ -137,8 +136,16 @@ qla2x00_async_iocb_timeout(srb_t *sp) | |||
137 | fcport->d_id.b.area, fcport->d_id.b.al_pa)); | 136 | fcport->d_id.b.area, fcport->d_id.b.al_pa)); |
138 | 137 | ||
139 | fcport->flags &= ~FCF_ASYNC_SENT; | 138 | fcport->flags &= ~FCF_ASYNC_SENT; |
140 | if (ctx->type == SRB_LOGIN_CMD) | 139 | if (ctx->type == SRB_LOGIN_CMD) { |
140 | struct srb_iocb *lio = ctx->u.iocb_cmd; | ||
141 | qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); | 141 | qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); |
142 | /* Retry as needed. */ | ||
143 | lio->u.logio.data[0] = MBS_COMMAND_ERROR; | ||
144 | lio->u.logio.data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ? | ||
145 | QLA_LOGIO_LOGIN_RETRIED : 0; | ||
146 | qla2x00_post_async_login_done_work(fcport->vha, fcport, | ||
147 | lio->u.logio.data); | ||
148 | } | ||
142 | } | 149 | } |
143 | 150 | ||
144 | static void | 151 | static void |
@@ -420,10 +427,11 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
420 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | 427 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) |
421 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); | 428 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); |
422 | else | 429 | else |
423 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | 430 | qla2x00_mark_device_lost(vha, fcport, 1, 1); |
424 | break; | 431 | break; |
425 | case MBS_PORT_ID_USED: | 432 | case MBS_PORT_ID_USED: |
426 | fcport->loop_id = data[1]; | 433 | fcport->loop_id = data[1]; |
434 | qla2x00_post_async_logout_work(vha, fcport, NULL); | ||
427 | qla2x00_post_async_login_work(vha, fcport, NULL); | 435 | qla2x00_post_async_login_work(vha, fcport, NULL); |
428 | break; | 436 | break; |
429 | case MBS_LOOP_ID_USED: | 437 | case MBS_LOOP_ID_USED: |
@@ -431,7 +439,7 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
431 | rval = qla2x00_find_new_loop_id(vha, fcport); | 439 | rval = qla2x00_find_new_loop_id(vha, fcport); |
432 | if (rval != QLA_SUCCESS) { | 440 | if (rval != QLA_SUCCESS) { |
433 | fcport->flags &= ~FCF_ASYNC_SENT; | 441 | fcport->flags &= ~FCF_ASYNC_SENT; |
434 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | 442 | qla2x00_mark_device_lost(vha, fcport, 1, 1); |
435 | break; | 443 | break; |
436 | } | 444 | } |
437 | qla2x00_post_async_login_work(vha, fcport, NULL); | 445 | qla2x00_post_async_login_work(vha, fcport, NULL); |
@@ -463,7 +471,7 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
463 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | 471 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) |
464 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); | 472 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); |
465 | else | 473 | else |
466 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | 474 | qla2x00_mark_device_lost(vha, fcport, 1, 1); |
467 | 475 | ||
468 | return; | 476 | return; |
469 | } | 477 | } |