diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 582 |
2 files changed, 419 insertions, 164 deletions
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 15a05682f012..d153d543a672 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -211,6 +211,7 @@ qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); | |||
211 | */ | 211 | */ |
212 | extern irqreturn_t qla2100_intr_handler(int, void *, struct pt_regs *); | 212 | extern irqreturn_t qla2100_intr_handler(int, void *, struct pt_regs *); |
213 | extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *); | 213 | extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *); |
214 | extern irqreturn_t qla24xx_intr_handler(int, void *, struct pt_regs *); | ||
214 | extern void qla2x00_process_response_queue(struct scsi_qla_host *); | 215 | extern void qla2x00_process_response_queue(struct scsi_qla_host *); |
215 | 216 | ||
216 | /* | 217 | /* |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f38d13628f43..b960bdfe91e9 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -19,14 +19,17 @@ | |||
19 | #include "qla_def.h" | 19 | #include "qla_def.h" |
20 | 20 | ||
21 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); | 21 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); |
22 | static void qla2x00_async_event(scsi_qla_host_t *, uint32_t); | 22 | static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *); |
23 | static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); | 23 | static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); |
24 | void qla2x00_process_response_queue(struct scsi_qla_host *); | 24 | void qla2x00_process_response_queue(struct scsi_qla_host *); |
25 | static void qla2x00_status_entry(scsi_qla_host_t *, sts_entry_t *); | 25 | static void qla2x00_status_entry(scsi_qla_host_t *, void *); |
26 | static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *); | 26 | static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *); |
27 | static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *); | 27 | static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *); |
28 | static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *); | 28 | static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *); |
29 | 29 | ||
30 | void qla24xx_process_response_queue(scsi_qla_host_t *); | ||
31 | static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *); | ||
32 | |||
30 | /** | 33 | /** |
31 | * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. | 34 | * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. |
32 | * @irq: | 35 | * @irq: |
@@ -45,7 +48,7 @@ qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
45 | int status; | 48 | int status; |
46 | unsigned long flags; | 49 | unsigned long flags; |
47 | unsigned long iter; | 50 | unsigned long iter; |
48 | uint32_t mbx; | 51 | uint16_t mb[4]; |
49 | 52 | ||
50 | ha = (scsi_qla_host_t *) dev_id; | 53 | ha = (scsi_qla_host_t *) dev_id; |
51 | if (!ha) { | 54 | if (!ha) { |
@@ -67,17 +70,20 @@ qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
67 | RD_REG_WORD(®->hccr); | 70 | RD_REG_WORD(®->hccr); |
68 | 71 | ||
69 | /* Get mailbox data. */ | 72 | /* Get mailbox data. */ |
70 | mbx = RD_MAILBOX_REG(ha, reg, 0); | 73 | mb[0] = RD_MAILBOX_REG(ha, reg, 0); |
71 | if (mbx > 0x3fff && mbx < 0x8000) { | 74 | if (mb[0] > 0x3fff && mb[0] < 0x8000) { |
72 | qla2x00_mbx_completion(ha, (uint16_t)mbx); | 75 | qla2x00_mbx_completion(ha, mb[0]); |
73 | status |= MBX_INTERRUPT; | 76 | status |= MBX_INTERRUPT; |
74 | } else if (mbx > 0x7fff && mbx < 0xc000) { | 77 | } else if (mb[0] > 0x7fff && mb[0] < 0xc000) { |
75 | qla2x00_async_event(ha, mbx); | 78 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); |
79 | mb[2] = RD_MAILBOX_REG(ha, reg, 2); | ||
80 | mb[3] = RD_MAILBOX_REG(ha, reg, 3); | ||
81 | qla2x00_async_event(ha, mb); | ||
76 | } else { | 82 | } else { |
77 | /*EMPTY*/ | 83 | /*EMPTY*/ |
78 | DEBUG2(printk("scsi(%ld): Unrecognized " | 84 | DEBUG2(printk("scsi(%ld): Unrecognized " |
79 | "interrupt type (%d)\n", | 85 | "interrupt type (%d).\n", |
80 | ha->host_no, mbx)); | 86 | ha->host_no, mb[0])); |
81 | } | 87 | } |
82 | /* Release mailbox registers. */ | 88 | /* Release mailbox registers. */ |
83 | WRT_REG_WORD(®->semaphore, 0); | 89 | WRT_REG_WORD(®->semaphore, 0); |
@@ -123,8 +129,8 @@ qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
123 | unsigned long flags; | 129 | unsigned long flags; |
124 | unsigned long iter; | 130 | unsigned long iter; |
125 | uint32_t stat; | 131 | uint32_t stat; |
126 | uint32_t mbx; | ||
127 | uint16_t hccr; | 132 | uint16_t hccr; |
133 | uint16_t mb[4]; | ||
128 | 134 | ||
129 | ha = (scsi_qla_host_t *) dev_id; | 135 | ha = (scsi_qla_host_t *) dev_id; |
130 | if (!ha) { | 136 | if (!ha) { |
@@ -146,7 +152,7 @@ qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
146 | "Parity error -- HCCR=%x.\n", hccr); | 152 | "Parity error -- HCCR=%x.\n", hccr); |
147 | else | 153 | else |
148 | qla_printk(KERN_INFO, ha, | 154 | qla_printk(KERN_INFO, ha, |
149 | "RISC paused -- HCCR=%x\n", hccr); | 155 | "RISC paused -- HCCR=%x.\n", hccr); |
150 | 156 | ||
151 | /* | 157 | /* |
152 | * Issue a "HARD" reset in order for the RISC | 158 | * Issue a "HARD" reset in order for the RISC |
@@ -160,35 +166,41 @@ qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
160 | } else if ((stat & HSR_RISC_INT) == 0) | 166 | } else if ((stat & HSR_RISC_INT) == 0) |
161 | break; | 167 | break; |
162 | 168 | ||
163 | mbx = MSW(stat); | ||
164 | switch (stat & 0xff) { | 169 | switch (stat & 0xff) { |
165 | case 0x13: | ||
166 | qla2x00_process_response_queue(ha); | ||
167 | break; | ||
168 | case 0x1: | 170 | case 0x1: |
169 | case 0x2: | 171 | case 0x2: |
170 | case 0x10: | 172 | case 0x10: |
171 | case 0x11: | 173 | case 0x11: |
172 | qla2x00_mbx_completion(ha, (uint16_t)mbx); | 174 | qla2x00_mbx_completion(ha, MSW(stat)); |
173 | status |= MBX_INTERRUPT; | 175 | status |= MBX_INTERRUPT; |
174 | 176 | ||
175 | /* Release mailbox registers. */ | 177 | /* Release mailbox registers. */ |
176 | WRT_REG_WORD(®->semaphore, 0); | 178 | WRT_REG_WORD(®->semaphore, 0); |
177 | break; | 179 | break; |
178 | case 0x12: | 180 | case 0x12: |
179 | qla2x00_async_event(ha, mbx); | 181 | mb[0] = MSW(stat); |
182 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
183 | mb[2] = RD_MAILBOX_REG(ha, reg, 2); | ||
184 | mb[3] = RD_MAILBOX_REG(ha, reg, 3); | ||
185 | qla2x00_async_event(ha, mb); | ||
186 | break; | ||
187 | case 0x13: | ||
188 | qla2x00_process_response_queue(ha); | ||
180 | break; | 189 | break; |
181 | case 0x15: | 190 | case 0x15: |
182 | mbx = mbx << 16 | MBA_CMPLT_1_16BIT; | 191 | mb[0] = MBA_CMPLT_1_16BIT; |
183 | qla2x00_async_event(ha, mbx); | 192 | mb[1] = MSW(stat); |
193 | qla2x00_async_event(ha, mb); | ||
184 | break; | 194 | break; |
185 | case 0x16: | 195 | case 0x16: |
186 | mbx = mbx << 16 | MBA_SCSI_COMPLETION; | 196 | mb[0] = MBA_SCSI_COMPLETION; |
187 | qla2x00_async_event(ha, mbx); | 197 | mb[1] = MSW(stat); |
198 | mb[2] = RD_MAILBOX_REG(ha, reg, 2); | ||
199 | qla2x00_async_event(ha, mb); | ||
188 | break; | 200 | break; |
189 | default: | 201 | default: |
190 | DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " | 202 | DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " |
191 | "(%d)\n", | 203 | "(%d).\n", |
192 | ha->host_no, stat & 0xff)); | 204 | ha->host_no, stat & 0xff)); |
193 | break; | 205 | break; |
194 | } | 206 | } |
@@ -250,14 +262,14 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0) | |||
250 | /** | 262 | /** |
251 | * qla2x00_async_event() - Process aynchronous events. | 263 | * qla2x00_async_event() - Process aynchronous events. |
252 | * @ha: SCSI driver HA context | 264 | * @ha: SCSI driver HA context |
253 | * @mb0: Mailbox0 register | 265 | * @mb: Mailbox registers (0 - 3) |
254 | */ | 266 | */ |
255 | static void | 267 | static void |
256 | qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | 268 | qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) |
257 | { | 269 | { |
258 | static char *link_speeds[5] = { "1", "2", "4", "?", "10" }; | 270 | #define LS_UNKNOWN 2 |
271 | static char *link_speeds[5] = { "1", "2", "?", "4", "10" }; | ||
259 | char *link_speed; | 272 | char *link_speed; |
260 | uint16_t mb[4]; | ||
261 | uint16_t handle_cnt; | 273 | uint16_t handle_cnt; |
262 | uint16_t cnt; | 274 | uint16_t cnt; |
263 | uint32_t handles[5]; | 275 | uint32_t handles[5]; |
@@ -267,61 +279,48 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
267 | 279 | ||
268 | /* Setup to process RIO completion. */ | 280 | /* Setup to process RIO completion. */ |
269 | handle_cnt = 0; | 281 | handle_cnt = 0; |
270 | mb[0] = LSW(mbx); | ||
271 | switch (mb[0]) { | 282 | switch (mb[0]) { |
272 | case MBA_SCSI_COMPLETION: | 283 | case MBA_SCSI_COMPLETION: |
273 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | 284 | handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1])); |
274 | handles[0] = le32_to_cpu( | ||
275 | ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) | | ||
276 | RD_MAILBOX_REG(ha, reg, 1)); | ||
277 | else | ||
278 | handles[0] = le32_to_cpu( | ||
279 | ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) | | ||
280 | MSW(mbx)); | ||
281 | handle_cnt = 1; | 285 | handle_cnt = 1; |
282 | break; | 286 | break; |
283 | case MBA_CMPLT_1_16BIT: | 287 | case MBA_CMPLT_1_16BIT: |
284 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | 288 | handles[0] = mb[1]; |
285 | handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); | ||
286 | else | ||
287 | handles[0] = MSW(mbx); | ||
288 | handle_cnt = 1; | 289 | handle_cnt = 1; |
289 | mb[0] = MBA_SCSI_COMPLETION; | 290 | mb[0] = MBA_SCSI_COMPLETION; |
290 | break; | 291 | break; |
291 | case MBA_CMPLT_2_16BIT: | 292 | case MBA_CMPLT_2_16BIT: |
292 | handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); | 293 | handles[0] = mb[1]; |
293 | handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2); | 294 | handles[1] = mb[2]; |
294 | handle_cnt = 2; | 295 | handle_cnt = 2; |
295 | mb[0] = MBA_SCSI_COMPLETION; | 296 | mb[0] = MBA_SCSI_COMPLETION; |
296 | break; | 297 | break; |
297 | case MBA_CMPLT_3_16BIT: | 298 | case MBA_CMPLT_3_16BIT: |
298 | handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); | 299 | handles[0] = mb[1]; |
299 | handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2); | 300 | handles[1] = mb[2]; |
300 | handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3); | 301 | handles[2] = mb[3]; |
301 | handle_cnt = 3; | 302 | handle_cnt = 3; |
302 | mb[0] = MBA_SCSI_COMPLETION; | 303 | mb[0] = MBA_SCSI_COMPLETION; |
303 | break; | 304 | break; |
304 | case MBA_CMPLT_4_16BIT: | 305 | case MBA_CMPLT_4_16BIT: |
305 | handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); | 306 | handles[0] = mb[1]; |
306 | handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2); | 307 | handles[1] = mb[2]; |
307 | handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3); | 308 | handles[2] = mb[3]; |
308 | handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6); | 309 | handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6); |
309 | handle_cnt = 4; | 310 | handle_cnt = 4; |
310 | mb[0] = MBA_SCSI_COMPLETION; | 311 | mb[0] = MBA_SCSI_COMPLETION; |
311 | break; | 312 | break; |
312 | case MBA_CMPLT_5_16BIT: | 313 | case MBA_CMPLT_5_16BIT: |
313 | handles[0] = (uint32_t)RD_MAILBOX_REG(ha, reg, 1); | 314 | handles[0] = mb[1]; |
314 | handles[1] = (uint32_t)RD_MAILBOX_REG(ha, reg, 2); | 315 | handles[1] = mb[2]; |
315 | handles[2] = (uint32_t)RD_MAILBOX_REG(ha, reg, 3); | 316 | handles[2] = mb[3]; |
316 | handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6); | 317 | handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6); |
317 | handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7); | 318 | handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7); |
318 | handle_cnt = 5; | 319 | handle_cnt = 5; |
319 | mb[0] = MBA_SCSI_COMPLETION; | 320 | mb[0] = MBA_SCSI_COMPLETION; |
320 | break; | 321 | break; |
321 | case MBA_CMPLT_2_32BIT: | 322 | case MBA_CMPLT_2_32BIT: |
322 | handles[0] = le32_to_cpu( | 323 | handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1])); |
323 | ((uint32_t)(RD_MAILBOX_REG(ha, reg, 2) << 16)) | | ||
324 | RD_MAILBOX_REG(ha, reg, 1)); | ||
325 | handles[1] = le32_to_cpu( | 324 | handles[1] = le32_to_cpu( |
326 | ((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) | | 325 | ((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) | |
327 | RD_MAILBOX_REG(ha, reg, 6)); | 326 | RD_MAILBOX_REG(ha, reg, 6)); |
@@ -358,7 +357,15 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
358 | 357 | ||
359 | ha->isp_ops.fw_dump(ha, 1); | 358 | ha->isp_ops.fw_dump(ha, 1); |
360 | 359 | ||
361 | if (mb[1] == 0) { | 360 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
361 | if (mb[1] == 0 && mb[2] == 0) { | ||
362 | qla_printk(KERN_ERR, ha, | ||
363 | "Unrecoverable Hardware Error: adapter " | ||
364 | "marked OFFLINE!\n"); | ||
365 | ha->flags.online = 0; | ||
366 | } else | ||
367 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
368 | } else if (mb[1] == 0) { | ||
362 | qla_printk(KERN_INFO, ha, | 369 | qla_printk(KERN_INFO, ha, |
363 | "Unrecoverable Hardware Error: adapter marked " | 370 | "Unrecoverable Hardware Error: adapter marked " |
364 | "OFFLINE!\n"); | 371 | "OFFLINE!\n"); |
@@ -389,8 +396,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
389 | break; | 396 | break; |
390 | 397 | ||
391 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ | 398 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ |
392 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
393 | |||
394 | DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no, | 399 | DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no, |
395 | mb[1])); | 400 | mb[1])); |
396 | qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]); | 401 | qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]); |
@@ -411,13 +416,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
411 | break; | 416 | break; |
412 | 417 | ||
413 | case MBA_LOOP_UP: /* Loop Up Event */ | 418 | case MBA_LOOP_UP: /* Loop Up Event */ |
414 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
415 | |||
416 | ha->link_data_rate = 0; | 419 | ha->link_data_rate = 0; |
417 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 420 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
418 | link_speed = link_speeds[0]; | 421 | link_speed = link_speeds[0]; |
419 | } else { | 422 | } else { |
420 | link_speed = link_speeds[3]; | 423 | link_speed = link_speeds[LS_UNKNOWN]; |
421 | if (mb[1] < 5) | 424 | if (mb[1] < 5) |
422 | link_speed = link_speeds[mb[1]]; | 425 | link_speed = link_speeds[mb[1]]; |
423 | ha->link_data_rate = mb[1]; | 426 | ha->link_data_rate = mb[1]; |
@@ -435,9 +438,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
435 | break; | 438 | break; |
436 | 439 | ||
437 | case MBA_LOOP_DOWN: /* Loop Down Event */ | 440 | case MBA_LOOP_DOWN: /* Loop Down Event */ |
438 | DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN.\n", | 441 | DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n", |
439 | ha->host_no)); | 442 | ha->host_no, mb[1])); |
440 | qla_printk(KERN_INFO, ha, "LOOP DOWN detected.\n"); | 443 | qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]); |
441 | 444 | ||
442 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 445 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
443 | atomic_set(&ha->loop_state, LOOP_DOWN); | 446 | atomic_set(&ha->loop_state, LOOP_DOWN); |
@@ -454,8 +457,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
454 | break; | 457 | break; |
455 | 458 | ||
456 | case MBA_LIP_RESET: /* LIP reset occurred */ | 459 | case MBA_LIP_RESET: /* LIP reset occurred */ |
457 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
458 | |||
459 | DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", | 460 | DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", |
460 | ha->host_no, mb[1])); | 461 | ha->host_no, mb[1])); |
461 | qla_printk(KERN_INFO, ha, | 462 | qla_printk(KERN_INFO, ha, |
@@ -506,8 +507,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
506 | if (IS_QLA2100(ha)) | 507 | if (IS_QLA2100(ha)) |
507 | break; | 508 | break; |
508 | 509 | ||
509 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
510 | |||
511 | DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection " | 510 | DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection " |
512 | "received.\n", | 511 | "received.\n", |
513 | ha->host_no)); | 512 | ha->host_no)); |
@@ -527,16 +526,14 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
527 | break; | 526 | break; |
528 | 527 | ||
529 | case MBA_PORT_UPDATE: /* Port database update */ | 528 | case MBA_PORT_UPDATE: /* Port database update */ |
530 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
531 | mb[2] = RD_MAILBOX_REG(ha, reg, 2); | ||
532 | |||
533 | /* | 529 | /* |
534 | * If a single remote port just logged into (or logged out of) | 530 | * If a single remote port just logged into (or logged out of) |
535 | * us, create a new entry in our rscn fcports list and handle | 531 | * us, create a new entry in our rscn fcports list and handle |
536 | * the event like an RSCN. | 532 | * the event like an RSCN. |
537 | */ | 533 | */ |
538 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && | 534 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && |
539 | !IS_QLA6322(ha) && ha->flags.init_done && mb[1] != 0xffff && | 535 | !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && |
536 | ha->flags.init_done && mb[1] != 0xffff && | ||
540 | ((ha->operating_mode == P2P && mb[1] != 0) || | 537 | ((ha->operating_mode == P2P && mb[1] != 0) || |
541 | (ha->operating_mode != P2P && mb[1] != | 538 | (ha->operating_mode != P2P && mb[1] != |
542 | SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) { | 539 | SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) { |
@@ -547,8 +544,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
547 | rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC); | 544 | rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC); |
548 | if (rscn_fcport) { | 545 | if (rscn_fcport) { |
549 | DEBUG14(printk("scsi(%ld): Port Update -- " | 546 | DEBUG14(printk("scsi(%ld): Port Update -- " |
550 | "creating RSCN fcport %p for %x/%x.\n", | 547 | "creating RSCN fcport %p for %x/%x/%x.\n", |
551 | ha->host_no, rscn_fcport, mb[1], mb[2])); | 548 | ha->host_no, rscn_fcport, mb[1], mb[2], |
549 | mb[3])); | ||
552 | 550 | ||
553 | rscn_fcport->loop_id = mb[1]; | 551 | rscn_fcport->loop_id = mb[1]; |
554 | rscn_fcport->d_id.b24 = INVALID_PORT_ID; | 552 | rscn_fcport->d_id.b24 = INVALID_PORT_ID; |
@@ -577,15 +575,16 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
577 | if (atomic_read(&ha->loop_state) != LOOP_DOWN && | 575 | if (atomic_read(&ha->loop_state) != LOOP_DOWN && |
578 | atomic_read(&ha->loop_state) != LOOP_DEAD) { | 576 | atomic_read(&ha->loop_state) != LOOP_DEAD) { |
579 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE " | 577 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE " |
580 | "ignored.\n", ha->host_no)); | 578 | "ignored %04x/%04x/%04x.\n", ha->host_no, mb[1], |
579 | mb[2], mb[3])); | ||
581 | break; | 580 | break; |
582 | } | 581 | } |
583 | 582 | ||
584 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n", | 583 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n", |
585 | ha->host_no)); | 584 | ha->host_no)); |
586 | DEBUG(printk(KERN_INFO | 585 | DEBUG(printk(KERN_INFO |
587 | "scsi(%ld): Port database changed %04x %04x.\n", | 586 | "scsi(%ld): Port database changed %04x %04x %04x.\n", |
588 | ha->host_no, mb[1], mb[2])); | 587 | ha->host_no, mb[1], mb[2], mb[3])); |
589 | 588 | ||
590 | /* | 589 | /* |
591 | * Mark all devices as missing so we will login again. | 590 | * Mark all devices as missing so we will login again. |
@@ -604,9 +603,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
604 | break; | 603 | break; |
605 | 604 | ||
606 | case MBA_RSCN_UPDATE: /* State Change Registration */ | 605 | case MBA_RSCN_UPDATE: /* State Change Registration */ |
607 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
608 | mb[2] = RD_MAILBOX_REG(ha, reg, 2); | ||
609 | |||
610 | DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", | 606 | DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", |
611 | ha->host_no)); | 607 | ha->host_no)); |
612 | DEBUG(printk(KERN_INFO | 608 | DEBUG(printk(KERN_INFO |
@@ -655,6 +651,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
655 | 651 | ||
656 | qla2x00_process_response_queue(ha); | 652 | qla2x00_process_response_queue(ha); |
657 | break; | 653 | break; |
654 | |||
655 | case MBA_DISCARD_RND_FRAME: | ||
656 | DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x " | ||
657 | "%04x.\n", ha->host_no, mb[1], mb[2], mb[3])); | ||
658 | break; | ||
658 | } | 659 | } |
659 | } | 660 | } |
660 | 661 | ||
@@ -801,31 +802,41 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha) | |||
801 | * @pkt: Entry pointer | 802 | * @pkt: Entry pointer |
802 | */ | 803 | */ |
803 | static void | 804 | static void |
804 | qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | 805 | qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) |
805 | { | 806 | { |
806 | unsigned b, t, l; | ||
807 | srb_t *sp; | 807 | srb_t *sp; |
808 | fc_port_t *fcport; | 808 | fc_port_t *fcport; |
809 | struct scsi_cmnd *cp; | 809 | struct scsi_cmnd *cp; |
810 | sts_entry_t *sts; | ||
811 | struct sts_entry_24xx *sts24; | ||
810 | uint16_t comp_status; | 812 | uint16_t comp_status; |
811 | uint16_t scsi_status; | 813 | uint16_t scsi_status; |
812 | uint8_t lscsi_status; | 814 | uint8_t lscsi_status; |
813 | int32_t resid; | 815 | int32_t resid; |
814 | uint8_t sense_sz = 0; | 816 | uint32_t sense_len, rsp_info_len, resid_len; |
815 | uint16_t rsp_info_len; | 817 | uint8_t *rsp_info, *sense_data; |
818 | |||
819 | sts = (sts_entry_t *) pkt; | ||
820 | sts24 = (struct sts_entry_24xx *) pkt; | ||
821 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | ||
822 | comp_status = le16_to_cpu(sts24->comp_status); | ||
823 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; | ||
824 | } else { | ||
825 | comp_status = le16_to_cpu(sts->comp_status); | ||
826 | scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; | ||
827 | } | ||
816 | 828 | ||
817 | /* Fast path completion. */ | 829 | /* Fast path completion. */ |
818 | if (le16_to_cpu(pkt->comp_status) == CS_COMPLETE && | 830 | if (comp_status == CS_COMPLETE && scsi_status == 0) { |
819 | (le16_to_cpu(pkt->scsi_status) & SS_MASK) == 0) { | 831 | qla2x00_process_completed_request(ha, sts->handle); |
820 | qla2x00_process_completed_request(ha, pkt->handle); | ||
821 | 832 | ||
822 | return; | 833 | return; |
823 | } | 834 | } |
824 | 835 | ||
825 | /* Validate handle. */ | 836 | /* Validate handle. */ |
826 | if (pkt->handle < MAX_OUTSTANDING_COMMANDS) { | 837 | if (sts->handle < MAX_OUTSTANDING_COMMANDS) { |
827 | sp = ha->outstanding_cmds[pkt->handle]; | 838 | sp = ha->outstanding_cmds[sts->handle]; |
828 | ha->outstanding_cmds[pkt->handle] = NULL; | 839 | ha->outstanding_cmds[sts->handle] = NULL; |
829 | } else | 840 | } else |
830 | sp = NULL; | 841 | sp = NULL; |
831 | 842 | ||
@@ -844,40 +855,49 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
844 | if (cp == NULL) { | 855 | if (cp == NULL) { |
845 | DEBUG2(printk("scsi(%ld): Command already returned back to OS " | 856 | DEBUG2(printk("scsi(%ld): Command already returned back to OS " |
846 | "pkt->handle=%d sp=%p sp->state:%d\n", | 857 | "pkt->handle=%d sp=%p sp->state:%d\n", |
847 | ha->host_no, pkt->handle, sp, sp->state)); | 858 | ha->host_no, sts->handle, sp, sp->state)); |
848 | qla_printk(KERN_WARNING, ha, | 859 | qla_printk(KERN_WARNING, ha, |
849 | "Command is NULL: already returned to OS (sp=%p)\n", sp); | 860 | "Command is NULL: already returned to OS (sp=%p)\n", sp); |
850 | 861 | ||
851 | return; | 862 | return; |
852 | } | 863 | } |
853 | 864 | ||
854 | comp_status = le16_to_cpu(pkt->comp_status); | 865 | lscsi_status = scsi_status & STATUS_MASK; |
855 | /* Mask of reserved bits 12-15, before we examine the scsi status */ | 866 | CMD_ENTRY_STATUS(cp) = sts->entry_status; |
856 | scsi_status = le16_to_cpu(pkt->scsi_status) & SS_MASK; | ||
857 | lscsi_status = scsi_status & STATUS_MASK; | ||
858 | |||
859 | CMD_ENTRY_STATUS(cp) = pkt->entry_status; | ||
860 | CMD_COMPL_STATUS(cp) = comp_status; | 867 | CMD_COMPL_STATUS(cp) = comp_status; |
861 | CMD_SCSI_STATUS(cp) = scsi_status; | 868 | CMD_SCSI_STATUS(cp) = scsi_status; |
862 | 869 | ||
863 | /* Generate LU queue on cntrl, target, LUN */ | ||
864 | b = cp->device->channel; | ||
865 | t = cp->device->id; | ||
866 | l = cp->device->lun, | ||
867 | |||
868 | fcport = sp->fcport; | 870 | fcport = sp->fcport; |
869 | 871 | ||
872 | sense_len = rsp_info_len = resid_len = 0; | ||
873 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | ||
874 | sense_len = le32_to_cpu(sts24->sense_len); | ||
875 | rsp_info_len = le32_to_cpu(sts24->rsp_data_len); | ||
876 | resid_len = le32_to_cpu(sts24->rsp_residual_count); | ||
877 | rsp_info = sts24->data; | ||
878 | sense_data = sts24->data; | ||
879 | host_to_fcp_swap(sts24->data, sizeof(sts24->data)); | ||
880 | } else { | ||
881 | sense_len = le16_to_cpu(sts->req_sense_length); | ||
882 | rsp_info_len = le16_to_cpu(sts->rsp_info_len); | ||
883 | resid_len = le32_to_cpu(sts->residual_length); | ||
884 | rsp_info = sts->rsp_info; | ||
885 | sense_data = sts->req_sense_data; | ||
886 | } | ||
887 | |||
870 | /* Check for any FCP transport errors. */ | 888 | /* Check for any FCP transport errors. */ |
871 | if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { | 889 | if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { |
872 | rsp_info_len = le16_to_cpu(pkt->rsp_info_len); | 890 | /* Sense data lies beyond any FCP RESPONSE data. */ |
873 | if (rsp_info_len > 3 && pkt->rsp_info[3]) { | 891 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) |
892 | sense_data += rsp_info_len; | ||
893 | if (rsp_info_len > 3 && rsp_info[3]) { | ||
874 | DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " | 894 | DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " |
875 | "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..." | 895 | "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..." |
876 | "retrying command\n", ha->host_no, b, t, l, | 896 | "retrying command\n", ha->host_no, |
877 | rsp_info_len, pkt->rsp_info[0], pkt->rsp_info[1], | 897 | cp->device->channel, cp->device->id, |
878 | pkt->rsp_info[2], pkt->rsp_info[3], | 898 | cp->device->lun, rsp_info_len, rsp_info[0], |
879 | pkt->rsp_info[4], pkt->rsp_info[5], | 899 | rsp_info[1], rsp_info[2], rsp_info[3], rsp_info[4], |
880 | pkt->rsp_info[6], pkt->rsp_info[7])); | 900 | rsp_info[5], rsp_info[6], rsp_info[7])); |
881 | 901 | ||
882 | cp->result = DID_BUS_BUSY << 16; | 902 | cp->result = DID_BUS_BUSY << 16; |
883 | qla2x00_sp_compl(ha, sp); | 903 | qla2x00_sp_compl(ha, sp); |
@@ -895,7 +915,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
895 | break; | 915 | break; |
896 | } | 916 | } |
897 | if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) { | 917 | if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) { |
898 | resid = le32_to_cpu(pkt->residual_length); | 918 | resid = resid_len; |
899 | cp->resid = resid; | 919 | cp->resid = resid; |
900 | CMD_RESID_LEN(cp) = resid; | 920 | CMD_RESID_LEN(cp) = resid; |
901 | } | 921 | } |
@@ -904,39 +924,34 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
904 | if (lscsi_status != SS_CHECK_CONDITION) | 924 | if (lscsi_status != SS_CHECK_CONDITION) |
905 | break; | 925 | break; |
906 | 926 | ||
907 | /* | 927 | /* Copy Sense Data into sense buffer. */ |
908 | * Copy Sense Data into sense buffer | ||
909 | */ | ||
910 | memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer)); | 928 | memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer)); |
911 | 929 | ||
912 | if (!(scsi_status & SS_SENSE_LEN_VALID)) | 930 | if (!(scsi_status & SS_SENSE_LEN_VALID)) |
913 | break; | 931 | break; |
914 | 932 | ||
915 | if (le16_to_cpu(pkt->req_sense_length) < | 933 | if (sense_len >= sizeof(cp->sense_buffer)) |
916 | sizeof(cp->sense_buffer)) | 934 | sense_len = sizeof(cp->sense_buffer); |
917 | sense_sz = le16_to_cpu(pkt->req_sense_length); | ||
918 | else | ||
919 | sense_sz = sizeof(cp->sense_buffer); | ||
920 | 935 | ||
921 | CMD_ACTUAL_SNSLEN(cp) = sense_sz; | 936 | CMD_ACTUAL_SNSLEN(cp) = sense_len; |
922 | sp->request_sense_length = sense_sz; | 937 | sp->request_sense_length = sense_len; |
923 | sp->request_sense_ptr = cp->sense_buffer; | 938 | sp->request_sense_ptr = cp->sense_buffer; |
924 | 939 | ||
925 | if (sp->request_sense_length > 32) | 940 | if (sp->request_sense_length > 32) |
926 | sense_sz = 32; | 941 | sense_len = 32; |
927 | 942 | ||
928 | memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz); | 943 | memcpy(cp->sense_buffer, sense_data, sense_len); |
929 | 944 | ||
930 | sp->request_sense_ptr += sense_sz; | 945 | sp->request_sense_ptr += sense_len; |
931 | sp->request_sense_length -= sense_sz; | 946 | sp->request_sense_length -= sense_len; |
932 | if (sp->request_sense_length != 0) | 947 | if (sp->request_sense_length != 0) |
933 | ha->status_srb = sp; | 948 | ha->status_srb = sp; |
934 | 949 | ||
935 | DEBUG5(printk("%s(): Check condition Sense data, " | 950 | DEBUG5(printk("%s(): Check condition Sense data, " |
936 | "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", | 951 | "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", __func__, |
937 | __func__, ha->host_no, b, t, l, cp, | 952 | ha->host_no, cp->device->channel, cp->device->id, |
938 | cp->serial_number)); | 953 | cp->device->lun, cp, cp->serial_number)); |
939 | if (sense_sz) | 954 | if (sense_len) |
940 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, | 955 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, |
941 | CMD_ACTUAL_SNSLEN(cp))); | 956 | CMD_ACTUAL_SNSLEN(cp))); |
942 | break; | 957 | break; |
@@ -944,9 +959,10 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
944 | case CS_DATA_UNDERRUN: | 959 | case CS_DATA_UNDERRUN: |
945 | DEBUG2(printk(KERN_INFO | 960 | DEBUG2(printk(KERN_INFO |
946 | "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n", | 961 | "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n", |
947 | ha->host_no, t, l, comp_status, scsi_status)); | 962 | ha->host_no, cp->device->id, cp->device->lun, comp_status, |
963 | scsi_status)); | ||
948 | 964 | ||
949 | resid = le32_to_cpu(pkt->residual_length); | 965 | resid = resid_len; |
950 | if (scsi_status & SS_RESIDUAL_UNDER) { | 966 | if (scsi_status & SS_RESIDUAL_UNDER) { |
951 | cp->resid = resid; | 967 | cp->resid = resid; |
952 | CMD_RESID_LEN(cp) = resid; | 968 | CMD_RESID_LEN(cp) = resid; |
@@ -968,31 +984,30 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
968 | if (!(scsi_status & SS_SENSE_LEN_VALID)) | 984 | if (!(scsi_status & SS_SENSE_LEN_VALID)) |
969 | break; | 985 | break; |
970 | 986 | ||
971 | if (le16_to_cpu(pkt->req_sense_length) < | 987 | if (sense_len >= sizeof(cp->sense_buffer)) |
972 | sizeof(cp->sense_buffer)) | 988 | sense_len = sizeof(cp->sense_buffer); |
973 | sense_sz = le16_to_cpu(pkt->req_sense_length); | ||
974 | else | ||
975 | sense_sz = sizeof(cp->sense_buffer); | ||
976 | 989 | ||
977 | CMD_ACTUAL_SNSLEN(cp) = sense_sz; | 990 | CMD_ACTUAL_SNSLEN(cp) = sense_len; |
978 | sp->request_sense_length = sense_sz; | 991 | sp->request_sense_length = sense_len; |
979 | sp->request_sense_ptr = cp->sense_buffer; | 992 | sp->request_sense_ptr = cp->sense_buffer; |
980 | 993 | ||
981 | if (sp->request_sense_length > 32) | 994 | if (sp->request_sense_length > 32) |
982 | sense_sz = 32; | 995 | sense_len = 32; |
983 | 996 | ||
984 | memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz); | 997 | memcpy(cp->sense_buffer, sense_data, sense_len); |
985 | 998 | ||
986 | sp->request_sense_ptr += sense_sz; | 999 | sp->request_sense_ptr += sense_len; |
987 | sp->request_sense_length -= sense_sz; | 1000 | sp->request_sense_length -= sense_len; |
988 | if (sp->request_sense_length != 0) | 1001 | if (sp->request_sense_length != 0) |
989 | ha->status_srb = sp; | 1002 | ha->status_srb = sp; |
990 | 1003 | ||
991 | DEBUG5(printk("%s(): Check condition Sense data, " | 1004 | DEBUG5(printk("%s(): Check condition Sense data, " |
992 | "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", | 1005 | "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", |
993 | __func__, ha->host_no, b, t, l, cp, | 1006 | __func__, ha->host_no, cp->device->channel, |
1007 | cp->device->id, cp->device->lun, cp, | ||
994 | cp->serial_number)); | 1008 | cp->serial_number)); |
995 | if (sense_sz) | 1009 | |
1010 | if (sense_len) | ||
996 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, | 1011 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, |
997 | CMD_ACTUAL_SNSLEN(cp))); | 1012 | CMD_ACTUAL_SNSLEN(cp))); |
998 | } else { | 1013 | } else { |
@@ -1004,8 +1019,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1004 | if (!(scsi_status & SS_RESIDUAL_UNDER)) { | 1019 | if (!(scsi_status & SS_RESIDUAL_UNDER)) { |
1005 | DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped " | 1020 | DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped " |
1006 | "frame(s) detected (%x of %x bytes)..." | 1021 | "frame(s) detected (%x of %x bytes)..." |
1007 | "retrying command.\n", | 1022 | "retrying command.\n", ha->host_no, |
1008 | ha->host_no, b, t, l, resid, | 1023 | cp->device->channel, cp->device->id, |
1024 | cp->device->lun, resid, | ||
1009 | cp->request_bufflen)); | 1025 | cp->request_bufflen)); |
1010 | 1026 | ||
1011 | cp->result = DID_BUS_BUSY << 16; | 1027 | cp->result = DID_BUS_BUSY << 16; |
@@ -1018,8 +1034,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1018 | qla_printk(KERN_INFO, ha, | 1034 | qla_printk(KERN_INFO, ha, |
1019 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " | 1035 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " |
1020 | "detected (%x of %x bytes)...returning " | 1036 | "detected (%x of %x bytes)...returning " |
1021 | "error status.\n", | 1037 | "error status.\n", ha->host_no, |
1022 | ha->host_no, b, t, l, resid, | 1038 | cp->device->channel, cp->device->id, |
1039 | cp->device->lun, resid, | ||
1023 | cp->request_bufflen); | 1040 | cp->request_bufflen); |
1024 | 1041 | ||
1025 | cp->result = DID_ERROR << 16; | 1042 | cp->result = DID_ERROR << 16; |
@@ -1034,7 +1051,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1034 | case CS_DATA_OVERRUN: | 1051 | case CS_DATA_OVERRUN: |
1035 | DEBUG2(printk(KERN_INFO | 1052 | DEBUG2(printk(KERN_INFO |
1036 | "scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n", | 1053 | "scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n", |
1037 | ha->host_no, t, l, comp_status, scsi_status)); | 1054 | ha->host_no, cp->device->id, cp->device->lun, comp_status, |
1055 | scsi_status)); | ||
1038 | DEBUG2(printk(KERN_INFO | 1056 | DEBUG2(printk(KERN_INFO |
1039 | "CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | 1057 | "CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", |
1040 | cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3], | 1058 | cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3], |
@@ -1042,8 +1060,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1042 | DEBUG2(printk(KERN_INFO | 1060 | DEBUG2(printk(KERN_INFO |
1043 | "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR " | 1061 | "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR " |
1044 | "status!\n", | 1062 | "status!\n", |
1045 | cp->serial_number, cp->request_bufflen, | 1063 | cp->serial_number, cp->request_bufflen, resid_len)); |
1046 | le32_to_cpu(pkt->residual_length))); | ||
1047 | 1064 | ||
1048 | cp->result = DID_ERROR << 16; | 1065 | cp->result = DID_ERROR << 16; |
1049 | break; | 1066 | break; |
@@ -1060,7 +1077,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1060 | */ | 1077 | */ |
1061 | DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down " | 1078 | DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down " |
1062 | "pid=%ld, compl status=0x%x, port state=0x%x\n", | 1079 | "pid=%ld, compl status=0x%x, port state=0x%x\n", |
1063 | ha->host_no, t, l, cp->serial_number, comp_status, | 1080 | ha->host_no, cp->device->id, cp->device->lun, |
1081 | cp->serial_number, comp_status, | ||
1064 | atomic_read(&fcport->state))); | 1082 | atomic_read(&fcport->state))); |
1065 | 1083 | ||
1066 | cp->result = DID_BUS_BUSY << 16; | 1084 | cp->result = DID_BUS_BUSY << 16; |
@@ -1091,17 +1109,25 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1091 | break; | 1109 | break; |
1092 | 1110 | ||
1093 | case CS_TIMEOUT: | 1111 | case CS_TIMEOUT: |
1112 | cp->result = DID_BUS_BUSY << 16; | ||
1113 | |||
1114 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { | ||
1115 | DEBUG2(printk(KERN_INFO | ||
1116 | "scsi(%ld:%d:%d:%d): TIMEOUT status detected " | ||
1117 | "0x%x-0x%x\n", ha->host_no, cp->device->channel, | ||
1118 | cp->device->id, cp->device->lun, comp_status, | ||
1119 | scsi_status)); | ||
1120 | break; | ||
1121 | } | ||
1094 | DEBUG2(printk(KERN_INFO | 1122 | DEBUG2(printk(KERN_INFO |
1095 | "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x " | 1123 | "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x " |
1096 | "sflags=%x.\n", ha->host_no, b, t, l, comp_status, | 1124 | "sflags=%x.\n", ha->host_no, cp->device->channel, |
1097 | scsi_status, le16_to_cpu(pkt->status_flags))); | 1125 | cp->device->id, cp->device->lun, comp_status, scsi_status, |
1098 | 1126 | le16_to_cpu(sts->status_flags))); | |
1099 | cp->result = DID_BUS_BUSY << 16; | ||
1100 | 1127 | ||
1101 | /* Check to see if logout occurred */ | 1128 | /* Check to see if logout occurred. */ |
1102 | if ((le16_to_cpu(pkt->status_flags) & SF_LOGOUT_SENT)) { | 1129 | if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) |
1103 | qla2x00_mark_device_lost(ha, fcport, 1); | 1130 | qla2x00_mark_device_lost(ha, fcport, 1); |
1104 | } | ||
1105 | break; | 1131 | break; |
1106 | 1132 | ||
1107 | case CS_QUEUE_FULL: | 1133 | case CS_QUEUE_FULL: |
@@ -1117,8 +1143,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1117 | 1143 | ||
1118 | default: | 1144 | default: |
1119 | DEBUG3(printk("scsi(%ld): Error detected (unknown status) " | 1145 | DEBUG3(printk("scsi(%ld): Error detected (unknown status) " |
1120 | "0x%x-0x%x.\n", | 1146 | "0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); |
1121 | ha->host_no, comp_status, scsi_status)); | ||
1122 | qla_printk(KERN_INFO, ha, | 1147 | qla_printk(KERN_INFO, ha, |
1123 | "Unknown status detected 0x%x-0x%x.\n", | 1148 | "Unknown status detected 0x%x-0x%x.\n", |
1124 | comp_status, scsi_status); | 1149 | comp_status, scsi_status); |
@@ -1166,6 +1191,8 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) | |||
1166 | } | 1191 | } |
1167 | 1192 | ||
1168 | /* Move sense data. */ | 1193 | /* Move sense data. */ |
1194 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) | ||
1195 | host_to_fcp_swap(pkt->data, sizeof(pkt->data)); | ||
1169 | memcpy(sp->request_sense_ptr, pkt->data, sense_sz); | 1196 | memcpy(sp->request_sense_ptr, pkt->data, sense_sz); |
1170 | DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); | 1197 | DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); |
1171 | 1198 | ||
@@ -1186,7 +1213,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) | |||
1186 | * @pkt: Entry pointer | 1213 | * @pkt: Entry pointer |
1187 | */ | 1214 | */ |
1188 | static void | 1215 | static void |
1189 | qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | 1216 | qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) |
1190 | { | 1217 | { |
1191 | srb_t *sp; | 1218 | srb_t *sp; |
1192 | 1219 | ||
@@ -1228,15 +1255,15 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1228 | } | 1255 | } |
1229 | qla2x00_sp_compl(ha, sp); | 1256 | qla2x00_sp_compl(ha, sp); |
1230 | 1257 | ||
1231 | } else if (pkt->entry_type == COMMAND_A64_TYPE || | 1258 | } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type == |
1232 | pkt->entry_type == COMMAND_TYPE) { | 1259 | COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7) { |
1233 | DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n", | 1260 | DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n", |
1234 | ha->host_no)); | 1261 | ha->host_no)); |
1235 | qla_printk(KERN_WARNING, ha, | 1262 | qla_printk(KERN_WARNING, ha, |
1236 | "Error entry - invalid handle\n"); | 1263 | "Error entry - invalid handle\n"); |
1237 | 1264 | ||
1238 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 1265 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
1239 | if (ha->dpc_wait && !ha->dpc_active) | 1266 | if (ha->dpc_wait && !ha->dpc_active) |
1240 | up(ha->dpc_wait); | 1267 | up(ha->dpc_wait); |
1241 | } | 1268 | } |
1242 | } | 1269 | } |
@@ -1247,7 +1274,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1247 | * @index: Response queue out pointer | 1274 | * @index: Response queue out pointer |
1248 | */ | 1275 | */ |
1249 | static void | 1276 | static void |
1250 | qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt) | 1277 | qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt) |
1251 | { | 1278 | { |
1252 | srb_t *sp; | 1279 | srb_t *sp; |
1253 | 1280 | ||
@@ -1277,3 +1304,230 @@ qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt) | |||
1277 | 1304 | ||
1278 | qla2x00_sp_compl(ha, sp); | 1305 | qla2x00_sp_compl(ha, sp); |
1279 | } | 1306 | } |
1307 | |||
1308 | |||
1309 | /** | ||
1310 | * qla24xx_mbx_completion() - Process mailbox command completions. | ||
1311 | * @ha: SCSI driver HA context | ||
1312 | * @mb0: Mailbox0 register | ||
1313 | */ | ||
1314 | static void | ||
1315 | qla24xx_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0) | ||
1316 | { | ||
1317 | uint16_t cnt; | ||
1318 | uint16_t __iomem *wptr; | ||
1319 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
1320 | |||
1321 | /* Load return mailbox registers. */ | ||
1322 | ha->flags.mbox_int = 1; | ||
1323 | ha->mailbox_out[0] = mb0; | ||
1324 | wptr = (uint16_t __iomem *)®->mailbox1; | ||
1325 | |||
1326 | for (cnt = 1; cnt < ha->mbx_count; cnt++) { | ||
1327 | ha->mailbox_out[cnt] = RD_REG_WORD(wptr); | ||
1328 | wptr++; | ||
1329 | } | ||
1330 | |||
1331 | if (ha->mcp) { | ||
1332 | DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n", | ||
1333 | __func__, ha->host_no, ha->mcp->mb[0])); | ||
1334 | } else { | ||
1335 | DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n", | ||
1336 | __func__, ha->host_no)); | ||
1337 | } | ||
1338 | } | ||
1339 | |||
1340 | /** | ||
1341 | * qla24xx_process_response_queue() - Process response queue entries. | ||
1342 | * @ha: SCSI driver HA context | ||
1343 | */ | ||
1344 | void | ||
1345 | qla24xx_process_response_queue(struct scsi_qla_host *ha) | ||
1346 | { | ||
1347 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
1348 | struct sts_entry_24xx *pkt; | ||
1349 | |||
1350 | if (!ha->flags.online) | ||
1351 | return; | ||
1352 | |||
1353 | while (ha->response_ring_ptr->signature != RESPONSE_PROCESSED) { | ||
1354 | pkt = (struct sts_entry_24xx *)ha->response_ring_ptr; | ||
1355 | |||
1356 | ha->rsp_ring_index++; | ||
1357 | if (ha->rsp_ring_index == ha->response_q_length) { | ||
1358 | ha->rsp_ring_index = 0; | ||
1359 | ha->response_ring_ptr = ha->response_ring; | ||
1360 | } else { | ||
1361 | ha->response_ring_ptr++; | ||
1362 | } | ||
1363 | |||
1364 | if (pkt->entry_status != 0) { | ||
1365 | DEBUG3(printk(KERN_INFO | ||
1366 | "scsi(%ld): Process error entry.\n", ha->host_no)); | ||
1367 | |||
1368 | //FIXME | ||
1369 | qla2x00_error_entry(ha, (sts_entry_t *) pkt); | ||
1370 | ((response_t *)pkt)->signature = RESPONSE_PROCESSED; | ||
1371 | wmb(); | ||
1372 | continue; | ||
1373 | } | ||
1374 | |||
1375 | switch (pkt->entry_type) { | ||
1376 | case STATUS_TYPE: | ||
1377 | qla2x00_status_entry(ha, pkt); | ||
1378 | break; | ||
1379 | case STATUS_CONT_TYPE: | ||
1380 | qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt); | ||
1381 | break; | ||
1382 | case MS_IOCB_TYPE: | ||
1383 | qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt); | ||
1384 | break; | ||
1385 | default: | ||
1386 | /* Type Not Supported. */ | ||
1387 | DEBUG4(printk(KERN_WARNING | ||
1388 | "scsi(%ld): Received unknown response pkt type %x " | ||
1389 | "entry status=%x.\n", | ||
1390 | ha->host_no, pkt->entry_type, pkt->entry_status)); | ||
1391 | break; | ||
1392 | } | ||
1393 | ((response_t *)pkt)->signature = RESPONSE_PROCESSED; | ||
1394 | wmb(); | ||
1395 | } | ||
1396 | |||
1397 | /* Adjust ring index */ | ||
1398 | WRT_REG_DWORD(®->rsp_q_out, ha->rsp_ring_index); | ||
1399 | } | ||
1400 | |||
1401 | /** | ||
1402 | * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. | ||
1403 | * @irq: | ||
1404 | * @dev_id: SCSI driver HA context | ||
1405 | * @regs: | ||
1406 | * | ||
1407 | * Called by system whenever the host adapter generates an interrupt. | ||
1408 | * | ||
1409 | * Returns handled flag. | ||
1410 | */ | ||
1411 | irqreturn_t | ||
1412 | qla24xx_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
1413 | { | ||
1414 | scsi_qla_host_t *ha; | ||
1415 | struct device_reg_24xx __iomem *reg; | ||
1416 | int status; | ||
1417 | unsigned long flags; | ||
1418 | unsigned long iter; | ||
1419 | uint32_t stat; | ||
1420 | uint32_t hccr; | ||
1421 | uint16_t mb[4]; | ||
1422 | |||
1423 | ha = (scsi_qla_host_t *) dev_id; | ||
1424 | if (!ha) { | ||
1425 | printk(KERN_INFO | ||
1426 | "%s(): NULL host pointer\n", __func__); | ||
1427 | return IRQ_NONE; | ||
1428 | } | ||
1429 | |||
1430 | reg = &ha->iobase->isp24; | ||
1431 | status = 0; | ||
1432 | |||
1433 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1434 | for (iter = 50; iter--; ) { | ||
1435 | stat = RD_REG_DWORD(®->host_status); | ||
1436 | if (stat & HSRX_RISC_PAUSED) { | ||
1437 | hccr = RD_REG_DWORD(®->hccr); | ||
1438 | |||
1439 | qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " | ||
1440 | "Dumping firmware!\n", hccr); | ||
1441 | qla24xx_fw_dump(ha, 1); | ||
1442 | |||
1443 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
1444 | break; | ||
1445 | } else if ((stat & HSRX_RISC_INT) == 0) | ||
1446 | break; | ||
1447 | |||
1448 | switch (stat & 0xff) { | ||
1449 | case 0x1: | ||
1450 | case 0x2: | ||
1451 | case 0x10: | ||
1452 | case 0x11: | ||
1453 | qla24xx_mbx_completion(ha, MSW(stat)); | ||
1454 | status |= MBX_INTERRUPT; | ||
1455 | |||
1456 | break; | ||
1457 | case 0x12: | ||
1458 | mb[0] = MSW(stat); | ||
1459 | mb[1] = RD_REG_WORD(®->mailbox1); | ||
1460 | mb[2] = RD_REG_WORD(®->mailbox2); | ||
1461 | mb[3] = RD_REG_WORD(®->mailbox3); | ||
1462 | qla2x00_async_event(ha, mb); | ||
1463 | break; | ||
1464 | case 0x13: | ||
1465 | qla24xx_process_response_queue(ha); | ||
1466 | break; | ||
1467 | default: | ||
1468 | DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " | ||
1469 | "(%d).\n", | ||
1470 | ha->host_no, stat & 0xff)); | ||
1471 | break; | ||
1472 | } | ||
1473 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | ||
1474 | RD_REG_DWORD_RELAXED(®->hccr); | ||
1475 | } | ||
1476 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1477 | |||
1478 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | ||
1479 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | ||
1480 | spin_lock_irqsave(&ha->mbx_reg_lock, flags); | ||
1481 | |||
1482 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
1483 | up(&ha->mbx_intr_sem); | ||
1484 | |||
1485 | spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); | ||
1486 | } | ||
1487 | |||
1488 | return IRQ_HANDLED; | ||
1489 | } | ||
1490 | |||
1491 | /** | ||
1492 | * qla24xx_ms_entry() - Process a Management Server entry. | ||
1493 | * @ha: SCSI driver HA context | ||
1494 | * @index: Response queue out pointer | ||
1495 | */ | ||
1496 | static void | ||
1497 | qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt) | ||
1498 | { | ||
1499 | srb_t *sp; | ||
1500 | |||
1501 | DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n", | ||
1502 | __func__, ha->host_no, pkt, pkt->handle)); | ||
1503 | |||
1504 | DEBUG9(printk("%s: ct pkt dump:\n", __func__);) | ||
1505 | DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx));) | ||
1506 | |||
1507 | /* Validate handle. */ | ||
1508 | if (pkt->handle < MAX_OUTSTANDING_COMMANDS) | ||
1509 | sp = ha->outstanding_cmds[pkt->handle]; | ||
1510 | else | ||
1511 | sp = NULL; | ||
1512 | |||
1513 | if (sp == NULL) { | ||
1514 | DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n", | ||
1515 | ha->host_no)); | ||
1516 | DEBUG10(printk("scsi(%ld): MS entry - invalid handle\n", | ||
1517 | ha->host_no)); | ||
1518 | qla_printk(KERN_WARNING, ha, "MS entry - invalid handle %d\n", | ||
1519 | pkt->handle); | ||
1520 | |||
1521 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
1522 | return; | ||
1523 | } | ||
1524 | |||
1525 | CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status); | ||
1526 | CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status; | ||
1527 | |||
1528 | /* Free outstanding command slot. */ | ||
1529 | ha->outstanding_cmds[pkt->handle] = NULL; | ||
1530 | |||
1531 | qla2x00_sp_compl(ha, sp); | ||
1532 | } | ||
1533 | |||