aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
authorReinette Chatre <reinette.chatre@intel.com>2009-09-25 17:24:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-09-28 16:55:05 -0400
commitb7a794048ff30d53764c1e41ccb2bff7f7bec2a8 (patch)
treec9c25b77c0bc9a11fd65fae5aae043d66d12691d /drivers/net/wireless/iwlwifi/iwl-agn.c
parent2814298639619b0aa994fe1aee55438f1e26a2a8 (diff)
iwlwifi: fix 3945 ucode info retrieval after failure
When hardware or uCode problem occurs driver captures significant information from device to enable debugging. The format of this information is different between 3945 and 4965 and later devices, yet currently the 3945 uses the 4965 and later format. Fix this by adding a new library call that is initialized to the correct formatting routine based on device. This moves the iwlagn event and error log handling back to iwl-agn.c to make it part of iwlagn module. Also remove the 3945 sysfs file that triggers dump of event log - there is already a debugfs file that can do it for all drivers. Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 00457bff1ed1..cdc07c477457 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1526,6 +1526,191 @@ static int iwl_read_ucode(struct iwl_priv *priv)
1526 return ret; 1526 return ret;
1527} 1527}
1528 1528
1529#ifdef CONFIG_IWLWIFI_DEBUG
1530static const char *desc_lookup_text[] = {
1531 "OK",
1532 "FAIL",
1533 "BAD_PARAM",
1534 "BAD_CHECKSUM",
1535 "NMI_INTERRUPT_WDG",
1536 "SYSASSERT",
1537 "FATAL_ERROR",
1538 "BAD_COMMAND",
1539 "HW_ERROR_TUNE_LOCK",
1540 "HW_ERROR_TEMPERATURE",
1541 "ILLEGAL_CHAN_FREQ",
1542 "VCC_NOT_STABLE",
1543 "FH_ERROR",
1544 "NMI_INTERRUPT_HOST",
1545 "NMI_INTERRUPT_ACTION_PT",
1546 "NMI_INTERRUPT_UNKNOWN",
1547 "UCODE_VERSION_MISMATCH",
1548 "HW_ERROR_ABS_LOCK",
1549 "HW_ERROR_CAL_LOCK_FAIL",
1550 "NMI_INTERRUPT_INST_ACTION_PT",
1551 "NMI_INTERRUPT_DATA_ACTION_PT",
1552 "NMI_TRM_HW_ER",
1553 "NMI_INTERRUPT_TRM",
1554 "NMI_INTERRUPT_BREAK_POINT"
1555 "DEBUG_0",
1556 "DEBUG_1",
1557 "DEBUG_2",
1558 "DEBUG_3",
1559 "UNKNOWN"
1560};
1561
1562static const char *desc_lookup(int i)
1563{
1564 int max = ARRAY_SIZE(desc_lookup_text) - 1;
1565
1566 if (i < 0 || i > max)
1567 i = max;
1568
1569 return desc_lookup_text[i];
1570}
1571
1572#define ERROR_START_OFFSET (1 * sizeof(u32))
1573#define ERROR_ELEM_SIZE (7 * sizeof(u32))
1574
1575void iwl_dump_nic_error_log(struct iwl_priv *priv)
1576{
1577 u32 data2, line;
1578 u32 desc, time, count, base, data1;
1579 u32 blink1, blink2, ilink1, ilink2;
1580
1581 if (priv->ucode_type == UCODE_INIT)
1582 base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
1583 else
1584 base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
1585
1586 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1587 IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
1588 return;
1589 }
1590
1591 count = iwl_read_targ_mem(priv, base);
1592
1593 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
1594 IWL_ERR(priv, "Start IWL Error Log Dump:\n");
1595 IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
1596 priv->status, count);
1597 }
1598
1599 desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
1600 blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
1601 blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
1602 ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
1603 ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
1604 data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
1605 data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
1606 line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
1607 time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
1608
1609 IWL_ERR(priv, "Desc Time "
1610 "data1 data2 line\n");
1611 IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
1612 desc_lookup(desc), desc, time, data1, data2, line);
1613 IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
1614 IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
1615 ilink1, ilink2);
1616
1617}
1618
1619#define EVENT_START_OFFSET (4 * sizeof(u32))
1620
1621/**
1622 * iwl_print_event_log - Dump error event log to syslog
1623 *
1624 */
1625static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
1626 u32 num_events, u32 mode)
1627{
1628 u32 i;
1629 u32 base; /* SRAM byte address of event log header */
1630 u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
1631 u32 ptr; /* SRAM byte address of log data */
1632 u32 ev, time, data; /* event log data */
1633
1634 if (num_events == 0)
1635 return;
1636 if (priv->ucode_type == UCODE_INIT)
1637 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
1638 else
1639 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1640
1641 if (mode == 0)
1642 event_size = 2 * sizeof(u32);
1643 else
1644 event_size = 3 * sizeof(u32);
1645
1646 ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
1647
1648 /* "time" is actually "data" for mode 0 (no timestamp).
1649 * place event id # at far right for easier visual parsing. */
1650 for (i = 0; i < num_events; i++) {
1651 ev = iwl_read_targ_mem(priv, ptr);
1652 ptr += sizeof(u32);
1653 time = iwl_read_targ_mem(priv, ptr);
1654 ptr += sizeof(u32);
1655 if (mode == 0) {
1656 /* data, ev */
1657 IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
1658 } else {
1659 data = iwl_read_targ_mem(priv, ptr);
1660 ptr += sizeof(u32);
1661 IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
1662 time, data, ev);
1663 }
1664 }
1665}
1666
1667void iwl_dump_nic_event_log(struct iwl_priv *priv)
1668{
1669 u32 base; /* SRAM byte address of event log header */
1670 u32 capacity; /* event log capacity in # entries */
1671 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
1672 u32 num_wraps; /* # times uCode wrapped to top of log */
1673 u32 next_entry; /* index of next entry to be written by uCode */
1674 u32 size; /* # entries that we'll print */
1675
1676 if (priv->ucode_type == UCODE_INIT)
1677 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
1678 else
1679 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1680
1681 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1682 IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
1683 return;
1684 }
1685
1686 /* event log header */
1687 capacity = iwl_read_targ_mem(priv, base);
1688 mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
1689 num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
1690 next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
1691
1692 size = num_wraps ? capacity : next_entry;
1693
1694 /* bail out if nothing in log */
1695 if (size == 0) {
1696 IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
1697 return;
1698 }
1699
1700 IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
1701 size, num_wraps);
1702
1703 /* if uCode has wrapped back to top of log, start at the oldest entry,
1704 * i.e the next one that uCode would fill. */
1705 if (num_wraps)
1706 iwl_print_event_log(priv, next_entry,
1707 capacity - next_entry, mode);
1708 /* (then/else) start at top of log */
1709 iwl_print_event_log(priv, 0, next_entry, mode);
1710
1711}
1712#endif
1713
1529/** 1714/**
1530 * iwl_alive_start - called after REPLY_ALIVE notification received 1715 * iwl_alive_start - called after REPLY_ALIVE notification received
1531 * from protocol/runtime uCode (initialization uCode's 1716 * from protocol/runtime uCode (initialization uCode's