Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 703f261d authored by Alan Liu's avatar Alan Liu Committed by Kalle Valo
Browse files

ath10k: add memory dump support for QCA6174/QCA9377



Add memory dump to the firmware crash data file which is provided to user space
via devcoredump interface. This makes it easier for firmware engineers to debug
firmware crashes.

Due to increased memory consumption the memory dump is disabled by default. To
enable it make sure that bit 3 is set in coredump_mask module parameter:

modprobe ath10k_core coredump_mask=0xffffffff

When RAMDUMP is enabled a buffer for the dump is allocated with vmalloc during
device probe. The actual memory layout is different in hardware versions and
the layouts are defined in coredump.c. The memory is split to regions and, to
get even finegrained control of what to copy, the region can split to smaller
sections as not all registers are readable (which could cause the whole system
to stall).

Signed-off-by: default avatarAlan Liu <alanliu@qca.qualcomm.com>
[kvalo@qca.qualcomm.com: refactoring and cleanup]
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 5c9d0a20
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -2563,10 +2563,16 @@ static void ath10k_core_register_work(struct work_struct *work)
		goto err_release_fw;
	}

	status = ath10k_coredump_register(ar);
	if (status) {
		ath10k_err(ar, "unable to register coredump\n");
		goto err_unregister_mac;
	}

	status = ath10k_debug_register(ar);
	if (status) {
		ath10k_err(ar, "unable to initialize debugfs\n");
		goto err_unregister_mac;
		goto err_unregister_coredump;
	}

	status = ath10k_spectral_create(ar);
@@ -2589,6 +2595,8 @@ static void ath10k_core_register_work(struct work_struct *work)
	ath10k_spectral_destroy(ar);
err_debug_destroy:
	ath10k_debug_destroy(ar);
err_unregister_coredump:
	ath10k_coredump_unregister(ar);
err_unregister_mac:
	ath10k_mac_unregister(ar);
err_release_fw:
+5 −0
Original line number Diff line number Diff line
@@ -460,12 +460,17 @@ struct ath10k_ce_crash_hdr {
	struct ath10k_ce_crash_data entries[];
};

#define MAX_MEM_DUMP_TYPE	5

/* used for crash-dump storage, protected by data-lock */
struct ath10k_fw_crash_data {
	guid_t guid;
	struct timespec64 timestamp;
	__le32 registers[REG_DUMP_COUNT_QCA988X];
	struct ath10k_ce_crash_data ce_crash_data[CE_COUNT_MAX];

	u8 *ramdump_buf;
	size_t ramdump_buf_len;
};

struct ath10k_debug {
+786 −0
Original line number Diff line number Diff line
@@ -17,9 +17,754 @@
#include "coredump.h"

#include <linux/devcoredump.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/utsname.h>

#include "debug.h"
#include "hw.h"

static const struct ath10k_mem_section qca6174_hw21_register_sections[] = {
	{0x800, 0x810},
	{0x820, 0x82C},
	{0x830, 0x8F4},
	{0x90C, 0x91C},
	{0xA14, 0xA18},
	{0xA84, 0xA94},
	{0xAA8, 0xAD4},
	{0xADC, 0xB40},
	{0x1000, 0x10A4},
	{0x10BC, 0x111C},
	{0x1134, 0x1138},
	{0x1144, 0x114C},
	{0x1150, 0x115C},
	{0x1160, 0x1178},
	{0x1240, 0x1260},
	{0x2000, 0x207C},
	{0x3000, 0x3014},
	{0x4000, 0x4014},
	{0x5000, 0x5124},
	{0x6000, 0x6040},
	{0x6080, 0x60CC},
	{0x6100, 0x611C},
	{0x6140, 0x61D8},
	{0x6200, 0x6238},
	{0x6240, 0x628C},
	{0x62C0, 0x62EC},
	{0x6380, 0x63E8},
	{0x6400, 0x6440},
	{0x6480, 0x64CC},
	{0x6500, 0x651C},
	{0x6540, 0x6580},
	{0x6600, 0x6638},
	{0x6640, 0x668C},
	{0x66C0, 0x66EC},
	{0x6780, 0x67E8},
	{0x7080, 0x708C},
	{0x70C0, 0x70C8},
	{0x7400, 0x741C},
	{0x7440, 0x7454},
	{0x7800, 0x7818},
	{0x8000, 0x8004},
	{0x8010, 0x8064},
	{0x8080, 0x8084},
	{0x80A0, 0x80A4},
	{0x80C0, 0x80C4},
	{0x80E0, 0x80F4},
	{0x8100, 0x8104},
	{0x8110, 0x812C},
	{0x9000, 0x9004},
	{0x9800, 0x982C},
	{0x9830, 0x9838},
	{0x9840, 0x986C},
	{0x9870, 0x9898},
	{0x9A00, 0x9C00},
	{0xD580, 0xD59C},
	{0xF000, 0xF0E0},
	{0xF140, 0xF190},
	{0xF250, 0xF25C},
	{0xF260, 0xF268},
	{0xF26C, 0xF2A8},
	{0x10008, 0x1000C},
	{0x10014, 0x10018},
	{0x1001C, 0x10020},
	{0x10024, 0x10028},
	{0x10030, 0x10034},
	{0x10040, 0x10054},
	{0x10058, 0x1007C},
	{0x10080, 0x100C4},
	{0x100C8, 0x10114},
	{0x1012C, 0x10130},
	{0x10138, 0x10144},
	{0x10200, 0x10220},
	{0x10230, 0x10250},
	{0x10260, 0x10280},
	{0x10290, 0x102B0},
	{0x102C0, 0x102DC},
	{0x102E0, 0x102F4},
	{0x102FC, 0x1037C},
	{0x10380, 0x10390},
	{0x10800, 0x10828},
	{0x10840, 0x10844},
	{0x10880, 0x10884},
	{0x108C0, 0x108E8},
	{0x10900, 0x10928},
	{0x10940, 0x10944},
	{0x10980, 0x10984},
	{0x109C0, 0x109E8},
	{0x10A00, 0x10A28},
	{0x10A40, 0x10A50},
	{0x11000, 0x11028},
	{0x11030, 0x11034},
	{0x11038, 0x11068},
	{0x11070, 0x11074},
	{0x11078, 0x110A8},
	{0x110B0, 0x110B4},
	{0x110B8, 0x110E8},
	{0x110F0, 0x110F4},
	{0x110F8, 0x11128},
	{0x11138, 0x11144},
	{0x11178, 0x11180},
	{0x111B8, 0x111C0},
	{0x111F8, 0x11200},
	{0x11238, 0x1123C},
	{0x11270, 0x11274},
	{0x11278, 0x1127C},
	{0x112B0, 0x112B4},
	{0x112B8, 0x112BC},
	{0x112F0, 0x112F4},
	{0x112F8, 0x112FC},
	{0x11338, 0x1133C},
	{0x11378, 0x1137C},
	{0x113B8, 0x113BC},
	{0x113F8, 0x113FC},
	{0x11438, 0x11440},
	{0x11478, 0x11480},
	{0x114B8, 0x114BC},
	{0x114F8, 0x114FC},
	{0x11538, 0x1153C},
	{0x11578, 0x1157C},
	{0x115B8, 0x115BC},
	{0x115F8, 0x115FC},
	{0x11638, 0x1163C},
	{0x11678, 0x1167C},
	{0x116B8, 0x116BC},
	{0x116F8, 0x116FC},
	{0x11738, 0x1173C},
	{0x11778, 0x1177C},
	{0x117B8, 0x117BC},
	{0x117F8, 0x117FC},
	{0x17000, 0x1701C},
	{0x17020, 0x170AC},
	{0x18000, 0x18050},
	{0x18054, 0x18074},
	{0x18080, 0x180D4},
	{0x180DC, 0x18104},
	{0x18108, 0x1813C},
	{0x18144, 0x18148},
	{0x18168, 0x18174},
	{0x18178, 0x18180},
	{0x181C8, 0x181E0},
	{0x181E4, 0x181E8},
	{0x181EC, 0x1820C},
	{0x1825C, 0x18280},
	{0x18284, 0x18290},
	{0x18294, 0x182A0},
	{0x18300, 0x18304},
	{0x18314, 0x18320},
	{0x18328, 0x18350},
	{0x1835C, 0x1836C},
	{0x18370, 0x18390},
	{0x18398, 0x183AC},
	{0x183BC, 0x183D8},
	{0x183DC, 0x183F4},
	{0x18400, 0x186F4},
	{0x186F8, 0x1871C},
	{0x18720, 0x18790},
	{0x19800, 0x19830},
	{0x19834, 0x19840},
	{0x19880, 0x1989C},
	{0x198A4, 0x198B0},
	{0x198BC, 0x19900},
	{0x19C00, 0x19C88},
	{0x19D00, 0x19D20},
	{0x19E00, 0x19E7C},
	{0x19E80, 0x19E94},
	{0x19E98, 0x19EAC},
	{0x19EB0, 0x19EBC},
	{0x19F70, 0x19F74},
	{0x19F80, 0x19F8C},
	{0x19FA0, 0x19FB4},
	{0x19FC0, 0x19FD8},
	{0x1A000, 0x1A200},
	{0x1A204, 0x1A210},
	{0x1A228, 0x1A22C},
	{0x1A230, 0x1A248},
	{0x1A250, 0x1A270},
	{0x1A280, 0x1A290},
	{0x1A2A0, 0x1A2A4},
	{0x1A2C0, 0x1A2EC},
	{0x1A300, 0x1A3BC},
	{0x1A3F0, 0x1A3F4},
	{0x1A3F8, 0x1A434},
	{0x1A438, 0x1A444},
	{0x1A448, 0x1A468},
	{0x1A580, 0x1A58C},
	{0x1A644, 0x1A654},
	{0x1A670, 0x1A698},
	{0x1A6AC, 0x1A6B0},
	{0x1A6D0, 0x1A6D4},
	{0x1A6EC, 0x1A70C},
	{0x1A710, 0x1A738},
	{0x1A7C0, 0x1A7D0},
	{0x1A7D4, 0x1A7D8},
	{0x1A7DC, 0x1A7E4},
	{0x1A7F0, 0x1A7F8},
	{0x1A888, 0x1A89C},
	{0x1A8A8, 0x1A8AC},
	{0x1A8C0, 0x1A8DC},
	{0x1A8F0, 0x1A8FC},
	{0x1AE04, 0x1AE08},
	{0x1AE18, 0x1AE24},
	{0x1AF80, 0x1AF8C},
	{0x1AFA0, 0x1AFB4},
	{0x1B000, 0x1B200},
	{0x1B284, 0x1B288},
	{0x1B2D0, 0x1B2D8},
	{0x1B2DC, 0x1B2EC},
	{0x1B300, 0x1B340},
	{0x1B374, 0x1B378},
	{0x1B380, 0x1B384},
	{0x1B388, 0x1B38C},
	{0x1B404, 0x1B408},
	{0x1B420, 0x1B428},
	{0x1B440, 0x1B444},
	{0x1B448, 0x1B44C},
	{0x1B450, 0x1B458},
	{0x1B45C, 0x1B468},
	{0x1B584, 0x1B58C},
	{0x1B68C, 0x1B690},
	{0x1B6AC, 0x1B6B0},
	{0x1B7F0, 0x1B7F8},
	{0x1C800, 0x1CC00},
	{0x1CE00, 0x1CE04},
	{0x1CF80, 0x1CF84},
	{0x1D200, 0x1D800},
	{0x1E000, 0x20014},
	{0x20100, 0x20124},
	{0x21400, 0x217A8},
	{0x21800, 0x21BA8},
	{0x21C00, 0x21FA8},
	{0x22000, 0x223A8},
	{0x22400, 0x227A8},
	{0x22800, 0x22BA8},
	{0x22C00, 0x22FA8},
	{0x23000, 0x233A8},
	{0x24000, 0x24034},
	{0x26000, 0x26064},
	{0x27000, 0x27024},
	{0x34000, 0x3400C},
	{0x34400, 0x3445C},
	{0x34800, 0x3485C},
	{0x34C00, 0x34C5C},
	{0x35000, 0x3505C},
	{0x35400, 0x3545C},
	{0x35800, 0x3585C},
	{0x35C00, 0x35C5C},
	{0x36000, 0x3605C},
	{0x38000, 0x38064},
	{0x38070, 0x380E0},
	{0x3A000, 0x3A064},
	{0x40000, 0x400A4},
	{0x80000, 0x8000C},
	{0x80010, 0x80020},
};

static const struct ath10k_mem_section qca6174_hw30_register_sections[] = {
	{0x800, 0x810},
	{0x820, 0x82C},
	{0x830, 0x8F4},
	{0x90C, 0x91C},
	{0xA14, 0xA18},
	{0xA84, 0xA94},
	{0xAA8, 0xAD4},
	{0xADC, 0xB40},
	{0x1000, 0x10A4},
	{0x10BC, 0x111C},
	{0x1134, 0x1138},
	{0x1144, 0x114C},
	{0x1150, 0x115C},
	{0x1160, 0x1178},
	{0x1240, 0x1260},
	{0x2000, 0x207C},
	{0x3000, 0x3014},
	{0x4000, 0x4014},
	{0x5000, 0x5124},
	{0x6000, 0x6040},
	{0x6080, 0x60CC},
	{0x6100, 0x611C},
	{0x6140, 0x61D8},
	{0x6200, 0x6238},
	{0x6240, 0x628C},
	{0x62C0, 0x62EC},
	{0x6380, 0x63E8},
	{0x6400, 0x6440},
	{0x6480, 0x64CC},
	{0x6500, 0x651C},
	{0x6540, 0x6580},
	{0x6600, 0x6638},
	{0x6640, 0x668C},
	{0x66C0, 0x66EC},
	{0x6780, 0x67E8},
	{0x7080, 0x708C},
	{0x70C0, 0x70C8},
	{0x7400, 0x741C},
	{0x7440, 0x7454},
	{0x7800, 0x7818},
	{0x8000, 0x8004},
	{0x8010, 0x8064},
	{0x8080, 0x8084},
	{0x80A0, 0x80A4},
	{0x80C0, 0x80C4},
	{0x80E0, 0x80F4},
	{0x8100, 0x8104},
	{0x8110, 0x812C},
	{0x9000, 0x9004},
	{0x9800, 0x982C},
	{0x9830, 0x9838},
	{0x9840, 0x986C},
	{0x9870, 0x9898},
	{0x9A00, 0x9C00},
	{0xD580, 0xD59C},
	{0xF000, 0xF0E0},
	{0xF140, 0xF190},
	{0xF250, 0xF25C},
	{0xF260, 0xF268},
	{0xF26C, 0xF2A8},
	{0x10008, 0x1000C},
	{0x10014, 0x10018},
	{0x1001C, 0x10020},
	{0x10024, 0x10028},
	{0x10030, 0x10034},
	{0x10040, 0x10054},
	{0x10058, 0x1007C},
	{0x10080, 0x100C4},
	{0x100C8, 0x10114},
	{0x1012C, 0x10130},
	{0x10138, 0x10144},
	{0x10200, 0x10220},
	{0x10230, 0x10250},
	{0x10260, 0x10280},
	{0x10290, 0x102B0},
	{0x102C0, 0x102DC},
	{0x102E0, 0x102F4},
	{0x102FC, 0x1037C},
	{0x10380, 0x10390},
	{0x10800, 0x10828},
	{0x10840, 0x10844},
	{0x10880, 0x10884},
	{0x108C0, 0x108E8},
	{0x10900, 0x10928},
	{0x10940, 0x10944},
	{0x10980, 0x10984},
	{0x109C0, 0x109E8},
	{0x10A00, 0x10A28},
	{0x10A40, 0x10A50},
	{0x11000, 0x11028},
	{0x11030, 0x11034},
	{0x11038, 0x11068},
	{0x11070, 0x11074},
	{0x11078, 0x110A8},
	{0x110B0, 0x110B4},
	{0x110B8, 0x110E8},
	{0x110F0, 0x110F4},
	{0x110F8, 0x11128},
	{0x11138, 0x11144},
	{0x11178, 0x11180},
	{0x111B8, 0x111C0},
	{0x111F8, 0x11200},
	{0x11238, 0x1123C},
	{0x11270, 0x11274},
	{0x11278, 0x1127C},
	{0x112B0, 0x112B4},
	{0x112B8, 0x112BC},
	{0x112F0, 0x112F4},
	{0x112F8, 0x112FC},
	{0x11338, 0x1133C},
	{0x11378, 0x1137C},
	{0x113B8, 0x113BC},
	{0x113F8, 0x113FC},
	{0x11438, 0x11440},
	{0x11478, 0x11480},
	{0x114B8, 0x114BC},
	{0x114F8, 0x114FC},
	{0x11538, 0x1153C},
	{0x11578, 0x1157C},
	{0x115B8, 0x115BC},
	{0x115F8, 0x115FC},
	{0x11638, 0x1163C},
	{0x11678, 0x1167C},
	{0x116B8, 0x116BC},
	{0x116F8, 0x116FC},
	{0x11738, 0x1173C},
	{0x11778, 0x1177C},
	{0x117B8, 0x117BC},
	{0x117F8, 0x117FC},
	{0x17000, 0x1701C},
	{0x17020, 0x170AC},
	{0x18000, 0x18050},
	{0x18054, 0x18074},
	{0x18080, 0x180D4},
	{0x180DC, 0x18104},
	{0x18108, 0x1813C},
	{0x18144, 0x18148},
	{0x18168, 0x18174},
	{0x18178, 0x18180},
	{0x181C8, 0x181E0},
	{0x181E4, 0x181E8},
	{0x181EC, 0x1820C},
	{0x1825C, 0x18280},
	{0x18284, 0x18290},
	{0x18294, 0x182A0},
	{0x18300, 0x18304},
	{0x18314, 0x18320},
	{0x18328, 0x18350},
	{0x1835C, 0x1836C},
	{0x18370, 0x18390},
	{0x18398, 0x183AC},
	{0x183BC, 0x183D8},
	{0x183DC, 0x183F4},
	{0x18400, 0x186F4},
	{0x186F8, 0x1871C},
	{0x18720, 0x18790},
	{0x19800, 0x19830},
	{0x19834, 0x19840},
	{0x19880, 0x1989C},
	{0x198A4, 0x198B0},
	{0x198BC, 0x19900},
	{0x19C00, 0x19C88},
	{0x19D00, 0x19D20},
	{0x19E00, 0x19E7C},
	{0x19E80, 0x19E94},
	{0x19E98, 0x19EAC},
	{0x19EB0, 0x19EBC},
	{0x19F70, 0x19F74},
	{0x19F80, 0x19F8C},
	{0x19FA0, 0x19FB4},
	{0x19FC0, 0x19FD8},
	{0x1A000, 0x1A200},
	{0x1A204, 0x1A210},
	{0x1A228, 0x1A22C},
	{0x1A230, 0x1A248},
	{0x1A250, 0x1A270},
	{0x1A280, 0x1A290},
	{0x1A2A0, 0x1A2A4},
	{0x1A2C0, 0x1A2EC},
	{0x1A300, 0x1A3BC},
	{0x1A3F0, 0x1A3F4},
	{0x1A3F8, 0x1A434},
	{0x1A438, 0x1A444},
	{0x1A448, 0x1A468},
	{0x1A580, 0x1A58C},
	{0x1A644, 0x1A654},
	{0x1A670, 0x1A698},
	{0x1A6AC, 0x1A6B0},
	{0x1A6D0, 0x1A6D4},
	{0x1A6EC, 0x1A70C},
	{0x1A710, 0x1A738},
	{0x1A7C0, 0x1A7D0},
	{0x1A7D4, 0x1A7D8},
	{0x1A7DC, 0x1A7E4},
	{0x1A7F0, 0x1A7F8},
	{0x1A888, 0x1A89C},
	{0x1A8A8, 0x1A8AC},
	{0x1A8C0, 0x1A8DC},
	{0x1A8F0, 0x1A8FC},
	{0x1AE04, 0x1AE08},
	{0x1AE18, 0x1AE24},
	{0x1AF80, 0x1AF8C},
	{0x1AFA0, 0x1AFB4},
	{0x1B000, 0x1B200},
	{0x1B284, 0x1B288},
	{0x1B2D0, 0x1B2D8},
	{0x1B2DC, 0x1B2EC},
	{0x1B300, 0x1B340},
	{0x1B374, 0x1B378},
	{0x1B380, 0x1B384},
	{0x1B388, 0x1B38C},
	{0x1B404, 0x1B408},
	{0x1B420, 0x1B428},
	{0x1B440, 0x1B444},
	{0x1B448, 0x1B44C},
	{0x1B450, 0x1B458},
	{0x1B45C, 0x1B468},
	{0x1B584, 0x1B58C},
	{0x1B68C, 0x1B690},
	{0x1B6AC, 0x1B6B0},
	{0x1B7F0, 0x1B7F8},
	{0x1C800, 0x1CC00},
	{0x1CE00, 0x1CE04},
	{0x1CF80, 0x1CF84},
	{0x1D200, 0x1D800},
	{0x1E000, 0x20014},
	{0x20100, 0x20124},
	{0x21400, 0x217A8},
	{0x21800, 0x21BA8},
	{0x21C00, 0x21FA8},
	{0x22000, 0x223A8},
	{0x22400, 0x227A8},
	{0x22800, 0x22BA8},
	{0x22C00, 0x22FA8},
	{0x23000, 0x233A8},
	{0x24000, 0x24034},
	{0x26000, 0x26064},
	{0x27000, 0x27024},
	{0x34000, 0x3400C},
	{0x34400, 0x3445C},
	{0x34800, 0x3485C},
	{0x34C00, 0x34C5C},
	{0x35000, 0x3505C},
	{0x35400, 0x3545C},
	{0x35800, 0x3585C},
	{0x35C00, 0x35C5C},
	{0x36000, 0x3605C},
	{0x38000, 0x38064},
	{0x38070, 0x380E0},
	{0x3A000, 0x3A074},
	{0x40000, 0x400A4},
	{0x80000, 0x8000C},
	{0x80010, 0x80020},
};

static const struct ath10k_mem_region qca6174_hw10_mem_regions[] = {
	{
		.type = ATH10K_MEM_REGION_TYPE_DRAM,
		.start = 0x400000,
		.len = 0x70000,
		.name = "DRAM",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
	{
		.type = ATH10K_MEM_REGION_TYPE_REG,

		/* RTC_SOC_BASE_ADDRESS */
		.start = 0x0,

		/* WLAN_MBOX_BASE_ADDRESS - RTC_SOC_BASE_ADDRESS */
		.len = 0x800 - 0x0,

		.name = "REG_PART1",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
	{
		.type = ATH10K_MEM_REGION_TYPE_REG,

		/* STEREO_BASE_ADDRESS */
		.start = 0x27000,

		/* USB_BASE_ADDRESS - STEREO_BASE_ADDRESS */
		.len = 0x60000 - 0x27000,

		.name = "REG_PART2",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
};

static const struct ath10k_mem_region qca6174_hw21_mem_regions[] = {
	{
		.type = ATH10K_MEM_REGION_TYPE_DRAM,
		.start = 0x400000,
		.len = 0x70000,
		.name = "DRAM",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
	{
		.type = ATH10K_MEM_REGION_TYPE_AXI,
		.start = 0xa0000,
		.len = 0x18000,
		.name = "AXI",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
	{
		.type = ATH10K_MEM_REGION_TYPE_REG,
		.start = 0x800,
		.len = 0x80020 - 0x800,
		.name = "REG_TOTAL",
		.section_table = {
			.sections = qca6174_hw21_register_sections,
			.size = ARRAY_SIZE(qca6174_hw21_register_sections),
		},
	},
};

static const struct ath10k_mem_region qca6174_hw30_mem_regions[] = {
	{
		.type = ATH10K_MEM_REGION_TYPE_DRAM,
		.start = 0x400000,
		.len = 0x90000,
		.name = "DRAM",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
	{
		.type = ATH10K_MEM_REGION_TYPE_AXI,
		.start = 0xa0000,
		.len = 0x18000,
		.name = "AXI",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
	{
		.type = ATH10K_MEM_REGION_TYPE_REG,
		.start = 0x800,
		.len = 0x80020 - 0x800,
		.name = "REG_TOTAL",
		.section_table = {
			.sections = qca6174_hw30_register_sections,
			.size = ARRAY_SIZE(qca6174_hw30_register_sections),
		},
	},

	/* IRAM dump must be put last */
	{
		.type = ATH10K_MEM_REGION_TYPE_IRAM1,
		.start = 0x00980000,
		.len = 0x00080000,
		.name = "IRAM1",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
	{
		.type = ATH10K_MEM_REGION_TYPE_IRAM2,
		.start = 0x00a00000,
		.len = 0x00040000,
		.name = "IRAM2",
		.section_table = {
			.sections = NULL,
			.size = 0,
		},
	},
};

static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
	{
		.hw_id = QCA6174_HW_1_0_VERSION,
		.region_table = {
			.regions = qca6174_hw10_mem_regions,
			.size = ARRAY_SIZE(qca6174_hw10_mem_regions),
		},
	},
	{
		.hw_id = QCA6174_HW_1_1_VERSION,
		.region_table = {
			.regions = qca6174_hw10_mem_regions,
			.size = ARRAY_SIZE(qca6174_hw10_mem_regions),
		},
	},
	{
		.hw_id = QCA6174_HW_1_3_VERSION,
		.region_table = {
			.regions = qca6174_hw10_mem_regions,
			.size = ARRAY_SIZE(qca6174_hw10_mem_regions),
		},
	},
	{
		.hw_id = QCA6174_HW_2_1_VERSION,
		.region_table = {
			.regions = qca6174_hw21_mem_regions,
			.size = ARRAY_SIZE(qca6174_hw21_mem_regions),
		},
	},
	{
		.hw_id = QCA6174_HW_3_0_VERSION,
		.region_table = {
			.regions = qca6174_hw30_mem_regions,
			.size = ARRAY_SIZE(qca6174_hw30_mem_regions),
		},
	},
	{
		.hw_id = QCA6174_HW_3_2_VERSION,
		.region_table = {
			.regions = qca6174_hw30_mem_regions,
			.size = ARRAY_SIZE(qca6174_hw30_mem_regions),
		},
	},
	{
		.hw_id = QCA9377_HW_1_1_DEV_VERSION,
		.region_table = {
			.regions = qca6174_hw30_mem_regions,
			.size = ARRAY_SIZE(qca6174_hw30_mem_regions),
		},
	},
};

static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
{
	const struct ath10k_hw_mem_layout *hw;
	const struct ath10k_mem_region *mem_region;
	size_t size = 0;
	int i;

	hw = ath10k_coredump_get_mem_layout(ar);

	if (!hw)
		return 0;

	mem_region = &hw->region_table.regions[0];

	for (i = 0; i < hw->region_table.size; i++) {
		size += mem_region->len;
		mem_region++;
	}

	/* reserve space for the headers */
	size += hw->region_table.size * sizeof(struct ath10k_dump_ram_data_hdr);

	/* make sure it is aligned 16 bytes for debug message print out */
	size = ALIGN(size, 16);

	return size;
}

const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar)
{
	int i;

	if (!test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask))
		return NULL;

	if (WARN_ON(ar->target_version == 0))
		return NULL;

	for (i = 0; i < ARRAY_SIZE(hw_mem_layouts); i++) {
		if (ar->target_version == hw_mem_layouts[i].hw_id)
			return &hw_mem_layouts[i];
	}

	return NULL;
}
EXPORT_SYMBOL(ath10k_coredump_get_mem_layout);

struct ath10k_fw_crash_data *ath10k_coredump_new(struct ath10k *ar)
{
@@ -57,6 +802,9 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
		len += sizeof(*dump_tlv) + sizeof(*ce_hdr) +
			CE_COUNT * sizeof(ce_hdr->entries[0]);

	if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask))
		len += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;

	sofar += hdr_len;

	/* This is going to get big when we start dumping FW RAM and such,
@@ -123,6 +871,16 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
			CE_COUNT * sizeof(ce_hdr->entries[0]);
	}

	/* Gather ram dump */
	if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) {
		dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
		dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_RAM_DATA);
		dump_tlv->tlv_len = cpu_to_le32(crash_data->ramdump_buf_len);
		memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
		       crash_data->ramdump_buf_len);
		sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
	}

	spin_unlock_bh(&ar->data_lock);

	return dump_data;
@@ -160,8 +918,36 @@ int ath10k_coredump_create(struct ath10k *ar)
	return 0;
}

int ath10k_coredump_register(struct ath10k *ar)
{
	struct ath10k_fw_crash_data *crash_data = ar->coredump.fw_crash_data;

	if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) {
		crash_data->ramdump_buf_len = ath10k_coredump_get_ramdump_size(ar);

		crash_data->ramdump_buf = vzalloc(crash_data->ramdump_buf_len);
		if (!crash_data->ramdump_buf)
			return -ENOMEM;
	}

	return 0;
}

void ath10k_coredump_unregister(struct ath10k *ar)
{
	struct ath10k_fw_crash_data *crash_data = ar->coredump.fw_crash_data;

	vfree(crash_data->ramdump_buf);
}

void ath10k_coredump_destroy(struct ath10k *ar)
{
	if (ar->coredump.fw_crash_data->ramdump_buf) {
		vfree(ar->coredump.fw_crash_data->ramdump_buf);
		ar->coredump.fw_crash_data->ramdump_buf = NULL;
		ar->coredump.fw_crash_data->ramdump_buf_len = 0;
	}

	vfree(ar->coredump.fw_crash_data);
	ar->coredump.fw_crash_data = NULL;
}
+93 −0
Original line number Diff line number Diff line
@@ -29,6 +29,9 @@ enum ath10k_fw_crash_dump_type {
	ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
	ATH10K_FW_CRASH_DUMP_CE_DATA = 1,

	/* contains multiple struct ath10k_dump_ram_data_hdr */
	ATH10K_FW_CRASH_DUMP_RAM_DATA = 2,

	ATH10K_FW_CRASH_DUMP_MAX,
};

@@ -99,13 +102,88 @@ struct ath10k_dump_file_data {
	u8 data[0];
} __packed;

struct ath10k_dump_ram_data_hdr {
	/* enum ath10k_mem_region_type */
	__le32 region_type;

	__le32 start;

	/* length of payload data, not including this header */
	__le32 length;

	u8 data[0];
};

/* magic number to fill the holes not copied due to sections in regions */
#define ATH10K_MAGIC_NOT_COPIED		0xAA

/* part of user space ABI */
enum ath10k_mem_region_type {
	ATH10K_MEM_REGION_TYPE_REG	= 1,
	ATH10K_MEM_REGION_TYPE_DRAM	= 2,
	ATH10K_MEM_REGION_TYPE_AXI	= 3,
	ATH10K_MEM_REGION_TYPE_IRAM1	= 4,
	ATH10K_MEM_REGION_TYPE_IRAM2	= 5,
};

/* Define a section of the region which should be copied. As not all parts
 * of the memory is possible to copy, for example some of the registers can
 * be like that, sections can be used to define what is safe to copy.
 *
 * To minimize the size of the array, the list must obey the format:
 * '{start0,stop0},{start1,stop1},{start2,stop2}....' The values below must
 * also obey to 'start0 < stop0 < start1 < stop1 < start2 < ...', otherwise
 * we may encouter error in the dump processing.
 */
struct ath10k_mem_section {
	u32 start;
	u32 end;
};

/* One region of a memory layout. If the sections field is null entire
 * region is copied. If sections is non-null only the areas specified in
 * sections are copied and rest of the areas are filled with
 * ATH10K_MAGIC_NOT_COPIED.
 */
struct ath10k_mem_region {
	enum ath10k_mem_region_type type;
	u32 start;
	u32 len;

	const char *name;

	struct {
		const struct ath10k_mem_section *sections;
		u32 size;
	} section_table;
};

/* Contains the memory layout of a hardware version identified with the
 * hardware id, split into regions.
 */
struct ath10k_hw_mem_layout {
	u32 hw_id;

	struct {
		const struct ath10k_mem_region *regions;
		int size;
	} region_table;
};

/* FIXME: where to put this? */
extern unsigned long ath10k_coredump_mask;

#ifdef CONFIG_DEV_COREDUMP

int ath10k_coredump_submit(struct ath10k *ar);
struct ath10k_fw_crash_data *ath10k_coredump_new(struct ath10k *ar);
int ath10k_coredump_create(struct ath10k *ar);
int ath10k_coredump_register(struct ath10k *ar);
void ath10k_coredump_unregister(struct ath10k *ar);
void ath10k_coredump_destroy(struct ath10k *ar);

const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar);

#else /* CONFIG_DEV_COREDUMP */

static inline int ath10k_coredump_submit(struct ath10k *ar)
@@ -123,10 +201,25 @@ static inline int ath10k_coredump_create(struct ath10k *ar)
	return 0;
}

static inline int ath10k_coredump_register(struct ath10k *ar)
{
	return 0;
}

static inline void ath10k_coredump_unregister(struct ath10k *ar)
{
}

static inline void ath10k_coredump_destroy(struct ath10k *ar)
{
}

static inline const struct ath10k_hw_mem_layout *
ath10k_coredump_get_mem_layout(struct ath10k *ar)
{
	return NULL;
}

#endif /* CONFIG_DEV_COREDUMP */

#endif /* _COREDUMP_H_ */
+1 −0
Original line number Diff line number Diff line
@@ -888,6 +888,7 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
#define PCIE_INTR_CLR_ADDRESS			ar->regs->pcie_intr_clr_address
#define SCRATCH_3_ADDRESS			ar->regs->scratch_3_address
#define CPU_INTR_ADDRESS			0x0010
#define FW_RAM_CONFIG_ADDRESS			0x0018

#define CCNT_TO_MSEC(ar, x) ((x) / ar->hw_params.channel_counters_freq_hz)

Loading