diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_dbg.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 4f478364fa43..34760f8d4f17 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -1324,6 +1324,330 @@ qla25xx_fw_dump_failed: | |||
1324 | if (!hardware_locked) | 1324 | if (!hardware_locked) |
1325 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1325 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
1326 | } | 1326 | } |
1327 | |||
1328 | void | ||
1329 | qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | ||
1330 | { | ||
1331 | int rval; | ||
1332 | uint32_t cnt; | ||
1333 | uint32_t risc_address; | ||
1334 | struct qla_hw_data *ha = vha->hw; | ||
1335 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
1336 | uint32_t __iomem *dmp_reg; | ||
1337 | uint32_t *iter_reg; | ||
1338 | uint16_t __iomem *mbx_reg; | ||
1339 | unsigned long flags; | ||
1340 | struct qla81xx_fw_dump *fw; | ||
1341 | uint32_t ext_mem_cnt; | ||
1342 | void *nxt, *nxt_chain; | ||
1343 | uint32_t *last_chain = NULL; | ||
1344 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | ||
1345 | |||
1346 | risc_address = ext_mem_cnt = 0; | ||
1347 | flags = 0; | ||
1348 | |||
1349 | if (!hardware_locked) | ||
1350 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1351 | |||
1352 | if (!ha->fw_dump) { | ||
1353 | qla_printk(KERN_WARNING, ha, | ||
1354 | "No buffer available for dump!!!\n"); | ||
1355 | goto qla81xx_fw_dump_failed; | ||
1356 | } | ||
1357 | |||
1358 | if (ha->fw_dumped) { | ||
1359 | qla_printk(KERN_WARNING, ha, | ||
1360 | "Firmware has been previously dumped (%p) -- ignoring " | ||
1361 | "request...\n", ha->fw_dump); | ||
1362 | goto qla81xx_fw_dump_failed; | ||
1363 | } | ||
1364 | fw = &ha->fw_dump->isp.isp81; | ||
1365 | qla2xxx_prep_dump(ha, ha->fw_dump); | ||
1366 | |||
1367 | fw->host_status = htonl(RD_REG_DWORD(®->host_status)); | ||
1368 | |||
1369 | /* Pause RISC. */ | ||
1370 | rval = qla24xx_pause_risc(reg); | ||
1371 | if (rval != QLA_SUCCESS) | ||
1372 | goto qla81xx_fw_dump_failed_0; | ||
1373 | |||
1374 | /* Host/Risc registers. */ | ||
1375 | iter_reg = fw->host_risc_reg; | ||
1376 | iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg); | ||
1377 | qla24xx_read_window(reg, 0x7010, 16, iter_reg); | ||
1378 | |||
1379 | /* PCIe registers. */ | ||
1380 | WRT_REG_DWORD(®->iobase_addr, 0x7C00); | ||
1381 | RD_REG_DWORD(®->iobase_addr); | ||
1382 | WRT_REG_DWORD(®->iobase_window, 0x01); | ||
1383 | dmp_reg = ®->iobase_c4; | ||
1384 | fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
1385 | fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
1386 | fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); | ||
1387 | fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); | ||
1388 | |||
1389 | WRT_REG_DWORD(®->iobase_window, 0x00); | ||
1390 | RD_REG_DWORD(®->iobase_window); | ||
1391 | |||
1392 | /* Host interface registers. */ | ||
1393 | dmp_reg = ®->flash_addr; | ||
1394 | for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) | ||
1395 | fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); | ||
1396 | |||
1397 | /* Disable interrupts. */ | ||
1398 | WRT_REG_DWORD(®->ictrl, 0); | ||
1399 | RD_REG_DWORD(®->ictrl); | ||
1400 | |||
1401 | /* Shadow registers. */ | ||
1402 | WRT_REG_DWORD(®->iobase_addr, 0x0F70); | ||
1403 | RD_REG_DWORD(®->iobase_addr); | ||
1404 | WRT_REG_DWORD(®->iobase_select, 0xB0000000); | ||
1405 | fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1406 | |||
1407 | WRT_REG_DWORD(®->iobase_select, 0xB0100000); | ||
1408 | fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1409 | |||
1410 | WRT_REG_DWORD(®->iobase_select, 0xB0200000); | ||
1411 | fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1412 | |||
1413 | WRT_REG_DWORD(®->iobase_select, 0xB0300000); | ||
1414 | fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1415 | |||
1416 | WRT_REG_DWORD(®->iobase_select, 0xB0400000); | ||
1417 | fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1418 | |||
1419 | WRT_REG_DWORD(®->iobase_select, 0xB0500000); | ||
1420 | fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1421 | |||
1422 | WRT_REG_DWORD(®->iobase_select, 0xB0600000); | ||
1423 | fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1424 | |||
1425 | WRT_REG_DWORD(®->iobase_select, 0xB0700000); | ||
1426 | fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1427 | |||
1428 | WRT_REG_DWORD(®->iobase_select, 0xB0800000); | ||
1429 | fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1430 | |||
1431 | WRT_REG_DWORD(®->iobase_select, 0xB0900000); | ||
1432 | fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1433 | |||
1434 | WRT_REG_DWORD(®->iobase_select, 0xB0A00000); | ||
1435 | fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); | ||
1436 | |||
1437 | /* RISC I/O register. */ | ||
1438 | WRT_REG_DWORD(®->iobase_addr, 0x0010); | ||
1439 | fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); | ||
1440 | |||
1441 | /* Mailbox registers. */ | ||
1442 | mbx_reg = ®->mailbox0; | ||
1443 | for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) | ||
1444 | fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); | ||
1445 | |||
1446 | /* Transfer sequence registers. */ | ||
1447 | iter_reg = fw->xseq_gp_reg; | ||
1448 | iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg); | ||
1449 | iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg); | ||
1450 | iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg); | ||
1451 | iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg); | ||
1452 | iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg); | ||
1453 | iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg); | ||
1454 | iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg); | ||
1455 | qla24xx_read_window(reg, 0xBF70, 16, iter_reg); | ||
1456 | |||
1457 | iter_reg = fw->xseq_0_reg; | ||
1458 | iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg); | ||
1459 | iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg); | ||
1460 | qla24xx_read_window(reg, 0xBFE0, 16, iter_reg); | ||
1461 | |||
1462 | qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg); | ||
1463 | |||
1464 | /* Receive sequence registers. */ | ||
1465 | iter_reg = fw->rseq_gp_reg; | ||
1466 | iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg); | ||
1467 | iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg); | ||
1468 | iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg); | ||
1469 | iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg); | ||
1470 | iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg); | ||
1471 | iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg); | ||
1472 | iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg); | ||
1473 | qla24xx_read_window(reg, 0xFF70, 16, iter_reg); | ||
1474 | |||
1475 | iter_reg = fw->rseq_0_reg; | ||
1476 | iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg); | ||
1477 | qla24xx_read_window(reg, 0xFFD0, 16, iter_reg); | ||
1478 | |||
1479 | qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg); | ||
1480 | qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg); | ||
1481 | |||
1482 | /* Auxiliary sequence registers. */ | ||
1483 | iter_reg = fw->aseq_gp_reg; | ||
1484 | iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg); | ||
1485 | iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg); | ||
1486 | iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg); | ||
1487 | iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg); | ||
1488 | iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg); | ||
1489 | iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg); | ||
1490 | iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg); | ||
1491 | qla24xx_read_window(reg, 0xB070, 16, iter_reg); | ||
1492 | |||
1493 | iter_reg = fw->aseq_0_reg; | ||
1494 | iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg); | ||
1495 | qla24xx_read_window(reg, 0xB0D0, 16, iter_reg); | ||
1496 | |||
1497 | qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg); | ||
1498 | qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg); | ||
1499 | |||
1500 | /* Command DMA registers. */ | ||
1501 | qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg); | ||
1502 | |||
1503 | /* Queues. */ | ||
1504 | iter_reg = fw->req0_dma_reg; | ||
1505 | iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg); | ||
1506 | dmp_reg = ®->iobase_q; | ||
1507 | for (cnt = 0; cnt < 7; cnt++) | ||
1508 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
1509 | |||
1510 | iter_reg = fw->resp0_dma_reg; | ||
1511 | iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg); | ||
1512 | dmp_reg = ®->iobase_q; | ||
1513 | for (cnt = 0; cnt < 7; cnt++) | ||
1514 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
1515 | |||
1516 | iter_reg = fw->req1_dma_reg; | ||
1517 | iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg); | ||
1518 | dmp_reg = ®->iobase_q; | ||
1519 | for (cnt = 0; cnt < 7; cnt++) | ||
1520 | *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); | ||
1521 | |||
1522 | /* Transmit DMA registers. */ | ||
1523 | iter_reg = fw->xmt0_dma_reg; | ||
1524 | iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg); | ||
1525 | qla24xx_read_window(reg, 0x7610, 16, iter_reg); | ||
1526 | |||
1527 | iter_reg = fw->xmt1_dma_reg; | ||
1528 | iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg); | ||
1529 | qla24xx_read_window(reg, 0x7630, 16, iter_reg); | ||
1530 | |||
1531 | iter_reg = fw->xmt2_dma_reg; | ||
1532 | iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg); | ||
1533 | qla24xx_read_window(reg, 0x7650, 16, iter_reg); | ||
1534 | |||
1535 | iter_reg = fw->xmt3_dma_reg; | ||
1536 | iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg); | ||
1537 | qla24xx_read_window(reg, 0x7670, 16, iter_reg); | ||
1538 | |||
1539 | iter_reg = fw->xmt4_dma_reg; | ||
1540 | iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg); | ||
1541 | qla24xx_read_window(reg, 0x7690, 16, iter_reg); | ||
1542 | |||
1543 | qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg); | ||
1544 | |||
1545 | /* Receive DMA registers. */ | ||
1546 | iter_reg = fw->rcvt0_data_dma_reg; | ||
1547 | iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg); | ||
1548 | qla24xx_read_window(reg, 0x7710, 16, iter_reg); | ||
1549 | |||
1550 | iter_reg = fw->rcvt1_data_dma_reg; | ||
1551 | iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg); | ||
1552 | qla24xx_read_window(reg, 0x7730, 16, iter_reg); | ||
1553 | |||
1554 | /* RISC registers. */ | ||
1555 | iter_reg = fw->risc_gp_reg; | ||
1556 | iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg); | ||
1557 | iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg); | ||
1558 | iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg); | ||
1559 | iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg); | ||
1560 | iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg); | ||
1561 | iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg); | ||
1562 | iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg); | ||
1563 | qla24xx_read_window(reg, 0x0F70, 16, iter_reg); | ||
1564 | |||
1565 | /* Local memory controller registers. */ | ||
1566 | iter_reg = fw->lmc_reg; | ||
1567 | iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg); | ||
1568 | iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg); | ||
1569 | iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg); | ||
1570 | iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg); | ||
1571 | iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg); | ||
1572 | iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg); | ||
1573 | iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg); | ||
1574 | qla24xx_read_window(reg, 0x3070, 16, iter_reg); | ||
1575 | |||
1576 | /* Fibre Protocol Module registers. */ | ||
1577 | iter_reg = fw->fpm_hdw_reg; | ||
1578 | iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg); | ||
1579 | iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg); | ||
1580 | iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg); | ||
1581 | iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg); | ||
1582 | iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg); | ||
1583 | iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg); | ||
1584 | iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg); | ||
1585 | iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg); | ||
1586 | iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg); | ||
1587 | iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg); | ||
1588 | iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg); | ||
1589 | iter_reg = qla24xx_read_window(reg, 0x40B0, 16, iter_reg); | ||
1590 | iter_reg = qla24xx_read_window(reg, 0x40C0, 16, iter_reg); | ||
1591 | qla24xx_read_window(reg, 0x40D0, 16, iter_reg); | ||
1592 | |||
1593 | /* Frame Buffer registers. */ | ||
1594 | iter_reg = fw->fb_hdw_reg; | ||
1595 | iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg); | ||
1596 | iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg); | ||
1597 | iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg); | ||
1598 | iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg); | ||
1599 | iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg); | ||
1600 | iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg); | ||
1601 | iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg); | ||
1602 | iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg); | ||
1603 | iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg); | ||
1604 | iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg); | ||
1605 | iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg); | ||
1606 | iter_reg = qla24xx_read_window(reg, 0x61C0, 16, iter_reg); | ||
1607 | qla24xx_read_window(reg, 0x6F00, 16, iter_reg); | ||
1608 | |||
1609 | /* Multi queue registers */ | ||
1610 | nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset, | ||
1611 | &last_chain); | ||
1612 | |||
1613 | rval = qla24xx_soft_reset(ha); | ||
1614 | if (rval != QLA_SUCCESS) | ||
1615 | goto qla81xx_fw_dump_failed_0; | ||
1616 | |||
1617 | rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram), | ||
1618 | &nxt); | ||
1619 | if (rval != QLA_SUCCESS) | ||
1620 | goto qla81xx_fw_dump_failed_0; | ||
1621 | |||
1622 | nxt = qla2xxx_copy_queues(ha, nxt); | ||
1623 | |||
1624 | nxt = qla24xx_copy_eft(ha, nxt); | ||
1625 | |||
1626 | /* Chain entries -- started with MQ. */ | ||
1627 | qla25xx_copy_fce(ha, nxt_chain, &last_chain); | ||
1628 | if (last_chain) { | ||
1629 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); | ||
1630 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); | ||
1631 | } | ||
1632 | |||
1633 | qla81xx_fw_dump_failed_0: | ||
1634 | if (rval != QLA_SUCCESS) { | ||
1635 | qla_printk(KERN_WARNING, ha, | ||
1636 | "Failed to dump firmware (%x)!!!\n", rval); | ||
1637 | ha->fw_dumped = 0; | ||
1638 | |||
1639 | } else { | ||
1640 | qla_printk(KERN_INFO, ha, | ||
1641 | "Firmware dump saved to temp buffer (%ld/%p).\n", | ||
1642 | base_vha->host_no, ha->fw_dump); | ||
1643 | ha->fw_dumped = 1; | ||
1644 | } | ||
1645 | |||
1646 | qla81xx_fw_dump_failed: | ||
1647 | if (!hardware_locked) | ||
1648 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1649 | } | ||
1650 | |||
1327 | /****************************************************************************/ | 1651 | /****************************************************************************/ |
1328 | /* Driver Debug Functions. */ | 1652 | /* Driver Debug Functions. */ |
1329 | /****************************************************************************/ | 1653 | /****************************************************************************/ |