diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 624 |
1 files changed, 437 insertions, 187 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index e7a8b74157a5..f910de6dd437 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * QLOGIC LINUX SOFTWARE | 2 | * QLOGIC LINUX SOFTWARE |
3 | * | 3 | * |
4 | * QLogic ISP2x00 device driver for Linux 2.6.x | 4 | * QLogic ISP2x00 device driver for Linux 2.6.x |
5 | * Copyright (C) 2003-2004 QLogic Corporation | 5 | * Copyright (C) 2003-2005 QLogic Corporation |
6 | * (www.qlogic.com) | 6 | * (www.qlogic.com) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
@@ -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: |
@@ -41,11 +44,11 @@ irqreturn_t | |||
41 | qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | 44 | qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs) |
42 | { | 45 | { |
43 | scsi_qla_host_t *ha; | 46 | scsi_qla_host_t *ha; |
44 | device_reg_t __iomem *reg; | 47 | struct device_reg_2xxx __iomem *reg; |
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) { |
@@ -54,7 +57,7 @@ qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
54 | return (IRQ_NONE); | 57 | return (IRQ_NONE); |
55 | } | 58 | } |
56 | 59 | ||
57 | reg = ha->iobase; | 60 | reg = &ha->iobase->isp; |
58 | status = 0; | 61 | status = 0; |
59 | 62 | ||
60 | spin_lock_irqsave(&ha->hardware_lock, flags); | 63 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -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); |
@@ -118,13 +124,13 @@ irqreturn_t | |||
118 | qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | 124 | qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs) |
119 | { | 125 | { |
120 | scsi_qla_host_t *ha; | 126 | scsi_qla_host_t *ha; |
121 | device_reg_t __iomem *reg; | 127 | struct device_reg_2xxx __iomem *reg; |
122 | int status; | 128 | int status; |
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) { |
@@ -133,7 +139,7 @@ qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
133 | return (IRQ_NONE); | 139 | return (IRQ_NONE); |
134 | } | 140 | } |
135 | 141 | ||
136 | reg = ha->iobase; | 142 | reg = &ha->iobase->isp; |
137 | status = 0; | 143 | status = 0; |
138 | 144 | ||
139 | spin_lock_irqsave(&ha->hardware_lock, flags); | 145 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -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 | } |
@@ -220,7 +232,7 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0) | |||
220 | { | 232 | { |
221 | uint16_t cnt; | 233 | uint16_t cnt; |
222 | uint16_t __iomem *wptr; | 234 | uint16_t __iomem *wptr; |
223 | device_reg_t __iomem *reg = ha->iobase; | 235 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
224 | 236 | ||
225 | /* Load return mailbox registers. */ | 237 | /* Load return mailbox registers. */ |
226 | ha->flags.mbox_int = 1; | 238 | ha->flags.mbox_int = 1; |
@@ -228,13 +240,13 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0) | |||
228 | wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1); | 240 | wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1); |
229 | 241 | ||
230 | for (cnt = 1; cnt < ha->mbx_count; cnt++) { | 242 | for (cnt = 1; cnt < ha->mbx_count; cnt++) { |
231 | if (IS_QLA2200(ha) && cnt == 8) | 243 | if (IS_QLA2200(ha) && cnt == 8) |
232 | wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8); | 244 | wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8); |
233 | if (cnt == 4 || cnt == 5) | 245 | if (cnt == 4 || cnt == 5) |
234 | ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr); | 246 | ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr); |
235 | else | 247 | else |
236 | ha->mailbox_out[cnt] = RD_REG_WORD(wptr); | 248 | ha->mailbox_out[cnt] = RD_REG_WORD(wptr); |
237 | 249 | ||
238 | wptr++; | 250 | wptr++; |
239 | } | 251 | } |
240 | 252 | ||
@@ -250,78 +262,65 @@ 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]; |
264 | device_reg_t __iomem *reg = ha->iobase; | 276 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
265 | uint32_t rscn_entry, host_pid; | 277 | uint32_t rscn_entry, host_pid; |
266 | uint8_t rscn_queue_index; | 278 | uint8_t rscn_queue_index; |
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)); |
@@ -356,12 +355,17 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
356 | "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", | 355 | "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", |
357 | mb[1], mb[2], mb[3]); | 356 | mb[1], mb[2], mb[3]); |
358 | 357 | ||
359 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | 358 | ha->isp_ops.fw_dump(ha, 1); |
360 | qla2100_fw_dump(ha, 1); | 359 | |
361 | else | 360 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { |
362 | qla2300_fw_dump(ha, 1); | 361 | if (mb[1] == 0 && mb[2] == 0) { |
363 | 362 | qla_printk(KERN_ERR, ha, | |
364 | if (mb[1] == 0) { | 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) { | ||
365 | qla_printk(KERN_INFO, ha, | 369 | qla_printk(KERN_INFO, ha, |
366 | "Unrecoverable Hardware Error: adapter marked " | 370 | "Unrecoverable Hardware Error: adapter marked " |
367 | "OFFLINE!\n"); | 371 | "OFFLINE!\n"); |
@@ -392,8 +396,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
392 | break; | 396 | break; |
393 | 397 | ||
394 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ | 398 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ |
395 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
396 | |||
397 | DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no, | 399 | DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no, |
398 | mb[1])); | 400 | mb[1])); |
399 | qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]); | 401 | qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]); |
@@ -414,13 +416,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
414 | break; | 416 | break; |
415 | 417 | ||
416 | case MBA_LOOP_UP: /* Loop Up Event */ | 418 | case MBA_LOOP_UP: /* Loop Up Event */ |
417 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
418 | |||
419 | ha->link_data_rate = 0; | 419 | ha->link_data_rate = 0; |
420 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 420 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
421 | link_speed = link_speeds[0]; | 421 | link_speed = link_speeds[0]; |
422 | } else { | 422 | } else { |
423 | link_speed = link_speeds[3]; | 423 | link_speed = link_speeds[LS_UNKNOWN]; |
424 | if (mb[1] < 5) | 424 | if (mb[1] < 5) |
425 | link_speed = link_speeds[mb[1]]; | 425 | link_speed = link_speeds[mb[1]]; |
426 | ha->link_data_rate = mb[1]; | 426 | ha->link_data_rate = mb[1]; |
@@ -438,9 +438,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
438 | break; | 438 | break; |
439 | 439 | ||
440 | case MBA_LOOP_DOWN: /* Loop Down Event */ | 440 | case MBA_LOOP_DOWN: /* Loop Down Event */ |
441 | DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN.\n", | 441 | DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n", |
442 | ha->host_no)); | 442 | ha->host_no, mb[1])); |
443 | qla_printk(KERN_INFO, ha, "LOOP DOWN detected.\n"); | 443 | qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]); |
444 | 444 | ||
445 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 445 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
446 | atomic_set(&ha->loop_state, LOOP_DOWN); | 446 | atomic_set(&ha->loop_state, LOOP_DOWN); |
@@ -457,8 +457,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
457 | break; | 457 | break; |
458 | 458 | ||
459 | case MBA_LIP_RESET: /* LIP reset occurred */ | 459 | case MBA_LIP_RESET: /* LIP reset occurred */ |
460 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
461 | |||
462 | DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", | 460 | DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", |
463 | ha->host_no, mb[1])); | 461 | ha->host_no, mb[1])); |
464 | qla_printk(KERN_INFO, ha, | 462 | qla_printk(KERN_INFO, ha, |
@@ -509,8 +507,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
509 | if (IS_QLA2100(ha)) | 507 | if (IS_QLA2100(ha)) |
510 | break; | 508 | break; |
511 | 509 | ||
512 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
513 | |||
514 | DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection " | 510 | DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection " |
515 | "received.\n", | 511 | "received.\n", |
516 | ha->host_no)); | 512 | ha->host_no)); |
@@ -518,7 +514,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
518 | "Configuration change detected: value=%x.\n", mb[1]); | 514 | "Configuration change detected: value=%x.\n", mb[1]); |
519 | 515 | ||
520 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 516 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
521 | atomic_set(&ha->loop_state, LOOP_DOWN); | 517 | atomic_set(&ha->loop_state, LOOP_DOWN); |
522 | if (!atomic_read(&ha->loop_down_timer)) | 518 | if (!atomic_read(&ha->loop_down_timer)) |
523 | atomic_set(&ha->loop_down_timer, | 519 | atomic_set(&ha->loop_down_timer, |
524 | LOOP_DOWN_TIME); | 520 | LOOP_DOWN_TIME); |
@@ -530,16 +526,14 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
530 | break; | 526 | break; |
531 | 527 | ||
532 | case MBA_PORT_UPDATE: /* Port database update */ | 528 | case MBA_PORT_UPDATE: /* Port database update */ |
533 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
534 | mb[2] = RD_MAILBOX_REG(ha, reg, 2); | ||
535 | |||
536 | /* | 529 | /* |
537 | * 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) |
538 | * 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 |
539 | * the event like an RSCN. | 532 | * the event like an RSCN. |
540 | */ | 533 | */ |
541 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && | 534 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && |
542 | !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 && | ||
543 | ((ha->operating_mode == P2P && mb[1] != 0) || | 537 | ((ha->operating_mode == P2P && mb[1] != 0) || |
544 | (ha->operating_mode != P2P && mb[1] != | 538 | (ha->operating_mode != P2P && mb[1] != |
545 | SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) { | 539 | SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) { |
@@ -550,8 +544,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
550 | rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC); | 544 | rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC); |
551 | if (rscn_fcport) { | 545 | if (rscn_fcport) { |
552 | DEBUG14(printk("scsi(%ld): Port Update -- " | 546 | DEBUG14(printk("scsi(%ld): Port Update -- " |
553 | "creating RSCN fcport %p for %x/%x.\n", | 547 | "creating RSCN fcport %p for %x/%x/%x.\n", |
554 | ha->host_no, rscn_fcport, mb[1], mb[2])); | 548 | ha->host_no, rscn_fcport, mb[1], mb[2], |
549 | mb[3])); | ||
555 | 550 | ||
556 | rscn_fcport->loop_id = mb[1]; | 551 | rscn_fcport->loop_id = mb[1]; |
557 | rscn_fcport->d_id.b24 = INVALID_PORT_ID; | 552 | rscn_fcport->d_id.b24 = INVALID_PORT_ID; |
@@ -580,15 +575,16 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
580 | if (atomic_read(&ha->loop_state) != LOOP_DOWN && | 575 | if (atomic_read(&ha->loop_state) != LOOP_DOWN && |
581 | atomic_read(&ha->loop_state) != LOOP_DEAD) { | 576 | atomic_read(&ha->loop_state) != LOOP_DEAD) { |
582 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE " | 577 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE " |
583 | "ignored.\n", ha->host_no)); | 578 | "ignored %04x/%04x/%04x.\n", ha->host_no, mb[1], |
579 | mb[2], mb[3])); | ||
584 | break; | 580 | break; |
585 | } | 581 | } |
586 | 582 | ||
587 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n", | 583 | DEBUG2(printk("scsi(%ld): Asynchronous PORT UPDATE.\n", |
588 | ha->host_no)); | 584 | ha->host_no)); |
589 | DEBUG(printk(KERN_INFO | 585 | DEBUG(printk(KERN_INFO |
590 | "scsi(%ld): Port database changed %04x %04x.\n", | 586 | "scsi(%ld): Port database changed %04x %04x %04x.\n", |
591 | ha->host_no, mb[1], mb[2])); | 587 | ha->host_no, mb[1], mb[2], mb[3])); |
592 | 588 | ||
593 | /* | 589 | /* |
594 | * Mark all devices as missing so we will login again. | 590 | * Mark all devices as missing so we will login again. |
@@ -607,9 +603,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
607 | break; | 603 | break; |
608 | 604 | ||
609 | case MBA_RSCN_UPDATE: /* State Change Registration */ | 605 | case MBA_RSCN_UPDATE: /* State Change Registration */ |
610 | mb[1] = RD_MAILBOX_REG(ha, reg, 1); | ||
611 | mb[2] = RD_MAILBOX_REG(ha, reg, 2); | ||
612 | |||
613 | DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", | 606 | DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", |
614 | ha->host_no)); | 607 | ha->host_no)); |
615 | DEBUG(printk(KERN_INFO | 608 | DEBUG(printk(KERN_INFO |
@@ -658,6 +651,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) | |||
658 | 651 | ||
659 | qla2x00_process_response_queue(ha); | 652 | qla2x00_process_response_queue(ha); |
660 | 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; | ||
661 | } | 659 | } |
662 | } | 660 | } |
663 | 661 | ||
@@ -710,7 +708,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *ha, uint32_t index) | |||
710 | void | 708 | void |
711 | qla2x00_process_response_queue(struct scsi_qla_host *ha) | 709 | qla2x00_process_response_queue(struct scsi_qla_host *ha) |
712 | { | 710 | { |
713 | device_reg_t __iomem *reg = ha->iobase; | 711 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
714 | sts_entry_t *pkt; | 712 | sts_entry_t *pkt; |
715 | uint16_t handle_cnt; | 713 | uint16_t handle_cnt; |
716 | uint16_t cnt; | 714 | uint16_t cnt; |
@@ -804,31 +802,41 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha) | |||
804 | * @pkt: Entry pointer | 802 | * @pkt: Entry pointer |
805 | */ | 803 | */ |
806 | static void | 804 | static void |
807 | qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | 805 | qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) |
808 | { | 806 | { |
809 | unsigned b, t, l; | ||
810 | srb_t *sp; | 807 | srb_t *sp; |
811 | fc_port_t *fcport; | 808 | fc_port_t *fcport; |
812 | struct scsi_cmnd *cp; | 809 | struct scsi_cmnd *cp; |
810 | sts_entry_t *sts; | ||
811 | struct sts_entry_24xx *sts24; | ||
813 | uint16_t comp_status; | 812 | uint16_t comp_status; |
814 | uint16_t scsi_status; | 813 | uint16_t scsi_status; |
815 | uint8_t lscsi_status; | 814 | uint8_t lscsi_status; |
816 | int32_t resid; | 815 | int32_t resid; |
817 | uint8_t sense_sz = 0; | 816 | uint32_t sense_len, rsp_info_len, resid_len; |
818 | 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 | } | ||
819 | 828 | ||
820 | /* Fast path completion. */ | 829 | /* Fast path completion. */ |
821 | if (le16_to_cpu(pkt->comp_status) == CS_COMPLETE && | 830 | if (comp_status == CS_COMPLETE && scsi_status == 0) { |
822 | (le16_to_cpu(pkt->scsi_status) & SS_MASK) == 0) { | 831 | qla2x00_process_completed_request(ha, sts->handle); |
823 | qla2x00_process_completed_request(ha, pkt->handle); | ||
824 | 832 | ||
825 | return; | 833 | return; |
826 | } | 834 | } |
827 | 835 | ||
828 | /* Validate handle. */ | 836 | /* Validate handle. */ |
829 | if (pkt->handle < MAX_OUTSTANDING_COMMANDS) { | 837 | if (sts->handle < MAX_OUTSTANDING_COMMANDS) { |
830 | sp = ha->outstanding_cmds[pkt->handle]; | 838 | sp = ha->outstanding_cmds[sts->handle]; |
831 | ha->outstanding_cmds[pkt->handle] = NULL; | 839 | ha->outstanding_cmds[sts->handle] = NULL; |
832 | } else | 840 | } else |
833 | sp = NULL; | 841 | sp = NULL; |
834 | 842 | ||
@@ -838,7 +846,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
838 | qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n"); | 846 | qla_printk(KERN_WARNING, ha, "Status Entry invalid handle.\n"); |
839 | 847 | ||
840 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 848 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
841 | if (ha->dpc_wait && !ha->dpc_active) | 849 | if (ha->dpc_wait && !ha->dpc_active) |
842 | up(ha->dpc_wait); | 850 | up(ha->dpc_wait); |
843 | 851 | ||
844 | return; | 852 | return; |
@@ -847,40 +855,49 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
847 | if (cp == NULL) { | 855 | if (cp == NULL) { |
848 | DEBUG2(printk("scsi(%ld): Command already returned back to OS " | 856 | DEBUG2(printk("scsi(%ld): Command already returned back to OS " |
849 | "pkt->handle=%d sp=%p sp->state:%d\n", | 857 | "pkt->handle=%d sp=%p sp->state:%d\n", |
850 | ha->host_no, pkt->handle, sp, sp->state)); | 858 | ha->host_no, sts->handle, sp, sp->state)); |
851 | qla_printk(KERN_WARNING, ha, | 859 | qla_printk(KERN_WARNING, ha, |
852 | "Command is NULL: already returned to OS (sp=%p)\n", sp); | 860 | "Command is NULL: already returned to OS (sp=%p)\n", sp); |
853 | 861 | ||
854 | return; | 862 | return; |
855 | } | 863 | } |
856 | 864 | ||
857 | comp_status = le16_to_cpu(pkt->comp_status); | 865 | lscsi_status = scsi_status & STATUS_MASK; |
858 | /* Mask of reserved bits 12-15, before we examine the scsi status */ | 866 | CMD_ENTRY_STATUS(cp) = sts->entry_status; |
859 | scsi_status = le16_to_cpu(pkt->scsi_status) & SS_MASK; | ||
860 | lscsi_status = scsi_status & STATUS_MASK; | ||
861 | |||
862 | CMD_ENTRY_STATUS(cp) = pkt->entry_status; | ||
863 | CMD_COMPL_STATUS(cp) = comp_status; | 867 | CMD_COMPL_STATUS(cp) = comp_status; |
864 | CMD_SCSI_STATUS(cp) = scsi_status; | 868 | CMD_SCSI_STATUS(cp) = scsi_status; |
865 | 869 | ||
866 | /* Generate LU queue on cntrl, target, LUN */ | ||
867 | b = cp->device->channel; | ||
868 | t = cp->device->id; | ||
869 | l = cp->device->lun, | ||
870 | |||
871 | fcport = sp->fcport; | 870 | fcport = sp->fcport; |
872 | 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 | |||
873 | /* Check for any FCP transport errors. */ | 888 | /* Check for any FCP transport errors. */ |
874 | if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { | 889 | if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { |
875 | rsp_info_len = le16_to_cpu(pkt->rsp_info_len); | 890 | /* Sense data lies beyond any FCP RESPONSE data. */ |
876 | 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]) { | ||
877 | DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " | 894 | DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " |
878 | "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..." | 895 | "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..." |
879 | "retrying command\n", ha->host_no, b, t, l, | 896 | "retrying command\n", ha->host_no, |
880 | rsp_info_len, pkt->rsp_info[0], pkt->rsp_info[1], | 897 | cp->device->channel, cp->device->id, |
881 | pkt->rsp_info[2], pkt->rsp_info[3], | 898 | cp->device->lun, rsp_info_len, rsp_info[0], |
882 | pkt->rsp_info[4], pkt->rsp_info[5], | 899 | rsp_info[1], rsp_info[2], rsp_info[3], rsp_info[4], |
883 | pkt->rsp_info[6], pkt->rsp_info[7])); | 900 | rsp_info[5], rsp_info[6], rsp_info[7])); |
884 | 901 | ||
885 | cp->result = DID_BUS_BUSY << 16; | 902 | cp->result = DID_BUS_BUSY << 16; |
886 | qla2x00_sp_compl(ha, sp); | 903 | qla2x00_sp_compl(ha, sp); |
@@ -898,7 +915,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
898 | break; | 915 | break; |
899 | } | 916 | } |
900 | if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) { | 917 | if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) { |
901 | resid = le32_to_cpu(pkt->residual_length); | 918 | resid = resid_len; |
902 | cp->resid = resid; | 919 | cp->resid = resid; |
903 | CMD_RESID_LEN(cp) = resid; | 920 | CMD_RESID_LEN(cp) = resid; |
904 | } | 921 | } |
@@ -907,39 +924,34 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
907 | if (lscsi_status != SS_CHECK_CONDITION) | 924 | if (lscsi_status != SS_CHECK_CONDITION) |
908 | break; | 925 | break; |
909 | 926 | ||
910 | /* | 927 | /* Copy Sense Data into sense buffer. */ |
911 | * Copy Sense Data into sense buffer | ||
912 | */ | ||
913 | memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer)); | 928 | memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer)); |
914 | 929 | ||
915 | if (!(scsi_status & SS_SENSE_LEN_VALID)) | 930 | if (!(scsi_status & SS_SENSE_LEN_VALID)) |
916 | break; | 931 | break; |
917 | 932 | ||
918 | if (le16_to_cpu(pkt->req_sense_length) < | 933 | if (sense_len >= sizeof(cp->sense_buffer)) |
919 | sizeof(cp->sense_buffer)) | 934 | sense_len = sizeof(cp->sense_buffer); |
920 | sense_sz = le16_to_cpu(pkt->req_sense_length); | ||
921 | else | ||
922 | sense_sz = sizeof(cp->sense_buffer); | ||
923 | 935 | ||
924 | CMD_ACTUAL_SNSLEN(cp) = sense_sz; | 936 | CMD_ACTUAL_SNSLEN(cp) = sense_len; |
925 | sp->request_sense_length = sense_sz; | 937 | sp->request_sense_length = sense_len; |
926 | sp->request_sense_ptr = cp->sense_buffer; | 938 | sp->request_sense_ptr = cp->sense_buffer; |
927 | 939 | ||
928 | if (sp->request_sense_length > 32) | 940 | if (sp->request_sense_length > 32) |
929 | sense_sz = 32; | 941 | sense_len = 32; |
930 | 942 | ||
931 | memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz); | 943 | memcpy(cp->sense_buffer, sense_data, sense_len); |
932 | 944 | ||
933 | sp->request_sense_ptr += sense_sz; | 945 | sp->request_sense_ptr += sense_len; |
934 | sp->request_sense_length -= sense_sz; | 946 | sp->request_sense_length -= sense_len; |
935 | if (sp->request_sense_length != 0) | 947 | if (sp->request_sense_length != 0) |
936 | ha->status_srb = sp; | 948 | ha->status_srb = sp; |
937 | 949 | ||
938 | DEBUG5(printk("%s(): Check condition Sense data, " | 950 | DEBUG5(printk("%s(): Check condition Sense data, " |
939 | "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", | 951 | "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", __func__, |
940 | __func__, ha->host_no, b, t, l, cp, | 952 | ha->host_no, cp->device->channel, cp->device->id, |
941 | cp->serial_number)); | 953 | cp->device->lun, cp, cp->serial_number)); |
942 | if (sense_sz) | 954 | if (sense_len) |
943 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, | 955 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, |
944 | CMD_ACTUAL_SNSLEN(cp))); | 956 | CMD_ACTUAL_SNSLEN(cp))); |
945 | break; | 957 | break; |
@@ -947,16 +959,17 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
947 | case CS_DATA_UNDERRUN: | 959 | case CS_DATA_UNDERRUN: |
948 | DEBUG2(printk(KERN_INFO | 960 | DEBUG2(printk(KERN_INFO |
949 | "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", |
950 | ha->host_no, t, l, comp_status, scsi_status)); | 962 | ha->host_no, cp->device->id, cp->device->lun, comp_status, |
963 | scsi_status)); | ||
951 | 964 | ||
952 | resid = le32_to_cpu(pkt->residual_length); | 965 | resid = resid_len; |
953 | if (scsi_status & SS_RESIDUAL_UNDER) { | 966 | if (scsi_status & SS_RESIDUAL_UNDER) { |
954 | cp->resid = resid; | 967 | cp->resid = resid; |
955 | CMD_RESID_LEN(cp) = resid; | 968 | CMD_RESID_LEN(cp) = resid; |
956 | } | 969 | } |
957 | 970 | ||
958 | /* | 971 | /* |
959 | * Check to see if SCSI Status is non zero. If so report SCSI | 972 | * Check to see if SCSI Status is non zero. If so report SCSI |
960 | * Status. | 973 | * Status. |
961 | */ | 974 | */ |
962 | if (lscsi_status != 0) { | 975 | if (lscsi_status != 0) { |
@@ -971,31 +984,30 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
971 | if (!(scsi_status & SS_SENSE_LEN_VALID)) | 984 | if (!(scsi_status & SS_SENSE_LEN_VALID)) |
972 | break; | 985 | break; |
973 | 986 | ||
974 | if (le16_to_cpu(pkt->req_sense_length) < | 987 | if (sense_len >= sizeof(cp->sense_buffer)) |
975 | sizeof(cp->sense_buffer)) | 988 | sense_len = sizeof(cp->sense_buffer); |
976 | sense_sz = le16_to_cpu(pkt->req_sense_length); | ||
977 | else | ||
978 | sense_sz = sizeof(cp->sense_buffer); | ||
979 | 989 | ||
980 | CMD_ACTUAL_SNSLEN(cp) = sense_sz; | 990 | CMD_ACTUAL_SNSLEN(cp) = sense_len; |
981 | sp->request_sense_length = sense_sz; | 991 | sp->request_sense_length = sense_len; |
982 | sp->request_sense_ptr = cp->sense_buffer; | 992 | sp->request_sense_ptr = cp->sense_buffer; |
983 | 993 | ||
984 | if (sp->request_sense_length > 32) | 994 | if (sp->request_sense_length > 32) |
985 | sense_sz = 32; | 995 | sense_len = 32; |
986 | 996 | ||
987 | memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz); | 997 | memcpy(cp->sense_buffer, sense_data, sense_len); |
988 | 998 | ||
989 | sp->request_sense_ptr += sense_sz; | 999 | sp->request_sense_ptr += sense_len; |
990 | sp->request_sense_length -= sense_sz; | 1000 | sp->request_sense_length -= sense_len; |
991 | if (sp->request_sense_length != 0) | 1001 | if (sp->request_sense_length != 0) |
992 | ha->status_srb = sp; | 1002 | ha->status_srb = sp; |
993 | 1003 | ||
994 | DEBUG5(printk("%s(): Check condition Sense data, " | 1004 | DEBUG5(printk("%s(): Check condition Sense data, " |
995 | "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", | 1005 | "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", |
996 | __func__, ha->host_no, b, t, l, cp, | 1006 | __func__, ha->host_no, cp->device->channel, |
1007 | cp->device->id, cp->device->lun, cp, | ||
997 | cp->serial_number)); | 1008 | cp->serial_number)); |
998 | if (sense_sz) | 1009 | |
1010 | if (sense_len) | ||
999 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, | 1011 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, |
1000 | CMD_ACTUAL_SNSLEN(cp))); | 1012 | CMD_ACTUAL_SNSLEN(cp))); |
1001 | } else { | 1013 | } else { |
@@ -1007,8 +1019,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1007 | if (!(scsi_status & SS_RESIDUAL_UNDER)) { | 1019 | if (!(scsi_status & SS_RESIDUAL_UNDER)) { |
1008 | DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped " | 1020 | DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped " |
1009 | "frame(s) detected (%x of %x bytes)..." | 1021 | "frame(s) detected (%x of %x bytes)..." |
1010 | "retrying command.\n", | 1022 | "retrying command.\n", ha->host_no, |
1011 | ha->host_no, b, t, l, resid, | 1023 | cp->device->channel, cp->device->id, |
1024 | cp->device->lun, resid, | ||
1012 | cp->request_bufflen)); | 1025 | cp->request_bufflen)); |
1013 | 1026 | ||
1014 | cp->result = DID_BUS_BUSY << 16; | 1027 | cp->result = DID_BUS_BUSY << 16; |
@@ -1021,8 +1034,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1021 | qla_printk(KERN_INFO, ha, | 1034 | qla_printk(KERN_INFO, ha, |
1022 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " | 1035 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " |
1023 | "detected (%x of %x bytes)...returning " | 1036 | "detected (%x of %x bytes)...returning " |
1024 | "error status.\n", | 1037 | "error status.\n", ha->host_no, |
1025 | ha->host_no, b, t, l, resid, | 1038 | cp->device->channel, cp->device->id, |
1039 | cp->device->lun, resid, | ||
1026 | cp->request_bufflen); | 1040 | cp->request_bufflen); |
1027 | 1041 | ||
1028 | cp->result = DID_ERROR << 16; | 1042 | cp->result = DID_ERROR << 16; |
@@ -1037,7 +1051,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1037 | case CS_DATA_OVERRUN: | 1051 | case CS_DATA_OVERRUN: |
1038 | DEBUG2(printk(KERN_INFO | 1052 | DEBUG2(printk(KERN_INFO |
1039 | "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", |
1040 | ha->host_no, t, l, comp_status, scsi_status)); | 1054 | ha->host_no, cp->device->id, cp->device->lun, comp_status, |
1055 | scsi_status)); | ||
1041 | DEBUG2(printk(KERN_INFO | 1056 | DEBUG2(printk(KERN_INFO |
1042 | "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", |
1043 | 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], |
@@ -1045,8 +1060,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1045 | DEBUG2(printk(KERN_INFO | 1060 | DEBUG2(printk(KERN_INFO |
1046 | "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 " |
1047 | "status!\n", | 1062 | "status!\n", |
1048 | cp->serial_number, cp->request_bufflen, | 1063 | cp->serial_number, cp->request_bufflen, resid_len)); |
1049 | le32_to_cpu(pkt->residual_length))); | ||
1050 | 1064 | ||
1051 | cp->result = DID_ERROR << 16; | 1065 | cp->result = DID_ERROR << 16; |
1052 | break; | 1066 | break; |
@@ -1063,7 +1077,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1063 | */ | 1077 | */ |
1064 | DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down " | 1078 | DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down " |
1065 | "pid=%ld, compl status=0x%x, port state=0x%x\n", | 1079 | "pid=%ld, compl status=0x%x, port state=0x%x\n", |
1066 | 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, | ||
1067 | atomic_read(&fcport->state))); | 1082 | atomic_read(&fcport->state))); |
1068 | 1083 | ||
1069 | cp->result = DID_BUS_BUSY << 16; | 1084 | cp->result = DID_BUS_BUSY << 16; |
@@ -1081,7 +1096,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1081 | break; | 1096 | break; |
1082 | 1097 | ||
1083 | case CS_ABORTED: | 1098 | case CS_ABORTED: |
1084 | /* | 1099 | /* |
1085 | * hv2.19.12 - DID_ABORT does not retry the request if we | 1100 | * hv2.19.12 - DID_ABORT does not retry the request if we |
1086 | * aborted this request then abort otherwise it must be a | 1101 | * aborted this request then abort otherwise it must be a |
1087 | * reset. | 1102 | * reset. |
@@ -1094,17 +1109,25 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1094 | break; | 1109 | break; |
1095 | 1110 | ||
1096 | 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 | } | ||
1097 | DEBUG2(printk(KERN_INFO | 1122 | DEBUG2(printk(KERN_INFO |
1098 | "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 " |
1099 | "sflags=%x.\n", ha->host_no, b, t, l, comp_status, | 1124 | "sflags=%x.\n", ha->host_no, cp->device->channel, |
1100 | scsi_status, le16_to_cpu(pkt->status_flags))); | 1125 | cp->device->id, cp->device->lun, comp_status, scsi_status, |
1101 | 1126 | le16_to_cpu(sts->status_flags))); | |
1102 | cp->result = DID_BUS_BUSY << 16; | ||
1103 | 1127 | ||
1104 | /* Check to see if logout occurred */ | 1128 | /* Check to see if logout occurred. */ |
1105 | if ((le16_to_cpu(pkt->status_flags) & SF_LOGOUT_SENT)) { | 1129 | if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) |
1106 | qla2x00_mark_device_lost(ha, fcport, 1); | 1130 | qla2x00_mark_device_lost(ha, fcport, 1); |
1107 | } | ||
1108 | break; | 1131 | break; |
1109 | 1132 | ||
1110 | case CS_QUEUE_FULL: | 1133 | case CS_QUEUE_FULL: |
@@ -1114,14 +1137,13 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1114 | 1137 | ||
1115 | /* SCSI Mid-Layer handles device queue full */ | 1138 | /* SCSI Mid-Layer handles device queue full */ |
1116 | 1139 | ||
1117 | cp->result = DID_OK << 16 | lscsi_status; | 1140 | cp->result = DID_OK << 16 | lscsi_status; |
1118 | 1141 | ||
1119 | break; | 1142 | break; |
1120 | 1143 | ||
1121 | default: | 1144 | default: |
1122 | DEBUG3(printk("scsi(%ld): Error detected (unknown status) " | 1145 | DEBUG3(printk("scsi(%ld): Error detected (unknown status) " |
1123 | "0x%x-0x%x.\n", | 1146 | "0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); |
1124 | ha->host_no, comp_status, scsi_status)); | ||
1125 | qla_printk(KERN_INFO, ha, | 1147 | qla_printk(KERN_INFO, ha, |
1126 | "Unknown status detected 0x%x-0x%x.\n", | 1148 | "Unknown status detected 0x%x-0x%x.\n", |
1127 | comp_status, scsi_status); | 1149 | comp_status, scsi_status); |
@@ -1156,7 +1178,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) | |||
1156 | "sp=%p sp->state:%d\n", __func__, sp, sp->state)); | 1178 | "sp=%p sp->state:%d\n", __func__, sp, sp->state)); |
1157 | qla_printk(KERN_INFO, ha, | 1179 | qla_printk(KERN_INFO, ha, |
1158 | "cmd is NULL: already returned to OS (sp=%p)\n", | 1180 | "cmd is NULL: already returned to OS (sp=%p)\n", |
1159 | sp); | 1181 | sp); |
1160 | 1182 | ||
1161 | ha->status_srb = NULL; | 1183 | ha->status_srb = NULL; |
1162 | return; | 1184 | return; |
@@ -1169,6 +1191,8 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) | |||
1169 | } | 1191 | } |
1170 | 1192 | ||
1171 | /* 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)); | ||
1172 | memcpy(sp->request_sense_ptr, pkt->data, sense_sz); | 1196 | memcpy(sp->request_sense_ptr, pkt->data, sense_sz); |
1173 | DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); | 1197 | DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); |
1174 | 1198 | ||
@@ -1189,7 +1213,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) | |||
1189 | * @pkt: Entry pointer | 1213 | * @pkt: Entry pointer |
1190 | */ | 1214 | */ |
1191 | static void | 1215 | static void |
1192 | 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) |
1193 | { | 1217 | { |
1194 | srb_t *sp; | 1218 | srb_t *sp; |
1195 | 1219 | ||
@@ -1199,7 +1223,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1199 | else if (pkt->entry_status & RF_INV_E_COUNT) | 1223 | else if (pkt->entry_status & RF_INV_E_COUNT) |
1200 | qla_printk(KERN_ERR, ha, "%s: Invalid Entry Count\n", __func__); | 1224 | qla_printk(KERN_ERR, ha, "%s: Invalid Entry Count\n", __func__); |
1201 | else if (pkt->entry_status & RF_INV_E_PARAM) | 1225 | else if (pkt->entry_status & RF_INV_E_PARAM) |
1202 | qla_printk(KERN_ERR, ha, | 1226 | qla_printk(KERN_ERR, ha, |
1203 | "%s: Invalid Entry Parameter\n", __func__); | 1227 | "%s: Invalid Entry Parameter\n", __func__); |
1204 | else if (pkt->entry_status & RF_INV_E_TYPE) | 1228 | else if (pkt->entry_status & RF_INV_E_TYPE) |
1205 | qla_printk(KERN_ERR, ha, "%s: Invalid Entry Type\n", __func__); | 1229 | qla_printk(KERN_ERR, ha, "%s: Invalid Entry Type\n", __func__); |
@@ -1231,15 +1255,15 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1231 | } | 1255 | } |
1232 | qla2x00_sp_compl(ha, sp); | 1256 | qla2x00_sp_compl(ha, sp); |
1233 | 1257 | ||
1234 | } else if (pkt->entry_type == COMMAND_A64_TYPE || | 1258 | } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type == |
1235 | pkt->entry_type == COMMAND_TYPE) { | 1259 | COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7) { |
1236 | DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n", | 1260 | DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n", |
1237 | ha->host_no)); | 1261 | ha->host_no)); |
1238 | qla_printk(KERN_WARNING, ha, | 1262 | qla_printk(KERN_WARNING, ha, |
1239 | "Error entry - invalid handle\n"); | 1263 | "Error entry - invalid handle\n"); |
1240 | 1264 | ||
1241 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 1265 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
1242 | if (ha->dpc_wait && !ha->dpc_active) | 1266 | if (ha->dpc_wait && !ha->dpc_active) |
1243 | up(ha->dpc_wait); | 1267 | up(ha->dpc_wait); |
1244 | } | 1268 | } |
1245 | } | 1269 | } |
@@ -1250,7 +1274,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) | |||
1250 | * @index: Response queue out pointer | 1274 | * @index: Response queue out pointer |
1251 | */ | 1275 | */ |
1252 | static void | 1276 | static void |
1253 | 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) |
1254 | { | 1278 | { |
1255 | srb_t *sp; | 1279 | srb_t *sp; |
1256 | 1280 | ||
@@ -1280,3 +1304,229 @@ qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt) | |||
1280 | 1304 | ||
1281 | qla2x00_sp_compl(ha, sp); | 1305 | qla2x00_sp_compl(ha, sp); |
1282 | } | 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 | qla2x00_error_entry(ha, (sts_entry_t *) pkt); | ||
1369 | ((response_t *)pkt)->signature = RESPONSE_PROCESSED; | ||
1370 | wmb(); | ||
1371 | continue; | ||
1372 | } | ||
1373 | |||
1374 | switch (pkt->entry_type) { | ||
1375 | case STATUS_TYPE: | ||
1376 | qla2x00_status_entry(ha, pkt); | ||
1377 | break; | ||
1378 | case STATUS_CONT_TYPE: | ||
1379 | qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt); | ||
1380 | break; | ||
1381 | case MS_IOCB_TYPE: | ||
1382 | qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt); | ||
1383 | break; | ||
1384 | default: | ||
1385 | /* Type Not Supported. */ | ||
1386 | DEBUG4(printk(KERN_WARNING | ||
1387 | "scsi(%ld): Received unknown response pkt type %x " | ||
1388 | "entry status=%x.\n", | ||
1389 | ha->host_no, pkt->entry_type, pkt->entry_status)); | ||
1390 | break; | ||
1391 | } | ||
1392 | ((response_t *)pkt)->signature = RESPONSE_PROCESSED; | ||
1393 | wmb(); | ||
1394 | } | ||
1395 | |||
1396 | /* Adjust ring index */ | ||
1397 | WRT_REG_DWORD(®->rsp_q_out, ha->rsp_ring_index); | ||
1398 | } | ||
1399 | |||
1400 | /** | ||
1401 | * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. | ||
1402 | * @irq: | ||
1403 | * @dev_id: SCSI driver HA context | ||
1404 | * @regs: | ||
1405 | * | ||
1406 | * Called by system whenever the host adapter generates an interrupt. | ||
1407 | * | ||
1408 | * Returns handled flag. | ||
1409 | */ | ||
1410 | irqreturn_t | ||
1411 | qla24xx_intr_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
1412 | { | ||
1413 | scsi_qla_host_t *ha; | ||
1414 | struct device_reg_24xx __iomem *reg; | ||
1415 | int status; | ||
1416 | unsigned long flags; | ||
1417 | unsigned long iter; | ||
1418 | uint32_t stat; | ||
1419 | uint32_t hccr; | ||
1420 | uint16_t mb[4]; | ||
1421 | |||
1422 | ha = (scsi_qla_host_t *) dev_id; | ||
1423 | if (!ha) { | ||
1424 | printk(KERN_INFO | ||
1425 | "%s(): NULL host pointer\n", __func__); | ||
1426 | return IRQ_NONE; | ||
1427 | } | ||
1428 | |||
1429 | reg = &ha->iobase->isp24; | ||
1430 | status = 0; | ||
1431 | |||
1432 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1433 | for (iter = 50; iter--; ) { | ||
1434 | stat = RD_REG_DWORD(®->host_status); | ||
1435 | if (stat & HSRX_RISC_PAUSED) { | ||
1436 | hccr = RD_REG_DWORD(®->hccr); | ||
1437 | |||
1438 | qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " | ||
1439 | "Dumping firmware!\n", hccr); | ||
1440 | qla24xx_fw_dump(ha, 1); | ||
1441 | |||
1442 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
1443 | break; | ||
1444 | } else if ((stat & HSRX_RISC_INT) == 0) | ||
1445 | break; | ||
1446 | |||
1447 | switch (stat & 0xff) { | ||
1448 | case 0x1: | ||
1449 | case 0x2: | ||
1450 | case 0x10: | ||
1451 | case 0x11: | ||
1452 | qla24xx_mbx_completion(ha, MSW(stat)); | ||
1453 | status |= MBX_INTERRUPT; | ||
1454 | |||
1455 | break; | ||
1456 | case 0x12: | ||
1457 | mb[0] = MSW(stat); | ||
1458 | mb[1] = RD_REG_WORD(®->mailbox1); | ||
1459 | mb[2] = RD_REG_WORD(®->mailbox2); | ||
1460 | mb[3] = RD_REG_WORD(®->mailbox3); | ||
1461 | qla2x00_async_event(ha, mb); | ||
1462 | break; | ||
1463 | case 0x13: | ||
1464 | qla24xx_process_response_queue(ha); | ||
1465 | break; | ||
1466 | default: | ||
1467 | DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " | ||
1468 | "(%d).\n", | ||
1469 | ha->host_no, stat & 0xff)); | ||
1470 | break; | ||
1471 | } | ||
1472 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | ||
1473 | RD_REG_DWORD_RELAXED(®->hccr); | ||
1474 | } | ||
1475 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1476 | |||
1477 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | ||
1478 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | ||
1479 | spin_lock_irqsave(&ha->mbx_reg_lock, flags); | ||
1480 | |||
1481 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
1482 | up(&ha->mbx_intr_sem); | ||
1483 | |||
1484 | spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); | ||
1485 | } | ||
1486 | |||
1487 | return IRQ_HANDLED; | ||
1488 | } | ||
1489 | |||
1490 | /** | ||
1491 | * qla24xx_ms_entry() - Process a Management Server entry. | ||
1492 | * @ha: SCSI driver HA context | ||
1493 | * @index: Response queue out pointer | ||
1494 | */ | ||
1495 | static void | ||
1496 | qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt) | ||
1497 | { | ||
1498 | srb_t *sp; | ||
1499 | |||
1500 | DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n", | ||
1501 | __func__, ha->host_no, pkt, pkt->handle)); | ||
1502 | |||
1503 | DEBUG9(printk("%s: ct pkt dump:\n", __func__);) | ||
1504 | DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx));) | ||
1505 | |||
1506 | /* Validate handle. */ | ||
1507 | if (pkt->handle < MAX_OUTSTANDING_COMMANDS) | ||
1508 | sp = ha->outstanding_cmds[pkt->handle]; | ||
1509 | else | ||
1510 | sp = NULL; | ||
1511 | |||
1512 | if (sp == NULL) { | ||
1513 | DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n", | ||
1514 | ha->host_no)); | ||
1515 | DEBUG10(printk("scsi(%ld): MS entry - invalid handle\n", | ||
1516 | ha->host_no)); | ||
1517 | qla_printk(KERN_WARNING, ha, "MS entry - invalid handle %d\n", | ||
1518 | pkt->handle); | ||
1519 | |||
1520 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
1521 | return; | ||
1522 | } | ||
1523 | |||
1524 | CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status); | ||
1525 | CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status; | ||
1526 | |||
1527 | /* Free outstanding command slot. */ | ||
1528 | ha->outstanding_cmds[pkt->handle] = NULL; | ||
1529 | |||
1530 | qla2x00_sp_compl(ha, sp); | ||
1531 | } | ||
1532 | |||