aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMadhuranath Iyengar <madhuranath.iyengar@qlogic.com>2010-05-04 18:01:29 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-16 18:21:57 -0400
commit3822263eb1e74821ad1ae886ddd2184ae9395ff7 (patch)
tree7b8ff05127a579bb0c3de9c8848f4052c0604d60 /drivers
parent4916392b56921b4aaaeaca3ef492135f42fbb5f2 (diff)
[SCSI] qla2xxx: Support for asynchronous TM and Marker IOCBs.
Currently we can only issue the task management (TM) commands via the mailbox mechanism. This is a limitation, since only one mailbox command can be issued at a time. The purpose of this effort is to provide support for issuing and processing the respose to TM and Marker IOCBs asynchronously. Towards achieving this, the consolidated srb architecture that is currently used for BSG and IOCB/Logio commands has been enhanced and used. Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h22
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c156
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c64
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c102
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c5
8 files changed, 366 insertions, 4 deletions
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 951db816ee45..b905dfe5ea61 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -317,6 +317,9 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
317 els->type = 317 els->type =
318 (bsg_job->request->msgcode == FC_BSG_RPT_ELS ? 318 (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
319 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); 319 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
320 els->name =
321 (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
322 "bsg_els_rpt" : "bsg_els_hst");
320 els->u.bsg_job = bsg_job; 323 els->u.bsg_job = bsg_job;
321 324
322 DEBUG2(qla_printk(KERN_INFO, ha, 325 DEBUG2(qla_printk(KERN_INFO, ha,
@@ -450,6 +453,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
450 453
451 ct = sp->ctx; 454 ct = sp->ctx;
452 ct->type = SRB_CT_CMD; 455 ct->type = SRB_CT_CMD;
456 ct->name = "bsg_ct";
453 ct->u.bsg_job = bsg_job; 457 ct->u.bsg_job = bsg_job;
454 458
455 DEBUG2(qla_printk(KERN_INFO, ha, 459 DEBUG2(qla_printk(KERN_INFO, ha,
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 08f5fd5359dd..0d2cecbb8f47 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -223,6 +223,26 @@ struct srb_iocb {
223#define SRB_LOGIN_SKIP_PRLI BIT_2 223#define SRB_LOGIN_SKIP_PRLI BIT_2
224 uint16_t data[2]; 224 uint16_t data[2];
225 } logio; 225 } logio;
226 struct {
227 /*
228 * Values for flags field below are as
229 * defined in tsk_mgmt_entry struct
230 * for control_flags field in qla_fw.h.
231 */
232 uint32_t flags;
233 uint32_t lun;
234 uint32_t data;
235 } tmf;
236 struct {
237 /*
238 * values for modif field below are as
239 * defined in mrk_entry_24xx struct
240 * for the modifier field in qla_fw.h.
241 */
242 uint8_t modif;
243 uint16_t lun;
244 uint32_t data;
245 } marker;
226 } u; 246 } u;
227 247
228 struct timer_list timer; 248 struct timer_list timer;
@@ -239,6 +259,8 @@ struct srb_iocb {
239#define SRB_ELS_CMD_HST 4 259#define SRB_ELS_CMD_HST 4
240#define SRB_CT_CMD 5 260#define SRB_CT_CMD 5
241#define SRB_ADISC_CMD 6 261#define SRB_ADISC_CMD 6
262#define SRB_TM_CMD 7
263#define SRB_MARKER_CMD 8
242 264
243struct srb_ctx { 265struct srb_ctx {
244 uint16_t type; 266 uint16_t type;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 408e5f0a53c1..3dbefe1a6b5f 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -58,12 +58,18 @@ extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
58extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); 58extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
59extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, 59extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
60 uint16_t *); 60 uint16_t *);
61extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
62extern int qla2x00_async_marker(fc_port_t *, uint16_t, uint8_t);
61extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, 63extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
62 uint16_t *); 64 uint16_t *);
63extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, 65extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
64 uint16_t *); 66 uint16_t *);
65extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *, 67extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
66 uint16_t *); 68 uint16_t *);
69extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *,
70 struct srb_iocb *);
71extern void qla2x00_async_marker_done(struct scsi_qla_host *, fc_port_t *,
72 struct srb_iocb *);
67 73
68extern fc_port_t * 74extern fc_port_t *
69qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t ); 75qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t );
@@ -87,6 +93,7 @@ extern int ql2xetsenable;
87extern int ql2xshiftctondsd; 93extern int ql2xshiftctondsd;
88extern int ql2xdbwr; 94extern int ql2xdbwr;
89extern int ql2xdontresethba; 95extern int ql2xdontresethba;
96extern int ql2xasynctmfenable;
90 97
91extern int qla2x00_loop_reset(scsi_qla_host_t *); 98extern int qla2x00_loop_reset(scsi_qla_host_t *);
92extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); 99extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 72b4ef270158..e78089ded517 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -125,7 +125,7 @@ done:
125#define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2) 125#define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2)
126 126
127static void 127static void
128qla2x00_async_logio_timeout(srb_t *sp) 128qla2x00_async_iocb_timeout(srb_t *sp)
129{ 129{
130 fc_port_t *fcport = sp->fcport; 130 fc_port_t *fcport = sp->fcport;
131 struct srb_ctx *ctx = sp->ctx; 131 struct srb_ctx *ctx = sp->ctx;
@@ -170,7 +170,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
170 ctx->type = SRB_LOGIN_CMD; 170 ctx->type = SRB_LOGIN_CMD;
171 ctx->name = "login"; 171 ctx->name = "login";
172 lio = ctx->u.iocb_cmd; 172 lio = ctx->u.iocb_cmd;
173 lio->timeout = qla2x00_async_logio_timeout; 173 lio->timeout = qla2x00_async_iocb_timeout;
174 lio->done = qla2x00_async_login_ctx_done; 174 lio->done = qla2x00_async_login_ctx_done;
175 lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI; 175 lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
176 if (data[1] & QLA_LOGIO_LOGIN_RETRIED) 176 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
@@ -222,7 +222,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
222 ctx->type = SRB_LOGOUT_CMD; 222 ctx->type = SRB_LOGOUT_CMD;
223 ctx->name = "logout"; 223 ctx->name = "logout";
224 lio = ctx->u.iocb_cmd; 224 lio = ctx->u.iocb_cmd;
225 lio->timeout = qla2x00_async_logio_timeout; 225 lio->timeout = qla2x00_async_iocb_timeout;
226 lio->done = qla2x00_async_logout_ctx_done; 226 lio->done = qla2x00_async_logout_ctx_done;
227 rval = qla2x00_start_sp(sp); 227 rval = qla2x00_start_sp(sp);
228 if (rval != QLA_SUCCESS) 228 if (rval != QLA_SUCCESS)
@@ -271,7 +271,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
271 ctx->type = SRB_ADISC_CMD; 271 ctx->type = SRB_ADISC_CMD;
272 ctx->name = "adisc"; 272 ctx->name = "adisc";
273 lio = ctx->u.iocb_cmd; 273 lio = ctx->u.iocb_cmd;
274 lio->timeout = qla2x00_async_logio_timeout; 274 lio->timeout = qla2x00_async_iocb_timeout;
275 lio->done = qla2x00_async_adisc_ctx_done; 275 lio->done = qla2x00_async_adisc_ctx_done;
276 if (data[1] & QLA_LOGIO_LOGIN_RETRIED) 276 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
277 lio->u.logio.flags |= SRB_LOGIN_RETRIED; 277 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
@@ -292,6 +292,112 @@ done:
292 return rval; 292 return rval;
293} 293}
294 294
295static void
296qla2x00_async_tm_cmd_ctx_done(srb_t *sp)
297{
298 struct srb_ctx *ctx = sp->ctx;
299 struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd;
300
301 qla2x00_async_tm_cmd_done(sp->fcport->vha, sp->fcport, iocb);
302 iocb->free(sp);
303}
304
305int
306qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
307 uint32_t tag)
308{
309 struct scsi_qla_host *vha = fcport->vha;
310 struct qla_hw_data *ha = vha->hw;
311 srb_t *sp;
312 struct srb_ctx *ctx;
313 struct srb_iocb *tcf;
314 int rval;
315
316 rval = QLA_FUNCTION_FAILED;
317 sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
318 ELS_TMO_2_RATOV(ha) + 2);
319 if (!sp)
320 goto done;
321
322 ctx = sp->ctx;
323 ctx->type = SRB_TM_CMD;
324 ctx->name = "tmf";
325 tcf = ctx->u.iocb_cmd;
326 tcf->u.tmf.flags = flags;
327 tcf->u.tmf.lun = lun;
328 tcf->u.tmf.data = tag;
329 tcf->timeout = qla2x00_async_iocb_timeout;
330 tcf->done = qla2x00_async_tm_cmd_ctx_done;
331
332 rval = qla2x00_start_sp(sp);
333 if (rval != QLA_SUCCESS)
334 goto done_free_sp;
335
336 DEBUG2(printk(KERN_DEBUG
337 "scsi(%ld:%x): Async-tmf - loop-id=%x portid=%02x%02x%02x.\n",
338 fcport->vha->host_no, sp->handle, fcport->loop_id,
339 fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
340
341 return rval;
342
343done_free_sp:
344 tcf->free(sp);
345done:
346 return rval;
347}
348
349static void
350qla2x00_async_marker_ctx_done(srb_t *sp)
351{
352 struct srb_ctx *ctx = sp->ctx;
353 struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd;
354
355 qla2x00_async_marker_done(sp->fcport->vha, sp->fcport, iocb);
356 iocb->free(sp);
357}
358
359int
360qla2x00_async_marker(fc_port_t *fcport, uint16_t lun, uint8_t modif)
361{
362 struct scsi_qla_host *vha = fcport->vha;
363 srb_t *sp;
364 struct srb_ctx *ctx;
365 struct srb_iocb *mrk;
366 int rval;
367
368 rval = QLA_FUNCTION_FAILED;
369 sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 0);
370 if (!sp)
371 goto done;
372
373 ctx = sp->ctx;
374 ctx->type = SRB_MARKER_CMD;
375 ctx->name = "marker";
376 mrk = ctx->u.iocb_cmd;
377 mrk->u.marker.lun = lun;
378 mrk->u.marker.modif = modif;
379 mrk->timeout = qla2x00_async_iocb_timeout;
380 mrk->done = qla2x00_async_marker_ctx_done;
381
382 rval = qla2x00_start_sp(sp);
383 if (rval != QLA_SUCCESS)
384 goto done_free_sp;
385
386 DEBUG2(printk(KERN_DEBUG
387 "scsi(%ld:%x): Async-marker - loop-id=%x "
388 "portid=%02x%02x%02x.\n",
389 fcport->vha->host_no, sp->handle, fcport->loop_id,
390 fcport->d_id.b.domain, fcport->d_id.b.area,
391 fcport->d_id.b.al_pa));
392
393 return rval;
394
395done_free_sp:
396 mrk->free(sp);
397done:
398 return rval;
399}
400
295void 401void
296qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, 402qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
297 uint16_t *data) 403 uint16_t *data)
@@ -360,6 +466,48 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
360 return; 466 return;
361} 467}
362 468
469void
470qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport,
471 struct srb_iocb *iocb)
472{
473 int rval;
474 uint32_t flags;
475 uint16_t lun;
476
477 flags = iocb->u.tmf.flags;
478 lun = (uint16_t)iocb->u.tmf.lun;
479
480 /* Issue Marker IOCB */
481 rval = qla2x00_async_marker(fcport, lun,
482 flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
483
484 if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
485 DEBUG2_3_11(printk(KERN_WARNING
486 "%s(%ld): TM IOCB failed (%x).\n",
487 __func__, vha->host_no, rval));
488 }
489
490 return;
491}
492
493void
494qla2x00_async_marker_done(struct scsi_qla_host *vha, fc_port_t *fcport,
495 struct srb_iocb *iocb)
496{
497 /*
498 * Currently we dont have any specific post response processing
499 * for this IOCB. We'll just return success or failed
500 * depending on whether the IOCB command succeeded or failed.
501 */
502 if (iocb->u.tmf.data) {
503 DEBUG2_3_11(printk(KERN_WARNING
504 "%s(%ld): Marker IOCB failed (%x).\n",
505 __func__, vha->host_no, iocb->u.tmf.data));
506 }
507
508 return;
509}
510
363/****************************************************************************/ 511/****************************************************************************/
364/* QLogic ISP2x00 Hardware Support Functions. */ 512/* QLogic ISP2x00 Hardware Support Functions. */
365/****************************************************************************/ 513/****************************************************************************/
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 8861b88319fb..d7a9fff15ad5 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1086,6 +1086,64 @@ qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
1086} 1086}
1087 1087
1088static void 1088static void
1089qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
1090{
1091 uint32_t flags;
1092 unsigned int lun;
1093 struct fc_port *fcport = sp->fcport;
1094 scsi_qla_host_t *vha = fcport->vha;
1095 struct qla_hw_data *ha = vha->hw;
1096 struct srb_ctx *ctx = sp->ctx;
1097 struct srb_iocb *iocb = ctx->u.iocb_cmd;
1098 struct req_que *req = vha->req;
1099
1100 flags = iocb->u.tmf.flags;
1101 lun = iocb->u.tmf.lun;
1102
1103 tsk->entry_type = TSK_MGMT_IOCB_TYPE;
1104 tsk->entry_count = 1;
1105 tsk->handle = MAKE_HANDLE(req->id, tsk->handle);
1106 tsk->nport_handle = cpu_to_le16(fcport->loop_id);
1107 tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1108 tsk->control_flags = cpu_to_le32(flags);
1109 tsk->port_id[0] = fcport->d_id.b.al_pa;
1110 tsk->port_id[1] = fcport->d_id.b.area;
1111 tsk->port_id[2] = fcport->d_id.b.domain;
1112 tsk->vp_index = fcport->vp_idx;
1113
1114 if (flags == TCF_LUN_RESET) {
1115 int_to_scsilun(lun, &tsk->lun);
1116 host_to_fcp_swap((uint8_t *)&tsk->lun,
1117 sizeof(tsk->lun));
1118 }
1119}
1120
1121static void
1122qla24xx_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk)
1123{
1124 uint16_t lun;
1125 uint8_t modif;
1126 struct fc_port *fcport = sp->fcport;
1127 scsi_qla_host_t *vha = fcport->vha;
1128 struct srb_ctx *ctx = sp->ctx;
1129 struct srb_iocb *iocb = ctx->u.iocb_cmd;
1130 struct req_que *req = vha->req;
1131
1132 lun = iocb->u.marker.lun;
1133 modif = iocb->u.marker.modif;
1134 mrk->entry_type = MARKER_TYPE;
1135 mrk->modifier = modif;
1136 if (modif != MK_SYNC_ALL) {
1137 mrk->nport_handle = cpu_to_le16(fcport->loop_id);
1138 mrk->lun[1] = LSB(lun);
1139 mrk->lun[2] = MSB(lun);
1140 host_to_fcp_swap(mrk->lun, sizeof(mrk->lun));
1141 mrk->vp_index = vha->vp_idx;
1142 mrk->handle = MAKE_HANDLE(req->id, mrk->handle);
1143 }
1144}
1145
1146static void
1089qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) 1147qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
1090{ 1148{
1091 struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; 1149 struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
@@ -1239,6 +1297,12 @@ qla2x00_start_sp(srb_t *sp)
1239 qla24xx_adisc_iocb(sp, pkt) : 1297 qla24xx_adisc_iocb(sp, pkt) :
1240 qla2x00_adisc_iocb(sp, pkt); 1298 qla2x00_adisc_iocb(sp, pkt);
1241 break; 1299 break;
1300 case SRB_TM_CMD:
1301 qla24xx_tm_iocb(sp, pkt);
1302 break;
1303 case SRB_MARKER_CMD:
1304 qla24xx_marker_iocb(sp, pkt);
1305 break;
1242 default: 1306 default:
1243 break; 1307 break;
1244 } 1308 }
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 166bb2045fd4..eed71ea1d947 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1161,6 +1161,99 @@ logio_done:
1161 lio->done(sp); 1161 lio->done(sp);
1162} 1162}
1163 1163
1164static void
1165qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
1166 struct tsk_mgmt_entry *tsk)
1167{
1168 const char func[] = "TMF-IOCB";
1169 const char *type;
1170 fc_port_t *fcport;
1171 srb_t *sp;
1172 struct srb_iocb *iocb;
1173 struct srb_ctx *ctx;
1174 struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
1175 int error = 1;
1176
1177 sp = qla2x00_get_sp_from_handle(vha, func, req, tsk);
1178 if (!sp)
1179 return;
1180
1181 ctx = sp->ctx;
1182 iocb = ctx->u.iocb_cmd;
1183 type = ctx->name;
1184 fcport = sp->fcport;
1185
1186 if (sts->entry_status) {
1187 DEBUG2(printk(KERN_WARNING
1188 "scsi(%ld:%x): Async-%s error - entry-status(%x).\n",
1189 fcport->vha->host_no, sp->handle, type,
1190 sts->entry_status));
1191 } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
1192 DEBUG2(printk(KERN_WARNING
1193 "scsi(%ld:%x): Async-%s error - completion status(%x).\n",
1194 fcport->vha->host_no, sp->handle, type,
1195 sts->comp_status));
1196 } else if (!(le16_to_cpu(sts->scsi_status) &
1197 SS_RESPONSE_INFO_LEN_VALID)) {
1198 DEBUG2(printk(KERN_WARNING
1199 "scsi(%ld:%x): Async-%s error - no response info(%x).\n",
1200 fcport->vha->host_no, sp->handle, type,
1201 sts->scsi_status));
1202 } else if (le32_to_cpu(sts->rsp_data_len) < 4) {
1203 DEBUG2(printk(KERN_WARNING
1204 "scsi(%ld:%x): Async-%s error - not enough response(%d).\n",
1205 fcport->vha->host_no, sp->handle, type,
1206 sts->rsp_data_len));
1207 } else if (sts->data[3]) {
1208 DEBUG2(printk(KERN_WARNING
1209 "scsi(%ld:%x): Async-%s error - response(%x).\n",
1210 fcport->vha->host_no, sp->handle, type,
1211 sts->data[3]));
1212 } else {
1213 error = 0;
1214 }
1215
1216 if (error) {
1217 iocb->u.tmf.data = error;
1218 DEBUG2(qla2x00_dump_buffer((uint8_t *)sts, sizeof(*sts)));
1219 }
1220
1221 iocb->done(sp);
1222}
1223
1224static void
1225qla24xx_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
1226 struct mrk_entry_24xx *mrk)
1227{
1228 const char func[] = "MRK-IOCB";
1229 const char *type;
1230 fc_port_t *fcport;
1231 srb_t *sp;
1232 struct srb_iocb *iocb;
1233 struct srb_ctx *ctx;
1234 struct sts_entry_24xx *sts = (struct sts_entry_24xx *)mrk;
1235
1236 sp = qla2x00_get_sp_from_handle(vha, func, req, mrk);
1237 if (!sp)
1238 return;
1239
1240 ctx = sp->ctx;
1241 iocb = ctx->u.iocb_cmd;
1242 type = ctx->name;
1243 fcport = sp->fcport;
1244
1245 if (sts->entry_status) {
1246 iocb->u.marker.data = 1;
1247 DEBUG2(printk(KERN_WARNING
1248 "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n",
1249 fcport->vha->host_no, sp->handle, type,
1250 sts->entry_status));
1251 DEBUG2(qla2x00_dump_buffer((uint8_t *)mrk, sizeof(*sts)));
1252 }
1253
1254 iocb->done(sp);
1255}
1256
1164/** 1257/**
1165 * qla2x00_process_response_queue() - Process response queue entries. 1258 * qla2x00_process_response_queue() - Process response queue entries.
1166 * @ha: SCSI driver HA context 1259 * @ha: SCSI driver HA context
@@ -1225,6 +1318,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
1225 case MBX_IOCB_TYPE: 1318 case MBX_IOCB_TYPE:
1226 qla2x00_mbx_iocb_entry(vha, rsp->req, 1319 qla2x00_mbx_iocb_entry(vha, rsp->req,
1227 (struct mbx_entry *)pkt); 1320 (struct mbx_entry *)pkt);
1321 break;
1228 default: 1322 default:
1229 /* Type Not Supported. */ 1323 /* Type Not Supported. */
1230 DEBUG4(printk(KERN_WARNING 1324 DEBUG4(printk(KERN_WARNING
@@ -1751,6 +1845,14 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
1751 qla24xx_logio_entry(vha, rsp->req, 1845 qla24xx_logio_entry(vha, rsp->req,
1752 (struct logio_entry_24xx *)pkt); 1846 (struct logio_entry_24xx *)pkt);
1753 break; 1847 break;
1848 case TSK_MGMT_IOCB_TYPE:
1849 qla24xx_tm_iocb_entry(vha, rsp->req,
1850 (struct tsk_mgmt_entry *)pkt);
1851 break;
1852 case MARKER_TYPE:
1853 qla24xx_marker_iocb_entry(vha, rsp->req,
1854 (struct mrk_entry_24xx *)pkt);
1855 break;
1754 case CT_IOCB_TYPE: 1856 case CT_IOCB_TYPE:
1755 qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); 1857 qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
1756 clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags); 1858 clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 2f3033228061..f3650d0434ca 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2464,12 +2464,22 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
2464int 2464int
2465qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag) 2465qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag)
2466{ 2466{
2467 struct qla_hw_data *ha = fcport->vha->hw;
2468
2469 if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
2470 return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
2471
2467 return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag); 2472 return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag);
2468} 2473}
2469 2474
2470int 2475int
2471qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag) 2476qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
2472{ 2477{
2478 struct qla_hw_data *ha = fcport->vha->hw;
2479
2480 if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
2481 return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
2482
2473 return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag); 2483 return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag);
2474} 2484}
2475 2485
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 70651f9fa653..523d414b59af 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -142,6 +142,11 @@ MODULE_PARM_DESC(ql2xdontresethba,
142 " 1 -- Do not reset on failure.\n"); 142 " 1 -- Do not reset on failure.\n");
143 143
144 144
145int ql2xasynctmfenable;
146module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR);
147MODULE_PARM_DESC(ql2xasynctmfenable,
148 "Enables issue of TM IOCBs asynchronously via IOCB mechanism"
149 "Default is 0 - Issue TM IOCBs via mailbox mechanism.");
145/* 150/*
146 * SCSI host template entry points 151 * SCSI host template entry points
147 */ 152 */