aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRon Mercer <ron.mercer@qlogic.com>2010-01-15 08:31:28 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-16 04:01:52 -0500
commit8aae2600030f54494f9061d2cde141802d774be9 (patch)
tree543f1b31264ee96703bb45ed454d293796f45948
parentb87babeb40aaf879d20268792390ce831805a557 (diff)
qlge: Add basic firmware dump.
Adding the infrstructure and basic data for the firmware core dump. The firmware coredump is turned OFF by default. There will be no memory allocations for data dumps to the log. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/qlge/qlge.h6
-rw-r--r--drivers/net/qlge/qlge_dbg.c523
-rw-r--r--drivers/net/qlge/qlge_main.c20
-rw-r--r--drivers/net/qlge/qlge_mpi.c73
4 files changed, 622 insertions, 0 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index a265325abb15..bbdd388aa9b7 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -2211,6 +2211,7 @@ extern int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
2211void ql_queue_fw_error(struct ql_adapter *qdev); 2211void ql_queue_fw_error(struct ql_adapter *qdev);
2212void ql_mpi_work(struct work_struct *work); 2212void ql_mpi_work(struct work_struct *work);
2213void ql_mpi_reset_work(struct work_struct *work); 2213void ql_mpi_reset_work(struct work_struct *work);
2214void ql_mpi_core_to_log(struct work_struct *work);
2214int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit); 2215int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit);
2215void ql_queue_asic_error(struct ql_adapter *qdev); 2216void ql_queue_asic_error(struct ql_adapter *qdev);
2216u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr); 2217u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr);
@@ -2221,6 +2222,11 @@ void ql_mpi_port_cfg_work(struct work_struct *work);
2221int ql_mb_get_fw_state(struct ql_adapter *qdev); 2222int ql_mb_get_fw_state(struct ql_adapter *qdev);
2222int ql_cam_route_initialize(struct ql_adapter *qdev); 2223int ql_cam_route_initialize(struct ql_adapter *qdev);
2223int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); 2224int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
2225int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data);
2226int ql_unpause_mpi_risc(struct ql_adapter *qdev);
2227int ql_pause_mpi_risc(struct ql_adapter *qdev);
2228int ql_core_dump(struct ql_adapter *qdev,
2229 struct ql_mpi_coredump *mpi_coredump);
2224int ql_mb_about_fw(struct ql_adapter *qdev); 2230int ql_mb_about_fw(struct ql_adapter *qdev);
2225int ql_wol(struct ql_adapter *qdev); 2231int ql_wol(struct ql_adapter *qdev);
2226int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol); 2232int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol);
diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c
index 9f58c4710761..1d026141b78d 100644
--- a/drivers/net/qlge/qlge_dbg.c
+++ b/drivers/net/qlge/qlge_dbg.c
@@ -91,6 +91,179 @@ err:
91 return status; 91 return status;
92} 92}
93 93
94/* Read the MPI Processor shadow registers */
95static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 * buf)
96{
97 u32 i;
98 int status;
99
100 for (i = 0; i < MPI_CORE_SH_REGS_CNT; i++, buf++) {
101 status = ql_write_mpi_reg(qdev, RISC_124,
102 (SHADOW_OFFSET | i << SHADOW_REG_SHIFT));
103 if (status)
104 goto end;
105 status = ql_read_mpi_reg(qdev, RISC_127, buf);
106 if (status)
107 goto end;
108 }
109end:
110 return status;
111}
112
113/* Read the MPI Processor core registers */
114static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 * buf,
115 u32 offset, u32 count)
116{
117 int i, status = 0;
118 for (i = 0; i < count; i++, buf++) {
119 status = ql_read_mpi_reg(qdev, offset + i, buf);
120 if (status)
121 return status;
122 }
123 return status;
124}
125
126
127/* Read out the routing index registers */
128static int ql_get_routing_index_registers(struct ql_adapter *qdev, u32 *buf)
129{
130 int status;
131 u32 type, index, index_max;
132 u32 result_index;
133 u32 result_data;
134 u32 val;
135
136 status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
137 if (status)
138 return status;
139
140 for (type = 0; type < 4; type++) {
141 if (type < 2)
142 index_max = 8;
143 else
144 index_max = 16;
145 for (index = 0; index < index_max; index++) {
146 val = RT_IDX_RS
147 | (type << RT_IDX_TYPE_SHIFT)
148 | (index << RT_IDX_IDX_SHIFT);
149 ql_write32(qdev, RT_IDX, val);
150 result_index = 0;
151 while ((result_index & RT_IDX_MR) == 0)
152 result_index = ql_read32(qdev, RT_IDX);
153 result_data = ql_read32(qdev, RT_DATA);
154 *buf = type;
155 buf++;
156 *buf = index;
157 buf++;
158 *buf = result_index;
159 buf++;
160 *buf = result_data;
161 buf++;
162 }
163 }
164 ql_sem_unlock(qdev, SEM_RT_IDX_MASK);
165 return status;
166}
167
168/* Read out the MAC protocol registers */
169static void ql_get_mac_protocol_registers(struct ql_adapter *qdev, u32 *buf)
170{
171 u32 result_index, result_data;
172 u32 type;
173 u32 index;
174 u32 offset;
175 u32 val;
176 u32 initial_val = MAC_ADDR_RS;
177 u32 max_index;
178 u32 max_offset;
179
180 for (type = 0; type < MAC_ADDR_TYPE_COUNT; type++) {
181 switch (type) {
182
183 case 0: /* CAM */
184 initial_val |= MAC_ADDR_ADR;
185 max_index = MAC_ADDR_MAX_CAM_ENTRIES;
186 max_offset = MAC_ADDR_MAX_CAM_WCOUNT;
187 break;
188 case 1: /* Multicast MAC Address */
189 max_index = MAC_ADDR_MAX_CAM_WCOUNT;
190 max_offset = MAC_ADDR_MAX_CAM_WCOUNT;
191 break;
192 case 2: /* VLAN filter mask */
193 case 3: /* MC filter mask */
194 max_index = MAC_ADDR_MAX_CAM_WCOUNT;
195 max_offset = MAC_ADDR_MAX_CAM_WCOUNT;
196 break;
197 case 4: /* FC MAC addresses */
198 max_index = MAC_ADDR_MAX_FC_MAC_ENTRIES;
199 max_offset = MAC_ADDR_MAX_FC_MAC_WCOUNT;
200 break;
201 case 5: /* Mgmt MAC addresses */
202 max_index = MAC_ADDR_MAX_MGMT_MAC_ENTRIES;
203 max_offset = MAC_ADDR_MAX_MGMT_MAC_WCOUNT;
204 break;
205 case 6: /* Mgmt VLAN addresses */
206 max_index = MAC_ADDR_MAX_MGMT_VLAN_ENTRIES;
207 max_offset = MAC_ADDR_MAX_MGMT_VLAN_WCOUNT;
208 break;
209 case 7: /* Mgmt IPv4 address */
210 max_index = MAC_ADDR_MAX_MGMT_V4_ENTRIES;
211 max_offset = MAC_ADDR_MAX_MGMT_V4_WCOUNT;
212 break;
213 case 8: /* Mgmt IPv6 address */
214 max_index = MAC_ADDR_MAX_MGMT_V6_ENTRIES;
215 max_offset = MAC_ADDR_MAX_MGMT_V6_WCOUNT;
216 break;
217 case 9: /* Mgmt TCP/UDP Dest port */
218 max_index = MAC_ADDR_MAX_MGMT_TU_DP_ENTRIES;
219 max_offset = MAC_ADDR_MAX_MGMT_TU_DP_WCOUNT;
220 break;
221 default:
222 printk(KERN_ERR"Bad type!!! 0x%08x\n", type);
223 max_index = 0;
224 max_offset = 0;
225 break;
226 }
227 for (index = 0; index < max_index; index++) {
228 for (offset = 0; offset < max_offset; offset++) {
229 val = initial_val
230 | (type << MAC_ADDR_TYPE_SHIFT)
231 | (index << MAC_ADDR_IDX_SHIFT)
232 | (offset);
233 ql_write32(qdev, MAC_ADDR_IDX, val);
234 result_index = 0;
235 while ((result_index & MAC_ADDR_MR) == 0) {
236 result_index = ql_read32(qdev,
237 MAC_ADDR_IDX);
238 }
239 result_data = ql_read32(qdev, MAC_ADDR_DATA);
240 *buf = result_index;
241 buf++;
242 *buf = result_data;
243 buf++;
244 }
245 }
246 }
247}
248
249static void ql_get_sem_registers(struct ql_adapter *qdev, u32 *buf)
250{
251 u32 func_num, reg, reg_val;
252 int status;
253
254 for (func_num = 0; func_num < MAX_SEMAPHORE_FUNCTIONS ; func_num++) {
255 reg = MPI_NIC_REG_BLOCK
256 | (func_num << MPI_NIC_FUNCTION_SHIFT)
257 | (SEM / 4);
258 status = ql_read_mpi_reg(qdev, reg, &reg_val);
259 *buf = reg_val;
260 /* if the read failed then dead fill the element. */
261 if (!status)
262 *buf = 0xdeadbeef;
263 buf++;
264 }
265}
266
94/* Create a coredump segment header */ 267/* Create a coredump segment header */
95static void ql_build_coredump_seg_header( 268static void ql_build_coredump_seg_header(
96 struct mpi_coredump_segment_header *seg_hdr, 269 struct mpi_coredump_segment_header *seg_hdr,
@@ -103,6 +276,329 @@ static void ql_build_coredump_seg_header(
103 memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); 276 memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1);
104} 277}
105 278
279/*
280 * This function should be called when a coredump / probedump
281 * is to be extracted from the HBA. It is assumed there is a
282 * qdev structure that contains the base address of the register
283 * space for this function as well as a coredump structure that
284 * will contain the dump.
285 */
286int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
287{
288 int status;
289 int i;
290
291 if (!mpi_coredump) {
292 QPRINTK(qdev, DRV, ERR,
293 "No memory available.\n");
294 return -ENOMEM;
295 }
296
297 /* Try to get the spinlock, but dont worry if
298 * it isn't available. If the firmware died it
299 * might be holding the sem.
300 */
301 ql_sem_spinlock(qdev, SEM_PROC_REG_MASK);
302
303 status = ql_pause_mpi_risc(qdev);
304 if (status) {
305 QPRINTK(qdev, DRV, ERR,
306 "Failed RISC pause. Status = 0x%.08x\n", status);
307 goto err;
308 }
309
310 /* Insert the global header */
311 memset(&(mpi_coredump->mpi_global_header), 0,
312 sizeof(struct mpi_coredump_global_header));
313 mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE;
314 mpi_coredump->mpi_global_header.headerSize =
315 sizeof(struct mpi_coredump_global_header);
316 mpi_coredump->mpi_global_header.imageSize =
317 sizeof(struct ql_mpi_coredump);
318 memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
319 sizeof(mpi_coredump->mpi_global_header.idString));
320
321 /* Get generic NIC reg dump */
322 ql_build_coredump_seg_header(&mpi_coredump->nic_regs_seg_hdr,
323 NIC1_CONTROL_SEG_NUM,
324 sizeof(struct mpi_coredump_segment_header) +
325 sizeof(mpi_coredump->nic_regs), "NIC1 Registers");
326
327 if (qdev->func & 1) {
328 /* Odd means our function is NIC 2 */
329 for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++)
330 mpi_coredump->nic2_regs[i] =
331 ql_read32(qdev, i * sizeof(u32));
332 } else {
333 /* Even means our function is NIC 1 */
334 for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++)
335 mpi_coredump->nic_regs[i] =
336 ql_read32(qdev, i * sizeof(u32));
337 }
338
339 ql_build_coredump_seg_header(&mpi_coredump->core_regs_seg_hdr,
340 CORE_SEG_NUM,
341 sizeof(mpi_coredump->core_regs_seg_hdr) +
342 sizeof(mpi_coredump->mpi_core_regs) +
343 sizeof(mpi_coredump->mpi_core_sh_regs),
344 "Core Registers");
345
346 /* Get the MPI Core Registers */
347 status = ql_get_mpi_regs(qdev, &mpi_coredump->mpi_core_regs[0],
348 MPI_CORE_REGS_ADDR, MPI_CORE_REGS_CNT);
349 if (status)
350 goto err;
351 /* Get the 16 MPI shadow registers */
352 status = ql_get_mpi_shadow_regs(qdev,
353 &mpi_coredump->mpi_core_sh_regs[0]);
354 if (status)
355 goto err;
356
357 /* Get the Test Logic Registers */
358 ql_build_coredump_seg_header(&mpi_coredump->test_logic_regs_seg_hdr,
359 TEST_LOGIC_SEG_NUM,
360 sizeof(struct mpi_coredump_segment_header)
361 + sizeof(mpi_coredump->test_logic_regs),
362 "Test Logic Regs");
363 status = ql_get_mpi_regs(qdev, &mpi_coredump->test_logic_regs[0],
364 TEST_REGS_ADDR, TEST_REGS_CNT);
365 if (status)
366 goto err;
367
368 /* Get the RMII Registers */
369 ql_build_coredump_seg_header(&mpi_coredump->rmii_regs_seg_hdr,
370 RMII_SEG_NUM,
371 sizeof(struct mpi_coredump_segment_header)
372 + sizeof(mpi_coredump->rmii_regs),
373 "RMII Registers");
374 status = ql_get_mpi_regs(qdev, &mpi_coredump->rmii_regs[0],
375 RMII_REGS_ADDR, RMII_REGS_CNT);
376 if (status)
377 goto err;
378
379 /* Get the FCMAC1 Registers */
380 ql_build_coredump_seg_header(&mpi_coredump->fcmac1_regs_seg_hdr,
381 FCMAC1_SEG_NUM,
382 sizeof(struct mpi_coredump_segment_header)
383 + sizeof(mpi_coredump->fcmac1_regs),
384 "FCMAC1 Registers");
385 status = ql_get_mpi_regs(qdev, &mpi_coredump->fcmac1_regs[0],
386 FCMAC1_REGS_ADDR, FCMAC_REGS_CNT);
387 if (status)
388 goto err;
389
390 /* Get the FCMAC2 Registers */
391
392 ql_build_coredump_seg_header(&mpi_coredump->fcmac2_regs_seg_hdr,
393 FCMAC2_SEG_NUM,
394 sizeof(struct mpi_coredump_segment_header)
395 + sizeof(mpi_coredump->fcmac2_regs),
396 "FCMAC2 Registers");
397
398 status = ql_get_mpi_regs(qdev, &mpi_coredump->fcmac2_regs[0],
399 FCMAC2_REGS_ADDR, FCMAC_REGS_CNT);
400 if (status)
401 goto err;
402
403 /* Get the FC1 MBX Registers */
404 ql_build_coredump_seg_header(&mpi_coredump->fc1_mbx_regs_seg_hdr,
405 FC1_MBOX_SEG_NUM,
406 sizeof(struct mpi_coredump_segment_header)
407 + sizeof(mpi_coredump->fc1_mbx_regs),
408 "FC1 MBox Regs");
409 status = ql_get_mpi_regs(qdev, &mpi_coredump->fc1_mbx_regs[0],
410 FC1_MBX_REGS_ADDR, FC_MBX_REGS_CNT);
411 if (status)
412 goto err;
413
414 /* Get the IDE Registers */
415 ql_build_coredump_seg_header(&mpi_coredump->ide_regs_seg_hdr,
416 IDE_SEG_NUM,
417 sizeof(struct mpi_coredump_segment_header)
418 + sizeof(mpi_coredump->ide_regs),
419 "IDE Registers");
420 status = ql_get_mpi_regs(qdev, &mpi_coredump->ide_regs[0],
421 IDE_REGS_ADDR, IDE_REGS_CNT);
422 if (status)
423 goto err;
424
425 /* Get the NIC1 MBX Registers */
426 ql_build_coredump_seg_header(&mpi_coredump->nic1_mbx_regs_seg_hdr,
427 NIC1_MBOX_SEG_NUM,
428 sizeof(struct mpi_coredump_segment_header)
429 + sizeof(mpi_coredump->nic1_mbx_regs),
430 "NIC1 MBox Regs");
431 status = ql_get_mpi_regs(qdev, &mpi_coredump->nic1_mbx_regs[0],
432 NIC1_MBX_REGS_ADDR, NIC_MBX_REGS_CNT);
433 if (status)
434 goto err;
435
436 /* Get the SMBus Registers */
437 ql_build_coredump_seg_header(&mpi_coredump->smbus_regs_seg_hdr,
438 SMBUS_SEG_NUM,
439 sizeof(struct mpi_coredump_segment_header)
440 + sizeof(mpi_coredump->smbus_regs),
441 "SMBus Registers");
442 status = ql_get_mpi_regs(qdev, &mpi_coredump->smbus_regs[0],
443 SMBUS_REGS_ADDR, SMBUS_REGS_CNT);
444 if (status)
445 goto err;
446
447 /* Get the FC2 MBX Registers */
448 ql_build_coredump_seg_header(&mpi_coredump->fc2_mbx_regs_seg_hdr,
449 FC2_MBOX_SEG_NUM,
450 sizeof(struct mpi_coredump_segment_header)
451 + sizeof(mpi_coredump->fc2_mbx_regs),
452 "FC2 MBox Regs");
453 status = ql_get_mpi_regs(qdev, &mpi_coredump->fc2_mbx_regs[0],
454 FC2_MBX_REGS_ADDR, FC_MBX_REGS_CNT);
455 if (status)
456 goto err;
457
458 /* Get the NIC2 MBX Registers */
459 ql_build_coredump_seg_header(&mpi_coredump->nic2_mbx_regs_seg_hdr,
460 NIC2_MBOX_SEG_NUM,
461 sizeof(struct mpi_coredump_segment_header)
462 + sizeof(mpi_coredump->nic2_mbx_regs),
463 "NIC2 MBox Regs");
464 status = ql_get_mpi_regs(qdev, &mpi_coredump->nic2_mbx_regs[0],
465 NIC2_MBX_REGS_ADDR, NIC_MBX_REGS_CNT);
466 if (status)
467 goto err;
468
469 /* Get the I2C Registers */
470 ql_build_coredump_seg_header(&mpi_coredump->i2c_regs_seg_hdr,
471 I2C_SEG_NUM,
472 sizeof(struct mpi_coredump_segment_header)
473 + sizeof(mpi_coredump->i2c_regs),
474 "I2C Registers");
475 status = ql_get_mpi_regs(qdev, &mpi_coredump->i2c_regs[0],
476 I2C_REGS_ADDR, I2C_REGS_CNT);
477 if (status)
478 goto err;
479
480 /* Get the MEMC Registers */
481 ql_build_coredump_seg_header(&mpi_coredump->memc_regs_seg_hdr,
482 MEMC_SEG_NUM,
483 sizeof(struct mpi_coredump_segment_header)
484 + sizeof(mpi_coredump->memc_regs),
485 "MEMC Registers");
486 status = ql_get_mpi_regs(qdev, &mpi_coredump->memc_regs[0],
487 MEMC_REGS_ADDR, MEMC_REGS_CNT);
488 if (status)
489 goto err;
490
491 /* Get the PBus Registers */
492 ql_build_coredump_seg_header(&mpi_coredump->pbus_regs_seg_hdr,
493 PBUS_SEG_NUM,
494 sizeof(struct mpi_coredump_segment_header)
495 + sizeof(mpi_coredump->pbus_regs),
496 "PBUS Registers");
497 status = ql_get_mpi_regs(qdev, &mpi_coredump->pbus_regs[0],
498 PBUS_REGS_ADDR, PBUS_REGS_CNT);
499 if (status)
500 goto err;
501
502 /* Get the MDE Registers */
503 ql_build_coredump_seg_header(&mpi_coredump->mde_regs_seg_hdr,
504 MDE_SEG_NUM,
505 sizeof(struct mpi_coredump_segment_header)
506 + sizeof(mpi_coredump->mde_regs),
507 "MDE Registers");
508 status = ql_get_mpi_regs(qdev, &mpi_coredump->mde_regs[0],
509 MDE_REGS_ADDR, MDE_REGS_CNT);
510 if (status)
511 goto err;
512
513 ql_build_coredump_seg_header(&mpi_coredump->misc_nic_seg_hdr,
514 MISC_NIC_INFO_SEG_NUM,
515 sizeof(struct mpi_coredump_segment_header)
516 + sizeof(mpi_coredump->misc_nic_info),
517 "MISC NIC INFO");
518 mpi_coredump->misc_nic_info.rx_ring_count = qdev->rx_ring_count;
519 mpi_coredump->misc_nic_info.tx_ring_count = qdev->tx_ring_count;
520 mpi_coredump->misc_nic_info.intr_count = qdev->intr_count;
521 mpi_coredump->misc_nic_info.function = qdev->func;
522
523 /* Segment 31 */
524 /* Get indexed register values. */
525 ql_build_coredump_seg_header(&mpi_coredump->intr_states_seg_hdr,
526 INTR_STATES_SEG_NUM,
527 sizeof(struct mpi_coredump_segment_header)
528 + sizeof(mpi_coredump->intr_states),
529 "INTR States");
530 ql_get_intr_states(qdev, &mpi_coredump->intr_states[0]);
531
532 ql_build_coredump_seg_header(&mpi_coredump->cam_entries_seg_hdr,
533 CAM_ENTRIES_SEG_NUM,
534 sizeof(struct mpi_coredump_segment_header)
535 + sizeof(mpi_coredump->cam_entries),
536 "CAM Entries");
537 status = ql_get_cam_entries(qdev, &mpi_coredump->cam_entries[0]);
538 if (status)
539 goto err;
540
541 ql_build_coredump_seg_header(&mpi_coredump->nic_routing_words_seg_hdr,
542 ROUTING_WORDS_SEG_NUM,
543 sizeof(struct mpi_coredump_segment_header)
544 + sizeof(mpi_coredump->nic_routing_words),
545 "Routing Words");
546 status = ql_get_routing_entries(qdev,
547 &mpi_coredump->nic_routing_words[0]);
548 if (status)
549 goto err;
550
551 /* Segment 34 (Rev C. step 23) */
552 ql_build_coredump_seg_header(&mpi_coredump->ets_seg_hdr,
553 ETS_SEG_NUM,
554 sizeof(struct mpi_coredump_segment_header)
555 + sizeof(mpi_coredump->ets),
556 "ETS Registers");
557 status = ql_get_ets_regs(qdev, &mpi_coredump->ets[0]);
558 if (status)
559 goto err;
560
561 ql_build_coredump_seg_header(&mpi_coredump->routing_reg_seg_hdr,
562 ROUTING_INDEX_SEG_NUM,
563 sizeof(struct mpi_coredump_segment_header)
564 + sizeof(mpi_coredump->routing_regs),
565 "Routing Regs");
566 status = ql_get_routing_index_registers(qdev,
567 &mpi_coredump->routing_regs[0]);
568 if (status)
569 goto err;
570
571 ql_build_coredump_seg_header(&mpi_coredump->mac_prot_reg_seg_hdr,
572 MAC_PROTOCOL_SEG_NUM,
573 sizeof(struct mpi_coredump_segment_header)
574 + sizeof(mpi_coredump->mac_prot_regs),
575 "MAC Prot Regs");
576 ql_get_mac_protocol_registers(qdev, &mpi_coredump->mac_prot_regs[0]);
577
578 /* Get the semaphore registers for all 5 functions */
579 ql_build_coredump_seg_header(&mpi_coredump->sem_regs_seg_hdr,
580 SEM_REGS_SEG_NUM,
581 sizeof(struct mpi_coredump_segment_header) +
582 sizeof(mpi_coredump->sem_regs), "Sem Registers");
583
584 ql_get_sem_registers(qdev, &mpi_coredump->sem_regs[0]);
585
586 /* Prevent the mpi restarting while we dump the memory.*/
587 ql_write_mpi_reg(qdev, MPI_TEST_FUNC_RST_STS, MPI_TEST_FUNC_RST_FRC);
588
589 /* clear the pause */
590 status = ql_unpause_mpi_risc(qdev);
591 if (status) {
592 QPRINTK(qdev, DRV, ERR,
593 "Failed RISC unpause. Status = 0x%.08x\n", status);
594 goto err;
595 }
596err:
597 ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */
598 return status;
599
600}
601
106void ql_gen_reg_dump(struct ql_adapter *qdev, 602void ql_gen_reg_dump(struct ql_adapter *qdev,
107 struct ql_reg_dump *mpi_coredump) 603 struct ql_reg_dump *mpi_coredump)
108{ 604{
@@ -180,6 +676,33 @@ void ql_gen_reg_dump(struct ql_adapter *qdev,
180 return; 676 return;
181} 677}
182 678
679/* Coredump to messages log file using separate worker thread */
680void ql_mpi_core_to_log(struct work_struct *work)
681{
682 struct ql_adapter *qdev =
683 container_of(work, struct ql_adapter, mpi_core_to_log.work);
684 u32 *tmp, count;
685 int i;
686
687 count = sizeof(struct ql_mpi_coredump) / sizeof(u32);
688 tmp = (u32 *)qdev->mpi_coredump;
689 QPRINTK(qdev, DRV, DEBUG, "Core is dumping to log file!\n");
690
691 for (i = 0; i < count; i += 8) {
692 printk(KERN_ERR "%.08x: %.08x %.08x %.08x %.08x %.08x "
693 "%.08x %.08x %.08x \n", i,
694 tmp[i + 0],
695 tmp[i + 1],
696 tmp[i + 2],
697 tmp[i + 3],
698 tmp[i + 4],
699 tmp[i + 5],
700 tmp[i + 6],
701 tmp[i + 7]);
702 msleep(5);
703 }
704}
705
183#ifdef QL_REG_DUMP 706#ifdef QL_REG_DUMP
184static void ql_dump_intr_states(struct ql_adapter *qdev) 707static void ql_dump_intr_states(struct ql_adapter *qdev)
185{ 708{
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 167a3dab2f18..e58892304e19 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -73,6 +73,13 @@ static int qlge_irq_type = MSIX_IRQ;
73module_param(qlge_irq_type, int, MSIX_IRQ); 73module_param(qlge_irq_type, int, MSIX_IRQ);
74MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); 74MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy.");
75 75
76static int qlge_mpi_coredump;
77module_param(qlge_mpi_coredump, int, 0);
78MODULE_PARM_DESC(qlge_mpi_coredump,
79 "Option to enable MPI firmware dump. "
80 "Default is OFF - Do Not allocate memory. "
81 "Do not perform firmware coredump.");
82
76static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = { 83static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = {
77 {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, 84 {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)},
78 {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)}, 85 {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)},
@@ -3842,6 +3849,7 @@ static int ql_adapter_down(struct ql_adapter *qdev)
3842 cancel_delayed_work_sync(&qdev->mpi_reset_work); 3849 cancel_delayed_work_sync(&qdev->mpi_reset_work);
3843 cancel_delayed_work_sync(&qdev->mpi_work); 3850 cancel_delayed_work_sync(&qdev->mpi_work);
3844 cancel_delayed_work_sync(&qdev->mpi_idc_work); 3851 cancel_delayed_work_sync(&qdev->mpi_idc_work);
3852 cancel_delayed_work_sync(&qdev->mpi_core_to_log);
3845 cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); 3853 cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
3846 3854
3847 for (i = 0; i < qdev->rss_ring_count; i++) 3855 for (i = 0; i < qdev->rss_ring_count; i++)
@@ -4398,6 +4406,7 @@ static void ql_release_all(struct pci_dev *pdev)
4398 iounmap(qdev->reg_base); 4406 iounmap(qdev->reg_base);
4399 if (qdev->doorbell_area) 4407 if (qdev->doorbell_area)
4400 iounmap(qdev->doorbell_area); 4408 iounmap(qdev->doorbell_area);
4409 vfree(qdev->mpi_coredump);
4401 pci_release_regions(pdev); 4410 pci_release_regions(pdev);
4402 pci_set_drvdata(pdev, NULL); 4411 pci_set_drvdata(pdev, NULL);
4403} 4412}
@@ -4479,6 +4488,15 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
4479 spin_lock_init(&qdev->hw_lock); 4488 spin_lock_init(&qdev->hw_lock);
4480 spin_lock_init(&qdev->stats_lock); 4489 spin_lock_init(&qdev->stats_lock);
4481 4490
4491 if (qlge_mpi_coredump) {
4492 qdev->mpi_coredump =
4493 vmalloc(sizeof(struct ql_mpi_coredump));
4494 if (qdev->mpi_coredump == NULL) {
4495 dev_err(&pdev->dev, "Coredump alloc failed.\n");
4496 err = -ENOMEM;
4497 goto err_out;
4498 }
4499 }
4482 /* make sure the EEPROM is good */ 4500 /* make sure the EEPROM is good */
4483 err = qdev->nic_ops->get_flash(qdev); 4501 err = qdev->nic_ops->get_flash(qdev);
4484 if (err) { 4502 if (err) {
@@ -4508,6 +4526,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
4508 INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); 4526 INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work);
4509 INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work); 4527 INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work);
4510 INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); 4528 INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work);
4529 INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log);
4511 init_completion(&qdev->ide_completion); 4530 init_completion(&qdev->ide_completion);
4512 4531
4513 if (!cards_found) { 4532 if (!cards_found) {
@@ -4630,6 +4649,7 @@ static void ql_eeh_close(struct net_device *ndev)
4630 cancel_delayed_work_sync(&qdev->mpi_reset_work); 4649 cancel_delayed_work_sync(&qdev->mpi_reset_work);
4631 cancel_delayed_work_sync(&qdev->mpi_work); 4650 cancel_delayed_work_sync(&qdev->mpi_work);
4632 cancel_delayed_work_sync(&qdev->mpi_idc_work); 4651 cancel_delayed_work_sync(&qdev->mpi_idc_work);
4652 cancel_delayed_work_sync(&qdev->mpi_core_to_log);
4633 cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); 4653 cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
4634 4654
4635 for (i = 0; i < qdev->rss_ring_count; i++) 4655 for (i = 0; i < qdev->rss_ring_count; i++)
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c
index e2b2286102d4..242b1ea955e4 100644
--- a/drivers/net/qlge/qlge_mpi.c
+++ b/drivers/net/qlge/qlge_mpi.c
@@ -1,5 +1,35 @@
1#include "qlge.h" 1#include "qlge.h"
2 2
3int ql_unpause_mpi_risc(struct ql_adapter *qdev)
4{
5 u32 tmp;
6
7 /* Un-pause the RISC */
8 tmp = ql_read32(qdev, CSR);
9 if (!(tmp & CSR_RP))
10 return -EIO;
11
12 ql_write32(qdev, CSR, CSR_CMD_CLR_PAUSE);
13 return 0;
14}
15
16int ql_pause_mpi_risc(struct ql_adapter *qdev)
17{
18 u32 tmp;
19 int count = UDELAY_COUNT;
20
21 /* Pause the RISC */
22 ql_write32(qdev, CSR, CSR_CMD_SET_PAUSE);
23 do {
24 tmp = ql_read32(qdev, CSR);
25 if (tmp & CSR_RP)
26 break;
27 mdelay(UDELAY_DELAY);
28 count--;
29 } while (count);
30 return (count == 0) ? -ETIMEDOUT : 0;
31}
32
3int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data) 33int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
4{ 34{
5 int status; 35 int status;
@@ -45,6 +75,35 @@ int ql_soft_reset_mpi_risc(struct ql_adapter *qdev)
45 return status; 75 return status;
46} 76}
47 77
78/* Determine if we are in charge of the firwmare. If
79 * we are the lower of the 2 NIC pcie functions, or if
80 * we are the higher function and the lower function
81 * is not enabled.
82 */
83int ql_own_firmware(struct ql_adapter *qdev)
84{
85 u32 temp;
86
87 /* If we are the lower of the 2 NIC functions
88 * on the chip the we are responsible for
89 * core dump and firmware reset after an error.
90 */
91 if (qdev->func < qdev->alt_func)
92 return 1;
93
94 /* If we are the higher of the 2 NIC functions
95 * on the chip and the lower function is not
96 * enabled, then we are responsible for
97 * core dump and firmware reset after an error.
98 */
99 temp = ql_read32(qdev, STS);
100 if (!(temp & (1 << (8 + qdev->alt_func))))
101 return 1;
102
103 return 0;
104
105}
106
48static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) 107static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp)
49{ 108{
50 int i, status; 109 int i, status;
@@ -1143,5 +1202,19 @@ void ql_mpi_reset_work(struct work_struct *work)
1143 cancel_delayed_work_sync(&qdev->mpi_work); 1202 cancel_delayed_work_sync(&qdev->mpi_work);
1144 cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); 1203 cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
1145 cancel_delayed_work_sync(&qdev->mpi_idc_work); 1204 cancel_delayed_work_sync(&qdev->mpi_idc_work);
1205 /* If we're not the dominant NIC function,
1206 * then there is nothing to do.
1207 */
1208 if (!ql_own_firmware(qdev)) {
1209 QPRINTK(qdev, DRV, ERR, "Don't own firmware!\n");
1210 return;
1211 }
1212
1213 if (!ql_core_dump(qdev, qdev->mpi_coredump)) {
1214 QPRINTK(qdev, DRV, ERR, "Core is dumped!\n");
1215 qdev->core_is_dumped = 1;
1216 queue_delayed_work(qdev->workqueue,
1217 &qdev->mpi_core_to_log, 5 * HZ);
1218 }
1146 ql_soft_reset_mpi_risc(qdev); 1219 ql_soft_reset_mpi_risc(qdev);
1147} 1220}