| /* |
| * Copyright (C) 2017 MediaTek Inc. |
| * |
| * This program is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #ifndef __MT_UFS_DEUBG__ |
| #define __MT_UFS_DEUBG__ |
| |
| #include "ufs-mtk.h" |
| |
| struct ufs_cmd_hlist_struct { |
| enum ufs_trace_event event; |
| u8 opcode; |
| u8 lun; |
| u8 crypted; |
| u8 keyslot; |
| pid_t pid; |
| u32 cpu; |
| u32 tag; |
| u32 transfer_len; |
| sector_t lba; |
| u64 time; |
| u64 duration; |
| struct request *rq; |
| unsigned long long ppn; |
| u32 region; |
| u32 subregion; |
| u32 resv; |
| }; |
| |
| /* |
| * snprintf may return a value of size or "more" to indicate |
| * that the output was truncated, thus be careful of "more" |
| * case. |
| */ |
| #define SPREAD_PRINTF(buff, size, evt, fmt, args...) \ |
| do { \ |
| if (buff && size && *(size)) { \ |
| unsigned long var = snprintf(*(buff), *(size), fmt, ##args); \ |
| if (var > 0) { \ |
| if (var > *(size)) \ |
| var = *(size); \ |
| *(size) -= var; \ |
| *(buff) += var; \ |
| } \ |
| } \ |
| if (evt) \ |
| seq_printf(evt, fmt, ##args); \ |
| if (!buff && !evt) { \ |
| pr_info(fmt, ##args); \ |
| } \ |
| } while (0) |
| |
| #define SPREAD_DEV_PRINTF(buff, size, evt, dev, fmt, args...) \ |
| do { \ |
| if (buff && size && *(size)) { \ |
| unsigned long var = snprintf(*(buff), *(size), fmt, ##args); \ |
| if (var > 0) { \ |
| *(size) -= var; \ |
| *(buff) += var; \ |
| } \ |
| } \ |
| if (evt) \ |
| seq_printf(evt, fmt, ##args); \ |
| if (!buff && !evt) { \ |
| dev_info(dev, fmt, ##args); \ |
| } \ |
| } while (0) |
| |
| enum { |
| UFS_CMDS_DUMP = 0, |
| UFS_GET_PWR_MODE = 1, |
| UFS_DUMP_HEALTH_DESCRIPTOR = 2, |
| UFS_CMD_HIST_BEGIN = 3, |
| UFS_CMD_HIST_STOP = 4, |
| UFS_CMD_UNKNOWN |
| }; |
| |
| #define UFS_PRINFO_PROC_MSG(evt, fmt, args...) \ |
| do { \ |
| if (evt == NULL) { \ |
| pr_info(fmt, ##args); \ |
| } \ |
| else { \ |
| seq_printf(evt, fmt, ##args); \ |
| } \ |
| } while (0) |
| |
| #define UFS_DEVINFO_PROC_MSG(evt, dev, fmt, args...) \ |
| do { \ |
| if (evt == NULL) { \ |
| dev_info(dev, fmt, ##args); \ |
| } \ |
| else { \ |
| seq_printf(evt, fmt, ##args); \ |
| } \ |
| } while (0) |
| |
| |
| #define UFS_PRDBG_PROC_MSG(evt, fmt, args...) \ |
| do { \ |
| if (evt == NULL) { \ |
| pr_dbg(fmt, ##args); \ |
| } \ |
| else { \ |
| seq_printf(evt, fmt, ##args); \ |
| } \ |
| } while (0) |
| |
| #define UFS_DEVDBG_PROC_MSG(evt, dev, fmt, args...) \ |
| do { \ |
| if (evt == NULL) { \ |
| dev_dbg(dev, fmt, ##args); \ |
| } \ |
| else { \ |
| seq_printf(evt, fmt, ##args); \ |
| } \ |
| } while (0) |
| |
| int ufs_mtk_debug_proc_init(struct ufs_hba *hba); |
| void ufs_mtk_dbg_add_trace(struct ufs_hba *hba, |
| enum ufs_trace_event event, u32 tag, |
| u8 lun, u32 transfer_len, sector_t lba, u8 opcode, |
| unsigned long long ppn, u32 region, u32 subregion, u32 resv); |
| void ufs_mtk_dbg_stop_trace(struct ufs_hba *hba); |
| void ufs_mtk_dbg_start_trace(struct ufs_hba *hba); |
| void ufs_mtk_dbg_hang_detect_dump(void); |
| void ufs_mtk_dbg_proc_dump(struct seq_file *m); |
| void ufs_mtk_dme_cmd_log(struct ufs_hba *hba, struct uic_command *ucmd, |
| enum ufs_trace_event event); |
| void ufs_mtk_dbg_dump_trace(char **buff, unsigned long *size, |
| u32 latest_cnt, struct seq_file *m); |
| |
| #endif |