blob: dc454628f0a1e289aa1e0e0f59ee5c30b2c96ce4 [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 | |
17 * | Queue Command and IO tracing | 0x302f | 0x3008 |
Arun Easie02587d2011-08-16 11:29:23 -070018 * | DPC Thread | 0x401c | |
Chad Dupuiscfb09192011-11-18 09:03:07 -080019 * | Async Events | 0x5057 | 0x5052 |
20 * | Timer Routines | 0x6011 | 0x600e,0x600f |
21 * | User Space Interactions | 0x709e | |
22 * | Task Management | 0x803c | 0x8025-0x8026 |
23 * | | | 0x800b,0x8039 |
Arun Easie02587d2011-08-16 11:29:23 -070024 * | AER/EEH | 0x900f | |
25 * | Virtual Port | 0xa007 | |
Chad Dupuisc8f65442011-11-18 09:02:17 -080026 * | ISP82XX Specific | 0xb052 | |
Arun Easie02587d2011-08-16 11:29:23 -070027 * | MultiQ | 0xc00b | |
28 * | Misc | 0xd00b | |
29 * ----------------------------------------------------------------------
Saurav Kashyap3ce88662011-07-14 12:00:12 -070030 */
31
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "qla_def.h"
33
34#include <linux/delay.h>
35
Saurav Kashyap3ce88662011-07-14 12:00:12 -070036static uint32_t ql_dbg_offset = 0x800;
37
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070038static inline void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080039qla2xxx_prep_dump(struct qla_hw_data *ha, struct qla2xxx_fw_dump *fw_dump)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070040{
41 fw_dump->fw_major_version = htonl(ha->fw_major_version);
42 fw_dump->fw_minor_version = htonl(ha->fw_minor_version);
43 fw_dump->fw_subminor_version = htonl(ha->fw_subminor_version);
44 fw_dump->fw_attributes = htonl(ha->fw_attributes);
45
46 fw_dump->vendor = htonl(ha->pdev->vendor);
47 fw_dump->device = htonl(ha->pdev->device);
48 fw_dump->subsystem_vendor = htonl(ha->pdev->subsystem_vendor);
49 fw_dump->subsystem_device = htonl(ha->pdev->subsystem_device);
50}
51
52static inline void *
Anirban Chakraborty73208df2008-12-09 16:45:39 -080053qla2xxx_copy_queues(struct qla_hw_data *ha, void *ptr)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070054{
Anirban Chakraborty73208df2008-12-09 16:45:39 -080055 struct req_que *req = ha->req_q_map[0];
56 struct rsp_que *rsp = ha->rsp_q_map[0];
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070057 /* Request queue. */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080058 memcpy(ptr, req->ring, req->length *
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070059 sizeof(request_t));
60
61 /* Response queue. */
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080062 ptr += req->length * sizeof(request_t);
63 memcpy(ptr, rsp->ring, rsp->length *
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070064 sizeof(response_t));
65
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080066 return ptr + (rsp->length * sizeof(response_t));
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070067}
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070069static int
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -080070qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
Andrew Vasquezc5722702008-04-24 15:21:22 -070071 uint32_t ram_dwords, void **nxt)
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070072{
73 int rval;
Andrew Vasquezc5722702008-04-24 15:21:22 -070074 uint32_t cnt, stat, timer, dwords, idx;
75 uint16_t mb0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070076 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
Andrew Vasquezc5722702008-04-24 15:21:22 -070077 dma_addr_t dump_dma = ha->gid_list_dma;
78 uint32_t *dump = (uint32_t *)ha->gid_list;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070079
80 rval = QLA_SUCCESS;
Andrew Vasquezc5722702008-04-24 15:21:22 -070081 mb0 = 0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070082
Andrew Vasquezc5722702008-04-24 15:21:22 -070083 WRT_REG_WORD(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070084 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
85
Andrew Vasquezc5722702008-04-24 15:21:22 -070086 dwords = GID_LIST_SIZE / 4;
87 for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
88 cnt += dwords, addr += dwords) {
89 if (cnt + dwords > ram_dwords)
90 dwords = ram_dwords - cnt;
91
92 WRT_REG_WORD(&reg->mailbox1, LSW(addr));
93 WRT_REG_WORD(&reg->mailbox8, MSW(addr));
94
95 WRT_REG_WORD(&reg->mailbox2, MSW(dump_dma));
96 WRT_REG_WORD(&reg->mailbox3, LSW(dump_dma));
97 WRT_REG_WORD(&reg->mailbox6, MSW(MSD(dump_dma)));
98 WRT_REG_WORD(&reg->mailbox7, LSW(MSD(dump_dma)));
99
100 WRT_REG_WORD(&reg->mailbox4, MSW(dwords));
101 WRT_REG_WORD(&reg->mailbox5, LSW(dwords));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700102 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
103
104 for (timer = 6000000; timer; timer--) {
105 /* Check for pending interrupts. */
106 stat = RD_REG_DWORD(&reg->host_status);
107 if (stat & HSRX_RISC_INT) {
108 stat &= 0xff;
109
110 if (stat == 0x1 || stat == 0x2 ||
111 stat == 0x10 || stat == 0x11) {
112 set_bit(MBX_INTERRUPT,
113 &ha->mbx_cmd_flags);
114
Andrew Vasquezc5722702008-04-24 15:21:22 -0700115 mb0 = RD_REG_WORD(&reg->mailbox0);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700116
117 WRT_REG_DWORD(&reg->hccr,
118 HCCRX_CLR_RISC_INT);
119 RD_REG_DWORD(&reg->hccr);
120 break;
121 }
122
123 /* Clear this intr; it wasn't a mailbox intr */
124 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
125 RD_REG_DWORD(&reg->hccr);
126 }
127 udelay(5);
128 }
129
130 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
Andrew Vasquezc5722702008-04-24 15:21:22 -0700131 rval = mb0 & MBS_MASK;
132 for (idx = 0; idx < dwords; idx++)
133 ram[cnt + idx] = swab32(dump[idx]);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700134 } else {
135 rval = QLA_FUNCTION_FAILED;
136 }
137 }
138
Andrew Vasquezc5722702008-04-24 15:21:22 -0700139 *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700140 return rval;
141}
142
Andrew Vasquezc5722702008-04-24 15:21:22 -0700143static int
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800144qla24xx_dump_memory(struct qla_hw_data *ha, uint32_t *code_ram,
Andrew Vasquezc5722702008-04-24 15:21:22 -0700145 uint32_t cram_size, void **nxt)
146{
147 int rval;
148
149 /* Code RAM. */
150 rval = qla24xx_dump_ram(ha, 0x20000, code_ram, cram_size / 4, nxt);
151 if (rval != QLA_SUCCESS)
152 return rval;
153
154 /* External Memory. */
155 return qla24xx_dump_ram(ha, 0x100000, *nxt,
156 ha->fw_memory_size - 0x100000 + 1, nxt);
157}
158
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700159static uint32_t *
160qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
161 uint32_t count, uint32_t *buf)
162{
163 uint32_t __iomem *dmp_reg;
164
165 WRT_REG_DWORD(&reg->iobase_addr, iobase);
166 dmp_reg = &reg->iobase_window;
167 while (count--)
168 *buf++ = htonl(RD_REG_DWORD(dmp_reg++));
169
170 return buf;
171}
172
173static inline int
174qla24xx_pause_risc(struct device_reg_24xx __iomem *reg)
175{
176 int rval = QLA_SUCCESS;
177 uint32_t cnt;
178
Andrew Vasquezc3b058a2007-09-20 14:07:38 -0700179 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
Andrew Vasquezaed10882009-06-03 09:55:26 -0700180 for (cnt = 30000;
181 ((RD_REG_DWORD(&reg->host_status) & HSRX_RISC_PAUSED) == 0) &&
Andrew Vasquezc3b058a2007-09-20 14:07:38 -0700182 rval == QLA_SUCCESS; cnt--) {
183 if (cnt)
184 udelay(100);
185 else
186 rval = QLA_FUNCTION_TIMEOUT;
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700187 }
188
189 return rval;
190}
191
192static int
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800193qla24xx_soft_reset(struct qla_hw_data *ha)
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700194{
195 int rval = QLA_SUCCESS;
196 uint32_t cnt;
197 uint16_t mb0, wd;
198 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
199
200 /* Reset RISC. */
201 WRT_REG_DWORD(&reg->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
202 for (cnt = 0; cnt < 30000; cnt++) {
203 if ((RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
204 break;
205
206 udelay(10);
207 }
208
209 WRT_REG_DWORD(&reg->ctrl_status,
210 CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
211 pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
212
213 udelay(100);
214 /* Wait for firmware to complete NVRAM accesses. */
215 mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
216 for (cnt = 10000 ; cnt && mb0; cnt--) {
217 udelay(5);
218 mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
219 barrier();
220 }
221
222 /* Wait for soft-reset to complete. */
223 for (cnt = 0; cnt < 30000; cnt++) {
224 if ((RD_REG_DWORD(&reg->ctrl_status) &
225 CSRX_ISP_SOFT_RESET) == 0)
226 break;
227
228 udelay(10);
229 }
230 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
231 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
232
233 for (cnt = 30000; RD_REG_WORD(&reg->mailbox0) != 0 &&
234 rval == QLA_SUCCESS; cnt--) {
235 if (cnt)
236 udelay(100);
237 else
238 rval = QLA_FUNCTION_TIMEOUT;
239 }
240
241 return rval;
242}
243
Andrew Vasquezc5722702008-04-24 15:21:22 -0700244static int
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800245qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint16_t *ram,
Andrew Vasqueze18e9632009-06-17 10:30:31 -0700246 uint32_t ram_words, void **nxt)
Andrew Vasquezc5722702008-04-24 15:21:22 -0700247{
248 int rval;
249 uint32_t cnt, stat, timer, words, idx;
250 uint16_t mb0;
251 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
252 dma_addr_t dump_dma = ha->gid_list_dma;
253 uint16_t *dump = (uint16_t *)ha->gid_list;
254
255 rval = QLA_SUCCESS;
256 mb0 = 0;
257
258 WRT_MAILBOX_REG(ha, reg, 0, MBC_DUMP_RISC_RAM_EXTENDED);
259 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
260
261 words = GID_LIST_SIZE / 2;
262 for (cnt = 0; cnt < ram_words && rval == QLA_SUCCESS;
263 cnt += words, addr += words) {
264 if (cnt + words > ram_words)
265 words = ram_words - cnt;
266
267 WRT_MAILBOX_REG(ha, reg, 1, LSW(addr));
268 WRT_MAILBOX_REG(ha, reg, 8, MSW(addr));
269
270 WRT_MAILBOX_REG(ha, reg, 2, MSW(dump_dma));
271 WRT_MAILBOX_REG(ha, reg, 3, LSW(dump_dma));
272 WRT_MAILBOX_REG(ha, reg, 6, MSW(MSD(dump_dma)));
273 WRT_MAILBOX_REG(ha, reg, 7, LSW(MSD(dump_dma)));
274
275 WRT_MAILBOX_REG(ha, reg, 4, words);
276 WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
277
278 for (timer = 6000000; timer; timer--) {
279 /* Check for pending interrupts. */
280 stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
281 if (stat & HSR_RISC_INT) {
282 stat &= 0xff;
283
284 if (stat == 0x1 || stat == 0x2) {
285 set_bit(MBX_INTERRUPT,
286 &ha->mbx_cmd_flags);
287
288 mb0 = RD_MAILBOX_REG(ha, reg, 0);
289
290 /* Release mailbox registers. */
291 WRT_REG_WORD(&reg->semaphore, 0);
292 WRT_REG_WORD(&reg->hccr,
293 HCCR_CLR_RISC_INT);
294 RD_REG_WORD(&reg->hccr);
295 break;
296 } else if (stat == 0x10 || stat == 0x11) {
297 set_bit(MBX_INTERRUPT,
298 &ha->mbx_cmd_flags);
299
300 mb0 = RD_MAILBOX_REG(ha, reg, 0);
301
302 WRT_REG_WORD(&reg->hccr,
303 HCCR_CLR_RISC_INT);
304 RD_REG_WORD(&reg->hccr);
305 break;
306 }
307
308 /* clear this intr; it wasn't a mailbox intr */
309 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
310 RD_REG_WORD(&reg->hccr);
311 }
312 udelay(5);
313 }
314
315 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
316 rval = mb0 & MBS_MASK;
317 for (idx = 0; idx < words; idx++)
318 ram[cnt + idx] = swab16(dump[idx]);
319 } else {
320 rval = QLA_FUNCTION_FAILED;
321 }
322 }
323
324 *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
325 return rval;
326}
327
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700328static inline void
329qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
330 uint16_t *buf)
331{
332 uint16_t __iomem *dmp_reg = &reg->u.isp2300.fb_cmd;
333
334 while (count--)
335 *buf++ = htons(RD_REG_WORD(dmp_reg++));
336}
337
Andrew Vasquezbb99de62009-01-05 11:18:08 -0800338static inline void *
339qla24xx_copy_eft(struct qla_hw_data *ha, void *ptr)
340{
341 if (!ha->eft)
342 return ptr;
343
344 memcpy(ptr, ha->eft, ntohl(ha->fw_dump->eft_size));
345 return ptr + ntohl(ha->fw_dump->eft_size);
346}
347
348static inline void *
349qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
350{
351 uint32_t cnt;
352 uint32_t *iter_reg;
353 struct qla2xxx_fce_chain *fcec = ptr;
354
355 if (!ha->fce)
356 return ptr;
357
358 *last_chain = &fcec->type;
359 fcec->type = __constant_htonl(DUMP_CHAIN_FCE);
360 fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) +
361 fce_calc_size(ha->fce_bufs));
362 fcec->size = htonl(fce_calc_size(ha->fce_bufs));
363 fcec->addr_l = htonl(LSD(ha->fce_dma));
364 fcec->addr_h = htonl(MSD(ha->fce_dma));
365
366 iter_reg = fcec->eregs;
367 for (cnt = 0; cnt < 8; cnt++)
368 *iter_reg++ = htonl(ha->fce_mb[cnt]);
369
370 memcpy(iter_reg, ha->fce, ntohl(fcec->size));
371
Giridhar Malavali3cb0a672011-11-18 09:03:11 -0800372 return (char *)iter_reg + ntohl(fcec->size);
Andrew Vasquezbb99de62009-01-05 11:18:08 -0800373}
374
Andrew Vasquezd63ab532009-01-05 11:18:09 -0800375static inline void *
376qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
377{
378 uint32_t cnt, que_idx;
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -0700379 uint8_t que_cnt;
Andrew Vasquezd63ab532009-01-05 11:18:09 -0800380 struct qla2xxx_mq_chain *mq = ptr;
381 struct device_reg_25xxmq __iomem *reg;
382
383 if (!ha->mqenable)
384 return ptr;
385
386 mq = ptr;
387 *last_chain = &mq->type;
388 mq->type = __constant_htonl(DUMP_CHAIN_MQ);
389 mq->chain_size = __constant_htonl(sizeof(struct qla2xxx_mq_chain));
390
Anirban Chakraborty2afa19a2009-04-06 22:33:40 -0700391 que_cnt = ha->max_req_queues > ha->max_rsp_queues ?
392 ha->max_req_queues : ha->max_rsp_queues;
Andrew Vasquezd63ab532009-01-05 11:18:09 -0800393 mq->count = htonl(que_cnt);
394 for (cnt = 0; cnt < que_cnt; cnt++) {
395 reg = (struct device_reg_25xxmq *) ((void *)
396 ha->mqiobase + cnt * QLA_QUE_PAGE);
397 que_idx = cnt * 4;
398 mq->qregs[que_idx] = htonl(RD_REG_DWORD(&reg->req_q_in));
399 mq->qregs[que_idx+1] = htonl(RD_REG_DWORD(&reg->req_q_out));
400 mq->qregs[que_idx+2] = htonl(RD_REG_DWORD(&reg->rsp_q_in));
401 mq->qregs[que_idx+3] = htonl(RD_REG_DWORD(&reg->rsp_q_out));
402 }
403
404 return ptr + sizeof(struct qla2xxx_mq_chain);
405}
406
Giridhar Malavali08de2842011-08-16 11:31:44 -0700407void
Andrew Vasquez3420d362009-10-13 15:16:45 -0700408qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval)
409{
410 struct qla_hw_data *ha = vha->hw;
411
412 if (rval != QLA_SUCCESS) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700413 ql_log(ql_log_warn, vha, 0xd000,
414 "Failed to dump firmware (%x).\n", rval);
Andrew Vasquez3420d362009-10-13 15:16:45 -0700415 ha->fw_dumped = 0;
416 } else {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700417 ql_log(ql_log_info, vha, 0xd001,
Andrew Vasquez3420d362009-10-13 15:16:45 -0700418 "Firmware dump saved to temp buffer (%ld/%p).\n",
419 vha->host_no, ha->fw_dump);
420 ha->fw_dumped = 1;
421 qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
422 }
423}
424
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425/**
426 * qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
427 * @ha: HA context
428 * @hardware_locked: Called with the hardware_lock
429 */
430void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800431qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
433 int rval;
Andrew Vasquezc5722702008-04-24 15:21:22 -0700434 uint32_t cnt;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800435 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700436 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 uint16_t __iomem *dmp_reg;
438 unsigned long flags;
439 struct qla2300_fw_dump *fw;
Andrew Vasquezc5722702008-04-24 15:21:22 -0700440 void *nxt;
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800441 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 flags = 0;
444
445 if (!hardware_locked)
446 spin_lock_irqsave(&ha->hardware_lock, flags);
447
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700448 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700449 ql_log(ql_log_warn, vha, 0xd002,
450 "No buffer available for dump.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 goto qla2300_fw_dump_failed;
452 }
453
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700454 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700455 ql_log(ql_log_warn, vha, 0xd003,
456 "Firmware has been previously dumped (%p) "
457 "-- ignoring request.\n",
458 ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 goto qla2300_fw_dump_failed;
460 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700461 fw = &ha->fw_dump->isp.isp23;
462 qla2xxx_prep_dump(ha, ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 rval = QLA_SUCCESS;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700465 fw->hccr = htons(RD_REG_WORD(&reg->hccr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
467 /* Pause RISC. */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700468 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 if (IS_QLA2300(ha)) {
470 for (cnt = 30000;
471 (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
472 rval == QLA_SUCCESS; cnt--) {
473 if (cnt)
474 udelay(100);
475 else
476 rval = QLA_FUNCTION_TIMEOUT;
477 }
478 } else {
479 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
480 udelay(10);
481 }
482
483 if (rval == QLA_SUCCESS) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700484 dmp_reg = &reg->flash_address;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700485 for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700486 fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700488 dmp_reg = &reg->u.isp2300.req_q_in;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700489 for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700490 fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700492 dmp_reg = &reg->u.isp2300.mailbox0;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700493 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700494 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
496 WRT_REG_WORD(&reg->ctrl_status, 0x40);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700497 qla2xxx_read_window(reg, 32, fw->resp_dma_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
499 WRT_REG_WORD(&reg->ctrl_status, 0x50);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700500 qla2xxx_read_window(reg, 48, fw->dma_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502 WRT_REG_WORD(&reg->ctrl_status, 0x00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700503 dmp_reg = &reg->risc_hw;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700504 for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700505 fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700507 WRT_REG_WORD(&reg->pcr, 0x2000);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700508 qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700510 WRT_REG_WORD(&reg->pcr, 0x2200);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700511 qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700513 WRT_REG_WORD(&reg->pcr, 0x2400);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700514 qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700516 WRT_REG_WORD(&reg->pcr, 0x2600);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700517 qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700519 WRT_REG_WORD(&reg->pcr, 0x2800);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700520 qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700522 WRT_REG_WORD(&reg->pcr, 0x2A00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700523 qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700525 WRT_REG_WORD(&reg->pcr, 0x2C00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700526 qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700528 WRT_REG_WORD(&reg->pcr, 0x2E00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700529 qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700531 WRT_REG_WORD(&reg->ctrl_status, 0x10);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700532 qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700534 WRT_REG_WORD(&reg->ctrl_status, 0x20);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700535 qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700537 WRT_REG_WORD(&reg->ctrl_status, 0x30);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700538 qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
540 /* Reset RISC. */
541 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
542 for (cnt = 0; cnt < 30000; cnt++) {
543 if ((RD_REG_WORD(&reg->ctrl_status) &
544 CSR_ISP_SOFT_RESET) == 0)
545 break;
546
547 udelay(10);
548 }
549 }
550
551 if (!IS_QLA2300(ha)) {
552 for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
553 rval == QLA_SUCCESS; cnt--) {
554 if (cnt)
555 udelay(100);
556 else
557 rval = QLA_FUNCTION_TIMEOUT;
558 }
559 }
560
Andrew Vasquezc5722702008-04-24 15:21:22 -0700561 /* Get RISC SRAM. */
562 if (rval == QLA_SUCCESS)
563 rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram,
564 sizeof(fw->risc_ram) / 2, &nxt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Andrew Vasquezc5722702008-04-24 15:21:22 -0700566 /* Get stack SRAM. */
567 if (rval == QLA_SUCCESS)
568 rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram,
569 sizeof(fw->stack_ram) / 2, &nxt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570
Andrew Vasquezc5722702008-04-24 15:21:22 -0700571 /* Get data SRAM. */
572 if (rval == QLA_SUCCESS)
573 rval = qla2xxx_dump_ram(ha, 0x11000, fw->data_ram,
574 ha->fw_memory_size - 0x11000 + 1, &nxt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700576 if (rval == QLA_SUCCESS)
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800577 qla2xxx_copy_queues(ha, nxt);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700578
Andrew Vasquez3420d362009-10-13 15:16:45 -0700579 qla2xxx_dump_post_process(base_vha, rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
581qla2300_fw_dump_failed:
582 if (!hardware_locked)
583 spin_unlock_irqrestore(&ha->hardware_lock, flags);
584}
585
586/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 * qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware.
588 * @ha: HA context
589 * @hardware_locked: Called with the hardware_lock
590 */
591void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800592qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 int rval;
595 uint32_t cnt, timer;
596 uint16_t risc_address;
597 uint16_t mb0, mb2;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800598 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700599 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 uint16_t __iomem *dmp_reg;
601 unsigned long flags;
602 struct qla2100_fw_dump *fw;
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800603 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
605 risc_address = 0;
606 mb0 = mb2 = 0;
607 flags = 0;
608
609 if (!hardware_locked)
610 spin_lock_irqsave(&ha->hardware_lock, flags);
611
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700612 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700613 ql_log(ql_log_warn, vha, 0xd004,
614 "No buffer available for dump.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 goto qla2100_fw_dump_failed;
616 }
617
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700618 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700619 ql_log(ql_log_warn, vha, 0xd005,
620 "Firmware has been previously dumped (%p) "
621 "-- ignoring request.\n",
622 ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 goto qla2100_fw_dump_failed;
624 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700625 fw = &ha->fw_dump->isp.isp21;
626 qla2xxx_prep_dump(ha, ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
628 rval = QLA_SUCCESS;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700629 fw->hccr = htons(RD_REG_WORD(&reg->hccr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 /* Pause RISC. */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700632 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 for (cnt = 30000; (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
634 rval == QLA_SUCCESS; cnt--) {
635 if (cnt)
636 udelay(100);
637 else
638 rval = QLA_FUNCTION_TIMEOUT;
639 }
640 if (rval == QLA_SUCCESS) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700641 dmp_reg = &reg->flash_address;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700642 for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700643 fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700645 dmp_reg = &reg->u.isp2100.mailbox0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 for (cnt = 0; cnt < ha->mbx_count; cnt++) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700647 if (cnt == 8)
648 dmp_reg = &reg->u_end.isp2200.mailbox8;
649
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700650 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 }
652
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700653 dmp_reg = &reg->u.isp2100.unused_2[0];
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700654 for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700655 fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657 WRT_REG_WORD(&reg->ctrl_status, 0x00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700658 dmp_reg = &reg->risc_hw;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700659 for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700660 fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700662 WRT_REG_WORD(&reg->pcr, 0x2000);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700663 qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700665 WRT_REG_WORD(&reg->pcr, 0x2100);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700666 qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700668 WRT_REG_WORD(&reg->pcr, 0x2200);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700669 qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700671 WRT_REG_WORD(&reg->pcr, 0x2300);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700672 qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700674 WRT_REG_WORD(&reg->pcr, 0x2400);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700675 qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700677 WRT_REG_WORD(&reg->pcr, 0x2500);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700678 qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700680 WRT_REG_WORD(&reg->pcr, 0x2600);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700681 qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700683 WRT_REG_WORD(&reg->pcr, 0x2700);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700684 qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700686 WRT_REG_WORD(&reg->ctrl_status, 0x10);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700687 qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700689 WRT_REG_WORD(&reg->ctrl_status, 0x20);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700690 qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700692 WRT_REG_WORD(&reg->ctrl_status, 0x30);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700693 qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694
695 /* Reset the ISP. */
696 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
697 }
698
699 for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
700 rval == QLA_SUCCESS; cnt--) {
701 if (cnt)
702 udelay(100);
703 else
704 rval = QLA_FUNCTION_TIMEOUT;
705 }
706
707 /* Pause RISC. */
708 if (rval == QLA_SUCCESS && (IS_QLA2200(ha) || (IS_QLA2100(ha) &&
709 (RD_REG_WORD(&reg->mctr) & (BIT_1 | BIT_0)) != 0))) {
710
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700711 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 for (cnt = 30000;
713 (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
714 rval == QLA_SUCCESS; cnt--) {
715 if (cnt)
716 udelay(100);
717 else
718 rval = QLA_FUNCTION_TIMEOUT;
719 }
720 if (rval == QLA_SUCCESS) {
721 /* Set memory configuration and timing. */
722 if (IS_QLA2100(ha))
723 WRT_REG_WORD(&reg->mctr, 0xf1);
724 else
725 WRT_REG_WORD(&reg->mctr, 0xf2);
726 RD_REG_WORD(&reg->mctr); /* PCI Posting. */
727
728 /* Release RISC. */
729 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
730 }
731 }
732
733 if (rval == QLA_SUCCESS) {
734 /* Get RISC SRAM. */
735 risc_address = 0x1000;
736 WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
737 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
738 }
739 for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
740 cnt++, risc_address++) {
741 WRT_MAILBOX_REG(ha, reg, 1, risc_address);
742 WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
743
744 for (timer = 6000000; timer != 0; timer--) {
745 /* Check for pending interrupts. */
746 if (RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) {
747 if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
748 set_bit(MBX_INTERRUPT,
749 &ha->mbx_cmd_flags);
750
751 mb0 = RD_MAILBOX_REG(ha, reg, 0);
752 mb2 = RD_MAILBOX_REG(ha, reg, 2);
753
754 WRT_REG_WORD(&reg->semaphore, 0);
755 WRT_REG_WORD(&reg->hccr,
756 HCCR_CLR_RISC_INT);
757 RD_REG_WORD(&reg->hccr);
758 break;
759 }
760 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
761 RD_REG_WORD(&reg->hccr);
762 }
763 udelay(5);
764 }
765
766 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
767 rval = mb0 & MBS_MASK;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700768 fw->risc_ram[cnt] = htons(mb2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 } else {
770 rval = QLA_FUNCTION_FAILED;
771 }
772 }
773
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700774 if (rval == QLA_SUCCESS)
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800775 qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]);
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700776
Andrew Vasquez3420d362009-10-13 15:16:45 -0700777 qla2xxx_dump_post_process(base_vha, rval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
779qla2100_fw_dump_failed:
780 if (!hardware_locked)
781 spin_unlock_irqrestore(&ha->hardware_lock, flags);
782}
783
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700784void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800785qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700786{
787 int rval;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700788 uint32_t cnt;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700789 uint32_t risc_address;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -0800790 struct qla_hw_data *ha = vha->hw;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700791 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
792 uint32_t __iomem *dmp_reg;
793 uint32_t *iter_reg;
794 uint16_t __iomem *mbx_reg;
795 unsigned long flags;
796 struct qla24xx_fw_dump *fw;
797 uint32_t ext_mem_cnt;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700798 void *nxt;
Anirban Chakraborty73208df2008-12-09 16:45:39 -0800799 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700800
Giridhar Malavalia9083012010-04-12 17:59:55 -0700801 if (IS_QLA82XX(ha))
802 return;
803
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700804 risc_address = ext_mem_cnt = 0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700805 flags = 0;
806
807 if (!hardware_locked)
808 spin_lock_irqsave(&ha->hardware_lock, flags);
809
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700810 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700811 ql_log(ql_log_warn, vha, 0xd006,
812 "No buffer available for dump.\n");
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700813 goto qla24xx_fw_dump_failed;
814 }
815
816 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700817 ql_log(ql_log_warn, vha, 0xd007,
818 "Firmware has been previously dumped (%p) "
819 "-- ignoring request.\n",
820 ha->fw_dump);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700821 goto qla24xx_fw_dump_failed;
822 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700823 fw = &ha->fw_dump->isp.isp24;
824 qla2xxx_prep_dump(ha, ha->fw_dump);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700825
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700826 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700827
828 /* Pause RISC. */
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700829 rval = qla24xx_pause_risc(reg);
830 if (rval != QLA_SUCCESS)
831 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700832
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700833 /* Host interface registers. */
834 dmp_reg = &reg->flash_addr;
835 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
836 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700837
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700838 /* Disable interrupts. */
839 WRT_REG_DWORD(&reg->ictrl, 0);
840 RD_REG_DWORD(&reg->ictrl);
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800841
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700842 /* Shadow registers. */
843 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
844 RD_REG_DWORD(&reg->iobase_addr);
845 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
846 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800847
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700848 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
849 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800850
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700851 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
852 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800853
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700854 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
855 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800856
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700857 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
858 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800859
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700860 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
861 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800862
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700863 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
864 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800865
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700866 /* Mailbox registers. */
867 mbx_reg = &reg->mailbox0;
868 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
869 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700870
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700871 /* Transfer sequence registers. */
872 iter_reg = fw->xseq_gp_reg;
873 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
874 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
875 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
876 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
877 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
878 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
879 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
880 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700881
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700882 qla24xx_read_window(reg, 0xBFE0, 16, fw->xseq_0_reg);
883 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700884
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700885 /* Receive sequence registers. */
886 iter_reg = fw->rseq_gp_reg;
887 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
888 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
889 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
890 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
891 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
892 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
893 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
894 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700895
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700896 qla24xx_read_window(reg, 0xFFD0, 16, fw->rseq_0_reg);
897 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
898 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700899
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700900 /* Command DMA registers. */
901 qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700902
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700903 /* Queues. */
904 iter_reg = fw->req0_dma_reg;
905 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
906 dmp_reg = &reg->iobase_q;
907 for (cnt = 0; cnt < 7; cnt++)
908 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700909
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700910 iter_reg = fw->resp0_dma_reg;
911 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
912 dmp_reg = &reg->iobase_q;
913 for (cnt = 0; cnt < 7; cnt++)
914 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700915
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700916 iter_reg = fw->req1_dma_reg;
917 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
918 dmp_reg = &reg->iobase_q;
919 for (cnt = 0; cnt < 7; cnt++)
920 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700921
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700922 /* Transmit DMA registers. */
923 iter_reg = fw->xmt0_dma_reg;
924 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
925 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700926
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700927 iter_reg = fw->xmt1_dma_reg;
928 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
929 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700930
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700931 iter_reg = fw->xmt2_dma_reg;
932 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
933 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700934
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700935 iter_reg = fw->xmt3_dma_reg;
936 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
937 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700938
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700939 iter_reg = fw->xmt4_dma_reg;
940 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
941 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700942
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700943 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700944
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700945 /* Receive DMA registers. */
946 iter_reg = fw->rcvt0_data_dma_reg;
947 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
948 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700949
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700950 iter_reg = fw->rcvt1_data_dma_reg;
951 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
952 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700953
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700954 /* RISC registers. */
955 iter_reg = fw->risc_gp_reg;
956 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
957 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
958 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
959 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
960 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
961 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
962 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
963 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700964
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700965 /* Local memory controller registers. */
966 iter_reg = fw->lmc_reg;
967 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
968 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
969 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
970 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
971 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
972 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
973 qla24xx_read_window(reg, 0x3060, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700974
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700975 /* Fibre Protocol Module registers. */
976 iter_reg = fw->fpm_hdw_reg;
977 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
978 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
979 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
980 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
981 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
982 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
983 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
984 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
985 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
986 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
987 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
988 qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700989
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700990 /* Frame Buffer registers. */
991 iter_reg = fw->fb_hdw_reg;
992 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
993 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
994 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
995 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
996 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
997 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
998 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
999 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1000 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1001 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1002 qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001003
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001004 rval = qla24xx_soft_reset(ha);
1005 if (rval != QLA_SUCCESS)
1006 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001007
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001008 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
Andrew Vasquezc5722702008-04-24 15:21:22 -07001009 &nxt);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001010 if (rval != QLA_SUCCESS)
1011 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001012
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001013 nxt = qla2xxx_copy_queues(ha, nxt);
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001014
1015 qla24xx_copy_eft(ha, nxt);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001016
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001017qla24xx_fw_dump_failed_0:
Andrew Vasquez3420d362009-10-13 15:16:45 -07001018 qla2xxx_dump_post_process(base_vha, rval);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001019
1020qla24xx_fw_dump_failed:
1021 if (!hardware_locked)
1022 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1023}
1024
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001025void
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001026qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001027{
1028 int rval;
1029 uint32_t cnt;
1030 uint32_t risc_address;
Anirban Chakraborty7b867cf2008-11-06 10:40:19 -08001031 struct qla_hw_data *ha = vha->hw;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001032 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
1033 uint32_t __iomem *dmp_reg;
1034 uint32_t *iter_reg;
1035 uint16_t __iomem *mbx_reg;
1036 unsigned long flags;
1037 struct qla25xx_fw_dump *fw;
1038 uint32_t ext_mem_cnt;
Andrew Vasquezd63ab532009-01-05 11:18:09 -08001039 void *nxt, *nxt_chain;
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001040 uint32_t *last_chain = NULL;
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001041 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001042
1043 risc_address = ext_mem_cnt = 0;
1044 flags = 0;
1045
1046 if (!hardware_locked)
1047 spin_lock_irqsave(&ha->hardware_lock, flags);
1048
1049 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001050 ql_log(ql_log_warn, vha, 0xd008,
1051 "No buffer available for dump.\n");
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001052 goto qla25xx_fw_dump_failed;
1053 }
1054
1055 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001056 ql_log(ql_log_warn, vha, 0xd009,
1057 "Firmware has been previously dumped (%p) "
1058 "-- ignoring request.\n",
1059 ha->fw_dump);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001060 goto qla25xx_fw_dump_failed;
1061 }
1062 fw = &ha->fw_dump->isp.isp25;
1063 qla2xxx_prep_dump(ha, ha->fw_dump);
Andrew Vasquezb5836922007-09-20 14:07:39 -07001064 ha->fw_dump->version = __constant_htonl(2);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001065
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001066 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
1067
1068 /* Pause RISC. */
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001069 rval = qla24xx_pause_risc(reg);
1070 if (rval != QLA_SUCCESS)
1071 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001072
Andrew Vasquezb5836922007-09-20 14:07:39 -07001073 /* Host/Risc registers. */
1074 iter_reg = fw->host_risc_reg;
1075 iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg);
1076 qla24xx_read_window(reg, 0x7010, 16, iter_reg);
1077
1078 /* PCIe registers. */
1079 WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
1080 RD_REG_DWORD(&reg->iobase_addr);
1081 WRT_REG_DWORD(&reg->iobase_window, 0x01);
1082 dmp_reg = &reg->iobase_c4;
1083 fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
1084 fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
1085 fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
1086 fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001087
Andrew Vasquezb5836922007-09-20 14:07:39 -07001088 WRT_REG_DWORD(&reg->iobase_window, 0x00);
1089 RD_REG_DWORD(&reg->iobase_window);
1090
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001091 /* Host interface registers. */
1092 dmp_reg = &reg->flash_addr;
1093 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
1094 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001095
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001096 /* Disable interrupts. */
1097 WRT_REG_DWORD(&reg->ictrl, 0);
1098 RD_REG_DWORD(&reg->ictrl);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001099
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001100 /* Shadow registers. */
1101 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1102 RD_REG_DWORD(&reg->iobase_addr);
1103 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
1104 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001105
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001106 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
1107 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001108
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001109 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
1110 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001111
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001112 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
1113 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001114
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001115 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
1116 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001117
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001118 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
1119 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001120
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001121 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
1122 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001123
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001124 WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
1125 fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001126
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001127 WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
1128 fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001129
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001130 WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
1131 fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001132
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001133 WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
1134 fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001135
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001136 /* RISC I/O register. */
1137 WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
1138 fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001139
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001140 /* Mailbox registers. */
1141 mbx_reg = &reg->mailbox0;
1142 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
1143 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001144
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001145 /* Transfer sequence registers. */
1146 iter_reg = fw->xseq_gp_reg;
1147 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
1148 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
1149 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
1150 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
1151 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
1152 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
1153 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
1154 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001155
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001156 iter_reg = fw->xseq_0_reg;
1157 iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
1158 iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
1159 qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001160
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001161 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001162
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001163 /* Receive sequence registers. */
1164 iter_reg = fw->rseq_gp_reg;
1165 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
1166 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
1167 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
1168 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
1169 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
1170 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
1171 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
1172 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001173
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001174 iter_reg = fw->rseq_0_reg;
1175 iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
1176 qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001177
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001178 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
1179 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001180
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001181 /* Auxiliary sequence registers. */
1182 iter_reg = fw->aseq_gp_reg;
1183 iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
1184 iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
1185 iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
1186 iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
1187 iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
1188 iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
1189 iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
1190 qla24xx_read_window(reg, 0xB070, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001191
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001192 iter_reg = fw->aseq_0_reg;
1193 iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
1194 qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001195
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001196 qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
1197 qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001198
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001199 /* Command DMA registers. */
1200 qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001201
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001202 /* Queues. */
1203 iter_reg = fw->req0_dma_reg;
1204 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
1205 dmp_reg = &reg->iobase_q;
1206 for (cnt = 0; cnt < 7; cnt++)
1207 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001208
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001209 iter_reg = fw->resp0_dma_reg;
1210 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
1211 dmp_reg = &reg->iobase_q;
1212 for (cnt = 0; cnt < 7; cnt++)
1213 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001214
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001215 iter_reg = fw->req1_dma_reg;
1216 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
1217 dmp_reg = &reg->iobase_q;
1218 for (cnt = 0; cnt < 7; cnt++)
1219 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001220
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001221 /* Transmit DMA registers. */
1222 iter_reg = fw->xmt0_dma_reg;
1223 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
1224 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001225
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001226 iter_reg = fw->xmt1_dma_reg;
1227 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
1228 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001229
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001230 iter_reg = fw->xmt2_dma_reg;
1231 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
1232 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001233
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001234 iter_reg = fw->xmt3_dma_reg;
1235 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
1236 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001237
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001238 iter_reg = fw->xmt4_dma_reg;
1239 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
1240 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001241
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001242 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001243
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001244 /* Receive DMA registers. */
1245 iter_reg = fw->rcvt0_data_dma_reg;
1246 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
1247 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001248
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001249 iter_reg = fw->rcvt1_data_dma_reg;
1250 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
1251 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001252
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001253 /* RISC registers. */
1254 iter_reg = fw->risc_gp_reg;
1255 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
1256 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
1257 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
1258 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
1259 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
1260 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
1261 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
1262 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001263
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001264 /* Local memory controller registers. */
1265 iter_reg = fw->lmc_reg;
1266 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
1267 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
1268 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
1269 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
1270 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
1271 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
1272 iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
1273 qla24xx_read_window(reg, 0x3070, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001274
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001275 /* Fibre Protocol Module registers. */
1276 iter_reg = fw->fpm_hdw_reg;
1277 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
1278 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
1279 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
1280 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
1281 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
1282 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
1283 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
1284 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
1285 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
1286 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
1287 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
1288 qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001289
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001290 /* Frame Buffer registers. */
1291 iter_reg = fw->fb_hdw_reg;
1292 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
1293 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
1294 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
1295 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
1296 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
1297 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
1298 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
1299 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1300 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1301 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1302 iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
1303 qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001304
Andrew Vasquezd63ab532009-01-05 11:18:09 -08001305 /* Multi queue registers */
1306 nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset,
1307 &last_chain);
1308
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001309 rval = qla24xx_soft_reset(ha);
1310 if (rval != QLA_SUCCESS)
1311 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001312
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001313 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
Andrew Vasquezc5722702008-04-24 15:21:22 -07001314 &nxt);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001315 if (rval != QLA_SUCCESS)
1316 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001317
Anirban Chakraborty73208df2008-12-09 16:45:39 -08001318 nxt = qla2xxx_copy_queues(ha, nxt);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001319
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001320 nxt = qla24xx_copy_eft(ha, nxt);
Andrew Vasquezdf613b92008-01-17 09:02:17 -08001321
Andrew Vasquezd63ab532009-01-05 11:18:09 -08001322 /* Chain entries -- started with MQ. */
1323 qla25xx_copy_fce(ha, nxt_chain, &last_chain);
Andrew Vasquezbb99de62009-01-05 11:18:08 -08001324 if (last_chain) {
1325 ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
1326 *last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
1327 }
Andrew Vasquezdf613b92008-01-17 09:02:17 -08001328
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001329qla25xx_fw_dump_failed_0:
Andrew Vasquez3420d362009-10-13 15:16:45 -07001330 qla2xxx_dump_post_process(base_vha, rval);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001331
1332qla25xx_fw_dump_failed:
1333 if (!hardware_locked)
1334 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1335}
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001336
1337void
1338qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
1339{
1340 int rval;
1341 uint32_t cnt;
1342 uint32_t risc_address;
1343 struct qla_hw_data *ha = vha->hw;
1344 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
1345 uint32_t __iomem *dmp_reg;
1346 uint32_t *iter_reg;
1347 uint16_t __iomem *mbx_reg;
1348 unsigned long flags;
1349 struct qla81xx_fw_dump *fw;
1350 uint32_t ext_mem_cnt;
1351 void *nxt, *nxt_chain;
1352 uint32_t *last_chain = NULL;
1353 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
1354
1355 risc_address = ext_mem_cnt = 0;
1356 flags = 0;
1357
1358 if (!hardware_locked)
1359 spin_lock_irqsave(&ha->hardware_lock, flags);
1360
1361 if (!ha->fw_dump) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001362 ql_log(ql_log_warn, vha, 0xd00a,
1363 "No buffer available for dump.\n");
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001364 goto qla81xx_fw_dump_failed;
1365 }
1366
1367 if (ha->fw_dumped) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -07001368 ql_log(ql_log_warn, vha, 0xd00b,
1369 "Firmware has been previously dumped (%p) "
1370 "-- ignoring request.\n",
1371 ha->fw_dump);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001372 goto qla81xx_fw_dump_failed;
1373 }
1374 fw = &ha->fw_dump->isp.isp81;
1375 qla2xxx_prep_dump(ha, ha->fw_dump);
1376
1377 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
1378
1379 /* Pause RISC. */
1380 rval = qla24xx_pause_risc(reg);
1381 if (rval != QLA_SUCCESS)
1382 goto qla81xx_fw_dump_failed_0;
1383
1384 /* Host/Risc registers. */
1385 iter_reg = fw->host_risc_reg;
1386 iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg);
1387 qla24xx_read_window(reg, 0x7010, 16, iter_reg);
1388
1389 /* PCIe registers. */
1390 WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
1391 RD_REG_DWORD(&reg->iobase_addr);
1392 WRT_REG_DWORD(&reg->iobase_window, 0x01);
1393 dmp_reg = &reg->iobase_c4;
1394 fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
1395 fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
1396 fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
1397 fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
1398
1399 WRT_REG_DWORD(&reg->iobase_window, 0x00);
1400 RD_REG_DWORD(&reg->iobase_window);
1401
1402 /* Host interface registers. */
1403 dmp_reg = &reg->flash_addr;
1404 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
1405 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
1406
1407 /* Disable interrupts. */
1408 WRT_REG_DWORD(&reg->ictrl, 0);
1409 RD_REG_DWORD(&reg->ictrl);
1410
1411 /* Shadow registers. */
1412 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1413 RD_REG_DWORD(&reg->iobase_addr);
1414 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
1415 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1416
1417 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
1418 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1419
1420 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
1421 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1422
1423 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
1424 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1425
1426 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
1427 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1428
1429 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
1430 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1431
1432 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
1433 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1434
1435 WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
1436 fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1437
1438 WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
1439 fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1440
1441 WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
1442 fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1443
1444 WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
1445 fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1446
1447 /* RISC I/O register. */
1448 WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
1449 fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
1450
1451 /* Mailbox registers. */
1452 mbx_reg = &reg->mailbox0;
1453 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
1454 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
1455
1456 /* Transfer sequence registers. */
1457 iter_reg = fw->xseq_gp_reg;
1458 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
1459 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
1460 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
1461 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
1462 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
1463 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
1464 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
1465 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
1466
1467 iter_reg = fw->xseq_0_reg;
1468 iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
1469 iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
1470 qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
1471
1472 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
1473
1474 /* Receive sequence registers. */
1475 iter_reg = fw->rseq_gp_reg;
1476 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
1477 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
1478 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
1479 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
1480 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
1481 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
1482 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
1483 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
1484
1485 iter_reg = fw->rseq_0_reg;
1486 iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
1487 qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
1488
1489 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
1490 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
1491
1492 /* Auxiliary sequence registers. */
1493 iter_reg = fw->aseq_gp_reg;
1494 iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
1495 iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
1496 iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
1497 iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
1498 iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
1499 iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
1500 iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
1501 qla24xx_read_window(reg, 0xB070, 16, iter_reg);
1502
1503 iter_reg = fw->aseq_0_reg;
1504 iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
1505 qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
1506
1507 qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
1508 qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
1509
1510 /* Command DMA registers. */
1511 qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
1512
1513 /* Queues. */
1514 iter_reg = fw->req0_dma_reg;
1515 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
1516 dmp_reg = &reg->iobase_q;
1517 for (cnt = 0; cnt < 7; cnt++)
1518 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1519
1520 iter_reg = fw->resp0_dma_reg;
1521 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
1522 dmp_reg = &reg->iobase_q;
1523 for (cnt = 0; cnt < 7; cnt++)
1524 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1525
1526 iter_reg = fw->req1_dma_reg;
1527 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
1528 dmp_reg = &reg->iobase_q;
1529 for (cnt = 0; cnt < 7; cnt++)
1530 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1531
1532 /* Transmit DMA registers. */
1533 iter_reg = fw->xmt0_dma_reg;
1534 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
1535 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
1536
1537 iter_reg = fw->xmt1_dma_reg;
1538 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
1539 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
1540
1541 iter_reg = fw->xmt2_dma_reg;
1542 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
1543 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
1544
1545 iter_reg = fw->xmt3_dma_reg;
1546 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
1547 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
1548
1549 iter_reg = fw->xmt4_dma_reg;
1550 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
1551 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
1552
1553 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
1554
1555 /* Receive DMA registers. */
1556 iter_reg = fw->rcvt0_data_dma_reg;
1557 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
1558 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
1559
1560 iter_reg = fw->rcvt1_data_dma_reg;
1561 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
1562 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
1563
1564 /* RISC registers. */
1565 iter_reg = fw->risc_gp_reg;
1566 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
1567 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
1568 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
1569 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
1570 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
1571 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
1572 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
1573 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
1574
1575 /* Local memory controller registers. */
1576 iter_reg = fw->lmc_reg;
1577 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
1578 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
1579 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
1580 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
1581 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
1582 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
1583 iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
1584 qla24xx_read_window(reg, 0x3070, 16, iter_reg);
1585
1586 /* Fibre Protocol Module registers. */
1587 iter_reg = fw->fpm_hdw_reg;
1588 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
1589 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
1590 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
1591 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
1592 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
1593 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
1594 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
1595 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
1596 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
1597 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
1598 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
1599 iter_reg = qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
1600 iter_reg = qla24xx_read_window(reg, 0x40C0, 16, iter_reg);
1601 qla24xx_read_window(reg, 0x40D0, 16, iter_reg);
1602
1603 /* Frame Buffer registers. */
1604 iter_reg = fw->fb_hdw_reg;
1605 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
1606 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
1607 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
1608 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
1609 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
1610 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
1611 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
1612 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1613 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1614 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1615 iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
1616 iter_reg = qla24xx_read_window(reg, 0x61C0, 16, iter_reg);
1617 qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
1618
1619 /* Multi queue registers */
1620 nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset,
1621 &last_chain);
1622
1623 rval = qla24xx_soft_reset(ha);
1624 if (rval != QLA_SUCCESS)
1625 goto qla81xx_fw_dump_failed_0;
1626
1627 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
1628 &nxt);
1629 if (rval != QLA_SUCCESS)
1630 goto qla81xx_fw_dump_failed_0;
1631
1632 nxt = qla2xxx_copy_queues(ha, nxt);
1633
1634 nxt = qla24xx_copy_eft(ha, nxt);
1635
1636 /* Chain entries -- started with MQ. */
1637 qla25xx_copy_fce(ha, nxt_chain, &last_chain);
1638 if (last_chain) {
1639 ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
1640 *last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
1641 }
1642
1643qla81xx_fw_dump_failed_0:
Andrew Vasquez3420d362009-10-13 15:16:45 -07001644 qla2xxx_dump_post_process(base_vha, rval);
Andrew Vasquez3a03eb72009-01-05 11:18:11 -08001645
1646qla81xx_fw_dump_failed:
1647 if (!hardware_locked)
1648 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1649}
1650
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651/****************************************************************************/
1652/* Driver Debug Functions. */
1653/****************************************************************************/
Chad Dupuiscfb09192011-11-18 09:03:07 -08001654
1655static inline int
1656ql_mask_match(uint32_t level)
1657{
1658 if (ql2xextended_error_logging == 1)
1659 ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
1660 return (level & ql2xextended_error_logging) == level;
1661}
1662
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001663/*
1664 * This function is for formatting and logging debug information.
1665 * It is to be used when vha is available. It formats the message
1666 * and logs it to the messages file.
1667 * parameters:
1668 * level: The level of the debug messages to be printed.
1669 * If ql2xextended_error_logging value is correctly set,
1670 * this message will appear in the messages file.
1671 * vha: Pointer to the scsi_qla_host_t.
1672 * id: This is a unique identifier for the level. It identifies the
1673 * part of the code from where the message originated.
1674 * msg: The message to be displayed.
1675 */
1676void
Joe Perches086b3e82011-11-18 09:03:05 -08001677ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
1678{
1679 va_list va;
1680 struct va_format vaf;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001681
Chad Dupuiscfb09192011-11-18 09:03:07 -08001682 if (!ql_mask_match(level))
Joe Perches086b3e82011-11-18 09:03:05 -08001683 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001684
Joe Perches086b3e82011-11-18 09:03:05 -08001685 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001686
Joe Perches086b3e82011-11-18 09:03:05 -08001687 vaf.fmt = fmt;
1688 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001689
Joe Perches086b3e82011-11-18 09:03:05 -08001690 if (vha != NULL) {
1691 const struct pci_dev *pdev = vha->hw->pdev;
1692 /* <module-name> <pci-name> <msg-id>:<host> Message */
1693 pr_warn("%s [%s]-%04x:%ld: %pV",
1694 QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset,
1695 vha->host_no, &vaf);
1696 } else {
1697 pr_warn("%s [%s]-%04x: : %pV",
1698 QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001699 }
1700
Joe Perches086b3e82011-11-18 09:03:05 -08001701 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001702
1703}
1704
1705/*
1706 * This function is for formatting and logging debug information.
1707 * It is to be used when vha is not available and pci is availble,
1708 * i.e., before host allocation. It formats the message and logs it
1709 * to the messages file.
1710 * parameters:
1711 * level: The level of the debug messages to be printed.
1712 * If ql2xextended_error_logging value is correctly set,
1713 * this message will appear in the messages file.
1714 * pdev: Pointer to the struct pci_dev.
1715 * id: This is a unique id for the level. It identifies the part
1716 * of the code from where the message originated.
1717 * msg: The message to be displayed.
1718 */
1719void
Joe Perches086b3e82011-11-18 09:03:05 -08001720ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
1721 const char *fmt, ...)
1722{
1723 va_list va;
1724 struct va_format vaf;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001725
1726 if (pdev == NULL)
1727 return;
Chad Dupuiscfb09192011-11-18 09:03:07 -08001728 if (!ql_mask_match(level))
Joe Perches086b3e82011-11-18 09:03:05 -08001729 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001730
Joe Perches086b3e82011-11-18 09:03:05 -08001731 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001732
Joe Perches086b3e82011-11-18 09:03:05 -08001733 vaf.fmt = fmt;
1734 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001735
Joe Perches086b3e82011-11-18 09:03:05 -08001736 /* <module-name> <dev-name>:<msg-id> Message */
1737 pr_warn("%s [%s]-%04x: : %pV",
1738 QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, &vaf);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001739
Joe Perches086b3e82011-11-18 09:03:05 -08001740 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001741}
1742
1743/*
1744 * This function is for formatting and logging log messages.
1745 * It is to be used when vha is available. It formats the message
1746 * and logs it to the messages file. All the messages will be logged
1747 * irrespective of value of ql2xextended_error_logging.
1748 * parameters:
1749 * level: The level of the log messages to be printed in the
1750 * messages file.
1751 * vha: Pointer to the scsi_qla_host_t
1752 * id: This is a unique id for the level. It identifies the
1753 * part of the code from where the message originated.
1754 * msg: The message to be displayed.
1755 */
1756void
Joe Perches086b3e82011-11-18 09:03:05 -08001757ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
1758{
1759 va_list va;
1760 struct va_format vaf;
1761 char pbuf[128];
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001762
Joe Perches086b3e82011-11-18 09:03:05 -08001763 if (level > ql_errlev)
1764 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001765
Joe Perches086b3e82011-11-18 09:03:05 -08001766 if (vha != NULL) {
1767 const struct pci_dev *pdev = vha->hw->pdev;
1768 /* <module-name> <msg-id>:<host> Message */
1769 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ",
1770 QL_MSGHDR, dev_name(&(pdev->dev)), id, vha->host_no);
1771 } else {
1772 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
1773 QL_MSGHDR, "0000:00:00.0", id);
1774 }
1775 pbuf[sizeof(pbuf) - 1] = 0;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001776
Joe Perches086b3e82011-11-18 09:03:05 -08001777 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001778
Joe Perches086b3e82011-11-18 09:03:05 -08001779 vaf.fmt = fmt;
1780 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001781
Joe Perches086b3e82011-11-18 09:03:05 -08001782 switch (level) {
1783 case 0: /* FATAL LOG */
1784 pr_crit("%s%pV", pbuf, &vaf);
1785 break;
1786 case 1:
1787 pr_err("%s%pV", pbuf, &vaf);
1788 break;
1789 case 2:
1790 pr_warn("%s%pV", pbuf, &vaf);
1791 break;
1792 default:
1793 pr_info("%s%pV", pbuf, &vaf);
1794 break;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001795 }
1796
Joe Perches086b3e82011-11-18 09:03:05 -08001797 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001798}
1799
1800/*
1801 * This function is for formatting and logging log messages.
1802 * It is to be used when vha is not available and pci is availble,
1803 * i.e., before host allocation. It formats the message and logs
1804 * it to the messages file. All the messages are logged irrespective
1805 * of the value of ql2xextended_error_logging.
1806 * parameters:
1807 * level: The level of the log messages to be printed in the
1808 * messages file.
1809 * pdev: Pointer to the struct pci_dev.
1810 * id: This is a unique id for the level. It identifies the
1811 * part of the code from where the message originated.
1812 * msg: The message to be displayed.
1813 */
1814void
Joe Perches086b3e82011-11-18 09:03:05 -08001815ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
1816 const char *fmt, ...)
1817{
1818 va_list va;
1819 struct va_format vaf;
1820 char pbuf[128];
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001821
1822 if (pdev == NULL)
1823 return;
Joe Perches086b3e82011-11-18 09:03:05 -08001824 if (level > ql_errlev)
1825 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001826
Joe Perches086b3e82011-11-18 09:03:05 -08001827 /* <module-name> <dev-name>:<msg-id> Message */
1828 snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
1829 QL_MSGHDR, dev_name(&(pdev->dev)), id);
1830 pbuf[sizeof(pbuf) - 1] = 0;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001831
Joe Perches086b3e82011-11-18 09:03:05 -08001832 va_start(va, fmt);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001833
Joe Perches086b3e82011-11-18 09:03:05 -08001834 vaf.fmt = fmt;
1835 vaf.va = &va;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001836
Joe Perches086b3e82011-11-18 09:03:05 -08001837 switch (level) {
1838 case 0: /* FATAL LOG */
1839 pr_crit("%s%pV", pbuf, &vaf);
1840 break;
1841 case 1:
1842 pr_err("%s%pV", pbuf, &vaf);
1843 break;
1844 case 2:
1845 pr_warn("%s%pV", pbuf, &vaf);
1846 break;
1847 default:
1848 pr_info("%s%pV", pbuf, &vaf);
1849 break;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001850 }
1851
Joe Perches086b3e82011-11-18 09:03:05 -08001852 va_end(va);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001853}
1854
1855void
1856ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id)
1857{
1858 int i;
1859 struct qla_hw_data *ha = vha->hw;
1860 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
1861 struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
1862 struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
1863 uint16_t __iomem *mbx_reg;
1864
Chad Dupuiscfb09192011-11-18 09:03:07 -08001865 if (!ql_mask_match(level))
1866 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001867
Chad Dupuiscfb09192011-11-18 09:03:07 -08001868 if (IS_QLA82XX(ha))
1869 mbx_reg = &reg82->mailbox_in[0];
1870 else if (IS_FWI2_CAPABLE(ha))
1871 mbx_reg = &reg24->mailbox0;
1872 else
1873 mbx_reg = MAILBOX_REG(ha, reg, 0);
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001874
Chad Dupuiscfb09192011-11-18 09:03:07 -08001875 ql_dbg(level, vha, id, "Mailbox registers:\n");
1876 for (i = 0; i < 6; i++)
1877 ql_dbg(level, vha, id,
1878 "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++));
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001879}
1880
1881
1882void
1883ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
1884 uint8_t *b, uint32_t size)
1885{
1886 uint32_t cnt;
1887 uint8_t c;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001888
Chad Dupuiscfb09192011-11-18 09:03:07 -08001889 if (!ql_mask_match(level))
1890 return;
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001891
Chad Dupuiscfb09192011-11-18 09:03:07 -08001892 ql_dbg(level, vha, id, " 0 1 2 3 4 5 6 7 8 "
1893 "9 Ah Bh Ch Dh Eh Fh\n");
1894 ql_dbg(level, vha, id, "----------------------------------"
1895 "----------------------------\n");
1896
1897 ql_dbg(level, vha, id, " ");
1898 for (cnt = 0; cnt < size;) {
1899 c = *b++;
1900 printk("%02x", (uint32_t) c);
1901 cnt++;
1902 if (!(cnt % 16))
1903 printk("\n");
1904 else
1905 printk(" ");
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001906 }
Chad Dupuiscfb09192011-11-18 09:03:07 -08001907 if (cnt % 16)
1908 ql_dbg(level, vha, id, "\n");
Saurav Kashyap3ce88662011-07-14 12:00:12 -07001909}