blob: cdf0617635444d1938d5e28e9f3d2a4e9fdfeae9 [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 * ----------------------------------------------------------------------
Chad Dupuiscfb09192011-11-18 09:03:07 -080014 * | Module Init and Probe | 0x0116 | 0xfa |
Giridhar Malavali63154912011-11-18 09:02:19 -080015 * | Mailbox commands | 0x112b | |
Chad Dupuiscfb09192011-11-18 09:03:07 -080016 * | Device Discovery | 0x2084 | |
Giridhar Malavali5162cf02011-11-18 09:03:18 -080017 * | Queue Command and IO tracing | 0x302f | 0x3008,0x302d, |
18 * | | | 0x302e |
Arun Easie02587d2011-08-16 11:29:23 -070019 * | DPC Thread | 0x401c | |
Chad Dupuiscfb09192011-11-18 09:03:07 -080020 * | Async Events | 0x5057 | 0x5052 |
21 * | 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 | |
Chad Dupuisc8f65442011-11-18 09:02:17 -080028 * | ISP82XX Specific | 0xb052 | |
Arun Easie02587d2011-08-16 11:29:23 -070029 * | MultiQ | 0xc00b | |
30 * | Misc | 0xd00b | |
31 * ----------------------------------------------------------------------
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
456 if (!ha->mqenable)
457 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
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732/****************************************************************************/
1733/* Driver Debug Functions. */
1734/****************************************************************************/
Chad Dupuiscfb09192011-11-18 09:03:07 -08001735
1736static inline int
1737ql_mask_match(uint32_t level)
1738{
1739 if (ql2xextended_error_logging == 1)
1740 ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
1741 return (level & ql2xextended_error_logging) == level;
1742}
1743
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001744/*
1745 * This function is for formatting and logging debug information.
1746 * It is to be used when vha is available. It formats the message
1747 * and logs it to the messages file.
1748 * parameters:
1749 * level: The level of the debug messages to be printed.
1750 * If ql2xextended_error_logging value is correctly set,
1751 * this message will appear in the messages file.
1752 * vha: Pointer to the scsi_qla_host_t.
1753 * id: This is a unique identifier for the level. It identifies the
1754 * part of the code from where the message originated.
1755 * msg: The message to be displayed.
1756 */
1757void
Joe Perches086b3e82011-11-18 09:03:05 -08001758ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
1759{
1760 va_list va;
1761 struct va_format vaf;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001762
Chad Dupuiscfb09192011-11-18 09:03:07 -08001763 if (!ql_mask_match(level))
Joe Perches086b3e82011-11-18 09:03:05 -08001764 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001765
Joe Perches086b3e82011-11-18 09:03:05 -08001766 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001767
Joe Perches086b3e82011-11-18 09:03:05 -08001768 vaf.fmt = fmt;
1769 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001770
Joe Perches086b3e82011-11-18 09:03:05 -08001771 if (vha != NULL) {
1772 const struct pci_dev *pdev = vha->hw->pdev;
1773 /* <module-name> <pci-name> <msg-id>:<host> Message */
1774 pr_warn("%s [%s]-%04x:%ld: %pV",
1775 QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset,
1776 vha->host_no, &vaf);
1777 } else {
1778 pr_warn("%s [%s]-%04x: : %pV",
1779 QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001780 }
1781
Joe Perches086b3e82011-11-18 09:03:05 -08001782 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001783
1784}
1785
1786/*
1787 * This function is for formatting and logging debug information.
1788 * It is to be used when vha is not available and pci is availble,
1789 * i.e., before host allocation. It formats the message and logs it
1790 * to the messages file.
1791 * parameters:
1792 * level: The level of the debug messages to be printed.
1793 * If ql2xextended_error_logging value is correctly set,
1794 * this message will appear in the messages file.
1795 * pdev: Pointer to the struct pci_dev.
1796 * id: This is a unique id for the level. It identifies the part
1797 * of the code from where the message originated.
1798 * msg: The message to be displayed.
1799 */
1800void
Joe Perches086b3e82011-11-18 09:03:05 -08001801ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
1802 const char *fmt, ...)
1803{
1804 va_list va;
1805 struct va_format vaf;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001806
1807 if (pdev == NULL)
1808 return;
Chad Dupuiscfb09192011-11-18 09:03:07 -08001809 if (!ql_mask_match(level))
Joe Perches086b3e82011-11-18 09:03:05 -08001810 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001811
Joe Perches086b3e82011-11-18 09:03:05 -08001812 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001813
Joe Perches086b3e82011-11-18 09:03:05 -08001814 vaf.fmt = fmt;
1815 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001816
Joe Perches086b3e82011-11-18 09:03:05 -08001817 /* <module-name> <dev-name>:<msg-id> Message */
1818 pr_warn("%s [%s]-%04x: : %pV",
1819 QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, &vaf);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001820
Joe Perches086b3e82011-11-18 09:03:05 -08001821 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001822}
1823
1824/*
1825 * This function is for formatting and logging log messages.
1826 * It is to be used when vha is available. It formats the message
1827 * and logs it to the messages file. All the messages will be logged
1828 * irrespective of value of ql2xextended_error_logging.
1829 * parameters:
1830 * level: The level of the log messages to be printed in the
1831 * messages file.
1832 * vha: Pointer to the scsi_qla_host_t
1833 * id: This is a unique id for the level. It identifies the
1834 * part of the code from where the message originated.
1835 * msg: The message to be displayed.
1836 */
1837void
Joe Perches086b3e82011-11-18 09:03:05 -08001838ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
1839{
1840 va_list va;
1841 struct va_format vaf;
1842 char pbuf[128];
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001843
Joe Perches086b3e82011-11-18 09:03:05 -08001844 if (level > ql_errlev)
1845 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001846
Joe Perches086b3e82011-11-18 09:03:05 -08001847 if (vha != NULL) {
1848 const struct pci_dev *pdev = vha->hw->pdev;
1849 /* <module-name> <msg-id>:<host> Message */
1850 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ",
1851 QL_MSGHDR, dev_name(&(pdev->dev)), id, vha->host_no);
1852 } else {
1853 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
1854 QL_MSGHDR, "0000:00:00.0", id);
1855 }
1856 pbuf[sizeof(pbuf) - 1] = 0;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001857
Joe Perches086b3e82011-11-18 09:03:05 -08001858 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001859
Joe Perches086b3e82011-11-18 09:03:05 -08001860 vaf.fmt = fmt;
1861 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001862
Joe Perches086b3e82011-11-18 09:03:05 -08001863 switch (level) {
1864 case 0: /* FATAL LOG */
1865 pr_crit("%s%pV", pbuf, &vaf);
1866 break;
1867 case 1:
1868 pr_err("%s%pV", pbuf, &vaf);
1869 break;
1870 case 2:
1871 pr_warn("%s%pV", pbuf, &vaf);
1872 break;
1873 default:
1874 pr_info("%s%pV", pbuf, &vaf);
1875 break;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001876 }
1877
Joe Perches086b3e82011-11-18 09:03:05 -08001878 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001879}
1880
1881/*
1882 * This function is for formatting and logging log messages.
1883 * It is to be used when vha is not available and pci is availble,
1884 * i.e., before host allocation. It formats the message and logs
1885 * it to the messages file. All the messages are logged irrespective
1886 * of the value of ql2xextended_error_logging.
1887 * parameters:
1888 * level: The level of the log messages to be printed in the
1889 * messages file.
1890 * pdev: Pointer to the struct pci_dev.
1891 * id: This is a unique id for the level. It identifies the
1892 * part of the code from where the message originated.
1893 * msg: The message to be displayed.
1894 */
1895void
Joe Perches086b3e82011-11-18 09:03:05 -08001896ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
1897 const char *fmt, ...)
1898{
1899 va_list va;
1900 struct va_format vaf;
1901 char pbuf[128];
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001902
1903 if (pdev == NULL)
1904 return;
Joe Perches086b3e82011-11-18 09:03:05 -08001905 if (level > ql_errlev)
1906 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001907
Joe Perches086b3e82011-11-18 09:03:05 -08001908 /* <module-name> <dev-name>:<msg-id> Message */
1909 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
1910 QL_MSGHDR, dev_name(&(pdev->dev)), id);
1911 pbuf[sizeof(pbuf) - 1] = 0;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001912
Joe Perches086b3e82011-11-18 09:03:05 -08001913 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001914
Joe Perches086b3e82011-11-18 09:03:05 -08001915 vaf.fmt = fmt;
1916 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001917
Joe Perches086b3e82011-11-18 09:03:05 -08001918 switch (level) {
1919 case 0: /* FATAL LOG */
1920 pr_crit("%s%pV", pbuf, &vaf);
1921 break;
1922 case 1:
1923 pr_err("%s%pV", pbuf, &vaf);
1924 break;
1925 case 2:
1926 pr_warn("%s%pV", pbuf, &vaf);
1927 break;
1928 default:
1929 pr_info("%s%pV", pbuf, &vaf);
1930 break;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001931 }
1932
Joe Perches086b3e82011-11-18 09:03:05 -08001933 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001934}
1935
1936void
1937ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id)
1938{
1939 int i;
1940 struct qla_hw_data *ha = vha->hw;
1941 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
1942 struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
1943 struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
1944 uint16_t __iomem *mbx_reg;
1945
Chad Dupuiscfb09192011-11-18 09:03:07 -08001946 if (!ql_mask_match(level))
1947 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001948
Chad Dupuiscfb09192011-11-18 09:03:07 -08001949 if (IS_QLA82XX(ha))
1950 mbx_reg = &reg82->mailbox_in[0];
1951 else if (IS_FWI2_CAPABLE(ha))
1952 mbx_reg = &reg24->mailbox0;
1953 else
1954 mbx_reg = MAILBOX_REG(ha, reg, 0);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001955
Chad Dupuiscfb09192011-11-18 09:03:07 -08001956 ql_dbg(level, vha, id, "Mailbox registers:\n");
1957 for (i = 0; i < 6; i++)
1958 ql_dbg(level, vha, id,
1959 "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++));
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001960}
1961
1962
1963void
1964ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
1965 uint8_t *b, uint32_t size)
1966{
1967 uint32_t cnt;
1968 uint8_t c;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001969
Chad Dupuiscfb09192011-11-18 09:03:07 -08001970 if (!ql_mask_match(level))
1971 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001972
Chad Dupuiscfb09192011-11-18 09:03:07 -08001973 ql_dbg(level, vha, id, " 0 1 2 3 4 5 6 7 8 "
1974 "9 Ah Bh Ch Dh Eh Fh\n");
1975 ql_dbg(level, vha, id, "----------------------------------"
1976 "----------------------------\n");
1977
1978 ql_dbg(level, vha, id, " ");
1979 for (cnt = 0; cnt < size;) {
1980 c = *b++;
1981 printk("%02x", (uint32_t) c);
1982 cnt++;
1983 if (!(cnt % 16))
1984 printk("\n");
1985 else
1986 printk(" ");
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001987 }
Chad Dupuiscfb09192011-11-18 09:03:07 -08001988 if (cnt % 16)
1989 ql_dbg(level, vha, id, "\n");
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001990}