aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2010-05-04 18:01:26 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-16 18:21:47 -0400
commit5ff1d58410ffb160b388d622ef0c6a0411a05559 (patch)
treea8d95de2c47bf3b0beaae6730b61b3d84c2bde56 /drivers/scsi
parent99b0bec7bbf3350d1a920a7138fa62c456a8ecf1 (diff)
[SCSI] qla2xxx: Limit mailbox command contention for ADISC requests.
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h8
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c88
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c39
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c33
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c31
6 files changed, 178 insertions, 28 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index b3cf6099600..a491338e1bf 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -219,6 +219,7 @@ typedef struct srb {
219#define SRB_ELS_CMD_RPT 3 219#define SRB_ELS_CMD_RPT 3
220#define SRB_ELS_CMD_HST 4 220#define SRB_ELS_CMD_HST 4
221#define SRB_CT_CMD 5 221#define SRB_CT_CMD 5
222#define SRB_ADISC_CMD 6
222 223
223struct srb_ctx { 224struct srb_ctx {
224 uint16_t type; 225 uint16_t type;
@@ -1623,6 +1624,7 @@ typedef struct fc_port {
1623#define FCF_FABRIC_DEVICE BIT_0 1624#define FCF_FABRIC_DEVICE BIT_0
1624#define FCF_LOGIN_NEEDED BIT_1 1625#define FCF_LOGIN_NEEDED BIT_1
1625#define FCF_FCP2_DEVICE BIT_2 1626#define FCF_FCP2_DEVICE BIT_2
1627#define FCF_ASYNC_SENT BIT_3
1626 1628
1627/* No loop ID flag. */ 1629/* No loop ID flag. */
1628#define FC_NO_LOOP_ID 0x1000 1630#define FC_NO_LOOP_ID 0x1000
@@ -2156,6 +2158,8 @@ enum qla_work_type {
2156 QLA_EVT_ASYNC_LOGIN_DONE, 2158 QLA_EVT_ASYNC_LOGIN_DONE,
2157 QLA_EVT_ASYNC_LOGOUT, 2159 QLA_EVT_ASYNC_LOGOUT,
2158 QLA_EVT_ASYNC_LOGOUT_DONE, 2160 QLA_EVT_ASYNC_LOGOUT_DONE,
2161 QLA_EVT_ASYNC_ADISC,
2162 QLA_EVT_ASYNC_ADISC_DONE,
2159 QLA_EVT_UEVENT, 2163 QLA_EVT_UEVENT,
2160}; 2164};
2161 2165
@@ -2514,6 +2518,9 @@ struct qla_hw_data {
2514 dma_addr_t ex_init_cb_dma; 2518 dma_addr_t ex_init_cb_dma;
2515 struct ex_init_cb_81xx *ex_init_cb; 2519 struct ex_init_cb_81xx *ex_init_cb;
2516 2520
2521 void *async_pd;
2522 dma_addr_t async_pd_dma;
2523
2517 /* These are used by mailbox operations. */ 2524 /* These are used by mailbox operations. */
2518 volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; 2525 volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
2519 2526
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index cff5a4ae762..03be2984190 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -56,10 +56,14 @@ extern void qla84xx_put_chip(struct scsi_qla_host *);
56extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *, 56extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
57 uint16_t *); 57 uint16_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 *,
60 uint16_t *);
59extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, 61extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
60 uint16_t *); 62 uint16_t *);
61extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, 63extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
62 uint16_t *); 64 uint16_t *);
65extern int qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
66 uint16_t *);
63 67
64extern fc_port_t * 68extern fc_port_t *
65qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t ); 69qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t );
@@ -97,6 +101,10 @@ extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
97 uint16_t *); 101 uint16_t *);
98extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *, 102extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
99 fc_port_t *, uint16_t *); 103 fc_port_t *, uint16_t *);
104extern int qla2x00_post_async_adisc_work(struct scsi_qla_host *, fc_port_t *,
105 uint16_t *);
106extern int qla2x00_post_async_adisc_done_work(struct scsi_qla_host *,
107 fc_port_t *, uint16_t *);
100extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); 108extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
101 109
102extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); 110extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index c3c2c3627a7..4e7a3d5493e 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -119,6 +119,7 @@ qla2x00_async_logio_timeout(srb_t *sp)
119 "scsi(%ld:%x): Async-%s timeout.\n", 119 "scsi(%ld:%x): Async-%s timeout.\n",
120 fcport->vha->host_no, sp->handle, lio->ctx.name)); 120 fcport->vha->host_no, sp->handle, lio->ctx.name));
121 121
122 fcport->flags &= ~FCF_ASYNC_SENT;
122 if (lio->ctx.type == SRB_LOGIN_CMD) 123 if (lio->ctx.type == SRB_LOGIN_CMD)
123 qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); 124 qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
124} 125}
@@ -220,6 +221,56 @@ done:
220 return rval; 221 return rval;
221} 222}
222 223
224static void
225qla2x00_async_adisc_ctx_done(srb_t *sp)
226{
227 struct srb_logio *lio = sp->ctx;
228
229 qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
230 lio->data);
231 lio->ctx.free(sp);
232}
233
234int
235qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
236 uint16_t *data)
237{
238 struct qla_hw_data *ha = vha->hw;
239 srb_t *sp;
240 struct srb_logio *lio;
241 int rval;
242
243 rval = QLA_FUNCTION_FAILED;
244 sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio),
245 ELS_TMO_2_RATOV(ha) + 2);
246 if (!sp)
247 goto done;
248
249 lio = sp->ctx;
250 lio->ctx.type = SRB_ADISC_CMD;
251 lio->ctx.name = "adisc";
252 lio->ctx.timeout = qla2x00_async_logio_timeout;
253 lio->ctx.done = qla2x00_async_adisc_ctx_done;
254 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
255 lio->flags |= SRB_LOGIN_RETRIED;
256 rval = qla2x00_start_sp(sp);
257 if (rval != QLA_SUCCESS)
258 goto done_free_sp;
259
260 DEBUG2(printk(KERN_DEBUG
261 "scsi(%ld:%x): Async-adisc - loop-id=%x portid=%02x%02x%02x.\n",
262 fcport->vha->host_no, sp->handle, fcport->loop_id,
263 fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa));
264
265 return rval;
266
267done_free_sp:
268 del_timer_sync(&lio->ctx.timer);
269 lio->ctx.free(sp);
270done:
271 return rval;
272}
273
223int 274int
224qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, 275qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
225 uint16_t *data) 276 uint16_t *data)
@@ -229,15 +280,14 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
229 switch (data[0]) { 280 switch (data[0]) {
230 case MBS_COMMAND_COMPLETE: 281 case MBS_COMMAND_COMPLETE:
231 if (fcport->flags & FCF_FCP2_DEVICE) { 282 if (fcport->flags & FCF_FCP2_DEVICE) {
232 rval = qla2x00_get_port_database(vha, fcport, BIT_1); 283 fcport->flags |= FCF_ASYNC_SENT;
233 if (rval != QLA_SUCCESS) { 284 qla2x00_post_async_adisc_work(vha, fcport, data);
234 qla2x00_mark_device_lost(vha, fcport, 1, 0); 285 break;
235 break;
236 }
237 } 286 }
238 qla2x00_update_fcport(vha, fcport); 287 qla2x00_update_fcport(vha, fcport);
239 break; 288 break;
240 case MBS_COMMAND_ERROR: 289 case MBS_COMMAND_ERROR:
290 fcport->flags &= ~FCF_ASYNC_SENT;
241 if (data[1] & QLA_LOGIO_LOGIN_RETRIED) 291 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
242 set_bit(RELOGIN_NEEDED, &vha->dpc_flags); 292 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
243 else 293 else
@@ -251,6 +301,7 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
251 fcport->loop_id++; 301 fcport->loop_id++;
252 rval = qla2x00_find_new_loop_id(vha, fcport); 302 rval = qla2x00_find_new_loop_id(vha, fcport);
253 if (rval != QLA_SUCCESS) { 303 if (rval != QLA_SUCCESS) {
304 fcport->flags &= ~FCF_ASYNC_SENT;
254 qla2x00_mark_device_lost(vha, fcport, 1, 0); 305 qla2x00_mark_device_lost(vha, fcport, 1, 0);
255 break; 306 break;
256 } 307 }
@@ -268,6 +319,26 @@ qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
268 return QLA_SUCCESS; 319 return QLA_SUCCESS;
269} 320}
270 321
322int
323qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
324 uint16_t *data)
325{
326 if (data[0] == MBS_COMMAND_COMPLETE) {
327 qla2x00_update_fcport(vha, fcport);
328
329 return QLA_SUCCESS;
330 }
331
332 /* Retry login. */
333 fcport->flags &= ~FCF_ASYNC_SENT;
334 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
335 set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
336 else
337 qla2x00_mark_device_lost(vha, fcport, 1, 0);
338
339 return QLA_SUCCESS;
340}
341
271/****************************************************************************/ 342/****************************************************************************/
272/* QLogic ISP2x00 Hardware Support Functions. */ 343/* QLogic ISP2x00 Hardware Support Functions. */
273/****************************************************************************/ 344/****************************************************************************/
@@ -2062,6 +2133,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
2062 if (IS_QLA23XX(ha)) { 2133 if (IS_QLA23XX(ha)) {
2063 nv->firmware_options[0] |= BIT_2; 2134 nv->firmware_options[0] |= BIT_2;
2064 nv->firmware_options[0] &= ~BIT_3; 2135 nv->firmware_options[0] &= ~BIT_3;
2136 nv->firmware_options[0] &= ~BIT_6;
2065 nv->add_firmware_options[1] |= BIT_5 | BIT_4; 2137 nv->add_firmware_options[1] |= BIT_5 | BIT_4;
2066 2138
2067 if (IS_QLA2300(ha)) { 2139 if (IS_QLA2300(ha)) {
@@ -2680,7 +2752,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
2680 PORT_RETRY_TIME; 2752 PORT_RETRY_TIME;
2681 atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * 2753 atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
2682 PORT_RETRY_TIME); 2754 PORT_RETRY_TIME);
2683 fcport->flags &= ~FCF_LOGIN_NEEDED; 2755 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
2684 2756
2685 qla2x00_iidma_fcport(vha, fcport); 2757 qla2x00_iidma_fcport(vha, fcport);
2686 2758
@@ -3326,11 +3398,15 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport,
3326 retry = 0; 3398 retry = 0;
3327 3399
3328 if (IS_ALOGIO_CAPABLE(ha)) { 3400 if (IS_ALOGIO_CAPABLE(ha)) {
3401 if (fcport->flags & FCF_ASYNC_SENT)
3402 return rval;
3403 fcport->flags |= FCF_ASYNC_SENT;
3329 rval = qla2x00_post_async_login_work(vha, fcport, NULL); 3404 rval = qla2x00_post_async_login_work(vha, fcport, NULL);
3330 if (!rval) 3405 if (!rval)
3331 return rval; 3406 return rval;
3332 } 3407 }
3333 3408
3409 fcport->flags &= ~FCF_ASYNC_SENT;
3334 rval = qla2x00_fabric_login(vha, fcport, next_loopid); 3410 rval = qla2x00_fabric_login(vha, fcport, next_loopid);
3335 if (rval == QLA_SUCCESS) { 3411 if (rval == QLA_SUCCESS) {
3336 /* Send an ADISC to FCP2 devices.*/ 3412 /* Send an ADISC to FCP2 devices.*/
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index d792ae32ed6..8112e41065f 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1054,6 +1054,36 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx)
1054} 1054}
1055 1055
1056static void 1056static void
1057qla24xx_adisc_iocb(srb_t *sp, struct logio_entry_24xx *logio)
1058{
1059 logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
1060 logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC);
1061 logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
1062 logio->vp_index = sp->fcport->vp_idx;
1063}
1064
1065static void
1066qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
1067{
1068 struct qla_hw_data *ha = sp->fcport->vha->hw;
1069
1070 mbx->entry_type = MBX_IOCB_TYPE;
1071 SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
1072 mbx->mb0 = cpu_to_le16(MBC_GET_PORT_DATABASE);
1073 if (HAS_EXTENDED_IDS(ha)) {
1074 mbx->mb1 = cpu_to_le16(sp->fcport->loop_id);
1075 mbx->mb10 = cpu_to_le16(BIT_0);
1076 } else {
1077 mbx->mb1 = cpu_to_le16((sp->fcport->loop_id << 8) | BIT_0);
1078 }
1079 mbx->mb2 = cpu_to_le16(MSW(ha->async_pd_dma));
1080 mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma));
1081 mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma)));
1082 mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma)));
1083 mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx);
1084}
1085
1086static void
1057qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) 1087qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
1058{ 1088{
1059 struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job; 1089 struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job;
@@ -1185,12 +1215,12 @@ qla2x00_start_sp(srb_t *sp)
1185 switch (ctx->type) { 1215 switch (ctx->type) {
1186 case SRB_LOGIN_CMD: 1216 case SRB_LOGIN_CMD:
1187 IS_FWI2_CAPABLE(ha) ? 1217 IS_FWI2_CAPABLE(ha) ?
1188 qla24xx_login_iocb(sp, pkt): 1218 qla24xx_login_iocb(sp, pkt) :
1189 qla2x00_login_iocb(sp, pkt); 1219 qla2x00_login_iocb(sp, pkt);
1190 break; 1220 break;
1191 case SRB_LOGOUT_CMD: 1221 case SRB_LOGOUT_CMD:
1192 IS_FWI2_CAPABLE(ha) ? 1222 IS_FWI2_CAPABLE(ha) ?
1193 qla24xx_logout_iocb(sp, pkt): 1223 qla24xx_logout_iocb(sp, pkt) :
1194 qla2x00_logout_iocb(sp, pkt); 1224 qla2x00_logout_iocb(sp, pkt);
1195 break; 1225 break;
1196 case SRB_ELS_CMD_RPT: 1226 case SRB_ELS_CMD_RPT:
@@ -1200,6 +1230,11 @@ qla2x00_start_sp(srb_t *sp)
1200 case SRB_CT_CMD: 1230 case SRB_CT_CMD:
1201 qla24xx_ct_iocb(sp, pkt); 1231 qla24xx_ct_iocb(sp, pkt);
1202 break; 1232 break;
1233 case SRB_ADISC_CMD:
1234 IS_FWI2_CAPABLE(ha) ?
1235 qla24xx_adisc_iocb(sp, pkt) :
1236 qla2x00_adisc_iocb(sp, pkt);
1237 break;
1203 default: 1238 default:
1204 break; 1239 break;
1205 } 1240 }
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 037bc41eef5..a1968eb5e9c 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -899,6 +899,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
899 srb_t *sp; 899 srb_t *sp;
900 struct srb_logio *lio; 900 struct srb_logio *lio;
901 uint16_t *data; 901 uint16_t *data;
902 uint16_t status;
902 903
903 sp = qla2x00_get_sp_from_handle(vha, func, req, mbx); 904 sp = qla2x00_get_sp_from_handle(vha, func, req, mbx);
904 if (!sp) 905 if (!sp)
@@ -910,7 +911,9 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
910 fcport = sp->fcport; 911 fcport = sp->fcport;
911 data = lio->data; 912 data = lio->data;
912 913
913 data[0] = data[1] = 0; 914 data[0] = MBS_COMMAND_ERROR;
915 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
916 QLA_LOGIO_LOGIN_RETRIED : 0;
914 if (mbx->entry_status) { 917 if (mbx->entry_status) {
915 DEBUG2(printk(KERN_WARNING 918 DEBUG2(printk(KERN_WARNING
916 "scsi(%ld:%x): Async-%s error entry - entry-status=%x " 919 "scsi(%ld:%x): Async-%s error entry - entry-status=%x "
@@ -921,26 +924,27 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
921 le16_to_cpu(mbx->status_flags))); 924 le16_to_cpu(mbx->status_flags)));
922 DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx))); 925 DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx)));
923 926
924 data[0] = MBS_COMMAND_ERROR;
925 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
926 QLA_LOGIO_LOGIN_RETRIED: 0;
927 goto logio_done; 927 goto logio_done;
928 } 928 }
929 929
930 if (!mbx->status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) { 930 status = le16_to_cpu(mbx->status);
931 if (status == 0x30 && lio->ctx.type == SRB_LOGIN_CMD &&
932 le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE)
933 status = 0;
934 if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) {
931 DEBUG2(printk(KERN_DEBUG 935 DEBUG2(printk(KERN_DEBUG
932 "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n", 936 "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n",
933 fcport->vha->host_no, sp->handle, type, 937 fcport->vha->host_no, sp->handle, type,
934 le16_to_cpu(mbx->mb1))); 938 le16_to_cpu(mbx->mb1)));
935 939
936 data[0] = MBS_COMMAND_COMPLETE; 940 data[0] = MBS_COMMAND_COMPLETE;
937 if (lio->ctx.type == SRB_LOGIN_CMD) 941 if (lio->ctx.type == SRB_LOGIN_CMD) {
938 fcport->port_type = FCT_TARGET; 942 fcport->port_type = FCT_TARGET;
939 if (le16_to_cpu(mbx->mb1) & BIT_0) 943 if (le16_to_cpu(mbx->mb1) & BIT_0)
940 fcport->port_type = FCT_INITIATOR; 944 fcport->port_type = FCT_INITIATOR;
941 if (le16_to_cpu(mbx->mb1) & BIT_1) 945 if (le16_to_cpu(mbx->mb1) & BIT_1)
942 fcport->flags |= FCF_FCP2_DEVICE; 946 fcport->flags |= FCF_FCP2_DEVICE;
943 947 }
944 goto logio_done; 948 goto logio_done;
945 } 949 }
946 950
@@ -953,15 +957,13 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
953 break; 957 break;
954 default: 958 default:
955 data[0] = MBS_COMMAND_ERROR; 959 data[0] = MBS_COMMAND_ERROR;
956 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
957 QLA_LOGIO_LOGIN_RETRIED: 0;
958 break; 960 break;
959 } 961 }
960 962
961 DEBUG2(printk(KERN_WARNING 963 DEBUG2(printk(KERN_WARNING
962 "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x " 964 "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x "
963 "mb6=%x mb7=%x.\n", 965 "mb6=%x mb7=%x.\n",
964 fcport->vha->host_no, sp->handle, type, le16_to_cpu(mbx->status), 966 fcport->vha->host_no, sp->handle, type, status,
965 le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1), 967 le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1),
966 le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6), 968 le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6),
967 le16_to_cpu(mbx->mb7))); 969 le16_to_cpu(mbx->mb7)));
@@ -1086,7 +1088,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
1086 fcport = sp->fcport; 1088 fcport = sp->fcport;
1087 data = lio->data; 1089 data = lio->data;
1088 1090
1089 data[0] = data[1] = 0; 1091 data[0] = MBS_COMMAND_ERROR;
1092 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
1093 QLA_LOGIO_LOGIN_RETRIED : 0;
1090 if (logio->entry_status) { 1094 if (logio->entry_status) {
1091 DEBUG2(printk(KERN_WARNING 1095 DEBUG2(printk(KERN_WARNING
1092 "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n", 1096 "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n",
@@ -1094,9 +1098,6 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
1094 logio->entry_status)); 1098 logio->entry_status));
1095 DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio))); 1099 DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio)));
1096 1100
1097 data[0] = MBS_COMMAND_ERROR;
1098 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
1099 QLA_LOGIO_LOGIN_RETRIED: 0;
1100 goto logio_done; 1101 goto logio_done;
1101 } 1102 }
1102 1103
@@ -1107,7 +1108,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
1107 le32_to_cpu(logio->io_parameter[0]))); 1108 le32_to_cpu(logio->io_parameter[0])));
1108 1109
1109 data[0] = MBS_COMMAND_COMPLETE; 1110 data[0] = MBS_COMMAND_COMPLETE;
1110 if (lio->ctx.type == SRB_LOGOUT_CMD) 1111 if (lio->ctx.type != SRB_LOGIN_CMD)
1111 goto logio_done; 1112 goto logio_done;
1112 1113
1113 iop[0] = le32_to_cpu(logio->io_parameter[0]); 1114 iop[0] = le32_to_cpu(logio->io_parameter[0]);
@@ -1144,8 +1145,6 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
1144 /* Fall through. */ 1145 /* Fall through. */
1145 default: 1146 default:
1146 data[0] = MBS_COMMAND_ERROR; 1147 data[0] = MBS_COMMAND_ERROR;
1147 data[1] = lio->flags & SRB_LOGIN_RETRIED ?
1148 QLA_LOGIO_LOGIN_RETRIED: 0;
1149 break; 1148 break;
1150 } 1149 }
1151 1150
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 10c14af2235..2e083c0d921 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2639,9 +2639,19 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
2639 2639
2640 INIT_LIST_HEAD(&ha->gbl_dsd_list); 2640 INIT_LIST_HEAD(&ha->gbl_dsd_list);
2641 2641
2642 /* Get consistent memory allocated for Async Port-Database. */
2643 if (!IS_FWI2_CAPABLE(ha)) {
2644 ha->async_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
2645 &ha->async_pd_dma);
2646 if (!ha->async_pd)
2647 goto fail_async_pd;
2648 }
2649
2642 INIT_LIST_HEAD(&ha->vp_list); 2650 INIT_LIST_HEAD(&ha->vp_list);
2643 return 1; 2651 return 1;
2644 2652
2653fail_async_pd:
2654 dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
2645fail_ex_init_cb: 2655fail_ex_init_cb:
2646 kfree(ha->npiv_info); 2656 kfree(ha->npiv_info);
2647fail_npiv_info: 2657fail_npiv_info:
@@ -2757,6 +2767,9 @@ qla2x00_mem_free(struct qla_hw_data *ha)
2757 dma_pool_free(ha->s_dma_pool, 2767 dma_pool_free(ha->s_dma_pool,
2758 ha->ex_init_cb, ha->ex_init_cb_dma); 2768 ha->ex_init_cb, ha->ex_init_cb_dma);
2759 2769
2770 if (ha->async_pd)
2771 dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
2772
2760 if (ha->s_dma_pool) 2773 if (ha->s_dma_pool)
2761 dma_pool_destroy(ha->s_dma_pool); 2774 dma_pool_destroy(ha->s_dma_pool);
2762 2775
@@ -2809,6 +2822,8 @@ qla2x00_mem_free(struct qla_hw_data *ha)
2809 ha->init_cb_dma = 0; 2822 ha->init_cb_dma = 0;
2810 ha->ex_init_cb = NULL; 2823 ha->ex_init_cb = NULL;
2811 ha->ex_init_cb_dma = 0; 2824 ha->ex_init_cb_dma = 0;
2825 ha->async_pd = NULL;
2826 ha->async_pd_dma = 0;
2812 2827
2813 ha->s_dma_pool = NULL; 2828 ha->s_dma_pool = NULL;
2814 ha->dl_dma_pool = NULL; 2829 ha->dl_dma_pool = NULL;
@@ -2935,6 +2950,8 @@ qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN);
2935qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE); 2950qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE);
2936qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); 2951qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
2937qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); 2952qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
2953qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
2954qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE);
2938 2955
2939int 2956int
2940qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code) 2957qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code)
@@ -3004,6 +3021,14 @@ qla2x00_do_work(struct scsi_qla_host *vha)
3004 qla2x00_async_logout_done(vha, e->u.logio.fcport, 3021 qla2x00_async_logout_done(vha, e->u.logio.fcport,
3005 e->u.logio.data); 3022 e->u.logio.data);
3006 break; 3023 break;
3024 case QLA_EVT_ASYNC_ADISC:
3025 qla2x00_async_adisc(vha, e->u.logio.fcport,
3026 e->u.logio.data);
3027 break;
3028 case QLA_EVT_ASYNC_ADISC_DONE:
3029 qla2x00_async_adisc_done(vha, e->u.logio.fcport,
3030 e->u.logio.data);
3031 break;
3007 case QLA_EVT_UEVENT: 3032 case QLA_EVT_UEVENT:
3008 qla2x00_uevent_emit(vha, e->u.uevent.code); 3033 qla2x00_uevent_emit(vha, e->u.uevent.code);
3009 break; 3034 break;
@@ -3029,9 +3054,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
3029 * If the port is not ONLINE then try to login 3054 * If the port is not ONLINE then try to login
3030 * to it if we haven't run out of retries. 3055 * to it if we haven't run out of retries.
3031 */ 3056 */
3032 if (atomic_read(&fcport->state) != 3057 if (atomic_read(&fcport->state) != FCS_ONLINE &&
3033 FCS_ONLINE && fcport->login_retry) { 3058 fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
3034
3035 fcport->login_retry--; 3059 fcport->login_retry--;
3036 if (fcport->flags & FCF_FABRIC_DEVICE) { 3060 if (fcport->flags & FCF_FABRIC_DEVICE) {
3037 if (fcport->flags & FCF_FCP2_DEVICE) 3061 if (fcport->flags & FCF_FCP2_DEVICE)
@@ -3042,6 +3066,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
3042 fcport->d_id.b.al_pa); 3066 fcport->d_id.b.al_pa);
3043 3067
3044 if (IS_ALOGIO_CAPABLE(ha)) { 3068 if (IS_ALOGIO_CAPABLE(ha)) {
3069 fcport->flags |= FCF_ASYNC_SENT;
3045 data[0] = 0; 3070 data[0] = 0;
3046 data[1] = QLA_LOGIO_LOGIN_RETRIED; 3071 data[1] = QLA_LOGIO_LOGIN_RETRIED;
3047 status = qla2x00_post_async_login_work( 3072 status = qla2x00_post_async_login_work(