rtw88: add dump firmware fifo support

Rtw88 currently has a function to dump reserved page section of the
firmware fifo. Reserved page is just part of the firmware fifo, there
are multiple sections in the firmware fifo for different usages, such as
firmware rx fifo and tx fifo.
This commit adds a function to check not only the reserved page section
but also other parts of the firmware fifo. In addition, we need to dump
firmware fifo to dump the debug log message if firmware crashes.

Signed-off-by: Tzu-En Huang <tehuang@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200925061219.23754-4-tehuang@realtek.com
This commit is contained in:
Tzu-En Huang 2020-09-25 14:12:17 +08:00 committed by Kalle Valo
parent 5c831644e1
commit 0fbc2f0f34
6 changed files with 85 additions and 18 deletions

View File

@ -229,7 +229,8 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v)
if (!buf)
return -ENOMEM;
ret = rtw_dump_drv_rsvd_page(rtwdev, offset, buf_size, (u32 *)buf);
ret = rtw_fw_dump_fifo(rtwdev, RTW_FW_FIFO_SEL_RSVD_PAGE, offset,
buf_size, (u32 *)buf);
if (ret) {
rtw_err(rtwdev, "failed to dump rsvd page\n");
vfree(buf);

View File

@ -1413,29 +1413,16 @@ int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev)
return ret;
}
int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
u32 offset, u32 size, u32 *buf)
static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size,
u32 *buf, u32 residue, u16 start_pg)
{
struct rtw_fifo_conf *fifo = &rtwdev->fifo;
u32 residue, i;
u16 start_pg;
u32 i;
u16 idx = 0;
u16 ctl;
u8 rcr;
if (size & 0x3) {
rtw_warn(rtwdev, "should be 4-byte aligned\n");
return -EINVAL;
}
offset += fifo->rsvd_boundary << TX_PAGE_SIZE_SHIFT;
residue = offset & (FIFO_PAGE_SIZE - 1);
start_pg = offset >> FIFO_PAGE_SIZE_SHIFT;
start_pg += RSVD_PAGE_START_ADDR;
rcr = rtw_read8(rtwdev, REG_RCR + 2);
ctl = rtw_read16(rtwdev, REG_PKTBUF_DBG_CTRL) & 0xf000;
/* disable rx clock gate */
rtw_write8(rtwdev, REG_RCR, rcr | BIT(3));
@ -1457,6 +1444,64 @@ int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
out:
rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, ctl);
rtw_write8(rtwdev, REG_RCR + 2, rcr);
}
static void rtw_fw_read_fifo(struct rtw_dev *rtwdev, enum rtw_fw_fifo_sel sel,
u32 offset, u32 size, u32 *buf)
{
struct rtw_chip_info *chip = rtwdev->chip;
u32 start_pg, residue;
if (sel >= RTW_FW_FIFO_MAX) {
rtw_dbg(rtwdev, RTW_DBG_FW, "wrong fw fifo sel\n");
return;
}
if (sel == RTW_FW_FIFO_SEL_RSVD_PAGE)
offset += rtwdev->fifo.rsvd_boundary << TX_PAGE_SIZE_SHIFT;
residue = offset & (FIFO_PAGE_SIZE - 1);
start_pg = (offset >> FIFO_PAGE_SIZE_SHIFT) + chip->fw_fifo_addr[sel];
rtw_fw_read_fifo_page(rtwdev, offset, size, buf, residue, start_pg);
}
static bool rtw_fw_dump_check_size(struct rtw_dev *rtwdev,
enum rtw_fw_fifo_sel sel,
u32 start_addr, u32 size)
{
switch (sel) {
case RTW_FW_FIFO_SEL_TX:
case RTW_FW_FIFO_SEL_RX:
if ((start_addr + size) > rtwdev->chip->fw_fifo_addr[sel])
return false;
/*fall through*/
default:
return true;
}
}
int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
u32 *buffer)
{
if (!rtwdev->chip->fw_fifo_addr) {
rtw_dbg(rtwdev, RTW_DBG_FW, "chip not support dump fw fifo\n");
return -ENOTSUPP;
}
if (size == 0 || !buffer)
return -EINVAL;
if (size & 0x3) {
rtw_dbg(rtwdev, RTW_DBG_FW, "not 4byte alignment\n");
return -EINVAL;
}
if (!rtw_fw_dump_check_size(rtwdev, fifo_sel, addr, size)) {
rtw_dbg(rtwdev, RTW_DBG_FW, "fw fifo dump size overflow\n");
return -EINVAL;
}
rtw_fw_read_fifo(rtwdev, fifo_sel, addr, size, buffer);
return 0;
}

View File

@ -16,7 +16,6 @@
#define FIFO_PAGE_SIZE_SHIFT 12
#define FIFO_PAGE_SIZE 4096
#define RSVD_PAGE_START_ADDR 0x780
#define FIFO_DUMP_ADDR 0x8000
#define DLFW_PAGE_SIZE_SHIFT_LEGACY 12
@ -565,5 +564,7 @@ void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev,
void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable);
void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c);
void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev);
int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
u32 *buffer);
#endif

View File

@ -1083,6 +1083,17 @@ enum rtw_wlan_cpu {
RTW_WCPU_11N,
};
enum rtw_fw_fifo_sel {
RTW_FW_FIFO_SEL_TX,
RTW_FW_FIFO_SEL_RX,
RTW_FW_FIFO_SEL_RSVD_PAGE,
RTW_FW_FIFO_SEL_REPORT,
RTW_FW_FIFO_SEL_LLT,
RTW_FW_FIFO_SEL_RXBUF_FW,
RTW_FW_FIFO_MAX,
};
/* hardware configuration for each IC */
struct rtw_chip_info {
struct rtw_chip_ops *ops;
@ -1099,6 +1110,7 @@ struct rtw_chip_info {
u32 ptct_efuse_size;
u32 txff_size;
u32 rxff_size;
u32 fw_rxff_size;
u8 band;
u8 page_size;
u8 csi_buf_pg_num;
@ -1109,6 +1121,8 @@ struct rtw_chip_info {
bool rx_ldpc;
u8 max_power_index;
u16 fw_fifo_addr[RTW_FW_FIFO_MAX];
bool ht_supported;
bool vht_supported;
u8 lps_deep_mode_supported;

View File

@ -2442,6 +2442,7 @@ struct rtw_chip_info rtw8822b_hw_spec = {
.ptct_efuse_size = 96,
.txff_size = 262144,
.rxff_size = 24576,
.fw_rxff_size = 12288,
.txgi_factor = 1,
.is_pwr_by_rate_dec = true,
.max_power_index = 0x3f,
@ -2504,6 +2505,8 @@ struct rtw_chip_info rtw8822b_hw_spec = {
.coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8822b),
.coex_info_hw_regs = coex_info_hw_regs_8822b,
.fw_fifo_addr = {0x780, 0x700, 0x780, 0x660, 0x650, 0x680},
};
EXPORT_SYMBOL(rtw8822b_hw_spec);

View File

@ -4294,6 +4294,7 @@ struct rtw_chip_info rtw8822c_hw_spec = {
.ptct_efuse_size = 124,
.txff_size = 262144,
.rxff_size = 24576,
.fw_rxff_size = 12288,
.txgi_factor = 2,
.is_pwr_by_rate_dec = false,
.max_power_index = 0x7f,
@ -4364,6 +4365,8 @@ struct rtw_chip_info rtw8822c_hw_spec = {
.coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8822c),
.coex_info_hw_regs = coex_info_hw_regs_8822c,
.fw_fifo_addr = {0x780, 0x700, 0x780, 0x660, 0x650, 0x680},
};
EXPORT_SYMBOL(rtw8822c_hw_spec);