1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
4 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
9 #include <linux/devcoredump.h>
10 #include <linux/kernel.h>
11 #include <linux/types.h>
12 #include <linux/utsname.h>
17 static const struct ath10k_mem_section qca6174_hw21_register_sections[] = {
273 static const struct ath10k_mem_section qca6174_hw30_sdio_register_sections[] = {
503 /* EFUSE0,1,2 is disabled here
504 * because its state may be reset
506 * {0x24800, 0x24804},
507 * {0x25000, 0x25004},
508 * {0x25800, 0x25804},
526 /* DBI windows is skipped here, it can be only accessed when pcie
527 * is active (not in reset) and CORE_CTRL_PCIE_LTSSM_EN = 0 &&
528 * PCIE_CTRL_APP_LTSSM_ENALBE=0.
529 * {0x3C000 , 0x3C004},
534 /* SI register is skiped here.
535 * Because it will cause bus hang
537 * {0x50000, 0x50018},
544 static const struct ath10k_mem_section qca6174_hw30_register_sections[] = {
800 static const struct ath10k_mem_region qca6174_hw10_mem_regions[] = {
802 .type = ATH10K_MEM_REGION_TYPE_DRAM,
812 .type = ATH10K_MEM_REGION_TYPE_REG,
814 /* RTC_SOC_BASE_ADDRESS */
817 /* WLAN_MBOX_BASE_ADDRESS - RTC_SOC_BASE_ADDRESS */
827 .type = ATH10K_MEM_REGION_TYPE_REG,
829 /* STEREO_BASE_ADDRESS */
832 /* USB_BASE_ADDRESS - STEREO_BASE_ADDRESS */
833 .len = 0x60000 - 0x27000,
843 static const struct ath10k_mem_region qca6174_hw21_mem_regions[] = {
845 .type = ATH10K_MEM_REGION_TYPE_DRAM,
855 .type = ATH10K_MEM_REGION_TYPE_AXI,
865 .type = ATH10K_MEM_REGION_TYPE_REG,
867 .len = 0x80020 - 0x800,
870 .sections = qca6174_hw21_register_sections,
871 .size = ARRAY_SIZE(qca6174_hw21_register_sections),
876 static const struct ath10k_mem_region qca6174_hw30_sdio_mem_regions[] = {
878 .type = ATH10K_MEM_REGION_TYPE_DRAM,
888 .type = ATH10K_MEM_REGION_TYPE_AXI,
898 .type = ATH10K_MEM_REGION_TYPE_IRAM1,
908 .type = ATH10K_MEM_REGION_TYPE_IRAM2,
918 .type = ATH10K_MEM_REGION_TYPE_REG,
920 .len = 0x80020 - 0x800,
923 .sections = qca6174_hw30_sdio_register_sections,
924 .size = ARRAY_SIZE(qca6174_hw30_sdio_register_sections),
929 static const struct ath10k_mem_region qca6174_hw30_mem_regions[] = {
931 .type = ATH10K_MEM_REGION_TYPE_DRAM,
941 .type = ATH10K_MEM_REGION_TYPE_AXI,
951 .type = ATH10K_MEM_REGION_TYPE_REG,
953 .len = 0x80020 - 0x800,
956 .sections = qca6174_hw30_register_sections,
957 .size = ARRAY_SIZE(qca6174_hw30_register_sections),
961 /* IRAM dump must be put last */
963 .type = ATH10K_MEM_REGION_TYPE_IRAM1,
973 .type = ATH10K_MEM_REGION_TYPE_IRAM2,
984 static const struct ath10k_mem_region qca988x_hw20_mem_regions[] = {
986 .type = ATH10K_MEM_REGION_TYPE_DRAM,
996 .type = ATH10K_MEM_REGION_TYPE_REG,
1006 .type = ATH10K_MEM_REGION_TYPE_REG,
1009 .name = "REG_PART2",
1017 static const struct ath10k_mem_region qca99x0_hw20_mem_regions[] = {
1019 .type = ATH10K_MEM_REGION_TYPE_DRAM,
1029 .type = ATH10K_MEM_REGION_TYPE_REG,
1039 .type = ATH10K_MEM_REGION_TYPE_IOSRAM,
1049 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1052 .name = "APB REG 1",
1059 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1062 .name = "APB REG 2",
1069 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1079 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1089 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1100 static const struct ath10k_mem_region qca9984_hw10_mem_regions[] = {
1102 .type = ATH10K_MEM_REGION_TYPE_DRAM,
1112 .type = ATH10K_MEM_REGION_TYPE_REG,
1122 .type = ATH10K_MEM_REGION_TYPE_IOSRAM,
1132 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1135 .name = "APB REG 1",
1142 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1145 .name = "APB REG 2",
1152 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1162 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1172 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1183 static const struct ath10k_mem_section ipq4019_soc_reg_range[] = {
1184 {0x080000, 0x080004},
1185 {0x080020, 0x080024},
1186 {0x080028, 0x080050},
1187 {0x0800d4, 0x0800ec},
1188 {0x08010c, 0x080118},
1189 {0x080284, 0x080290},
1190 {0x0802a8, 0x0802b8},
1191 {0x0802dc, 0x08030c},
1192 {0x082000, 0x083fff}
1195 static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
1197 .type = ATH10K_MEM_REGION_TYPE_DRAM,
1207 .type = ATH10K_MEM_REGION_TYPE_REG,
1217 .type = ATH10K_MEM_REGION_TYPE_REG,
1227 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1230 .name = "APB REG 1",
1237 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1240 .name = "APB REG 2",
1247 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1257 .type = ATH10K_MEM_REGION_TYPE_IOREG,
1267 .type = ATH10K_MEM_REGION_TYPE_REG,
1269 .len = 0x083fff - 0x080000,
1270 .name = "REG_TOTAL",
1272 .sections = ipq4019_soc_reg_range,
1273 .size = ARRAY_SIZE(ipq4019_soc_reg_range),
1278 static const struct ath10k_mem_region wcn399x_hw10_mem_regions[] = {
1280 /* MSA region start is not fixed, hence it is assigned at runtime */
1281 .type = ATH10K_MEM_REGION_TYPE_MSA,
1291 static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
1293 .hw_id = QCA6174_HW_1_0_VERSION,
1294 .hw_rev = ATH10K_HW_QCA6174,
1295 .bus = ATH10K_BUS_PCI,
1297 .regions = qca6174_hw10_mem_regions,
1298 .size = ARRAY_SIZE(qca6174_hw10_mem_regions),
1302 .hw_id = QCA6174_HW_1_1_VERSION,
1303 .hw_rev = ATH10K_HW_QCA6174,
1304 .bus = ATH10K_BUS_PCI,
1306 .regions = qca6174_hw10_mem_regions,
1307 .size = ARRAY_SIZE(qca6174_hw10_mem_regions),
1311 .hw_id = QCA6174_HW_1_3_VERSION,
1312 .hw_rev = ATH10K_HW_QCA6174,
1313 .bus = ATH10K_BUS_PCI,
1315 .regions = qca6174_hw10_mem_regions,
1316 .size = ARRAY_SIZE(qca6174_hw10_mem_regions),
1320 .hw_id = QCA6174_HW_2_1_VERSION,
1321 .hw_rev = ATH10K_HW_QCA6174,
1322 .bus = ATH10K_BUS_PCI,
1324 .regions = qca6174_hw21_mem_regions,
1325 .size = ARRAY_SIZE(qca6174_hw21_mem_regions),
1329 .hw_id = QCA6174_HW_3_0_VERSION,
1330 .hw_rev = ATH10K_HW_QCA6174,
1331 .bus = ATH10K_BUS_PCI,
1333 .regions = qca6174_hw30_mem_regions,
1334 .size = ARRAY_SIZE(qca6174_hw30_mem_regions),
1338 .hw_id = QCA6174_HW_3_2_VERSION,
1339 .hw_rev = ATH10K_HW_QCA6174,
1340 .bus = ATH10K_BUS_PCI,
1342 .regions = qca6174_hw30_mem_regions,
1343 .size = ARRAY_SIZE(qca6174_hw30_mem_regions),
1347 .hw_id = QCA6174_HW_3_2_VERSION,
1348 .hw_rev = ATH10K_HW_QCA6174,
1349 .bus = ATH10K_BUS_SDIO,
1351 .regions = qca6174_hw30_sdio_mem_regions,
1352 .size = ARRAY_SIZE(qca6174_hw30_sdio_mem_regions),
1356 .hw_id = QCA9377_HW_1_1_DEV_VERSION,
1357 .hw_rev = ATH10K_HW_QCA9377,
1358 .bus = ATH10K_BUS_PCI,
1360 .regions = qca6174_hw30_mem_regions,
1361 .size = ARRAY_SIZE(qca6174_hw30_mem_regions),
1365 .hw_id = QCA988X_HW_2_0_VERSION,
1366 .hw_rev = ATH10K_HW_QCA988X,
1367 .bus = ATH10K_BUS_PCI,
1369 .regions = qca988x_hw20_mem_regions,
1370 .size = ARRAY_SIZE(qca988x_hw20_mem_regions),
1374 .hw_id = QCA9984_HW_1_0_DEV_VERSION,
1375 .hw_rev = ATH10K_HW_QCA9984,
1376 .bus = ATH10K_BUS_PCI,
1378 .regions = qca9984_hw10_mem_regions,
1379 .size = ARRAY_SIZE(qca9984_hw10_mem_regions),
1383 .hw_id = QCA9888_HW_2_0_DEV_VERSION,
1384 .hw_rev = ATH10K_HW_QCA9888,
1385 .bus = ATH10K_BUS_PCI,
1387 .regions = qca9984_hw10_mem_regions,
1388 .size = ARRAY_SIZE(qca9984_hw10_mem_regions),
1392 .hw_id = QCA99X0_HW_2_0_DEV_VERSION,
1393 .hw_rev = ATH10K_HW_QCA99X0,
1394 .bus = ATH10K_BUS_PCI,
1396 .regions = qca99x0_hw20_mem_regions,
1397 .size = ARRAY_SIZE(qca99x0_hw20_mem_regions),
1401 .hw_id = QCA4019_HW_1_0_DEV_VERSION,
1402 .hw_rev = ATH10K_HW_QCA4019,
1403 .bus = ATH10K_BUS_AHB,
1405 .regions = qca4019_hw10_mem_regions,
1406 .size = ARRAY_SIZE(qca4019_hw10_mem_regions),
1410 .hw_id = WCN3990_HW_1_0_DEV_VERSION,
1411 .hw_rev = ATH10K_HW_WCN3990,
1412 .bus = ATH10K_BUS_SNOC,
1414 .regions = wcn399x_hw10_mem_regions,
1415 .size = ARRAY_SIZE(wcn399x_hw10_mem_regions),
1420 static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
1422 const struct ath10k_hw_mem_layout *hw;
1423 const struct ath10k_mem_region *mem_region;
1427 hw = ath10k_coredump_get_mem_layout(ar);
1432 mem_region = &hw->region_table.regions[0];
1434 for (i = 0; i < hw->region_table.size; i++) {
1435 size += mem_region->len;
1439 /* reserve space for the headers */
1440 size += hw->region_table.size * sizeof(struct ath10k_dump_ram_data_hdr);
1442 /* make sure it is aligned 16 bytes for debug message print out */
1443 size = ALIGN(size, 16);
1448 const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar)
1450 if (!test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask))
1453 return _ath10k_coredump_get_mem_layout(ar);
1455 EXPORT_SYMBOL(ath10k_coredump_get_mem_layout);
1457 const struct ath10k_hw_mem_layout *_ath10k_coredump_get_mem_layout(struct ath10k *ar)
1461 if (WARN_ON(ar->target_version == 0))
1464 for (i = 0; i < ARRAY_SIZE(hw_mem_layouts); i++) {
1465 if (ar->target_version == hw_mem_layouts[i].hw_id &&
1466 ar->hw_rev == hw_mem_layouts[i].hw_rev &&
1467 hw_mem_layouts[i].bus == ar->hif.bus)
1468 return &hw_mem_layouts[i];
1474 struct ath10k_fw_crash_data *ath10k_coredump_new(struct ath10k *ar)
1476 struct ath10k_fw_crash_data *crash_data = ar->coredump.fw_crash_data;
1478 lockdep_assert_held(&ar->dump_mutex);
1480 if (ath10k_coredump_mask == 0)
1481 /* coredump disabled */
1484 guid_gen(&crash_data->guid);
1485 ktime_get_real_ts64(&crash_data->timestamp);
1489 EXPORT_SYMBOL(ath10k_coredump_new);
1491 static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
1493 struct ath10k_fw_crash_data *crash_data = ar->coredump.fw_crash_data;
1494 struct ath10k_ce_crash_hdr *ce_hdr;
1495 struct ath10k_dump_file_data *dump_data;
1496 struct ath10k_tlv_dump_data *dump_tlv;
1497 size_t hdr_len = sizeof(*dump_data);
1498 size_t len, sofar = 0;
1503 if (test_bit(ATH10K_FW_CRASH_DUMP_REGISTERS, &ath10k_coredump_mask))
1504 len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
1506 if (test_bit(ATH10K_FW_CRASH_DUMP_CE_DATA, &ath10k_coredump_mask))
1507 len += sizeof(*dump_tlv) + sizeof(*ce_hdr) +
1508 CE_COUNT * sizeof(ce_hdr->entries[0]);
1510 if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask))
1511 len += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
1515 /* This is going to get big when we start dumping FW RAM and such,
1516 * so go ahead and use vmalloc.
1522 mutex_lock(&ar->dump_mutex);
1524 dump_data = (struct ath10k_dump_file_data *)(buf);
1525 strscpy(dump_data->df_magic, "ATH10K-FW-DUMP",
1526 sizeof(dump_data->df_magic));
1527 dump_data->len = cpu_to_le32(len);
1529 dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
1531 guid_copy(&dump_data->guid, &crash_data->guid);
1532 dump_data->chip_id = cpu_to_le32(ar->bus_param.chip_id);
1533 dump_data->bus_type = cpu_to_le32(0);
1534 dump_data->target_version = cpu_to_le32(ar->target_version);
1535 dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
1536 dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
1537 dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
1538 dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
1539 dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
1540 dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
1541 dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
1542 dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
1543 dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
1544 dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
1546 strscpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
1547 sizeof(dump_data->fw_ver));
1549 dump_data->kernel_ver_code = 0;
1550 strscpy(dump_data->kernel_ver, init_utsname()->release,
1551 sizeof(dump_data->kernel_ver));
1553 dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
1554 dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
1556 if (test_bit(ATH10K_FW_CRASH_DUMP_REGISTERS, &ath10k_coredump_mask)) {
1557 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
1558 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
1559 dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
1560 memcpy(dump_tlv->tlv_data, &crash_data->registers,
1561 sizeof(crash_data->registers));
1562 sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
1565 if (test_bit(ATH10K_FW_CRASH_DUMP_CE_DATA, &ath10k_coredump_mask)) {
1566 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
1567 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_CE_DATA);
1568 dump_tlv->tlv_len = cpu_to_le32(struct_size(ce_hdr, entries,
1570 ce_hdr = (struct ath10k_ce_crash_hdr *)(dump_tlv->tlv_data);
1571 ce_hdr->ce_count = cpu_to_le32(CE_COUNT);
1572 memset(ce_hdr->reserved, 0, sizeof(ce_hdr->reserved));
1573 memcpy(ce_hdr->entries, crash_data->ce_crash_data,
1574 CE_COUNT * sizeof(ce_hdr->entries[0]));
1575 sofar += sizeof(*dump_tlv) + sizeof(*ce_hdr) +
1576 CE_COUNT * sizeof(ce_hdr->entries[0]);
1579 /* Gather ram dump */
1580 if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) {
1581 dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
1582 dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_RAM_DATA);
1583 dump_tlv->tlv_len = cpu_to_le32(crash_data->ramdump_buf_len);
1584 if (crash_data->ramdump_buf_len) {
1585 memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
1586 crash_data->ramdump_buf_len);
1587 sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
1591 mutex_unlock(&ar->dump_mutex);
1596 int ath10k_coredump_submit(struct ath10k *ar)
1598 struct ath10k_dump_file_data *dump;
1600 if (ath10k_coredump_mask == 0)
1601 /* coredump disabled */
1604 dump = ath10k_coredump_build(ar);
1606 ath10k_warn(ar, "no crash dump data found for devcoredump");
1610 dev_coredumpv(ar->dev, dump, le32_to_cpu(dump->len), GFP_KERNEL);
1615 int ath10k_coredump_create(struct ath10k *ar)
1617 if (ath10k_coredump_mask == 0)
1618 /* coredump disabled */
1621 ar->coredump.fw_crash_data = vzalloc(sizeof(*ar->coredump.fw_crash_data));
1622 if (!ar->coredump.fw_crash_data)
1628 int ath10k_coredump_register(struct ath10k *ar)
1630 struct ath10k_fw_crash_data *crash_data = ar->coredump.fw_crash_data;
1632 if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) {
1633 crash_data->ramdump_buf_len = ath10k_coredump_get_ramdump_size(ar);
1635 if (!crash_data->ramdump_buf_len)
1638 crash_data->ramdump_buf = vzalloc(crash_data->ramdump_buf_len);
1639 if (!crash_data->ramdump_buf)
1646 void ath10k_coredump_unregister(struct ath10k *ar)
1648 struct ath10k_fw_crash_data *crash_data = ar->coredump.fw_crash_data;
1650 vfree(crash_data->ramdump_buf);
1653 void ath10k_coredump_destroy(struct ath10k *ar)
1655 if (ar->coredump.fw_crash_data->ramdump_buf) {
1656 vfree(ar->coredump.fw_crash_data->ramdump_buf);
1657 ar->coredump.fw_crash_data->ramdump_buf = NULL;
1658 ar->coredump.fw_crash_data->ramdump_buf_len = 0;
1661 vfree(ar->coredump.fw_crash_data);
1662 ar->coredump.fw_crash_data = NULL;