diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2009-08-20 14:06:05 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-09-05 10:41:57 -0400 |
commit | ac280b670e6d6666667aba02324e2fc50bd96ae7 (patch) | |
tree | 4d0d9187b26513ef9f820ab140f29a4f49f678b8 /drivers/scsi | |
parent | cf53b069f52ae3f83dec1acd339e3c3a2e979478 (diff) |
[SCSI] qla2xxx: Add asynchronous-login support.
ISPs which support this feature include 23xx and above.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
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.h | 32 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 20 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 215 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 202 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 250 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 72 |
7 files changed, 784 insertions, 9 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 9eb7be684f0a..efdfb1eb26ba 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -207,6 +207,28 @@ typedef struct srb { | |||
207 | #define SRB_DMA_VALID BIT_0 /* Command sent to ISP */ | 207 | #define SRB_DMA_VALID BIT_0 /* Command sent to ISP */ |
208 | 208 | ||
209 | /* | 209 | /* |
210 | * SRB extensions. | ||
211 | */ | ||
212 | struct srb_ctx { | ||
213 | #define SRB_LOGIN_CMD 1 | ||
214 | #define SRB_LOGOUT_CMD 2 | ||
215 | uint16_t type; | ||
216 | struct timer_list timer; | ||
217 | |||
218 | void (*free)(srb_t *sp); | ||
219 | void (*timeout)(srb_t *sp); | ||
220 | }; | ||
221 | |||
222 | struct srb_logio { | ||
223 | struct srb_ctx ctx; | ||
224 | |||
225 | #define SRB_LOGIN_RETRIED BIT_0 | ||
226 | #define SRB_LOGIN_COND_PLOGI BIT_1 | ||
227 | #define SRB_LOGIN_SKIP_PRLI BIT_2 | ||
228 | uint16_t flags; | ||
229 | }; | ||
230 | |||
231 | /* | ||
210 | * ISP I/O Register Set structure definitions. | 232 | * ISP I/O Register Set structure definitions. |
211 | */ | 233 | */ |
212 | struct device_reg_2xxx { | 234 | struct device_reg_2xxx { |
@@ -2096,6 +2118,10 @@ struct qla_msix_entry { | |||
2096 | enum qla_work_type { | 2118 | enum qla_work_type { |
2097 | QLA_EVT_AEN, | 2119 | QLA_EVT_AEN, |
2098 | QLA_EVT_IDC_ACK, | 2120 | QLA_EVT_IDC_ACK, |
2121 | QLA_EVT_ASYNC_LOGIN, | ||
2122 | QLA_EVT_ASYNC_LOGIN_DONE, | ||
2123 | QLA_EVT_ASYNC_LOGOUT, | ||
2124 | QLA_EVT_ASYNC_LOGOUT_DONE, | ||
2099 | }; | 2125 | }; |
2100 | 2126 | ||
2101 | 2127 | ||
@@ -2114,6 +2140,11 @@ struct qla_work_evt { | |||
2114 | #define QLA_IDC_ACK_REGS 7 | 2140 | #define QLA_IDC_ACK_REGS 7 |
2115 | uint16_t mb[QLA_IDC_ACK_REGS]; | 2141 | uint16_t mb[QLA_IDC_ACK_REGS]; |
2116 | } idc_ack; | 2142 | } idc_ack; |
2143 | struct { | ||
2144 | struct fc_port *fcport; | ||
2145 | #define QLA_LOGIO_LOGIN_RETRIED BIT_0 | ||
2146 | u16 data[2]; | ||
2147 | } logio; | ||
2117 | } u; | 2148 | } u; |
2118 | }; | 2149 | }; |
2119 | 2150 | ||
@@ -2354,6 +2385,7 @@ struct qla_hw_data { | |||
2354 | (ha)->flags.msix_enabled) | 2385 | (ha)->flags.msix_enabled) |
2355 | #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha)) | 2386 | #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha)) |
2356 | #define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha)) | 2387 | #define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha)) |
2388 | #define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha)) | ||
2357 | 2389 | ||
2358 | #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) | 2390 | #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) |
2359 | #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) | 2391 | #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 65b12d82867c..f3d1d1afa95b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -52,6 +52,14 @@ extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *); | |||
52 | 52 | ||
53 | extern void qla84xx_put_chip(struct scsi_qla_host *); | 53 | extern void qla84xx_put_chip(struct scsi_qla_host *); |
54 | 54 | ||
55 | extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *, | ||
56 | uint16_t *); | ||
57 | extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); | ||
58 | extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, | ||
59 | uint16_t *); | ||
60 | extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, | ||
61 | uint16_t *); | ||
62 | |||
55 | /* | 63 | /* |
56 | * Global Data in qla_os.c source file. | 64 | * Global Data in qla_os.c source file. |
57 | */ | 65 | */ |
@@ -76,6 +84,15 @@ extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); | |||
76 | extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum | 84 | extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum |
77 | fc_host_event_code, u32); | 85 | fc_host_event_code, u32); |
78 | extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *); | 86 | extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *); |
87 | extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *, | ||
88 | uint16_t *); | ||
89 | extern int qla2x00_post_async_login_done_work(struct scsi_qla_host *, | ||
90 | fc_port_t *, uint16_t *); | ||
91 | extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *, | ||
92 | uint16_t *); | ||
93 | extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *, | ||
94 | fc_port_t *, uint16_t *); | ||
95 | |||
79 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); | 96 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); |
80 | 97 | ||
81 | extern void qla2x00_abort_fcport_cmds(fc_port_t *); | 98 | extern void qla2x00_abort_fcport_cmds(fc_port_t *); |
@@ -83,6 +100,8 @@ extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *, | |||
83 | struct qla_hw_data *); | 100 | struct qla_hw_data *); |
84 | extern void qla2x00_free_host(struct scsi_qla_host *); | 101 | extern void qla2x00_free_host(struct scsi_qla_host *); |
85 | extern void qla2x00_relogin(struct scsi_qla_host *); | 102 | extern void qla2x00_relogin(struct scsi_qla_host *); |
103 | extern void qla2x00_do_work(struct scsi_qla_host *); | ||
104 | |||
86 | /* | 105 | /* |
87 | * Global Functions in qla_mid.c source file. | 106 | * Global Functions in qla_mid.c source file. |
88 | */ | 107 | */ |
@@ -135,6 +154,7 @@ int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, | |||
135 | uint16_t, uint16_t, uint8_t); | 154 | uint16_t, uint16_t, uint8_t); |
136 | int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, | 155 | int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, |
137 | uint16_t, uint16_t, uint8_t); | 156 | uint16_t, uint16_t, uint8_t); |
157 | extern int qla2x00_start_sp(srb_t *); | ||
138 | 158 | ||
139 | /* | 159 | /* |
140 | * Global Function Prototypes in qla_mbx.c source file. | 160 | * Global Function Prototypes in qla_mbx.c source file. |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 0cbe39e92506..37c99a27874c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -40,6 +40,210 @@ static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *); | |||
40 | static int qla84xx_init_chip(scsi_qla_host_t *); | 40 | static int qla84xx_init_chip(scsi_qla_host_t *); |
41 | static int qla25xx_init_queues(struct qla_hw_data *); | 41 | static int qla25xx_init_queues(struct qla_hw_data *); |
42 | 42 | ||
43 | /* SRB Extensions ---------------------------------------------------------- */ | ||
44 | |||
45 | static void | ||
46 | qla2x00_ctx_sp_timeout(unsigned long __data) | ||
47 | { | ||
48 | srb_t *sp = (srb_t *)__data; | ||
49 | struct srb_ctx *ctx; | ||
50 | fc_port_t *fcport = sp->fcport; | ||
51 | struct qla_hw_data *ha = fcport->vha->hw; | ||
52 | struct req_que *req; | ||
53 | unsigned long flags; | ||
54 | |||
55 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
56 | req = ha->req_q_map[0]; | ||
57 | req->outstanding_cmds[sp->handle] = NULL; | ||
58 | ctx = sp->ctx; | ||
59 | ctx->timeout(sp); | ||
60 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
61 | |||
62 | ctx->free(sp); | ||
63 | } | ||
64 | |||
65 | static void | ||
66 | qla2x00_ctx_sp_free(srb_t *sp) | ||
67 | { | ||
68 | struct srb_ctx *ctx = sp->ctx; | ||
69 | |||
70 | kfree(ctx); | ||
71 | mempool_free(sp, sp->fcport->vha->hw->srb_mempool); | ||
72 | } | ||
73 | |||
74 | inline srb_t * | ||
75 | qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, | ||
76 | unsigned long tmo) | ||
77 | { | ||
78 | srb_t *sp; | ||
79 | struct qla_hw_data *ha = vha->hw; | ||
80 | struct srb_ctx *ctx; | ||
81 | |||
82 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | ||
83 | if (!sp) | ||
84 | goto done; | ||
85 | ctx = kzalloc(size, GFP_KERNEL); | ||
86 | if (!ctx) { | ||
87 | mempool_free(sp, ha->srb_mempool); | ||
88 | goto done; | ||
89 | } | ||
90 | |||
91 | memset(sp, 0, sizeof(*sp)); | ||
92 | sp->fcport = fcport; | ||
93 | sp->ctx = ctx; | ||
94 | ctx->free = qla2x00_ctx_sp_free; | ||
95 | |||
96 | init_timer(&ctx->timer); | ||
97 | if (!tmo) | ||
98 | goto done; | ||
99 | ctx->timer.expires = jiffies + tmo * HZ; | ||
100 | ctx->timer.data = (unsigned long)sp; | ||
101 | ctx->timer.function = qla2x00_ctx_sp_timeout; | ||
102 | add_timer(&ctx->timer); | ||
103 | done: | ||
104 | return sp; | ||
105 | } | ||
106 | |||
107 | /* Asynchronous Login/Logout Routines -------------------------------------- */ | ||
108 | |||
109 | #define ELS_TMO_2_RATOV(ha) ((ha)->r_a_tov / 10 * 2) | ||
110 | |||
111 | static void | ||
112 | qla2x00_async_logio_timeout(srb_t *sp) | ||
113 | { | ||
114 | fc_port_t *fcport = sp->fcport; | ||
115 | struct srb_logio *lio = sp->ctx; | ||
116 | |||
117 | DEBUG2(printk(KERN_WARNING | ||
118 | "scsi(%ld:%x): Async-%s timeout.\n", | ||
119 | fcport->vha->host_no, sp->handle, | ||
120 | lio->ctx.type == SRB_LOGIN_CMD ? "login": "logout")); | ||
121 | |||
122 | if (lio->ctx.type == SRB_LOGIN_CMD) | ||
123 | qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); | ||
124 | } | ||
125 | |||
126 | int | ||
127 | qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
128 | uint16_t *data) | ||
129 | { | ||
130 | struct qla_hw_data *ha = vha->hw; | ||
131 | srb_t *sp; | ||
132 | struct srb_logio *lio; | ||
133 | int rval; | ||
134 | |||
135 | rval = QLA_FUNCTION_FAILED; | ||
136 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio), | ||
137 | ELS_TMO_2_RATOV(ha) + 2); | ||
138 | if (!sp) | ||
139 | goto done; | ||
140 | |||
141 | lio = sp->ctx; | ||
142 | lio->ctx.type = SRB_LOGIN_CMD; | ||
143 | lio->ctx.timeout = qla2x00_async_logio_timeout; | ||
144 | lio->flags |= SRB_LOGIN_COND_PLOGI; | ||
145 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | ||
146 | lio->flags |= SRB_LOGIN_RETRIED; | ||
147 | rval = qla2x00_start_sp(sp); | ||
148 | if (rval != QLA_SUCCESS) | ||
149 | goto done_free_sp; | ||
150 | |||
151 | DEBUG2(printk(KERN_DEBUG | ||
152 | "scsi(%ld:%x): Async-login - loop-id=%x portid=%02x%02x%02x " | ||
153 | "retries=%d.\n", fcport->vha->host_no, sp->handle, fcport->loop_id, | ||
154 | fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, | ||
155 | fcport->login_retry)); | ||
156 | return rval; | ||
157 | |||
158 | done_free_sp: | ||
159 | del_timer_sync(&lio->ctx.timer); | ||
160 | lio->ctx.free(sp); | ||
161 | done: | ||
162 | return rval; | ||
163 | } | ||
164 | |||
165 | int | ||
166 | qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) | ||
167 | { | ||
168 | struct qla_hw_data *ha = vha->hw; | ||
169 | srb_t *sp; | ||
170 | struct srb_logio *lio; | ||
171 | int rval; | ||
172 | |||
173 | rval = QLA_FUNCTION_FAILED; | ||
174 | sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio), | ||
175 | ELS_TMO_2_RATOV(ha) + 2); | ||
176 | if (!sp) | ||
177 | goto done; | ||
178 | |||
179 | lio = sp->ctx; | ||
180 | lio->ctx.type = SRB_LOGOUT_CMD; | ||
181 | lio->ctx.timeout = qla2x00_async_logio_timeout; | ||
182 | rval = qla2x00_start_sp(sp); | ||
183 | if (rval != QLA_SUCCESS) | ||
184 | goto done_free_sp; | ||
185 | |||
186 | DEBUG2(printk(KERN_DEBUG | ||
187 | "scsi(%ld:%x): Async-logout - loop-id=%x portid=%02x%02x%02x.\n", | ||
188 | fcport->vha->host_no, sp->handle, fcport->loop_id, | ||
189 | fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa)); | ||
190 | return rval; | ||
191 | |||
192 | done_free_sp: | ||
193 | del_timer_sync(&lio->ctx.timer); | ||
194 | lio->ctx.free(sp); | ||
195 | done: | ||
196 | return rval; | ||
197 | } | ||
198 | |||
199 | int | ||
200 | qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
201 | uint16_t *data) | ||
202 | { | ||
203 | int rval; | ||
204 | uint8_t opts = 0; | ||
205 | |||
206 | switch (data[0]) { | ||
207 | case MBS_COMMAND_COMPLETE: | ||
208 | if (fcport->flags & FCF_TAPE_PRESENT) | ||
209 | opts |= BIT_1; | ||
210 | rval = qla2x00_get_port_database(vha, fcport, opts); | ||
211 | if (rval != QLA_SUCCESS) | ||
212 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
213 | else | ||
214 | qla2x00_update_fcport(vha, fcport); | ||
215 | break; | ||
216 | case MBS_COMMAND_ERROR: | ||
217 | if (data[1] & QLA_LOGIO_LOGIN_RETRIED) | ||
218 | set_bit(RELOGIN_NEEDED, &vha->dpc_flags); | ||
219 | else | ||
220 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
221 | break; | ||
222 | case MBS_PORT_ID_USED: | ||
223 | fcport->loop_id = data[1]; | ||
224 | qla2x00_post_async_login_work(vha, fcport, NULL); | ||
225 | break; | ||
226 | case MBS_LOOP_ID_USED: | ||
227 | fcport->loop_id++; | ||
228 | rval = qla2x00_find_new_loop_id(vha, fcport); | ||
229 | if (rval != QLA_SUCCESS) { | ||
230 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
231 | break; | ||
232 | } | ||
233 | qla2x00_post_async_login_work(vha, fcport, NULL); | ||
234 | break; | ||
235 | } | ||
236 | return QLA_SUCCESS; | ||
237 | } | ||
238 | |||
239 | int | ||
240 | qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, | ||
241 | uint16_t *data) | ||
242 | { | ||
243 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
244 | return QLA_SUCCESS; | ||
245 | } | ||
246 | |||
43 | /****************************************************************************/ | 247 | /****************************************************************************/ |
44 | /* QLogic ISP2x00 Hardware Support Functions. */ | 248 | /* QLogic ISP2x00 Hardware Support Functions. */ |
45 | /****************************************************************************/ | 249 | /****************************************************************************/ |
@@ -1977,7 +2181,7 @@ qla2x00_rport_del(void *data) | |||
1977 | struct fc_rport *rport; | 2181 | struct fc_rport *rport; |
1978 | 2182 | ||
1979 | spin_lock_irq(fcport->vha->host->host_lock); | 2183 | spin_lock_irq(fcport->vha->host->host_lock); |
1980 | rport = fcport->drport; | 2184 | rport = fcport->drport ? fcport->drport: fcport->rport; |
1981 | fcport->drport = NULL; | 2185 | fcport->drport = NULL; |
1982 | spin_unlock_irq(fcport->vha->host->host_lock); | 2186 | spin_unlock_irq(fcport->vha->host->host_lock); |
1983 | if (rport) | 2187 | if (rport) |
@@ -2344,8 +2548,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) | |||
2344 | struct fc_rport *rport; | 2548 | struct fc_rport *rport; |
2345 | struct qla_hw_data *ha = vha->hw; | 2549 | struct qla_hw_data *ha = vha->hw; |
2346 | 2550 | ||
2347 | if (fcport->drport) | 2551 | qla2x00_rport_del(fcport); |
2348 | qla2x00_rport_del(fcport); | ||
2349 | 2552 | ||
2350 | rport_ids.node_name = wwn_to_u64(fcport->node_name); | 2553 | rport_ids.node_name = wwn_to_u64(fcport->node_name); |
2351 | rport_ids.port_name = wwn_to_u64(fcport->port_name); | 2554 | rport_ids.port_name = wwn_to_u64(fcport->port_name); |
@@ -3038,6 +3241,12 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
3038 | rval = QLA_SUCCESS; | 3241 | rval = QLA_SUCCESS; |
3039 | retry = 0; | 3242 | retry = 0; |
3040 | 3243 | ||
3244 | if (IS_ALOGIO_CAPABLE(ha)) { | ||
3245 | rval = qla2x00_post_async_login_work(vha, fcport, NULL); | ||
3246 | if (!rval) | ||
3247 | return rval; | ||
3248 | } | ||
3249 | |||
3041 | rval = qla2x00_fabric_login(vha, fcport, next_loopid); | 3250 | rval = qla2x00_fabric_login(vha, fcport, next_loopid); |
3042 | if (rval == QLA_SUCCESS) { | 3251 | if (rval == QLA_SUCCESS) { |
3043 | /* Send an ADISC to tape devices.*/ | 3252 | /* Send an ADISC to tape devices.*/ |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d37554ecd313..c5ccac0bef76 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -860,3 +860,205 @@ static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) | |||
860 | else | 860 | else |
861 | *rsp = ha->rsp_q_map[0]; | 861 | *rsp = ha->rsp_q_map[0]; |
862 | } | 862 | } |
863 | |||
864 | /* Generic Control-SRB manipulation functions. */ | ||
865 | |||
866 | static void * | ||
867 | qla2x00_alloc_iocbs(srb_t *sp) | ||
868 | { | ||
869 | scsi_qla_host_t *vha = sp->fcport->vha; | ||
870 | struct qla_hw_data *ha = vha->hw; | ||
871 | struct req_que *req = ha->req_q_map[0]; | ||
872 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); | ||
873 | uint32_t index, handle; | ||
874 | request_t *pkt; | ||
875 | uint16_t cnt, req_cnt; | ||
876 | |||
877 | pkt = NULL; | ||
878 | req_cnt = 1; | ||
879 | |||
880 | /* Check for room in outstanding command list. */ | ||
881 | handle = req->current_outstanding_cmd; | ||
882 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { | ||
883 | handle++; | ||
884 | if (handle == MAX_OUTSTANDING_COMMANDS) | ||
885 | handle = 1; | ||
886 | if (!req->outstanding_cmds[handle]) | ||
887 | break; | ||
888 | } | ||
889 | if (index == MAX_OUTSTANDING_COMMANDS) | ||
890 | goto queuing_error; | ||
891 | |||
892 | /* Check for room on request queue. */ | ||
893 | if (req->cnt < req_cnt) { | ||
894 | if (ha->mqenable) | ||
895 | cnt = RD_REG_DWORD(®->isp25mq.req_q_out); | ||
896 | else if (IS_FWI2_CAPABLE(ha)) | ||
897 | cnt = RD_REG_DWORD(®->isp24.req_q_out); | ||
898 | else | ||
899 | cnt = qla2x00_debounce_register( | ||
900 | ISP_REQ_Q_OUT(ha, ®->isp)); | ||
901 | |||
902 | if (req->ring_index < cnt) | ||
903 | req->cnt = cnt - req->ring_index; | ||
904 | else | ||
905 | req->cnt = req->length - | ||
906 | (req->ring_index - cnt); | ||
907 | } | ||
908 | if (req->cnt < req_cnt) | ||
909 | goto queuing_error; | ||
910 | |||
911 | /* Prep packet */ | ||
912 | req->current_outstanding_cmd = handle; | ||
913 | req->outstanding_cmds[handle] = sp; | ||
914 | req->cnt -= req_cnt; | ||
915 | |||
916 | pkt = req->ring_ptr; | ||
917 | memset(pkt, 0, REQUEST_ENTRY_SIZE); | ||
918 | pkt->entry_count = req_cnt; | ||
919 | pkt->handle = handle; | ||
920 | sp->handle = handle; | ||
921 | |||
922 | queuing_error: | ||
923 | return pkt; | ||
924 | } | ||
925 | |||
926 | static void | ||
927 | qla2x00_start_iocbs(srb_t *sp) | ||
928 | { | ||
929 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
930 | struct req_que *req = ha->req_q_map[0]; | ||
931 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); | ||
932 | struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; | ||
933 | |||
934 | /* Adjust ring index. */ | ||
935 | req->ring_index++; | ||
936 | if (req->ring_index == req->length) { | ||
937 | req->ring_index = 0; | ||
938 | req->ring_ptr = req->ring; | ||
939 | } else | ||
940 | req->ring_ptr++; | ||
941 | |||
942 | /* Set chip new ring index. */ | ||
943 | if (ha->mqenable) { | ||
944 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); | ||
945 | RD_REG_DWORD(&ioreg->hccr); | ||
946 | } else if (IS_FWI2_CAPABLE(ha)) { | ||
947 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); | ||
948 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | ||
949 | } else { | ||
950 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), req->ring_index); | ||
951 | RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); | ||
952 | } | ||
953 | } | ||
954 | |||
955 | static void | ||
956 | qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) | ||
957 | { | ||
958 | struct srb_logio *lio = sp->ctx; | ||
959 | |||
960 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
961 | logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); | ||
962 | if (lio->flags & SRB_LOGIN_COND_PLOGI) | ||
963 | logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI); | ||
964 | if (lio->flags & SRB_LOGIN_SKIP_PRLI) | ||
965 | logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); | ||
966 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
967 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
968 | logio->port_id[1] = sp->fcport->d_id.b.area; | ||
969 | logio->port_id[2] = sp->fcport->d_id.b.domain; | ||
970 | logio->vp_index = sp->fcport->vp_idx; | ||
971 | } | ||
972 | |||
973 | static void | ||
974 | qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) | ||
975 | { | ||
976 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
977 | struct srb_logio *lio = sp->ctx; | ||
978 | uint16_t opts; | ||
979 | |||
980 | mbx->entry_type = MBX_IOCB_TYPE;; | ||
981 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | ||
982 | mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT); | ||
983 | opts = lio->flags & SRB_LOGIN_COND_PLOGI ? BIT_0: 0; | ||
984 | opts |= lio->flags & SRB_LOGIN_SKIP_PRLI ? BIT_1: 0; | ||
985 | if (HAS_EXTENDED_IDS(ha)) { | ||
986 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); | ||
987 | mbx->mb10 = cpu_to_le16(opts); | ||
988 | } else { | ||
989 | mbx->mb1 = cpu_to_le16((sp->fcport->loop_id << 8) | opts); | ||
990 | } | ||
991 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); | ||
992 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | | ||
993 | sp->fcport->d_id.b.al_pa); | ||
994 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | ||
995 | } | ||
996 | |||
997 | static void | ||
998 | qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio) | ||
999 | { | ||
1000 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
1001 | logio->control_flags = | ||
1002 | cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); | ||
1003 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1004 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
1005 | logio->port_id[1] = sp->fcport->d_id.b.area; | ||
1006 | logio->port_id[2] = sp->fcport->d_id.b.domain; | ||
1007 | logio->vp_index = sp->fcport->vp_idx; | ||
1008 | } | ||
1009 | |||
1010 | static void | ||
1011 | qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) | ||
1012 | { | ||
1013 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
1014 | |||
1015 | mbx->entry_type = MBX_IOCB_TYPE;; | ||
1016 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | ||
1017 | mbx->mb0 = cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); | ||
1018 | mbx->mb1 = HAS_EXTENDED_IDS(ha) ? | ||
1019 | cpu_to_le16(sp->fcport->loop_id): | ||
1020 | cpu_to_le16(sp->fcport->loop_id << 8); | ||
1021 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); | ||
1022 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | | ||
1023 | sp->fcport->d_id.b.al_pa); | ||
1024 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | ||
1025 | /* Implicit: mbx->mbx10 = 0. */ | ||
1026 | } | ||
1027 | |||
1028 | int | ||
1029 | qla2x00_start_sp(srb_t *sp) | ||
1030 | { | ||
1031 | int rval; | ||
1032 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
1033 | void *pkt; | ||
1034 | struct srb_ctx *ctx = sp->ctx; | ||
1035 | unsigned long flags; | ||
1036 | |||
1037 | rval = QLA_FUNCTION_FAILED; | ||
1038 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1039 | pkt = qla2x00_alloc_iocbs(sp); | ||
1040 | if (!pkt) | ||
1041 | goto done; | ||
1042 | |||
1043 | rval = QLA_SUCCESS; | ||
1044 | switch (ctx->type) { | ||
1045 | case SRB_LOGIN_CMD: | ||
1046 | IS_FWI2_CAPABLE(ha) ? | ||
1047 | qla24xx_login_iocb(sp, pkt): | ||
1048 | qla2x00_login_iocb(sp, pkt); | ||
1049 | break; | ||
1050 | case SRB_LOGOUT_CMD: | ||
1051 | IS_FWI2_CAPABLE(ha) ? | ||
1052 | qla24xx_logout_iocb(sp, pkt): | ||
1053 | qla2x00_logout_iocb(sp, pkt); | ||
1054 | break; | ||
1055 | default: | ||
1056 | break; | ||
1057 | } | ||
1058 | |||
1059 | wmb(); | ||
1060 | qla2x00_start_iocbs(sp); | ||
1061 | done: | ||
1062 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1063 | return rval; | ||
1064 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 74fa6f992041..c0fec6914b96 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -919,6 +919,249 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, | |||
919 | } | 919 | } |
920 | } | 920 | } |
921 | 921 | ||
922 | static srb_t * | ||
923 | qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, | ||
924 | struct req_que *req, void *iocb) | ||
925 | { | ||
926 | struct qla_hw_data *ha = vha->hw; | ||
927 | sts_entry_t *pkt = iocb; | ||
928 | srb_t *sp = NULL; | ||
929 | uint16_t index; | ||
930 | |||
931 | index = LSW(pkt->handle); | ||
932 | if (index >= MAX_OUTSTANDING_COMMANDS) { | ||
933 | qla_printk(KERN_WARNING, ha, | ||
934 | "%s: Invalid completion handle (%x).\n", func, index); | ||
935 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
936 | goto done; | ||
937 | } | ||
938 | sp = req->outstanding_cmds[index]; | ||
939 | if (!sp) { | ||
940 | qla_printk(KERN_WARNING, ha, | ||
941 | "%s: Invalid completion handle (%x) -- timed-out.\n", func, | ||
942 | index); | ||
943 | return sp; | ||
944 | } | ||
945 | if (sp->handle != index) { | ||
946 | qla_printk(KERN_WARNING, ha, | ||
947 | "%s: SRB handle (%x) mismatch %x.\n", func, sp->handle, | ||
948 | index); | ||
949 | return NULL; | ||
950 | } | ||
951 | req->outstanding_cmds[index] = NULL; | ||
952 | done: | ||
953 | return sp; | ||
954 | } | ||
955 | |||
956 | static void | ||
957 | qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
958 | struct mbx_entry *mbx) | ||
959 | { | ||
960 | const char func[] = "MBX-IOCB"; | ||
961 | const char *type; | ||
962 | struct qla_hw_data *ha = vha->hw; | ||
963 | fc_port_t *fcport; | ||
964 | srb_t *sp; | ||
965 | struct srb_logio *lio; | ||
966 | uint16_t data[2]; | ||
967 | |||
968 | sp = qla2x00_get_sp_from_handle(vha, func, req, mbx); | ||
969 | if (!sp) | ||
970 | return; | ||
971 | |||
972 | type = NULL; | ||
973 | lio = sp->ctx; | ||
974 | switch (lio->ctx.type) { | ||
975 | case SRB_LOGIN_CMD: | ||
976 | type = "login"; | ||
977 | break; | ||
978 | case SRB_LOGOUT_CMD: | ||
979 | type = "logout"; | ||
980 | break; | ||
981 | default: | ||
982 | qla_printk(KERN_WARNING, ha, | ||
983 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
984 | lio->ctx.type); | ||
985 | return; | ||
986 | } | ||
987 | |||
988 | del_timer(&lio->ctx.timer); | ||
989 | fcport = sp->fcport; | ||
990 | |||
991 | data[0] = data[1] = 0; | ||
992 | if (mbx->entry_status) { | ||
993 | DEBUG2(printk(KERN_WARNING | ||
994 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x " | ||
995 | "status=%x state-flag=%x status-flags=%x.\n", | ||
996 | fcport->vha->host_no, sp->handle, type, | ||
997 | mbx->entry_status, le16_to_cpu(mbx->status), | ||
998 | le16_to_cpu(mbx->state_flags), | ||
999 | le16_to_cpu(mbx->status_flags))); | ||
1000 | DEBUG2(qla2x00_dump_buffer((uint8_t *)mbx, sizeof(*mbx))); | ||
1001 | |||
1002 | data[0] = MBS_COMMAND_ERROR; | ||
1003 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1004 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1005 | goto done_post_logio_done_work; | ||
1006 | } | ||
1007 | |||
1008 | if (!mbx->status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) { | ||
1009 | DEBUG2(printk(KERN_DEBUG | ||
1010 | "scsi(%ld:%x): Async-%s complete - mbx1=%x.\n", | ||
1011 | fcport->vha->host_no, sp->handle, type, | ||
1012 | le16_to_cpu(mbx->mb1))); | ||
1013 | |||
1014 | data[0] = MBS_COMMAND_COMPLETE; | ||
1015 | if (lio->ctx.type == SRB_LOGIN_CMD && le16_to_cpu(mbx->mb1) & BIT_1) | ||
1016 | fcport->flags |= FCF_TAPE_PRESENT; | ||
1017 | |||
1018 | goto done_post_logio_done_work; | ||
1019 | } | ||
1020 | |||
1021 | data[0] = le16_to_cpu(mbx->mb0); | ||
1022 | switch (data[0]) { | ||
1023 | case MBS_PORT_ID_USED: | ||
1024 | data[1] = le16_to_cpu(mbx->mb1); | ||
1025 | break; | ||
1026 | case MBS_LOOP_ID_USED: | ||
1027 | break; | ||
1028 | default: | ||
1029 | data[0] = MBS_COMMAND_ERROR; | ||
1030 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1031 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1032 | break; | ||
1033 | } | ||
1034 | |||
1035 | DEBUG2(printk(KERN_WARNING | ||
1036 | "scsi(%ld:%x): Async-%s failed - status=%x mb0=%x mb1=%x mb2=%x " | ||
1037 | "mb6=%x mb7=%x.\n", | ||
1038 | fcport->vha->host_no, sp->handle, type, le16_to_cpu(mbx->status), | ||
1039 | le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1), | ||
1040 | le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6), | ||
1041 | le16_to_cpu(mbx->mb7))); | ||
1042 | |||
1043 | done_post_logio_done_work: | ||
1044 | lio->ctx.type == SRB_LOGIN_CMD ? | ||
1045 | qla2x00_post_async_login_done_work(fcport->vha, fcport, data): | ||
1046 | qla2x00_post_async_logout_done_work(fcport->vha, fcport, data); | ||
1047 | |||
1048 | lio->ctx.free(sp); | ||
1049 | } | ||
1050 | |||
1051 | static void | ||
1052 | qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
1053 | struct logio_entry_24xx *logio) | ||
1054 | { | ||
1055 | const char func[] = "LOGIO-IOCB"; | ||
1056 | const char *type; | ||
1057 | struct qla_hw_data *ha = vha->hw; | ||
1058 | fc_port_t *fcport; | ||
1059 | srb_t *sp; | ||
1060 | struct srb_logio *lio; | ||
1061 | uint16_t data[2]; | ||
1062 | uint32_t iop[2]; | ||
1063 | |||
1064 | sp = qla2x00_get_sp_from_handle(vha, func, req, logio); | ||
1065 | if (!sp) | ||
1066 | return; | ||
1067 | |||
1068 | type = NULL; | ||
1069 | lio = sp->ctx; | ||
1070 | switch (lio->ctx.type) { | ||
1071 | case SRB_LOGIN_CMD: | ||
1072 | type = "login"; | ||
1073 | break; | ||
1074 | case SRB_LOGOUT_CMD: | ||
1075 | type = "logout"; | ||
1076 | break; | ||
1077 | default: | ||
1078 | qla_printk(KERN_WARNING, ha, | ||
1079 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
1080 | lio->ctx.type); | ||
1081 | return; | ||
1082 | } | ||
1083 | |||
1084 | del_timer(&lio->ctx.timer); | ||
1085 | fcport = sp->fcport; | ||
1086 | |||
1087 | data[0] = data[1] = 0; | ||
1088 | if (logio->entry_status) { | ||
1089 | DEBUG2(printk(KERN_WARNING | ||
1090 | "scsi(%ld:%x): Async-%s error entry - entry-status=%x.\n", | ||
1091 | fcport->vha->host_no, sp->handle, type, | ||
1092 | logio->entry_status)); | ||
1093 | DEBUG2(qla2x00_dump_buffer((uint8_t *)logio, sizeof(*logio))); | ||
1094 | |||
1095 | data[0] = MBS_COMMAND_ERROR; | ||
1096 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1097 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1098 | goto done_post_logio_done_work; | ||
1099 | } | ||
1100 | |||
1101 | if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { | ||
1102 | DEBUG2(printk(KERN_DEBUG | ||
1103 | "scsi(%ld:%x): Async-%s complete - iop0=%x.\n", | ||
1104 | fcport->vha->host_no, sp->handle, type, | ||
1105 | le32_to_cpu(logio->io_parameter[0]))); | ||
1106 | |||
1107 | data[0] = MBS_COMMAND_COMPLETE; | ||
1108 | if (lio->ctx.type == SRB_LOGOUT_CMD) | ||
1109 | goto done_post_logio_done_work; | ||
1110 | |||
1111 | iop[0] = le32_to_cpu(logio->io_parameter[0]); | ||
1112 | if (iop[0] & BIT_4) { | ||
1113 | fcport->port_type = FCT_TARGET; | ||
1114 | if (iop[0] & BIT_8) | ||
1115 | fcport->flags |= FCF_TAPE_PRESENT; | ||
1116 | } | ||
1117 | if (iop[0] & BIT_5) | ||
1118 | fcport->port_type = FCT_INITIATOR; | ||
1119 | if (logio->io_parameter[7] || logio->io_parameter[8]) | ||
1120 | fcport->supported_classes |= FC_COS_CLASS2; | ||
1121 | if (logio->io_parameter[9] || logio->io_parameter[10]) | ||
1122 | fcport->supported_classes |= FC_COS_CLASS3; | ||
1123 | |||
1124 | goto done_post_logio_done_work; | ||
1125 | } | ||
1126 | |||
1127 | iop[0] = le32_to_cpu(logio->io_parameter[0]); | ||
1128 | iop[1] = le32_to_cpu(logio->io_parameter[1]); | ||
1129 | switch (iop[0]) { | ||
1130 | case LSC_SCODE_PORTID_USED: | ||
1131 | data[0] = MBS_PORT_ID_USED; | ||
1132 | data[1] = LSW(iop[1]); | ||
1133 | break; | ||
1134 | case LSC_SCODE_NPORT_USED: | ||
1135 | data[0] = MBS_LOOP_ID_USED; | ||
1136 | break; | ||
1137 | case LSC_SCODE_CMD_FAILED: | ||
1138 | if ((iop[1] & 0xff) == 0x05) { | ||
1139 | data[0] = MBS_NOT_LOGGED_IN; | ||
1140 | break; | ||
1141 | } | ||
1142 | /* Fall through. */ | ||
1143 | default: | ||
1144 | data[0] = MBS_COMMAND_ERROR; | ||
1145 | data[1] = lio->flags & SRB_LOGIN_RETRIED ? | ||
1146 | QLA_LOGIO_LOGIN_RETRIED: 0; | ||
1147 | break; | ||
1148 | } | ||
1149 | |||
1150 | DEBUG2(printk(KERN_WARNING | ||
1151 | "scsi(%ld:%x): Async-%s failed - comp=%x iop0=%x iop1=%x.\n", | ||
1152 | fcport->vha->host_no, sp->handle, type, | ||
1153 | le16_to_cpu(logio->comp_status), | ||
1154 | le32_to_cpu(logio->io_parameter[0]), | ||
1155 | le32_to_cpu(logio->io_parameter[1]))); | ||
1156 | |||
1157 | done_post_logio_done_work: | ||
1158 | lio->ctx.type == SRB_LOGIN_CMD ? | ||
1159 | qla2x00_post_async_login_done_work(fcport->vha, fcport, data): | ||
1160 | qla2x00_post_async_logout_done_work(fcport->vha, fcport, data); | ||
1161 | |||
1162 | lio->ctx.free(sp); | ||
1163 | } | ||
1164 | |||
922 | /** | 1165 | /** |
923 | * qla2x00_process_response_queue() - Process response queue entries. | 1166 | * qla2x00_process_response_queue() - Process response queue entries. |
924 | * @ha: SCSI driver HA context | 1167 | * @ha: SCSI driver HA context |
@@ -980,6 +1223,9 @@ qla2x00_process_response_queue(struct rsp_que *rsp) | |||
980 | case STATUS_CONT_TYPE: | 1223 | case STATUS_CONT_TYPE: |
981 | qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); | 1224 | qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); |
982 | break; | 1225 | break; |
1226 | case MBX_IOCB_TYPE: | ||
1227 | qla2x00_mbx_iocb_entry(vha, rsp->req, | ||
1228 | (struct mbx_entry *)pkt); | ||
983 | default: | 1229 | default: |
984 | /* Type Not Supported. */ | 1230 | /* Type Not Supported. */ |
985 | DEBUG4(printk(KERN_WARNING | 1231 | DEBUG4(printk(KERN_WARNING |
@@ -1590,6 +1836,10 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1590 | qla24xx_report_id_acquisition(vha, | 1836 | qla24xx_report_id_acquisition(vha, |
1591 | (struct vp_rpt_id_entry_24xx *)pkt); | 1837 | (struct vp_rpt_id_entry_24xx *)pkt); |
1592 | break; | 1838 | break; |
1839 | case LOGINOUT_PORT_IOCB_TYPE: | ||
1840 | qla24xx_logio_entry(vha, rsp->req, | ||
1841 | (struct logio_entry_24xx *)pkt); | ||
1842 | break; | ||
1593 | default: | 1843 | default: |
1594 | /* Type Not Supported. */ | 1844 | /* Type Not Supported. */ |
1595 | DEBUG4(printk(KERN_WARNING | 1845 | DEBUG4(printk(KERN_WARNING |
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 6238be37d7bb..a748a95efb10 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -253,6 +253,8 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) | |||
253 | if (!(ha->current_topology & ISP_CFG_F)) | 253 | if (!(ha->current_topology & ISP_CFG_F)) |
254 | return 0; | 254 | return 0; |
255 | 255 | ||
256 | qla2x00_do_work(vha); | ||
257 | |||
256 | if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { | 258 | if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { |
257 | /* VP acquired. complete port configuration */ | 259 | /* VP acquired. complete port configuration */ |
258 | if (atomic_read(&base_vha->loop_state) == LOOP_READY) { | 260 | if (atomic_read(&base_vha->loop_state) == LOOP_READY) { |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b6c088caf35e..5fd7adbff30b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1170,6 +1170,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1170 | int que, cnt; | 1170 | int que, cnt; |
1171 | unsigned long flags; | 1171 | unsigned long flags; |
1172 | srb_t *sp; | 1172 | srb_t *sp; |
1173 | struct srb_ctx *ctx; | ||
1173 | struct qla_hw_data *ha = vha->hw; | 1174 | struct qla_hw_data *ha = vha->hw; |
1174 | struct req_que *req; | 1175 | struct req_que *req; |
1175 | 1176 | ||
@@ -1182,8 +1183,14 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1182 | sp = req->outstanding_cmds[cnt]; | 1183 | sp = req->outstanding_cmds[cnt]; |
1183 | if (sp) { | 1184 | if (sp) { |
1184 | req->outstanding_cmds[cnt] = NULL; | 1185 | req->outstanding_cmds[cnt] = NULL; |
1185 | sp->cmd->result = res; | 1186 | if (!sp->ctx) { |
1186 | qla2x00_sp_compl(ha, sp); | 1187 | sp->cmd->result = res; |
1188 | qla2x00_sp_compl(ha, sp); | ||
1189 | } else { | ||
1190 | ctx = sp->ctx; | ||
1191 | del_timer_sync(&ctx->timer); | ||
1192 | ctx->free(sp); | ||
1193 | } | ||
1187 | } | 1194 | } |
1188 | } | 1195 | } |
1189 | } | 1196 | } |
@@ -2618,7 +2625,31 @@ qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb) | |||
2618 | return qla2x00_post_work(vha, e); | 2625 | return qla2x00_post_work(vha, e); |
2619 | } | 2626 | } |
2620 | 2627 | ||
2621 | static void | 2628 | #define qla2x00_post_async_work(name, type) \ |
2629 | int qla2x00_post_async_##name##_work( \ | ||
2630 | struct scsi_qla_host *vha, \ | ||
2631 | fc_port_t *fcport, uint16_t *data) \ | ||
2632 | { \ | ||
2633 | struct qla_work_evt *e; \ | ||
2634 | \ | ||
2635 | e = qla2x00_alloc_work(vha, type); \ | ||
2636 | if (!e) \ | ||
2637 | return QLA_FUNCTION_FAILED; \ | ||
2638 | \ | ||
2639 | e->u.logio.fcport = fcport; \ | ||
2640 | if (data) { \ | ||
2641 | e->u.logio.data[0] = data[0]; \ | ||
2642 | e->u.logio.data[1] = data[1]; \ | ||
2643 | } \ | ||
2644 | return qla2x00_post_work(vha, e); \ | ||
2645 | } | ||
2646 | |||
2647 | qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN); | ||
2648 | qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE); | ||
2649 | qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); | ||
2650 | qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); | ||
2651 | |||
2652 | void | ||
2622 | qla2x00_do_work(struct scsi_qla_host *vha) | 2653 | qla2x00_do_work(struct scsi_qla_host *vha) |
2623 | { | 2654 | { |
2624 | struct qla_work_evt *e, *tmp; | 2655 | struct qla_work_evt *e, *tmp; |
@@ -2640,6 +2671,21 @@ qla2x00_do_work(struct scsi_qla_host *vha) | |||
2640 | case QLA_EVT_IDC_ACK: | 2671 | case QLA_EVT_IDC_ACK: |
2641 | qla81xx_idc_ack(vha, e->u.idc_ack.mb); | 2672 | qla81xx_idc_ack(vha, e->u.idc_ack.mb); |
2642 | break; | 2673 | break; |
2674 | case QLA_EVT_ASYNC_LOGIN: | ||
2675 | qla2x00_async_login(vha, e->u.logio.fcport, | ||
2676 | e->u.logio.data); | ||
2677 | break; | ||
2678 | case QLA_EVT_ASYNC_LOGIN_DONE: | ||
2679 | qla2x00_async_login_done(vha, e->u.logio.fcport, | ||
2680 | e->u.logio.data); | ||
2681 | break; | ||
2682 | case QLA_EVT_ASYNC_LOGOUT: | ||
2683 | qla2x00_async_logout(vha, e->u.logio.fcport); | ||
2684 | break; | ||
2685 | case QLA_EVT_ASYNC_LOGOUT_DONE: | ||
2686 | qla2x00_async_logout_done(vha, e->u.logio.fcport, | ||
2687 | e->u.logio.data); | ||
2688 | break; | ||
2643 | } | 2689 | } |
2644 | if (e->flags & QLA_EVT_FLAG_FREE) | 2690 | if (e->flags & QLA_EVT_FLAG_FREE) |
2645 | kfree(e); | 2691 | kfree(e); |
@@ -2655,6 +2701,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2655 | int status; | 2701 | int status; |
2656 | uint16_t next_loopid = 0; | 2702 | uint16_t next_loopid = 0; |
2657 | struct qla_hw_data *ha = vha->hw; | 2703 | struct qla_hw_data *ha = vha->hw; |
2704 | uint16_t data[2]; | ||
2658 | 2705 | ||
2659 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 2706 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
2660 | /* | 2707 | /* |
@@ -2664,6 +2711,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2664 | if (atomic_read(&fcport->state) != | 2711 | if (atomic_read(&fcport->state) != |
2665 | FCS_ONLINE && fcport->login_retry) { | 2712 | FCS_ONLINE && fcport->login_retry) { |
2666 | 2713 | ||
2714 | fcport->login_retry--; | ||
2667 | if (fcport->flags & FCF_FABRIC_DEVICE) { | 2715 | if (fcport->flags & FCF_FABRIC_DEVICE) { |
2668 | if (fcport->flags & FCF_TAPE_PRESENT) | 2716 | if (fcport->flags & FCF_TAPE_PRESENT) |
2669 | ha->isp_ops->fabric_logout(vha, | 2717 | ha->isp_ops->fabric_logout(vha, |
@@ -2672,13 +2720,22 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2672 | fcport->d_id.b.area, | 2720 | fcport->d_id.b.area, |
2673 | fcport->d_id.b.al_pa); | 2721 | fcport->d_id.b.al_pa); |
2674 | 2722 | ||
2675 | status = qla2x00_fabric_login(vha, fcport, | 2723 | if (IS_ALOGIO_CAPABLE(ha)) { |
2676 | &next_loopid); | 2724 | data[0] = 0; |
2725 | data[1] = QLA_LOGIO_LOGIN_RETRIED; | ||
2726 | status = qla2x00_post_async_login_work( | ||
2727 | vha, fcport, data); | ||
2728 | if (status == QLA_SUCCESS) | ||
2729 | continue; | ||
2730 | /* Attempt a retry. */ | ||
2731 | status = 1; | ||
2732 | } else | ||
2733 | status = qla2x00_fabric_login(vha, | ||
2734 | fcport, &next_loopid); | ||
2677 | } else | 2735 | } else |
2678 | status = qla2x00_local_device_login(vha, | 2736 | status = qla2x00_local_device_login(vha, |
2679 | fcport); | 2737 | fcport); |
2680 | 2738 | ||
2681 | fcport->login_retry--; | ||
2682 | if (status == QLA_SUCCESS) { | 2739 | if (status == QLA_SUCCESS) { |
2683 | fcport->old_loop_id = fcport->loop_id; | 2740 | fcport->old_loop_id = fcport->loop_id; |
2684 | 2741 | ||
@@ -2851,6 +2908,9 @@ qla2x00_do_dpc(void *data) | |||
2851 | */ | 2908 | */ |
2852 | ha->dpc_active = 0; | 2909 | ha->dpc_active = 0; |
2853 | 2910 | ||
2911 | /* Cleanup any residual CTX SRBs. */ | ||
2912 | qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); | ||
2913 | |||
2854 | return 0; | 2914 | return 0; |
2855 | } | 2915 | } |
2856 | 2916 | ||