blob: e4c6b9409933124918afe683fac7381f0f92fd23 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Andrew Vasquezfa90c542005-10-27 11:10:08 -07002 * QLogic Fibre Channel HBA Driver
Andrew Vasquez07e264b2011-03-30 11:46:23 -07003 * Copyright (c) 2003-2011 QLogic Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Andrew Vasquezfa90c542005-10-27 11:10:08 -07005 * See LICENSE.qla2xxx for copyright and licensing details.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
Saurav Kashyap3ce88662011-07-14 12:00:12 -07007
8/*
9 * Table for showing the current message id in use for particular level
10 * Change this table for addition of log/debug messages.
Arun Easie02587d2011-08-16 11:29:23 -070011 * ----------------------------------------------------------------------
12 * | Level | Last Value Used | Holes |
13 * ----------------------------------------------------------------------
Giridhar Malavali6246b8a2012-02-09 11:15:34 -080014 * | Module Init and Probe | 0x011f | 0x4b,0xfa |
15 * | Mailbox commands | 0x1139 | 0x112c-0x112e |
16 * | Device Discovery | 0x2084 | |
17 * | Queue Command and IO tracing | 0x302f | 0x3008 |
18 * | | | 0x302d-0x302e |
Arun Easie02587d2011-08-16 11:29:23 -070019 * | DPC Thread | 0x401c | |
Chad Dupuiscfb09192011-11-18 09:03:07 -080020 * | Async Events | 0x5057 | 0x5052 |
Giridhar Malavali6246b8a2012-02-09 11:15:34 -080021 * | Timer Routines | 0x6011 | 0x600e-0x600f |
Andrew Vasquezd051a5aa2012-02-09 11:14:05 -080022 * | User Space Interactions | 0x709e | 0x7018,0x702e |
23 * | | | 0x7039,0x7045 |
Chad Dupuiscfb09192011-11-18 09:03:07 -080024 * | Task Management | 0x803c | 0x8025-0x8026 |
25 * | | | 0x800b,0x8039 |
Arun Easie02587d2011-08-16 11:29:23 -070026 * | AER/EEH | 0x900f | |
27 * | Virtual Port | 0xa007 | |
Giridhar Malavali6246b8a2012-02-09 11:15:34 -080028 * | ISP82XX Specific | 0xb052 | |
29 * | MultiQ | 0xc00c | |
30 * | Misc | 0xd010 | |
Arun Easie02587d2011-08-16 11:29:23 -070031 * ----------------------------------------------------------------------
Saurav Kashyap3ce88662011-07-14 12:00:12 -070032 */
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include "qla_def.h"
35
36#include <linux/delay.h>
37
Saurav Kashyap3ce88662011-07-14 12:00:12 -070038static uint32_t ql_dbg_offset = 0x800;
39
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070040static inline void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080041qla2xxx_prep_dump(struct qla_hw_data *ha, struct qla2xxx_fw_dump *fw_dump)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070042{
43 fw_dump->fw_major_version = htonl(ha->fw_major_version);
44 fw_dump->fw_minor_version = htonl(ha->fw_minor_version);
45 fw_dump->fw_subminor_version = htonl(ha->fw_subminor_version);
46 fw_dump->fw_attributes = htonl(ha->fw_attributes);
47
48 fw_dump->vendor = htonl(ha->pdev->vendor);
49 fw_dump->device = htonl(ha->pdev->device);
50 fw_dump->subsystem_vendor = htonl(ha->pdev->subsystem_vendor);
51 fw_dump->subsystem_device = htonl(ha->pdev->subsystem_device);
52}
53
54static inline void *
Anirban Chakraborty73208df2008-12-09 16:45:39 -080055qla2xxx_copy_queues(struct qla_hw_data *ha, void *ptr)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070056{
Anirban Chakraborty73208df2008-12-09 16:45:39 -080057 struct req_que *req = ha->req_q_map[0];
58 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070059 /* Request queue. */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080060 memcpy(ptr, req->ring, req->length *
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070061 sizeof(request_t));
62
63 /* Response queue. */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080064 ptr += req->length * sizeof(request_t);
65 memcpy(ptr, rsp->ring, rsp->length *
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070066 sizeof(response_t));
67
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080068 return ptr + (rsp->length * sizeof(response_t));
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070069}
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070071static int
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080072qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
Andrew Vasquezc5722702008-04-24 15:21:22 -070073 uint32_t ram_dwords, void **nxt)
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070074{
75 int rval;
Andrew Vasquezc5722702008-04-24 15:21:22 -070076 uint32_t cnt, stat, timer, dwords, idx;
77 uint16_t mb0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070078 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
Andrew Vasquezc5722702008-04-24 15:21:22 -070079 dma_addr_t dump_dma = ha->gid_list_dma;
80 uint32_t *dump = (uint32_t *)ha->gid_list;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070081
82 rval = QLA_SUCCESS;
Andrew Vasquezc5722702008-04-24 15:21:22 -070083 mb0 = 0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070084
Andrew Vasquezc5722702008-04-24 15:21:22 -070085 WRT_REG_WORD(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070086 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
87
Andrew Vasquezc5722702008-04-24 15:21:22 -070088 dwords = GID_LIST_SIZE / 4;
89 for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
90 cnt += dwords, addr += dwords) {
91 if (cnt + dwords > ram_dwords)
92 dwords = ram_dwords - cnt;
93
94 WRT_REG_WORD(&reg->mailbox1, LSW(addr));
95 WRT_REG_WORD(&reg->mailbox8, MSW(addr));
96
97 WRT_REG_WORD(&reg->mailbox2, MSW(dump_dma));
98 WRT_REG_WORD(&reg->mailbox3, LSW(dump_dma));
99 WRT_REG_WORD(&reg->mailbox6, MSW(MSD(dump_dma)));
100 WRT_REG_WORD(&reg->mailbox7, LSW(MSD(dump_dma)));
101
102 WRT_REG_WORD(&reg->mailbox4, MSW(dwords));
103 WRT_REG_WORD(&reg->mailbox5, LSW(dwords));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700104 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
105
106 for (timer = 6000000; timer; timer--) {
107 /* Check for pending interrupts. */
108 stat = RD_REG_DWORD(&reg->host_status);
109 if (stat & HSRX_RISC_INT) {
110 stat &= 0xff;
111
112 if (stat == 0x1 || stat == 0x2 ||
113 stat == 0x10 || stat == 0x11) {
114 set_bit(MBX_INTERRUPT,
115 &ha->mbx_cmd_flags);
116
Andrew Vasquezc5722702008-04-24 15:21:22 -0700117 mb0 = RD_REG_WORD(&reg->mailbox0);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700118
119 WRT_REG_DWORD(&reg->hccr,
120 HCCRX_CLR_RISC_INT);
121 RD_REG_DWORD(&reg->hccr);
122 break;
123 }
124
125 /* Clear this intr; it wasn't a mailbox intr */
126 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
127 RD_REG_DWORD(&reg->hccr);
128 }
129 udelay(5);
130 }
131
132 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
Andrew Vasquezc5722702008-04-24 15:21:22 -0700133 rval = mb0 & MBS_MASK;
134 for (idx = 0; idx < dwords; idx++)
135 ram[cnt + idx] = swab32(dump[idx]);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700136 } else {
137 rval = QLA_FUNCTION_FAILED;
138 }
139 }
140
Andrew Vasquezc5722702008-04-24 15:21:22 -0700141 *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700142 return rval;
143}
144
Andrew Vasquezc5722702008-04-24 15:21:22 -0700145static int
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800146qla24xx_dump_memory(struct qla_hw_data *ha, uint32_t *code_ram,
Andrew Vasquezc5722702008-04-24 15:21:22 -0700147 uint32_t cram_size, void **nxt)
148{
149 int rval;
150
151 /* Code RAM. */
152 rval = qla24xx_dump_ram(ha, 0x20000, code_ram, cram_size / 4, nxt);
153 if (rval != QLA_SUCCESS)
154 return rval;
155
156 /* External Memory. */
157 return qla24xx_dump_ram(ha, 0x100000, *nxt,
158 ha->fw_memory_size - 0x100000 + 1, nxt);
159}
160
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700161static uint32_t *
162qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
163 uint32_t count, uint32_t *buf)
164{
165 uint32_t __iomem *dmp_reg;
166
167 WRT_REG_DWORD(&reg->iobase_addr, iobase);
168 dmp_reg = &reg->iobase_window;
169 while (count--)
170 *buf++ = htonl(RD_REG_DWORD(dmp_reg++));
171
172 return buf;
173}
174
175static inline int
176qla24xx_pause_risc(struct device_reg_24xx __iomem *reg)
177{
178 int rval = QLA_SUCCESS;
179 uint32_t cnt;
180
Andrew Vasquezc3b058a2007-09-20 14:07:38 -0700181 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
Andrew Vasquezaed10882009-06-03 09:55:26 -0700182 for (cnt = 30000;
183 ((RD_REG_DWORD(&reg->host_status) & HSRX_RISC_PAUSED) == 0) &&
Andrew Vasquezc3b058a2007-09-20 14:07:38 -0700184 rval == QLA_SUCCESS; cnt--) {
185 if (cnt)
186 udelay(100);
187 else
188 rval = QLA_FUNCTION_TIMEOUT;
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700189 }
190
191 return rval;
192}
193
194static int
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800195qla24xx_soft_reset(struct qla_hw_data *ha)
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700196{
197 int rval = QLA_SUCCESS;
198 uint32_t cnt;
199 uint16_t mb0, wd;
200 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
201
202 /* Reset RISC. */
203 WRT_REG_DWORD(&reg->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
204 for (cnt = 0; cnt < 30000; cnt++) {
205 if ((RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
206 break;
207
208 udelay(10);
209 }
210
211 WRT_REG_DWORD(&reg->ctrl_status,
212 CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
213 pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
214
215 udelay(100);
216 /* Wait for firmware to complete NVRAM accesses. */
217 mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
218 for (cnt = 10000 ; cnt && mb0; cnt--) {
219 udelay(5);
220 mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
221 barrier();
222 }
223
224 /* Wait for soft-reset to complete. */
225 for (cnt = 0; cnt < 30000; cnt++) {
226 if ((RD_REG_DWORD(&reg->ctrl_status) &
227 CSRX_ISP_SOFT_RESET) == 0)
228 break;
229
230 udelay(10);
231 }
232 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
233 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
234
235 for (cnt = 30000; RD_REG_WORD(&reg->mailbox0) != 0 &&
236 rval == QLA_SUCCESS; cnt--) {
237 if (cnt)
238 udelay(100);
239 else
240 rval = QLA_FUNCTION_TIMEOUT;
241 }
242
243 return rval;
244}
245
Andrew Vasquezc5722702008-04-24 15:21:22 -0700246static int
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800247qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint16_t *ram,
Andrew Vasqueze18e9632009-06-17 10:30:31 -0700248 uint32_t ram_words, void **nxt)
Andrew Vasquezc5722702008-04-24 15:21:22 -0700249{
250 int rval;
251 uint32_t cnt, stat, timer, words, idx;
252 uint16_t mb0;
253 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
254 dma_addr_t dump_dma = ha->gid_list_dma;
255 uint16_t *dump = (uint16_t *)ha->gid_list;
256
257 rval = QLA_SUCCESS;
258 mb0 = 0;
259
260 WRT_MAILBOX_REG(ha, reg, 0, MBC_DUMP_RISC_RAM_EXTENDED);
261 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
262
263 words = GID_LIST_SIZE / 2;
264 for (cnt = 0; cnt < ram_words && rval == QLA_SUCCESS;
265 cnt += words, addr += words) {
266 if (cnt + words > ram_words)
267 words = ram_words - cnt;
268
269 WRT_MAILBOX_REG(ha, reg, 1, LSW(addr));
270 WRT_MAILBOX_REG(ha, reg, 8, MSW(addr));
271
272 WRT_MAILBOX_REG(ha, reg, 2, MSW(dump_dma));
273 WRT_MAILBOX_REG(ha, reg, 3, LSW(dump_dma));
274 WRT_MAILBOX_REG(ha, reg, 6, MSW(MSD(dump_dma)));
275 WRT_MAILBOX_REG(ha, reg, 7, LSW(MSD(dump_dma)));
276
277 WRT_MAILBOX_REG(ha, reg, 4, words);
278 WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
279
280 for (timer = 6000000; timer; timer--) {
281 /* Check for pending interrupts. */
282 stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
283 if (stat & HSR_RISC_INT) {
284 stat &= 0xff;
285
286 if (stat == 0x1 || stat == 0x2) {
287 set_bit(MBX_INTERRUPT,
288 &ha->mbx_cmd_flags);
289
290 mb0 = RD_MAILBOX_REG(ha, reg, 0);
291
292 /* Release mailbox registers. */
293 WRT_REG_WORD(&reg->semaphore, 0);
294 WRT_REG_WORD(&reg->hccr,
295 HCCR_CLR_RISC_INT);
296 RD_REG_WORD(&reg->hccr);
297 break;
298 } else if (stat == 0x10 || stat == 0x11) {
299 set_bit(MBX_INTERRUPT,
300 &ha->mbx_cmd_flags);
301
302 mb0 = RD_MAILBOX_REG(ha, reg, 0);
303
304 WRT_REG_WORD(&reg->hccr,
305 HCCR_CLR_RISC_INT);
306 RD_REG_WORD(&reg->hccr);
307 break;
308 }
309
310 /* clear this intr; it wasn't a mailbox intr */
311 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
312 RD_REG_WORD(&reg->hccr);
313 }
314 udelay(5);
315 }
316
317 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
318 rval = mb0 & MBS_MASK;
319 for (idx = 0; idx < words; idx++)
320 ram[cnt + idx] = swab16(dump[idx]);
321 } else {
322 rval = QLA_FUNCTION_FAILED;
323 }
324 }
325
326 *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
327 return rval;
328}
329
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700330static inline void
331qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
332 uint16_t *buf)
333{
334 uint16_t __iomem *dmp_reg = &reg->u.isp2300.fb_cmd;
335
336 while (count--)
337 *buf++ = htons(RD_REG_WORD(dmp_reg++));
338}
339
Andrew Vasquezbb99de62009-01-05 11:18:08 -0800340static inline void *
341qla24xx_copy_eft(struct qla_hw_data *ha, void *ptr)
342{
343 if (!ha->eft)
344 return ptr;
345
346 memcpy(ptr, ha->eft, ntohl(ha->fw_dump->eft_size));
347 return ptr + ntohl(ha->fw_dump->eft_size);
348}
349
350static inline void *
351qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
352{
353 uint32_t cnt;
354 uint32_t *iter_reg;
355 struct qla2xxx_fce_chain *fcec = ptr;
356
357 if (!ha->fce)
358 return ptr;
359
360 *last_chain = &fcec->type;
361 fcec->type = __constant_htonl(DUMP_CHAIN_FCE);
362 fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) +
363 fce_calc_size(ha->fce_bufs));
364 fcec->size = htonl(fce_calc_size(ha->fce_bufs));
365 fcec->addr_l = htonl(LSD(ha->fce_dma));
366 fcec->addr_h = htonl(MSD(ha->fce_dma));
367
368 iter_reg = fcec->eregs;
369 for (cnt = 0; cnt < 8; cnt++)
370 *iter_reg++ = htonl(ha->fce_mb[cnt]);
371
372 memcpy(iter_reg, ha->fce, ntohl(fcec->size));
373
Giridhar Malavali3cb0a672011-11-18 09:03:11 -0800374 return (char *)iter_reg + ntohl(fcec->size);
Andrew Vasquezbb99de62009-01-05 11:18:08 -0800375}
376
Andrew Vasquezd63ab532009-01-05 11:18:09 -0800377static inline void *
Giridhar Malavali050c9bb2012-02-09 11:15:33 -0800378qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
379{
380 struct qla2xxx_mqueue_chain *q;
381 struct qla2xxx_mqueue_header *qh;
382 struct req_que *req;
383 struct rsp_que *rsp;
384 int que;
385
386 if (!ha->mqenable)
387 return ptr;
388
389 /* Request queues */
390 for (que = 1; que < ha->max_req_queues; que++) {
391 req = ha->req_q_map[que];
392 if (!req)
393 break;
394
395 /* Add chain. */
396 q = ptr;
397 *last_chain = &q->type;
398 q->type = __constant_htonl(DUMP_CHAIN_QUEUE);
399 q->chain_size = htonl(
400 sizeof(struct qla2xxx_mqueue_chain) +
401 sizeof(struct qla2xxx_mqueue_header) +
402 (req->length * sizeof(request_t)));
403 ptr += sizeof(struct qla2xxx_mqueue_chain);
404
405 /* Add header. */
406 qh = ptr;
407 qh->queue = __constant_htonl(TYPE_REQUEST_QUEUE);
408 qh->number = htonl(que);
409 qh->size = htonl(req->length * sizeof(request_t));
410 ptr += sizeof(struct qla2xxx_mqueue_header);
411
412 /* Add data. */
413 memcpy(ptr, req->ring, req->length * sizeof(request_t));
414 ptr += req->length * sizeof(request_t);
415 }
416
417 /* Response queues */
418 for (que = 1; que < ha->max_rsp_queues; que++) {
419 rsp = ha->rsp_q_map[que];
420 if (!rsp)
421 break;
422
423 /* Add chain. */
424 q = ptr;
425 *last_chain = &q->type;
426 q->type = __constant_htonl(DUMP_CHAIN_QUEUE);
427 q->chain_size = htonl(
428 sizeof(struct qla2xxx_mqueue_chain) +
429 sizeof(struct qla2xxx_mqueue_header) +
430 (rsp->length * sizeof(response_t)));
431 ptr += sizeof(struct qla2xxx_mqueue_chain);
432
433 /* Add header. */
434 qh = ptr;
435 qh->queue = __constant_htonl(TYPE_RESPONSE_QUEUE);
436 qh->number = htonl(que);
437 qh->size = htonl(rsp->length * sizeof(response_t));
438 ptr += sizeof(struct qla2xxx_mqueue_header);
439
440 /* Add data. */
441 memcpy(ptr, rsp->ring, rsp->length * sizeof(response_t));
442 ptr += rsp->length * sizeof(response_t);
443 }
444
445 return ptr;
446}
447
448static inline void *
Andrew Vasquezd63ab532009-01-05 11:18:09 -0800449qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
450{
451 uint32_t cnt, que_idx;
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -0700452 uint8_t que_cnt;
Andrew Vasquezd63ab532009-01-05 11:18:09 -0800453 struct qla2xxx_mq_chain *mq = ptr;
454 struct device_reg_25xxmq __iomem *reg;
455
Giridhar Malavali6246b8a2012-02-09 11:15:34 -0800456 if (!ha->mqenable || IS_QLA83XX(ha))
Andrew Vasquezd63ab532009-01-05 11:18:09 -0800457 return ptr;
458
459 mq = ptr;
460 *last_chain = &mq->type;
461 mq->type = __constant_htonl(DUMP_CHAIN_MQ);
462 mq->chain_size = __constant_htonl(sizeof(struct qla2xxx_mq_chain));
463
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -0700464 que_cnt = ha->max_req_queues > ha->max_rsp_queues ?
465 ha->max_req_queues : ha->max_rsp_queues;
Andrew Vasquezd63ab532009-01-05 11:18:09 -0800466 mq->count = htonl(que_cnt);
467 for (cnt = 0; cnt < que_cnt; cnt++) {
468 reg = (struct device_reg_25xxmq *) ((void *)
469 ha->mqiobase + cnt * QLA_QUE_PAGE);
470 que_idx = cnt * 4;
471 mq->qregs[que_idx] = htonl(RD_REG_DWORD(&reg->req_q_in));
472 mq->qregs[que_idx+1] = htonl(RD_REG_DWORD(&reg->req_q_out));
473 mq->qregs[que_idx+2] = htonl(RD_REG_DWORD(&reg->rsp_q_in));
474 mq->qregs[que_idx+3] = htonl(RD_REG_DWORD(&reg->rsp_q_out));
475 }
476
477 return ptr + sizeof(struct qla2xxx_mq_chain);
478}
479
Giridhar Malavali08de2842011-08-16 11:31:44 -0700480void
Andrew Vasquez3420d362009-10-13 15:16:45 -0700481qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval)
482{
483 struct qla_hw_data *ha = vha->hw;
484
485 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700486 ql_log(ql_log_warn, vha, 0xd000,
487 "Failed to dump firmware (%x).\n", rval);
Andrew Vasquez3420d362009-10-13 15:16:45 -0700488 ha->fw_dumped = 0;
489 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700490 ql_log(ql_log_info, vha, 0xd001,
Andrew Vasquez3420d362009-10-13 15:16:45 -0700491 "Firmware dump saved to temp buffer (%ld/%p).\n",
492 vha->host_no, ha->fw_dump);
493 ha->fw_dumped = 1;
494 qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
495 }
496}
497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498/**
499 * qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
500 * @ha: HA context
501 * @hardware_locked: Called with the hardware_lock
502 */
503void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800504qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505{
506 int rval;
Andrew Vasquezc5722702008-04-24 15:21:22 -0700507 uint32_t cnt;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800508 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700509 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 uint16_t __iomem *dmp_reg;
511 unsigned long flags;
512 struct qla2300_fw_dump *fw;
Andrew Vasquezc5722702008-04-24 15:21:22 -0700513 void *nxt;
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800514 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 flags = 0;
517
518 if (!hardware_locked)
519 spin_lock_irqsave(&ha->hardware_lock, flags);
520
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700521 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700522 ql_log(ql_log_warn, vha, 0xd002,
523 "No buffer available for dump.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 goto qla2300_fw_dump_failed;
525 }
526
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700527 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700528 ql_log(ql_log_warn, vha, 0xd003,
529 "Firmware has been previously dumped (%p) "
530 "-- ignoring request.\n",
531 ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 goto qla2300_fw_dump_failed;
533 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700534 fw = &ha->fw_dump->isp.isp23;
535 qla2xxx_prep_dump(ha, ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537 rval = QLA_SUCCESS;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700538 fw->hccr = htons(RD_REG_WORD(&reg->hccr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
540 /* Pause RISC. */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700541 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 if (IS_QLA2300(ha)) {
543 for (cnt = 30000;
544 (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
545 rval == QLA_SUCCESS; cnt--) {
546 if (cnt)
547 udelay(100);
548 else
549 rval = QLA_FUNCTION_TIMEOUT;
550 }
551 } else {
552 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
553 udelay(10);
554 }
555
556 if (rval == QLA_SUCCESS) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700557 dmp_reg = &reg->flash_address;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700558 for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700559 fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700561 dmp_reg = &reg->u.isp2300.req_q_in;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700562 for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700563 fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700565 dmp_reg = &reg->u.isp2300.mailbox0;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700566 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700567 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569 WRT_REG_WORD(&reg->ctrl_status, 0x40);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700570 qla2xxx_read_window(reg, 32, fw->resp_dma_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
572 WRT_REG_WORD(&reg->ctrl_status, 0x50);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700573 qla2xxx_read_window(reg, 48, fw->dma_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
575 WRT_REG_WORD(&reg->ctrl_status, 0x00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700576 dmp_reg = &reg->risc_hw;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700577 for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700578 fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700580 WRT_REG_WORD(&reg->pcr, 0x2000);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700581 qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700583 WRT_REG_WORD(&reg->pcr, 0x2200);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700584 qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700586 WRT_REG_WORD(&reg->pcr, 0x2400);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700587 qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700589 WRT_REG_WORD(&reg->pcr, 0x2600);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700590 qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700592 WRT_REG_WORD(&reg->pcr, 0x2800);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700593 qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700595 WRT_REG_WORD(&reg->pcr, 0x2A00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700596 qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700598 WRT_REG_WORD(&reg->pcr, 0x2C00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700599 qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700601 WRT_REG_WORD(&reg->pcr, 0x2E00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700602 qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700604 WRT_REG_WORD(&reg->ctrl_status, 0x10);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700605 qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700607 WRT_REG_WORD(&reg->ctrl_status, 0x20);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700608 qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700610 WRT_REG_WORD(&reg->ctrl_status, 0x30);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700611 qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
613 /* Reset RISC. */
614 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
615 for (cnt = 0; cnt < 30000; cnt++) {
616 if ((RD_REG_WORD(&reg->ctrl_status) &
617 CSR_ISP_SOFT_RESET) == 0)
618 break;
619
620 udelay(10);
621 }
622 }
623
624 if (!IS_QLA2300(ha)) {
625 for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
626 rval == QLA_SUCCESS; cnt--) {
627 if (cnt)
628 udelay(100);
629 else
630 rval = QLA_FUNCTION_TIMEOUT;
631 }
632 }
633
Andrew Vasquezc5722702008-04-24 15:21:22 -0700634 /* Get RISC SRAM. */
635 if (rval == QLA_SUCCESS)
636 rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram,
637 sizeof(fw->risc_ram) / 2, &nxt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Andrew Vasquezc5722702008-04-24 15:21:22 -0700639 /* Get stack SRAM. */
640 if (rval == QLA_SUCCESS)
641 rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram,
642 sizeof(fw->stack_ram) / 2, &nxt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Andrew Vasquezc5722702008-04-24 15:21:22 -0700644 /* Get data SRAM. */
645 if (rval == QLA_SUCCESS)
646 rval = qla2xxx_dump_ram(ha, 0x11000, fw->data_ram,
647 ha->fw_memory_size - 0x11000 + 1, &nxt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700649 if (rval == QLA_SUCCESS)
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800650 qla2xxx_copy_queues(ha, nxt);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700651
Andrew Vasquez3420d362009-10-13 15:16:45 -0700652 qla2xxx_dump_post_process(base_vha, rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
654qla2300_fw_dump_failed:
655 if (!hardware_locked)
656 spin_unlock_irqrestore(&ha->hardware_lock, flags);
657}
658
659/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 * qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware.
661 * @ha: HA context
662 * @hardware_locked: Called with the hardware_lock
663 */
664void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800665qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666{
667 int rval;
668 uint32_t cnt, timer;
669 uint16_t risc_address;
670 uint16_t mb0, mb2;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800671 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700672 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 uint16_t __iomem *dmp_reg;
674 unsigned long flags;
675 struct qla2100_fw_dump *fw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800676 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 risc_address = 0;
679 mb0 = mb2 = 0;
680 flags = 0;
681
682 if (!hardware_locked)
683 spin_lock_irqsave(&ha->hardware_lock, flags);
684
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700685 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700686 ql_log(ql_log_warn, vha, 0xd004,
687 "No buffer available for dump.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 goto qla2100_fw_dump_failed;
689 }
690
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700691 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700692 ql_log(ql_log_warn, vha, 0xd005,
693 "Firmware has been previously dumped (%p) "
694 "-- ignoring request.\n",
695 ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 goto qla2100_fw_dump_failed;
697 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700698 fw = &ha->fw_dump->isp.isp21;
699 qla2xxx_prep_dump(ha, ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
701 rval = QLA_SUCCESS;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700702 fw->hccr = htons(RD_REG_WORD(&reg->hccr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
704 /* Pause RISC. */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700705 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 for (cnt = 30000; (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
707 rval == QLA_SUCCESS; cnt--) {
708 if (cnt)
709 udelay(100);
710 else
711 rval = QLA_FUNCTION_TIMEOUT;
712 }
713 if (rval == QLA_SUCCESS) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700714 dmp_reg = &reg->flash_address;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700715 for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700716 fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700718 dmp_reg = &reg->u.isp2100.mailbox0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 for (cnt = 0; cnt < ha->mbx_count; cnt++) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700720 if (cnt == 8)
721 dmp_reg = &reg->u_end.isp2200.mailbox8;
722
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700723 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 }
725
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700726 dmp_reg = &reg->u.isp2100.unused_2[0];
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700727 for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700728 fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730 WRT_REG_WORD(&reg->ctrl_status, 0x00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700731 dmp_reg = &reg->risc_hw;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700732 for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700733 fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700735 WRT_REG_WORD(&reg->pcr, 0x2000);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700736 qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700738 WRT_REG_WORD(&reg->pcr, 0x2100);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700739 qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700741 WRT_REG_WORD(&reg->pcr, 0x2200);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700742 qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700744 WRT_REG_WORD(&reg->pcr, 0x2300);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700745 qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700747 WRT_REG_WORD(&reg->pcr, 0x2400);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700748 qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700750 WRT_REG_WORD(&reg->pcr, 0x2500);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700751 qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700753 WRT_REG_WORD(&reg->pcr, 0x2600);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700754 qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700756 WRT_REG_WORD(&reg->pcr, 0x2700);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700757 qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700759 WRT_REG_WORD(&reg->ctrl_status, 0x10);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700760 qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700762 WRT_REG_WORD(&reg->ctrl_status, 0x20);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700763 qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700765 WRT_REG_WORD(&reg->ctrl_status, 0x30);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700766 qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
768 /* Reset the ISP. */
769 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
770 }
771
772 for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
773 rval == QLA_SUCCESS; cnt--) {
774 if (cnt)
775 udelay(100);
776 else
777 rval = QLA_FUNCTION_TIMEOUT;
778 }
779
780 /* Pause RISC. */
781 if (rval == QLA_SUCCESS && (IS_QLA2200(ha) || (IS_QLA2100(ha) &&
782 (RD_REG_WORD(&reg->mctr) & (BIT_1 | BIT_0)) != 0))) {
783
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700784 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 for (cnt = 30000;
786 (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
787 rval == QLA_SUCCESS; cnt--) {
788 if (cnt)
789 udelay(100);
790 else
791 rval = QLA_FUNCTION_TIMEOUT;
792 }
793 if (rval == QLA_SUCCESS) {
794 /* Set memory configuration and timing. */
795 if (IS_QLA2100(ha))
796 WRT_REG_WORD(&reg->mctr, 0xf1);
797 else
798 WRT_REG_WORD(&reg->mctr, 0xf2);
799 RD_REG_WORD(&reg->mctr); /* PCI Posting. */
800
801 /* Release RISC. */
802 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
803 }
804 }
805
806 if (rval == QLA_SUCCESS) {
807 /* Get RISC SRAM. */
808 risc_address = 0x1000;
809 WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
810 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
811 }
812 for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
813 cnt++, risc_address++) {
814 WRT_MAILBOX_REG(ha, reg, 1, risc_address);
815 WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
816
817 for (timer = 6000000; timer != 0; timer--) {
818 /* Check for pending interrupts. */
819 if (RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) {
820 if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
821 set_bit(MBX_INTERRUPT,
822 &ha->mbx_cmd_flags);
823
824 mb0 = RD_MAILBOX_REG(ha, reg, 0);
825 mb2 = RD_MAILBOX_REG(ha, reg, 2);
826
827 WRT_REG_WORD(&reg->semaphore, 0);
828 WRT_REG_WORD(&reg->hccr,
829 HCCR_CLR_RISC_INT);
830 RD_REG_WORD(&reg->hccr);
831 break;
832 }
833 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
834 RD_REG_WORD(&reg->hccr);
835 }
836 udelay(5);
837 }
838
839 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
840 rval = mb0 & MBS_MASK;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700841 fw->risc_ram[cnt] = htons(mb2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 } else {
843 rval = QLA_FUNCTION_FAILED;
844 }
845 }
846
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700847 if (rval == QLA_SUCCESS)
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800848 qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700849
Andrew Vasquez3420d362009-10-13 15:16:45 -0700850 qla2xxx_dump_post_process(base_vha, rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
852qla2100_fw_dump_failed:
853 if (!hardware_locked)
854 spin_unlock_irqrestore(&ha->hardware_lock, flags);
855}
856
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700857void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800858qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700859{
860 int rval;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700861 uint32_t cnt;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700862 uint32_t risc_address;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800863 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700864 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
865 uint32_t __iomem *dmp_reg;
866 uint32_t *iter_reg;
867 uint16_t __iomem *mbx_reg;
868 unsigned long flags;
869 struct qla24xx_fw_dump *fw;
870 uint32_t ext_mem_cnt;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700871 void *nxt;
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800872 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700873
Giridhar Malavalia9083012010-04-12 17:59:55 -0700874 if (IS_QLA82XX(ha))
875 return;
876
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700877 risc_address = ext_mem_cnt = 0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700878 flags = 0;
879
880 if (!hardware_locked)
881 spin_lock_irqsave(&ha->hardware_lock, flags);
882
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700883 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700884 ql_log(ql_log_warn, vha, 0xd006,
885 "No buffer available for dump.\n");
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700886 goto qla24xx_fw_dump_failed;
887 }
888
889 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700890 ql_log(ql_log_warn, vha, 0xd007,
891 "Firmware has been previously dumped (%p) "
892 "-- ignoring request.\n",
893 ha->fw_dump);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700894 goto qla24xx_fw_dump_failed;
895 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700896 fw = &ha->fw_dump->isp.isp24;
897 qla2xxx_prep_dump(ha, ha->fw_dump);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700898
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700899 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700900
901 /* Pause RISC. */
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700902 rval = qla24xx_pause_risc(reg);
903 if (rval != QLA_SUCCESS)
904 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700905
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700906 /* Host interface registers. */
907 dmp_reg = &reg->flash_addr;
908 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
909 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700910
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700911 /* Disable interrupts. */
912 WRT_REG_DWORD(&reg->ictrl, 0);
913 RD_REG_DWORD(&reg->ictrl);
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800914
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700915 /* Shadow registers. */
916 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
917 RD_REG_DWORD(&reg->iobase_addr);
918 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
919 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800920
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700921 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
922 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800923
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700924 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
925 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800926
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700927 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
928 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800929
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700930 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
931 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800932
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700933 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
934 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800935
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700936 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
937 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800938
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700939 /* Mailbox registers. */
940 mbx_reg = &reg->mailbox0;
941 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
942 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700943
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700944 /* Transfer sequence registers. */
945 iter_reg = fw->xseq_gp_reg;
946 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
947 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
948 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
949 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
950 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
951 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
952 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
953 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700954
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700955 qla24xx_read_window(reg, 0xBFE0, 16, fw->xseq_0_reg);
956 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700957
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700958 /* Receive sequence registers. */
959 iter_reg = fw->rseq_gp_reg;
960 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
961 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
962 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
963 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
964 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
965 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
966 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
967 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700968
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700969 qla24xx_read_window(reg, 0xFFD0, 16, fw->rseq_0_reg);
970 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
971 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700972
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700973 /* Command DMA registers. */
974 qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700975
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700976 /* Queues. */
977 iter_reg = fw->req0_dma_reg;
978 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
979 dmp_reg = &reg->iobase_q;
980 for (cnt = 0; cnt < 7; cnt++)
981 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700982
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700983 iter_reg = fw->resp0_dma_reg;
984 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
985 dmp_reg = &reg->iobase_q;
986 for (cnt = 0; cnt < 7; cnt++)
987 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700988
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700989 iter_reg = fw->req1_dma_reg;
990 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
991 dmp_reg = &reg->iobase_q;
992 for (cnt = 0; cnt < 7; cnt++)
993 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700994
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700995 /* Transmit DMA registers. */
996 iter_reg = fw->xmt0_dma_reg;
997 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
998 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700999
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001000 iter_reg = fw->xmt1_dma_reg;
1001 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
1002 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001003
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001004 iter_reg = fw->xmt2_dma_reg;
1005 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
1006 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001007
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001008 iter_reg = fw->xmt3_dma_reg;
1009 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
1010 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001011
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001012 iter_reg = fw->xmt4_dma_reg;
1013 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
1014 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001015
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001016 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001017
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001018 /* Receive DMA registers. */
1019 iter_reg = fw->rcvt0_data_dma_reg;
1020 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
1021 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001022
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001023 iter_reg = fw->rcvt1_data_dma_reg;
1024 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
1025 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001026
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001027 /* RISC registers. */
1028 iter_reg = fw->risc_gp_reg;
1029 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
1030 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
1031 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
1032 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
1033 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
1034 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
1035 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
1036 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001037
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001038 /* Local memory controller registers. */
1039 iter_reg = fw->lmc_reg;
1040 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
1041 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
1042 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
1043 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
1044 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
1045 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
1046 qla24xx_read_window(reg, 0x3060, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001047
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001048 /* Fibre Protocol Module registers. */
1049 iter_reg = fw->fpm_hdw_reg;
1050 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
1051 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
1052 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
1053 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
1054 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
1055 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
1056 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
1057 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
1058 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
1059 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
1060 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
1061 qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001062
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001063 /* Frame Buffer registers. */
1064 iter_reg = fw->fb_hdw_reg;
1065 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
1066 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
1067 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
1068 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
1069 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
1070 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
1071 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
1072 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1073 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1074 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1075 qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001076
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001077 rval = qla24xx_soft_reset(ha);
1078 if (rval != QLA_SUCCESS)
1079 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001080
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001081 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
Andrew Vasquezc5722702008-04-24 15:21:22 -07001082 &nxt);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001083 if (rval != QLA_SUCCESS)
1084 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001085
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001086 nxt = qla2xxx_copy_queues(ha, nxt);
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001087
1088 qla24xx_copy_eft(ha, nxt);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001089
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001090qla24xx_fw_dump_failed_0:
Andrew Vasquez3420d362009-10-13 15:16:45 -07001091 qla2xxx_dump_post_process(base_vha, rval);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001092
1093qla24xx_fw_dump_failed:
1094 if (!hardware_locked)
1095 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1096}
1097
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001098void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001099qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001100{
1101 int rval;
1102 uint32_t cnt;
1103 uint32_t risc_address;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001104 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001105 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
1106 uint32_t __iomem *dmp_reg;
1107 uint32_t *iter_reg;
1108 uint16_t __iomem *mbx_reg;
1109 unsigned long flags;
1110 struct qla25xx_fw_dump *fw;
1111 uint32_t ext_mem_cnt;
Andrew Vasquezd63ab532009-01-05 11:18:09 -08001112 void *nxt, *nxt_chain;
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001113 uint32_t *last_chain = NULL;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001114 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001115
1116 risc_address = ext_mem_cnt = 0;
1117 flags = 0;
1118
1119 if (!hardware_locked)
1120 spin_lock_irqsave(&ha->hardware_lock, flags);
1121
1122 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001123 ql_log(ql_log_warn, vha, 0xd008,
1124 "No buffer available for dump.\n");
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001125 goto qla25xx_fw_dump_failed;
1126 }
1127
1128 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001129 ql_log(ql_log_warn, vha, 0xd009,
1130 "Firmware has been previously dumped (%p) "
1131 "-- ignoring request.\n",
1132 ha->fw_dump);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001133 goto qla25xx_fw_dump_failed;
1134 }
1135 fw = &ha->fw_dump->isp.isp25;
1136 qla2xxx_prep_dump(ha, ha->fw_dump);
Andrew Vasquezb5836922007-09-20 14:07:39 -07001137 ha->fw_dump->version = __constant_htonl(2);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001138
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001139 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
1140
1141 /* Pause RISC. */
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001142 rval = qla24xx_pause_risc(reg);
1143 if (rval != QLA_SUCCESS)
1144 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001145
Andrew Vasquezb5836922007-09-20 14:07:39 -07001146 /* Host/Risc registers. */
1147 iter_reg = fw->host_risc_reg;
1148 iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg);
1149 qla24xx_read_window(reg, 0x7010, 16, iter_reg);
1150
1151 /* PCIe registers. */
1152 WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
1153 RD_REG_DWORD(&reg->iobase_addr);
1154 WRT_REG_DWORD(&reg->iobase_window, 0x01);
1155 dmp_reg = &reg->iobase_c4;
1156 fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
1157 fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
1158 fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
1159 fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001160
Andrew Vasquezb5836922007-09-20 14:07:39 -07001161 WRT_REG_DWORD(&reg->iobase_window, 0x00);
1162 RD_REG_DWORD(&reg->iobase_window);
1163
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001164 /* Host interface registers. */
1165 dmp_reg = &reg->flash_addr;
1166 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
1167 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001168
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001169 /* Disable interrupts. */
1170 WRT_REG_DWORD(&reg->ictrl, 0);
1171 RD_REG_DWORD(&reg->ictrl);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001172
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001173 /* Shadow registers. */
1174 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1175 RD_REG_DWORD(&reg->iobase_addr);
1176 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
1177 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001178
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001179 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
1180 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001181
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001182 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
1183 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001184
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001185 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
1186 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001187
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001188 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
1189 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001190
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001191 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
1192 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001193
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001194 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
1195 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001196
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001197 WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
1198 fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001199
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001200 WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
1201 fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001202
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001203 WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
1204 fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001205
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001206 WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
1207 fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001208
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001209 /* RISC I/O register. */
1210 WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
1211 fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001212
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001213 /* Mailbox registers. */
1214 mbx_reg = &reg->mailbox0;
1215 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
1216 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001217
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001218 /* Transfer sequence registers. */
1219 iter_reg = fw->xseq_gp_reg;
1220 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
1221 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
1222 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
1223 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
1224 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
1225 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
1226 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
1227 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001228
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001229 iter_reg = fw->xseq_0_reg;
1230 iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
1231 iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
1232 qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001233
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001234 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001235
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001236 /* Receive sequence registers. */
1237 iter_reg = fw->rseq_gp_reg;
1238 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
1239 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
1240 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
1241 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
1242 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
1243 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
1244 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
1245 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001246
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001247 iter_reg = fw->rseq_0_reg;
1248 iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
1249 qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001250
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001251 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
1252 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001253
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001254 /* Auxiliary sequence registers. */
1255 iter_reg = fw->aseq_gp_reg;
1256 iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
1257 iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
1258 iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
1259 iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
1260 iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
1261 iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
1262 iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
1263 qla24xx_read_window(reg, 0xB070, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001264
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001265 iter_reg = fw->aseq_0_reg;
1266 iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
1267 qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001268
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001269 qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
1270 qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001271
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001272 /* Command DMA registers. */
1273 qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001274
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001275 /* Queues. */
1276 iter_reg = fw->req0_dma_reg;
1277 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
1278 dmp_reg = &reg->iobase_q;
1279 for (cnt = 0; cnt < 7; cnt++)
1280 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001281
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001282 iter_reg = fw->resp0_dma_reg;
1283 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
1284 dmp_reg = &reg->iobase_q;
1285 for (cnt = 0; cnt < 7; cnt++)
1286 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001287
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001288 iter_reg = fw->req1_dma_reg;
1289 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
1290 dmp_reg = &reg->iobase_q;
1291 for (cnt = 0; cnt < 7; cnt++)
1292 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001293
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001294 /* Transmit DMA registers. */
1295 iter_reg = fw->xmt0_dma_reg;
1296 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
1297 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001298
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001299 iter_reg = fw->xmt1_dma_reg;
1300 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
1301 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001302
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001303 iter_reg = fw->xmt2_dma_reg;
1304 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
1305 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001306
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001307 iter_reg = fw->xmt3_dma_reg;
1308 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
1309 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001310
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001311 iter_reg = fw->xmt4_dma_reg;
1312 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
1313 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001314
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001315 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001316
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001317 /* Receive DMA registers. */
1318 iter_reg = fw->rcvt0_data_dma_reg;
1319 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
1320 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001321
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001322 iter_reg = fw->rcvt1_data_dma_reg;
1323 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
1324 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001325
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001326 /* RISC registers. */
1327 iter_reg = fw->risc_gp_reg;
1328 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
1329 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
1330 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
1331 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
1332 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
1333 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
1334 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
1335 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001336
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001337 /* Local memory controller registers. */
1338 iter_reg = fw->lmc_reg;
1339 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
1340 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
1341 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
1342 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
1343 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
1344 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
1345 iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
1346 qla24xx_read_window(reg, 0x3070, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001347
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001348 /* Fibre Protocol Module registers. */
1349 iter_reg = fw->fpm_hdw_reg;
1350 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
1351 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
1352 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
1353 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
1354 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
1355 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
1356 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
1357 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
1358 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
1359 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
1360 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
1361 qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001362
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001363 /* Frame Buffer registers. */
1364 iter_reg = fw->fb_hdw_reg;
1365 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
1366 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
1367 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
1368 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
1369 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
1370 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
1371 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
1372 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1373 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1374 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1375 iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
1376 qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001377
Andrew Vasquezd63ab532009-01-05 11:18:09 -08001378 /* Multi queue registers */
1379 nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset,
1380 &last_chain);
1381
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001382 rval = qla24xx_soft_reset(ha);
1383 if (rval != QLA_SUCCESS)
1384 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001385
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001386 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
Andrew Vasquezc5722702008-04-24 15:21:22 -07001387 &nxt);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001388 if (rval != QLA_SUCCESS)
1389 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001390
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001391 nxt = qla2xxx_copy_queues(ha, nxt);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001392
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001393 nxt = qla24xx_copy_eft(ha, nxt);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08001394
Andrew Vasquezd63ab532009-01-05 11:18:09 -08001395 /* Chain entries -- started with MQ. */
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08001396 nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
1397 nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001398 if (last_chain) {
1399 ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
1400 *last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
1401 }
Andrew Vasquezdf613b92008-01-17 09:02:17 -08001402
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08001403 /* Adjust valid length. */
1404 ha->fw_dump_len = (nxt_chain - (void *)ha->fw_dump);
1405
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001406qla25xx_fw_dump_failed_0:
Andrew Vasquez3420d362009-10-13 15:16:45 -07001407 qla2xxx_dump_post_process(base_vha, rval);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001408
1409qla25xx_fw_dump_failed:
1410 if (!hardware_locked)
1411 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1412}
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001413
1414void
1415qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
1416{
1417 int rval;
1418 uint32_t cnt;
1419 uint32_t risc_address;
1420 struct qla_hw_data *ha = vha->hw;
1421 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
1422 uint32_t __iomem *dmp_reg;
1423 uint32_t *iter_reg;
1424 uint16_t __iomem *mbx_reg;
1425 unsigned long flags;
1426 struct qla81xx_fw_dump *fw;
1427 uint32_t ext_mem_cnt;
1428 void *nxt, *nxt_chain;
1429 uint32_t *last_chain = NULL;
1430 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
1431
1432 risc_address = ext_mem_cnt = 0;
1433 flags = 0;
1434
1435 if (!hardware_locked)
1436 spin_lock_irqsave(&ha->hardware_lock, flags);
1437
1438 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001439 ql_log(ql_log_warn, vha, 0xd00a,
1440 "No buffer available for dump.\n");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001441 goto qla81xx_fw_dump_failed;
1442 }
1443
1444 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001445 ql_log(ql_log_warn, vha, 0xd00b,
1446 "Firmware has been previously dumped (%p) "
1447 "-- ignoring request.\n",
1448 ha->fw_dump);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001449 goto qla81xx_fw_dump_failed;
1450 }
1451 fw = &ha->fw_dump->isp.isp81;
1452 qla2xxx_prep_dump(ha, ha->fw_dump);
1453
1454 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
1455
1456 /* Pause RISC. */
1457 rval = qla24xx_pause_risc(reg);
1458 if (rval != QLA_SUCCESS)
1459 goto qla81xx_fw_dump_failed_0;
1460
1461 /* Host/Risc registers. */
1462 iter_reg = fw->host_risc_reg;
1463 iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg);
1464 qla24xx_read_window(reg, 0x7010, 16, iter_reg);
1465
1466 /* PCIe registers. */
1467 WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
1468 RD_REG_DWORD(&reg->iobase_addr);
1469 WRT_REG_DWORD(&reg->iobase_window, 0x01);
1470 dmp_reg = &reg->iobase_c4;
1471 fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
1472 fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
1473 fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
1474 fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
1475
1476 WRT_REG_DWORD(&reg->iobase_window, 0x00);
1477 RD_REG_DWORD(&reg->iobase_window);
1478
1479 /* Host interface registers. */
1480 dmp_reg = &reg->flash_addr;
1481 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
1482 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
1483
1484 /* Disable interrupts. */
1485 WRT_REG_DWORD(&reg->ictrl, 0);
1486 RD_REG_DWORD(&reg->ictrl);
1487
1488 /* Shadow registers. */
1489 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1490 RD_REG_DWORD(&reg->iobase_addr);
1491 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
1492 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1493
1494 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
1495 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1496
1497 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
1498 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1499
1500 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
1501 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1502
1503 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
1504 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1505
1506 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
1507 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1508
1509 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
1510 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1511
1512 WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
1513 fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1514
1515 WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
1516 fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1517
1518 WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
1519 fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1520
1521 WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
1522 fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1523
1524 /* RISC I/O register. */
1525 WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
1526 fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
1527
1528 /* Mailbox registers. */
1529 mbx_reg = &reg->mailbox0;
1530 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
1531 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
1532
1533 /* Transfer sequence registers. */
1534 iter_reg = fw->xseq_gp_reg;
1535 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
1536 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
1537 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
1538 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
1539 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
1540 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
1541 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
1542 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
1543
1544 iter_reg = fw->xseq_0_reg;
1545 iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
1546 iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
1547 qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
1548
1549 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
1550
1551 /* Receive sequence registers. */
1552 iter_reg = fw->rseq_gp_reg;
1553 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
1554 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
1555 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
1556 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
1557 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
1558 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
1559 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
1560 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
1561
1562 iter_reg = fw->rseq_0_reg;
1563 iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
1564 qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
1565
1566 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
1567 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
1568
1569 /* Auxiliary sequence registers. */
1570 iter_reg = fw->aseq_gp_reg;
1571 iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
1572 iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
1573 iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
1574 iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
1575 iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
1576 iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
1577 iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
1578 qla24xx_read_window(reg, 0xB070, 16, iter_reg);
1579
1580 iter_reg = fw->aseq_0_reg;
1581 iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
1582 qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
1583
1584 qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
1585 qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
1586
1587 /* Command DMA registers. */
1588 qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
1589
1590 /* Queues. */
1591 iter_reg = fw->req0_dma_reg;
1592 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
1593 dmp_reg = &reg->iobase_q;
1594 for (cnt = 0; cnt < 7; cnt++)
1595 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1596
1597 iter_reg = fw->resp0_dma_reg;
1598 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
1599 dmp_reg = &reg->iobase_q;
1600 for (cnt = 0; cnt < 7; cnt++)
1601 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1602
1603 iter_reg = fw->req1_dma_reg;
1604 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
1605 dmp_reg = &reg->iobase_q;
1606 for (cnt = 0; cnt < 7; cnt++)
1607 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1608
1609 /* Transmit DMA registers. */
1610 iter_reg = fw->xmt0_dma_reg;
1611 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
1612 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
1613
1614 iter_reg = fw->xmt1_dma_reg;
1615 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
1616 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
1617
1618 iter_reg = fw->xmt2_dma_reg;
1619 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
1620 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
1621
1622 iter_reg = fw->xmt3_dma_reg;
1623 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
1624 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
1625
1626 iter_reg = fw->xmt4_dma_reg;
1627 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
1628 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
1629
1630 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
1631
1632 /* Receive DMA registers. */
1633 iter_reg = fw->rcvt0_data_dma_reg;
1634 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
1635 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
1636
1637 iter_reg = fw->rcvt1_data_dma_reg;
1638 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
1639 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
1640
1641 /* RISC registers. */
1642 iter_reg = fw->risc_gp_reg;
1643 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
1644 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
1645 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
1646 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
1647 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
1648 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
1649 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
1650 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
1651
1652 /* Local memory controller registers. */
1653 iter_reg = fw->lmc_reg;
1654 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
1655 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
1656 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
1657 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
1658 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
1659 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
1660 iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
1661 qla24xx_read_window(reg, 0x3070, 16, iter_reg);
1662
1663 /* Fibre Protocol Module registers. */
1664 iter_reg = fw->fpm_hdw_reg;
1665 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
1666 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
1667 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
1668 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
1669 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
1670 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
1671 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
1672 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
1673 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
1674 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
1675 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
1676 iter_reg = qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
1677 iter_reg = qla24xx_read_window(reg, 0x40C0, 16, iter_reg);
1678 qla24xx_read_window(reg, 0x40D0, 16, iter_reg);
1679
1680 /* Frame Buffer registers. */
1681 iter_reg = fw->fb_hdw_reg;
1682 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
1683 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
1684 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
1685 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
1686 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
1687 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
1688 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
1689 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1690 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1691 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1692 iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
1693 iter_reg = qla24xx_read_window(reg, 0x61C0, 16, iter_reg);
1694 qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
1695
1696 /* Multi queue registers */
1697 nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset,
1698 &last_chain);
1699
1700 rval = qla24xx_soft_reset(ha);
1701 if (rval != QLA_SUCCESS)
1702 goto qla81xx_fw_dump_failed_0;
1703
1704 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
1705 &nxt);
1706 if (rval != QLA_SUCCESS)
1707 goto qla81xx_fw_dump_failed_0;
1708
1709 nxt = qla2xxx_copy_queues(ha, nxt);
1710
1711 nxt = qla24xx_copy_eft(ha, nxt);
1712
1713 /* Chain entries -- started with MQ. */
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08001714 nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
1715 nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001716 if (last_chain) {
1717 ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
1718 *last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
1719 }
1720
Giridhar Malavali050c9bb2012-02-09 11:15:33 -08001721 /* Adjust valid length. */
1722 ha->fw_dump_len = (nxt_chain - (void *)ha->fw_dump);
1723
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001724qla81xx_fw_dump_failed_0:
Andrew Vasquez3420d362009-10-13 15:16:45 -07001725 qla2xxx_dump_post_process(base_vha, rval);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001726
1727qla81xx_fw_dump_failed:
1728 if (!hardware_locked)
1729 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1730}
1731
Giridhar Malavali6246b8a2012-02-09 11:15:34 -08001732void
1733qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
1734{
1735 int rval;
1736 uint32_t cnt, reg_data;
1737 uint32_t risc_address;
1738 struct qla_hw_data *ha = vha->hw;
1739 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
1740 uint32_t __iomem *dmp_reg;
1741 uint32_t *iter_reg;
1742 uint16_t __iomem *mbx_reg;
1743 unsigned long flags;
1744 struct qla83xx_fw_dump *fw;
1745 uint32_t ext_mem_cnt;
1746 void *nxt, *nxt_chain;
1747 uint32_t *last_chain = NULL;
1748 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
1749
1750 risc_address = ext_mem_cnt = 0;
1751 flags = 0;
1752
1753 if (!hardware_locked)
1754 spin_lock_irqsave(&ha->hardware_lock, flags);
1755
1756 if (!ha->fw_dump) {
1757 ql_log(ql_log_warn, vha, 0xd00c,
1758 "No buffer available for dump!!!\n");
1759 goto qla83xx_fw_dump_failed;
1760 }
1761
1762 if (ha->fw_dumped) {
1763 ql_log(ql_log_warn, vha, 0xd00d,
1764 "Firmware has been previously dumped (%p) -- ignoring "
1765 "request...\n", ha->fw_dump);
1766 goto qla83xx_fw_dump_failed;
1767 }
1768 fw = &ha->fw_dump->isp.isp83;
1769 qla2xxx_prep_dump(ha, ha->fw_dump);
1770
1771 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
1772
1773 /* Pause RISC. */
1774 rval = qla24xx_pause_risc(reg);
1775 if (rval != QLA_SUCCESS)
1776 goto qla83xx_fw_dump_failed_0;
1777
1778 WRT_REG_DWORD(&reg->iobase_addr, 0x6000);
1779 dmp_reg = &reg->iobase_window;
1780 reg_data = RD_REG_DWORD(dmp_reg);
1781 WRT_REG_DWORD(dmp_reg, 0);
1782
1783 dmp_reg = &reg->unused_4_1[0];
1784 reg_data = RD_REG_DWORD(dmp_reg);
1785 WRT_REG_DWORD(dmp_reg, 0);
1786
1787 WRT_REG_DWORD(&reg->iobase_addr, 0x6010);
1788 dmp_reg = &reg->unused_4_1[2];
1789 reg_data = RD_REG_DWORD(dmp_reg);
1790 WRT_REG_DWORD(dmp_reg, 0);
1791
1792 /* select PCR and disable ecc checking and correction */
1793 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1794 RD_REG_DWORD(&reg->iobase_addr);
1795 WRT_REG_DWORD(&reg->iobase_select, 0x60000000); /* write to F0h = PCR */
1796
1797 /* Host/Risc registers. */
1798 iter_reg = fw->host_risc_reg;
1799 iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg);
1800 iter_reg = qla24xx_read_window(reg, 0x7010, 16, iter_reg);
1801 qla24xx_read_window(reg, 0x7040, 16, iter_reg);
1802
1803 /* PCIe registers. */
1804 WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
1805 RD_REG_DWORD(&reg->iobase_addr);
1806 WRT_REG_DWORD(&reg->iobase_window, 0x01);
1807 dmp_reg = &reg->iobase_c4;
1808 fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
1809 fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
1810 fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
1811 fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
1812
1813 WRT_REG_DWORD(&reg->iobase_window, 0x00);
1814 RD_REG_DWORD(&reg->iobase_window);
1815
1816 /* Host interface registers. */
1817 dmp_reg = &reg->flash_addr;
1818 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
1819 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
1820
1821 /* Disable interrupts. */
1822 WRT_REG_DWORD(&reg->ictrl, 0);
1823 RD_REG_DWORD(&reg->ictrl);
1824
1825 /* Shadow registers. */
1826 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1827 RD_REG_DWORD(&reg->iobase_addr);
1828 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
1829 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1830
1831 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
1832 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1833
1834 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
1835 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1836
1837 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
1838 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1839
1840 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
1841 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1842
1843 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
1844 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1845
1846 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
1847 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1848
1849 WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
1850 fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1851
1852 WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
1853 fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1854
1855 WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
1856 fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1857
1858 WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
1859 fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1860
1861 /* RISC I/O register. */
1862 WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
1863 fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
1864
1865 /* Mailbox registers. */
1866 mbx_reg = &reg->mailbox0;
1867 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
1868 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
1869
1870 /* Transfer sequence registers. */
1871 iter_reg = fw->xseq_gp_reg;
1872 iter_reg = qla24xx_read_window(reg, 0xBE00, 16, iter_reg);
1873 iter_reg = qla24xx_read_window(reg, 0xBE10, 16, iter_reg);
1874 iter_reg = qla24xx_read_window(reg, 0xBE20, 16, iter_reg);
1875 iter_reg = qla24xx_read_window(reg, 0xBE30, 16, iter_reg);
1876 iter_reg = qla24xx_read_window(reg, 0xBE40, 16, iter_reg);
1877 iter_reg = qla24xx_read_window(reg, 0xBE50, 16, iter_reg);
1878 iter_reg = qla24xx_read_window(reg, 0xBE60, 16, iter_reg);
1879 iter_reg = qla24xx_read_window(reg, 0xBE70, 16, iter_reg);
1880 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
1881 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
1882 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
1883 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
1884 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
1885 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
1886 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
1887 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
1888
1889 iter_reg = fw->xseq_0_reg;
1890 iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
1891 iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
1892 qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
1893
1894 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
1895
1896 qla24xx_read_window(reg, 0xBEF0, 16, fw->xseq_2_reg);
1897
1898 /* Receive sequence registers. */
1899 iter_reg = fw->rseq_gp_reg;
1900 iter_reg = qla24xx_read_window(reg, 0xFE00, 16, iter_reg);
1901 iter_reg = qla24xx_read_window(reg, 0xFE10, 16, iter_reg);
1902 iter_reg = qla24xx_read_window(reg, 0xFE20, 16, iter_reg);
1903 iter_reg = qla24xx_read_window(reg, 0xFE30, 16, iter_reg);
1904 iter_reg = qla24xx_read_window(reg, 0xFE40, 16, iter_reg);
1905 iter_reg = qla24xx_read_window(reg, 0xFE50, 16, iter_reg);
1906 iter_reg = qla24xx_read_window(reg, 0xFE60, 16, iter_reg);
1907 iter_reg = qla24xx_read_window(reg, 0xFE70, 16, iter_reg);
1908 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
1909 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
1910 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
1911 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
1912 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
1913 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
1914 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
1915 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
1916
1917 iter_reg = fw->rseq_0_reg;
1918 iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
1919 qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
1920
1921 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
1922 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
1923 qla24xx_read_window(reg, 0xFEF0, 16, fw->rseq_3_reg);
1924
1925 /* Auxiliary sequence registers. */
1926 iter_reg = fw->aseq_gp_reg;
1927 iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
1928 iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
1929 iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
1930 iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
1931 iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
1932 iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
1933 iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
1934 iter_reg = qla24xx_read_window(reg, 0xB070, 16, iter_reg);
1935 iter_reg = qla24xx_read_window(reg, 0xB100, 16, iter_reg);
1936 iter_reg = qla24xx_read_window(reg, 0xB110, 16, iter_reg);
1937 iter_reg = qla24xx_read_window(reg, 0xB120, 16, iter_reg);
1938 iter_reg = qla24xx_read_window(reg, 0xB130, 16, iter_reg);
1939 iter_reg = qla24xx_read_window(reg, 0xB140, 16, iter_reg);
1940 iter_reg = qla24xx_read_window(reg, 0xB150, 16, iter_reg);
1941 iter_reg = qla24xx_read_window(reg, 0xB160, 16, iter_reg);
1942 qla24xx_read_window(reg, 0xB170, 16, iter_reg);
1943
1944 iter_reg = fw->aseq_0_reg;
1945 iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
1946 qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
1947
1948 qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
1949 qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
1950 qla24xx_read_window(reg, 0xB1F0, 16, fw->aseq_3_reg);
1951
1952 /* Command DMA registers. */
1953 iter_reg = fw->cmd_dma_reg;
1954 iter_reg = qla24xx_read_window(reg, 0x7100, 16, iter_reg);
1955 iter_reg = qla24xx_read_window(reg, 0x7120, 16, iter_reg);
1956 iter_reg = qla24xx_read_window(reg, 0x7130, 16, iter_reg);
1957 qla24xx_read_window(reg, 0x71F0, 16, iter_reg);
1958
1959 /* Queues. */
1960 iter_reg = fw->req0_dma_reg;
1961 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
1962 dmp_reg = &reg->iobase_q;
1963 for (cnt = 0; cnt < 7; cnt++)
1964 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1965
1966 iter_reg = fw->resp0_dma_reg;
1967 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
1968 dmp_reg = &reg->iobase_q;
1969 for (cnt = 0; cnt < 7; cnt++)
1970 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1971
1972 iter_reg = fw->req1_dma_reg;
1973 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
1974 dmp_reg = &reg->iobase_q;
1975 for (cnt = 0; cnt < 7; cnt++)
1976 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1977
1978 /* Transmit DMA registers. */
1979 iter_reg = fw->xmt0_dma_reg;
1980 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
1981 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
1982
1983 iter_reg = fw->xmt1_dma_reg;
1984 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
1985 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
1986
1987 iter_reg = fw->xmt2_dma_reg;
1988 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
1989 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
1990
1991 iter_reg = fw->xmt3_dma_reg;
1992 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
1993 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
1994
1995 iter_reg = fw->xmt4_dma_reg;
1996 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
1997 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
1998
1999 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
2000
2001 /* Receive DMA registers. */
2002 iter_reg = fw->rcvt0_data_dma_reg;
2003 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
2004 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
2005
2006 iter_reg = fw->rcvt1_data_dma_reg;
2007 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
2008 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
2009
2010 /* RISC registers. */
2011 iter_reg = fw->risc_gp_reg;
2012 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
2013 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
2014 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
2015 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
2016 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
2017 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
2018 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
2019 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
2020
2021 /* Local memory controller registers. */
2022 iter_reg = fw->lmc_reg;
2023 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
2024 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
2025 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
2026 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
2027 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
2028 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
2029 iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
2030 qla24xx_read_window(reg, 0x3070, 16, iter_reg);
2031
2032 /* Fibre Protocol Module registers. */
2033 iter_reg = fw->fpm_hdw_reg;
2034 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
2035 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
2036 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
2037 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
2038 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
2039 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
2040 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
2041 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
2042 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
2043 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
2044 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
2045 iter_reg = qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
2046 iter_reg = qla24xx_read_window(reg, 0x40C0, 16, iter_reg);
2047 iter_reg = qla24xx_read_window(reg, 0x40D0, 16, iter_reg);
2048 iter_reg = qla24xx_read_window(reg, 0x40E0, 16, iter_reg);
2049 qla24xx_read_window(reg, 0x40F0, 16, iter_reg);
2050
2051 /* RQ0 Array registers. */
2052 iter_reg = fw->rq0_array_reg;
2053 iter_reg = qla24xx_read_window(reg, 0x5C00, 16, iter_reg);
2054 iter_reg = qla24xx_read_window(reg, 0x5C10, 16, iter_reg);
2055 iter_reg = qla24xx_read_window(reg, 0x5C20, 16, iter_reg);
2056 iter_reg = qla24xx_read_window(reg, 0x5C30, 16, iter_reg);
2057 iter_reg = qla24xx_read_window(reg, 0x5C40, 16, iter_reg);
2058 iter_reg = qla24xx_read_window(reg, 0x5C50, 16, iter_reg);
2059 iter_reg = qla24xx_read_window(reg, 0x5C60, 16, iter_reg);
2060 iter_reg = qla24xx_read_window(reg, 0x5C70, 16, iter_reg);
2061 iter_reg = qla24xx_read_window(reg, 0x5C80, 16, iter_reg);
2062 iter_reg = qla24xx_read_window(reg, 0x5C90, 16, iter_reg);
2063 iter_reg = qla24xx_read_window(reg, 0x5CA0, 16, iter_reg);
2064 iter_reg = qla24xx_read_window(reg, 0x5CB0, 16, iter_reg);
2065 iter_reg = qla24xx_read_window(reg, 0x5CC0, 16, iter_reg);
2066 iter_reg = qla24xx_read_window(reg, 0x5CD0, 16, iter_reg);
2067 iter_reg = qla24xx_read_window(reg, 0x5CE0, 16, iter_reg);
2068 qla24xx_read_window(reg, 0x5CF0, 16, iter_reg);
2069
2070 /* RQ1 Array registers. */
2071 iter_reg = fw->rq1_array_reg;
2072 iter_reg = qla24xx_read_window(reg, 0x5D00, 16, iter_reg);
2073 iter_reg = qla24xx_read_window(reg, 0x5D10, 16, iter_reg);
2074 iter_reg = qla24xx_read_window(reg, 0x5D20, 16, iter_reg);
2075 iter_reg = qla24xx_read_window(reg, 0x5D30, 16, iter_reg);
2076 iter_reg = qla24xx_read_window(reg, 0x5D40, 16, iter_reg);
2077 iter_reg = qla24xx_read_window(reg, 0x5D50, 16, iter_reg);
2078 iter_reg = qla24xx_read_window(reg, 0x5D60, 16, iter_reg);
2079 iter_reg = qla24xx_read_window(reg, 0x5D70, 16, iter_reg);
2080 iter_reg = qla24xx_read_window(reg, 0x5D80, 16, iter_reg);
2081 iter_reg = qla24xx_read_window(reg, 0x5D90, 16, iter_reg);
2082 iter_reg = qla24xx_read_window(reg, 0x5DA0, 16, iter_reg);
2083 iter_reg = qla24xx_read_window(reg, 0x5DB0, 16, iter_reg);
2084 iter_reg = qla24xx_read_window(reg, 0x5DC0, 16, iter_reg);
2085 iter_reg = qla24xx_read_window(reg, 0x5DD0, 16, iter_reg);
2086 iter_reg = qla24xx_read_window(reg, 0x5DE0, 16, iter_reg);
2087 qla24xx_read_window(reg, 0x5DF0, 16, iter_reg);
2088
2089 /* RP0 Array registers. */
2090 iter_reg = fw->rp0_array_reg;
2091 iter_reg = qla24xx_read_window(reg, 0x5E00, 16, iter_reg);
2092 iter_reg = qla24xx_read_window(reg, 0x5E10, 16, iter_reg);
2093 iter_reg = qla24xx_read_window(reg, 0x5E20, 16, iter_reg);
2094 iter_reg = qla24xx_read_window(reg, 0x5E30, 16, iter_reg);
2095 iter_reg = qla24xx_read_window(reg, 0x5E40, 16, iter_reg);
2096 iter_reg = qla24xx_read_window(reg, 0x5E50, 16, iter_reg);
2097 iter_reg = qla24xx_read_window(reg, 0x5E60, 16, iter_reg);
2098 iter_reg = qla24xx_read_window(reg, 0x5E70, 16, iter_reg);
2099 iter_reg = qla24xx_read_window(reg, 0x5E80, 16, iter_reg);
2100 iter_reg = qla24xx_read_window(reg, 0x5E90, 16, iter_reg);
2101 iter_reg = qla24xx_read_window(reg, 0x5EA0, 16, iter_reg);
2102 iter_reg = qla24xx_read_window(reg, 0x5EB0, 16, iter_reg);
2103 iter_reg = qla24xx_read_window(reg, 0x5EC0, 16, iter_reg);
2104 iter_reg = qla24xx_read_window(reg, 0x5ED0, 16, iter_reg);
2105 iter_reg = qla24xx_read_window(reg, 0x5EE0, 16, iter_reg);
2106 qla24xx_read_window(reg, 0x5EF0, 16, iter_reg);
2107
2108 /* RP1 Array registers. */
2109 iter_reg = fw->rp1_array_reg;
2110 iter_reg = qla24xx_read_window(reg, 0x5F00, 16, iter_reg);
2111 iter_reg = qla24xx_read_window(reg, 0x5F10, 16, iter_reg);
2112 iter_reg = qla24xx_read_window(reg, 0x5F20, 16, iter_reg);
2113 iter_reg = qla24xx_read_window(reg, 0x5F30, 16, iter_reg);
2114 iter_reg = qla24xx_read_window(reg, 0x5F40, 16, iter_reg);
2115 iter_reg = qla24xx_read_window(reg, 0x5F50, 16, iter_reg);
2116 iter_reg = qla24xx_read_window(reg, 0x5F60, 16, iter_reg);
2117 iter_reg = qla24xx_read_window(reg, 0x5F70, 16, iter_reg);
2118 iter_reg = qla24xx_read_window(reg, 0x5F80, 16, iter_reg);
2119 iter_reg = qla24xx_read_window(reg, 0x5F90, 16, iter_reg);
2120 iter_reg = qla24xx_read_window(reg, 0x5FA0, 16, iter_reg);
2121 iter_reg = qla24xx_read_window(reg, 0x5FB0, 16, iter_reg);
2122 iter_reg = qla24xx_read_window(reg, 0x5FC0, 16, iter_reg);
2123 iter_reg = qla24xx_read_window(reg, 0x5FD0, 16, iter_reg);
2124 iter_reg = qla24xx_read_window(reg, 0x5FE0, 16, iter_reg);
2125 qla24xx_read_window(reg, 0x5FF0, 16, iter_reg);
2126
2127 iter_reg = fw->at0_array_reg;
2128 iter_reg = qla24xx_read_window(reg, 0x7080, 16, iter_reg);
2129 iter_reg = qla24xx_read_window(reg, 0x7090, 16, iter_reg);
2130 iter_reg = qla24xx_read_window(reg, 0x70A0, 16, iter_reg);
2131 iter_reg = qla24xx_read_window(reg, 0x70B0, 16, iter_reg);
2132 iter_reg = qla24xx_read_window(reg, 0x70C0, 16, iter_reg);
2133 iter_reg = qla24xx_read_window(reg, 0x70D0, 16, iter_reg);
2134 iter_reg = qla24xx_read_window(reg, 0x70E0, 16, iter_reg);
2135 qla24xx_read_window(reg, 0x70F0, 16, iter_reg);
2136
2137 /* I/O Queue Control registers. */
2138 qla24xx_read_window(reg, 0x7800, 16, fw->queue_control_reg);
2139
2140 /* Frame Buffer registers. */
2141 iter_reg = fw->fb_hdw_reg;
2142 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
2143 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
2144 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
2145 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
2146 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
2147 iter_reg = qla24xx_read_window(reg, 0x6060, 16, iter_reg);
2148 iter_reg = qla24xx_read_window(reg, 0x6070, 16, iter_reg);
2149 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
2150 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
2151 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
2152 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
2153 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
2154 iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
2155 iter_reg = qla24xx_read_window(reg, 0x61C0, 16, iter_reg);
2156 iter_reg = qla24xx_read_window(reg, 0x6530, 16, iter_reg);
2157 iter_reg = qla24xx_read_window(reg, 0x6540, 16, iter_reg);
2158 iter_reg = qla24xx_read_window(reg, 0x6550, 16, iter_reg);
2159 iter_reg = qla24xx_read_window(reg, 0x6560, 16, iter_reg);
2160 iter_reg = qla24xx_read_window(reg, 0x6570, 16, iter_reg);
2161 iter_reg = qla24xx_read_window(reg, 0x6580, 16, iter_reg);
2162 iter_reg = qla24xx_read_window(reg, 0x6590, 16, iter_reg);
2163 iter_reg = qla24xx_read_window(reg, 0x65A0, 16, iter_reg);
2164 iter_reg = qla24xx_read_window(reg, 0x65B0, 16, iter_reg);
2165 iter_reg = qla24xx_read_window(reg, 0x65C0, 16, iter_reg);
2166 iter_reg = qla24xx_read_window(reg, 0x65D0, 16, iter_reg);
2167 iter_reg = qla24xx_read_window(reg, 0x65E0, 16, iter_reg);
2168 qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
2169
2170 /* Multi queue registers */
2171 nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset,
2172 &last_chain);
2173
2174 rval = qla24xx_soft_reset(ha);
2175 if (rval != QLA_SUCCESS) {
2176 ql_log(ql_log_warn, vha, 0xd00e,
2177 "SOFT RESET FAILED, forcing continuation of dump!!!\n");
2178 rval = QLA_SUCCESS;
2179
2180 ql_log(ql_log_warn, vha, 0xd00f, "try a bigger hammer!!!\n");
2181
2182 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
2183 RD_REG_DWORD(&reg->hccr);
2184
2185 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
2186 RD_REG_DWORD(&reg->hccr);
2187
2188 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
2189 RD_REG_DWORD(&reg->hccr);
2190
2191 for (cnt = 30000; cnt && (RD_REG_WORD(&reg->mailbox0)); cnt--)
2192 udelay(5);
2193
2194 if (!cnt) {
2195 nxt = fw->code_ram;
2196 nxt += sizeof(fw->code_ram),
2197 nxt += (ha->fw_memory_size - 0x100000 + 1);
2198 goto copy_queue;
2199 } else
2200 ql_log(ql_log_warn, vha, 0xd010,
2201 "bigger hammer success?\n");
2202 }
2203
2204 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
2205 &nxt);
2206 if (rval != QLA_SUCCESS)
2207 goto qla83xx_fw_dump_failed_0;
2208
2209copy_queue:
2210 nxt = qla2xxx_copy_queues(ha, nxt);
2211
2212 nxt = qla24xx_copy_eft(ha, nxt);
2213
2214 /* Chain entries -- started with MQ. */
2215 nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
2216 nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
2217 if (last_chain) {
2218 ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
2219 *last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
2220 }
2221
2222 /* Adjust valid length. */
2223 ha->fw_dump_len = (nxt_chain - (void *)ha->fw_dump);
2224
2225qla83xx_fw_dump_failed_0:
2226 qla2xxx_dump_post_process(base_vha, rval);
2227
2228qla83xx_fw_dump_failed:
2229 if (!hardware_locked)
2230 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2231}
2232
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233/****************************************************************************/
2234/* Driver Debug Functions. */
2235/****************************************************************************/
Chad Dupuiscfb09192011-11-18 09:03:07 -08002236
2237static inline int
2238ql_mask_match(uint32_t level)
2239{
2240 if (ql2xextended_error_logging == 1)
2241 ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
2242 return (level & ql2xextended_error_logging) == level;
2243}
2244
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002245/*
2246 * This function is for formatting and logging debug information.
2247 * It is to be used when vha is available. It formats the message
2248 * and logs it to the messages file.
2249 * parameters:
2250 * level: The level of the debug messages to be printed.
2251 * If ql2xextended_error_logging value is correctly set,
2252 * this message will appear in the messages file.
2253 * vha: Pointer to the scsi_qla_host_t.
2254 * id: This is a unique identifier for the level. It identifies the
2255 * part of the code from where the message originated.
2256 * msg: The message to be displayed.
2257 */
2258void
Joe Perches086b3e82011-11-18 09:03:05 -08002259ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
2260{
2261 va_list va;
2262 struct va_format vaf;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002263
Chad Dupuiscfb09192011-11-18 09:03:07 -08002264 if (!ql_mask_match(level))
Joe Perches086b3e82011-11-18 09:03:05 -08002265 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002266
Joe Perches086b3e82011-11-18 09:03:05 -08002267 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002268
Joe Perches086b3e82011-11-18 09:03:05 -08002269 vaf.fmt = fmt;
2270 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002271
Joe Perches086b3e82011-11-18 09:03:05 -08002272 if (vha != NULL) {
2273 const struct pci_dev *pdev = vha->hw->pdev;
2274 /* <module-name> <pci-name> <msg-id>:<host> Message */
2275 pr_warn("%s [%s]-%04x:%ld: %pV",
2276 QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset,
2277 vha->host_no, &vaf);
2278 } else {
2279 pr_warn("%s [%s]-%04x: : %pV",
2280 QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002281 }
2282
Joe Perches086b3e82011-11-18 09:03:05 -08002283 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002284
2285}
2286
2287/*
2288 * This function is for formatting and logging debug information.
2289 * It is to be used when vha is not available and pci is availble,
2290 * i.e., before host allocation. It formats the message and logs it
2291 * to the messages file.
2292 * parameters:
2293 * level: The level of the debug messages to be printed.
2294 * If ql2xextended_error_logging value is correctly set,
2295 * this message will appear in the messages file.
2296 * pdev: Pointer to the struct pci_dev.
2297 * id: This is a unique id for the level. It identifies the part
2298 * of the code from where the message originated.
2299 * msg: The message to be displayed.
2300 */
2301void
Joe Perches086b3e82011-11-18 09:03:05 -08002302ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
2303 const char *fmt, ...)
2304{
2305 va_list va;
2306 struct va_format vaf;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002307
2308 if (pdev == NULL)
2309 return;
Chad Dupuiscfb09192011-11-18 09:03:07 -08002310 if (!ql_mask_match(level))
Joe Perches086b3e82011-11-18 09:03:05 -08002311 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002312
Joe Perches086b3e82011-11-18 09:03:05 -08002313 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002314
Joe Perches086b3e82011-11-18 09:03:05 -08002315 vaf.fmt = fmt;
2316 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002317
Joe Perches086b3e82011-11-18 09:03:05 -08002318 /* <module-name> <dev-name>:<msg-id> Message */
2319 pr_warn("%s [%s]-%04x: : %pV",
2320 QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, &vaf);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002321
Joe Perches086b3e82011-11-18 09:03:05 -08002322 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002323}
2324
2325/*
2326 * This function is for formatting and logging log messages.
2327 * It is to be used when vha is available. It formats the message
2328 * and logs it to the messages file. All the messages will be logged
2329 * irrespective of value of ql2xextended_error_logging.
2330 * parameters:
2331 * level: The level of the log messages to be printed in the
2332 * messages file.
2333 * vha: Pointer to the scsi_qla_host_t
2334 * id: This is a unique id for the level. It identifies the
2335 * part of the code from where the message originated.
2336 * msg: The message to be displayed.
2337 */
2338void
Joe Perches086b3e82011-11-18 09:03:05 -08002339ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
2340{
2341 va_list va;
2342 struct va_format vaf;
2343 char pbuf[128];
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002344
Joe Perches086b3e82011-11-18 09:03:05 -08002345 if (level > ql_errlev)
2346 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002347
Joe Perches086b3e82011-11-18 09:03:05 -08002348 if (vha != NULL) {
2349 const struct pci_dev *pdev = vha->hw->pdev;
2350 /* <module-name> <msg-id>:<host> Message */
2351 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ",
2352 QL_MSGHDR, dev_name(&(pdev->dev)), id, vha->host_no);
2353 } else {
2354 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
2355 QL_MSGHDR, "0000:00:00.0", id);
2356 }
2357 pbuf[sizeof(pbuf) - 1] = 0;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002358
Joe Perches086b3e82011-11-18 09:03:05 -08002359 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002360
Joe Perches086b3e82011-11-18 09:03:05 -08002361 vaf.fmt = fmt;
2362 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002363
Joe Perches086b3e82011-11-18 09:03:05 -08002364 switch (level) {
2365 case 0: /* FATAL LOG */
2366 pr_crit("%s%pV", pbuf, &vaf);
2367 break;
2368 case 1:
2369 pr_err("%s%pV", pbuf, &vaf);
2370 break;
2371 case 2:
2372 pr_warn("%s%pV", pbuf, &vaf);
2373 break;
2374 default:
2375 pr_info("%s%pV", pbuf, &vaf);
2376 break;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002377 }
2378
Joe Perches086b3e82011-11-18 09:03:05 -08002379 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002380}
2381
2382/*
2383 * This function is for formatting and logging log messages.
2384 * It is to be used when vha is not available and pci is availble,
2385 * i.e., before host allocation. It formats the message and logs
2386 * it to the messages file. All the messages are logged irrespective
2387 * of the value of ql2xextended_error_logging.
2388 * parameters:
2389 * level: The level of the log messages to be printed in the
2390 * messages file.
2391 * pdev: Pointer to the struct pci_dev.
2392 * id: This is a unique id for the level. It identifies the
2393 * part of the code from where the message originated.
2394 * msg: The message to be displayed.
2395 */
2396void
Joe Perches086b3e82011-11-18 09:03:05 -08002397ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
2398 const char *fmt, ...)
2399{
2400 va_list va;
2401 struct va_format vaf;
2402 char pbuf[128];
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002403
2404 if (pdev == NULL)
2405 return;
Joe Perches086b3e82011-11-18 09:03:05 -08002406 if (level > ql_errlev)
2407 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002408
Joe Perches086b3e82011-11-18 09:03:05 -08002409 /* <module-name> <dev-name>:<msg-id> Message */
2410 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
2411 QL_MSGHDR, dev_name(&(pdev->dev)), id);
2412 pbuf[sizeof(pbuf) - 1] = 0;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002413
Joe Perches086b3e82011-11-18 09:03:05 -08002414 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002415
Joe Perches086b3e82011-11-18 09:03:05 -08002416 vaf.fmt = fmt;
2417 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002418
Joe Perches086b3e82011-11-18 09:03:05 -08002419 switch (level) {
2420 case 0: /* FATAL LOG */
2421 pr_crit("%s%pV", pbuf, &vaf);
2422 break;
2423 case 1:
2424 pr_err("%s%pV", pbuf, &vaf);
2425 break;
2426 case 2:
2427 pr_warn("%s%pV", pbuf, &vaf);
2428 break;
2429 default:
2430 pr_info("%s%pV", pbuf, &vaf);
2431 break;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002432 }
2433
Joe Perches086b3e82011-11-18 09:03:05 -08002434 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002435}
2436
2437void
2438ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id)
2439{
2440 int i;
2441 struct qla_hw_data *ha = vha->hw;
2442 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
2443 struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
2444 struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
2445 uint16_t __iomem *mbx_reg;
2446
Chad Dupuiscfb09192011-11-18 09:03:07 -08002447 if (!ql_mask_match(level))
2448 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002449
Chad Dupuiscfb09192011-11-18 09:03:07 -08002450 if (IS_QLA82XX(ha))
2451 mbx_reg = &reg82->mailbox_in[0];
2452 else if (IS_FWI2_CAPABLE(ha))
2453 mbx_reg = &reg24->mailbox0;
2454 else
2455 mbx_reg = MAILBOX_REG(ha, reg, 0);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002456
Chad Dupuiscfb09192011-11-18 09:03:07 -08002457 ql_dbg(level, vha, id, "Mailbox registers:\n");
2458 for (i = 0; i < 6; i++)
2459 ql_dbg(level, vha, id,
2460 "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++));
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002461}
2462
2463
2464void
2465ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
2466 uint8_t *b, uint32_t size)
2467{
2468 uint32_t cnt;
2469 uint8_t c;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002470
Chad Dupuiscfb09192011-11-18 09:03:07 -08002471 if (!ql_mask_match(level))
2472 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002473
Chad Dupuiscfb09192011-11-18 09:03:07 -08002474 ql_dbg(level, vha, id, " 0 1 2 3 4 5 6 7 8 "
2475 "9 Ah Bh Ch Dh Eh Fh\n");
2476 ql_dbg(level, vha, id, "----------------------------------"
2477 "----------------------------\n");
2478
2479 ql_dbg(level, vha, id, " ");
2480 for (cnt = 0; cnt < size;) {
2481 c = *b++;
2482 printk("%02x", (uint32_t) c);
2483 cnt++;
2484 if (!(cnt % 16))
2485 printk("\n");
2486 else
2487 printk(" ");
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002488 }
Chad Dupuiscfb09192011-11-18 09:03:07 -08002489 if (cnt % 16)
2490 ql_dbg(level, vha, id, "\n");
Saurav Kashyap3ce88662011-07-14 12:00:12 -07002491}