/* * DebugFS code for XRadio drivers * * Copyright (c) 2013 * Xradio Technology Co., Ltd. * * 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. */ #ifndef XRADIO_DEBUG_H_INCLUDED #define XRADIO_DEBUG_H_INCLUDED #include "itp.h" /* Message always need to be present even in release version. */ #define XRADIO_DBG_ALWY 0x01 /* Error message to report an error, it can hardly works. */ #define XRADIO_DBG_ERROR 0x02 /* Warning message to inform us of something unnormal or * something very important, but it still work. */ #define XRADIO_DBG_WARN 0x04 /* Important message we need to know in unstable version. */ #define XRADIO_DBG_NIY 0x08 /* Normal message just for debug in developing stage. */ #define XRADIO_DBG_MSG 0x10 /* Trace of functions, for sequence of functions called. Normally, * don't set this level because there are too more print. */ #define XRADIO_DBG_TRC 0x20 #define XRADIO_DBG_LEVEL 0xFF /* for host debuglevel*/ extern u8 dbg_common ; extern u8 dbg_sbus ; extern u8 dbg_bh ; extern u8 dbg_txrx ; extern u8 dbg_wsm ; extern u8 dbg_sta ; extern u8 dbg_scan ; extern u8 dbg_ap ; extern u8 dbg_pm ; extern u8 dbg_itp ; extern u8 dbg_etf ; extern u8 dbg_logfile; /*for sdio clk debug*/ extern u32 dbg_sdio_clk; /*hang driver for debug when error occurs.*/ #ifdef ERROR_HANG_DRIVER extern u8 error_hang_driver; #endif /* for ps debug */ extern u8 ps_disable; extern u8 ps_idleperiod; extern u8 ps_changeperiod; /* info of bh thread*/ extern u32 irq_count; extern u32 int_miss_cnt; extern u32 fix_miss_cnt; extern u32 next_rx_cnt; extern u32 rx_total_cnt; extern u32 tx_total_cnt; extern u32 tx_buf_limit; extern u32 tx_limit; extern u32 tx_rx_idle; extern u32 bh_idle; extern u32 queue_lock_cnt; extern u32 overfull_lock_cnt; extern u32 policy_lock_cnt; extern u32 dbg_txconfirm[32]; extern int tx_burst_limit; extern u32 dbg_tx_delay_min; extern u32 dbg_tx_delay_max; extern u32 dbg_tx_media_delay[16]; extern u32 sdio_reg_cnt1; extern u32 sdio_reg_cnt2; extern u32 sdio_reg_cnt3; extern u32 sdio_reg_cnt4; extern u32 sdio_reg_cnt5; extern u32 sdio_reg_cnt6; extern u32 tx_limit_cnt1; extern u32 tx_limit_cnt2; extern u32 tx_limit_cnt3; extern u32 tx_limit_cnt4; extern u32 tx_limit_cnt5; extern u32 tx_limit_cnt6; /* time info of bh tx and rx */ #define PERF_INFO_TEST 0 #if PERF_INFO_TEST #define TEST_GETTIME 0 struct perf_info { u32 count; u32 totaltime; u32 totalsize; u32 min_time; u32 max_time; }; extern struct perf_info data_tx; extern struct perf_info data_rx; extern struct perf_info bh_others; extern struct perf_info bh_wait; extern struct perf_info sdio_reg; extern struct perf_info prepare_tx; extern struct perf_info sdio_write; extern struct perf_info dev_wake; extern struct perf_info prepare_rx; extern struct perf_info sdio_read; extern struct perf_info handle_rx; #ifdef BH_PROC_THREAD extern struct perf_info get_item; extern struct perf_info wake_proc; extern struct perf_info proc_rx; extern struct perf_info proc_tx; extern struct perf_info proc_wait; #endif extern struct perf_info ind_rx; extern struct perf_info mac_rx; extern struct perf_info mac_tx; #if TEST_GETTIME extern struct perf_info get_time; #define PERF_INFO_GETTIME(t) do { \ do_gettimeofday(t); \ perf_info_stamp(t, &get_time, 0, NULL); \ } while (0) #else #define PERF_INFO_GETTIME(t) do_gettimeofday(t) #endif #define PERF_INFO_STAMP(t, p, s) perf_info_stamp(t, p, s, NULL) #define PERF_INFO_STAMP_GET(t, p, s, g) perf_info_stamp(t, p, s, g) #define PERF_INFO_STAMP_UPDATE(t, p, s) perf_info_stamp(t, p, s, t) #include #include static inline void perf_info_stamp(struct timeval *oldtime, struct perf_info *info, u32 size, struct timeval *gettime) { u32 time_int; struct timeval newtime; do_gettimeofday(&newtime); time_int = (newtime.tv_sec - oldtime->tv_sec) * 1000000 + \ (long)(newtime.tv_usec - oldtime->tv_usec); if (time_int <= info->min_time) info->min_time = time_int; if (time_int > info->max_time) info->max_time = time_int; info->totalsize += size; info->totaltime += time_int; info->count++; /*do_gettimeofday consume 0.5us*/ if (gettime != NULL) { memcpy(gettime, &newtime, sizeof(newtime)); } } #else /* #if PERF_INFO_TEST */ #define PERF_INFO_GETTIME(t) #define PERF_INFO_STAMP(t, p, s) #define PERF_INFO_STAMP_GET(t, p, s, g) #define PERF_INFO_STAMP_UPDATE(t, p, s) #endif /* #if PERF_INFO_TEST */ #ifdef SUPPORT_HT40 extern u32 TxedHtofdmRateMap[4][8]; extern u32 TxedLegacyRateMap[2][8]; extern u32 RxedHtofdmRateMap[4][8]; extern u32 RxedLegacyRateMap[2][8]; #else extern u32 TxedRateIdx_Map[24]; extern u32 RxedRateIdx_Map[24]; #endif #if (SUPPORT_EPTA) extern u32 epta_stat_dbg_ctrl; #endif #define WSM_DUMP_MAX_SIZE 20 #if defined(CONFIG_XRADIO_DEBUG) #define DGB_LOG_FILE 0 /*Don't log more than 500byte once.*/ #define DGB_XRADIO_QC 1 /*Enable this only in QC test.*/ #define DGB_XRADIO_HWT 0 /*Only in hardware test with special fw.*/ #define DBG_XRADIO_HIF 1 #define DBG_PAS_RAM 1 /*Enabel this only when PAS RAM CHECK is needed.*/ #define DBG_AHB_RAM 1 /*Enabel this only when AHB RAM CHECK is needed.*/ #else #define DGB_LOG_FILE 0 /*Don't log more than 500byte once.*/ #define DGB_XRADIO_QC 0 /*Enable this only in QC test.*/ #define DGB_XRADIO_HWT 0 /*Only in hardware test with special fw.*/ #define DBG_XRADIO_HIF 0 #define DBG_PAS_RAM 0 #define DBG_AHB_RAM 0 #endif #if (DBG_XRADIO_HIF) | (DBG_PAS_RAM) #define WRITE_READ_MAX_LEN 0x1000 #define PAS_RAM_START_ADDR 0x09000000 #define PAS_RAM_END_ADDR 0X0901ffff #endif #if (DBG_AHB_RAM) #define AHB_WRITE_MAX_LEN 0x1000 #define AHB_READ_MAX_LEN 0x0004 #define AHB_RAM_START_ADDR 0x08000000 #define AHB_RAM_END_ADDR 0X08007fff #endif #if DGB_LOG_FILE #define DGB_LOG_BUF_LEN 1500 #define DGB_LOG_PATH0 "/data/xradio_err.log" extern u8 log_buffer[DGB_LOG_BUF_LEN]; extern u16 log_pos; int xradio_logfile(char *buffer, int buf_len, u8 b_time); #define LOG_FILE(b_time, msg) xradio_logfile(msg, -1, b_time) #define LOG_FILE_VARS(b_time, ...) do { \ if (!log_pos) \ memset(log_buffer, 0, DGB_LOG_BUF_LEN); \ if (log_pos <= 1000) \ log_pos += sprintf((char *)(log_buffer+log_pos), __VA_ARGS__); \ if (xradio_logfile(log_buffer, log_pos, b_time) >= 0) \ log_pos = 0; \ } while (0) #else /*DGB_LOG_FILE disable*/ #define LOG_FILE(b_time, msg) #define LOG_FILE_VARS(b_time, ...) #endif #if (defined(CONFIG_XRADIO_DEBUG)) /****************************** debug version *******************************/ #if (defined(CONFIG_XRADIO_DUMP_ON_ERROR)) #define SYS_BUG(c) BUG_ON(c) #define SYS_WARN(c) WARN_ON(c) #else #define SYS_BUG(c) WARN_ON(c) #define SYS_WARN(c) WARN_ON(c) #endif #define xradio_dbg(level, ...) \ do { \ if ((level) & dbg_common & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[XRADIO_ERR] " __VA_ARGS__); \ else if ((level) & dbg_common & XRADIO_DBG_WARN) \ printk(KERN_ERR "[XRADIO_WRN] " __VA_ARGS__); \ else if ((level) & dbg_common) \ printk(KERN_ERR "[XRADIO] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[XRADIO_ERR] " __VA_ARGS__); \ } while (0) #define sbus_printk(level, ...) \ do { \ if ((level) & dbg_sbus & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[SBUS_ERR] " __VA_ARGS__); \ else if ((level) & dbg_sbus & XRADIO_DBG_WARN) \ printk(KERN_ERR "[SBUS_WRN] " __VA_ARGS__); \ else if ((level) & dbg_sbus) \ printk(KERN_ERR "[SBUS] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[SBUS_ERR] " __VA_ARGS__); \ } while (0) #define txrx_printk(level, ...) \ do { \ if ((level) & dbg_txrx & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[TXRX_ERR] " __VA_ARGS__); \ else if ((level) & dbg_txrx & XRADIO_DBG_WARN) \ printk(KERN_ERR "[TXRX_WRN] " __VA_ARGS__); \ else if ((level) & dbg_txrx) \ printk(KERN_ERR "[TXRX] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[TXRX_ERR] " __VA_ARGS__); \ } while (0) #define bh_printk(level, ...) \ do { \ if ((level) & dbg_bh & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[BH_ERR] " __VA_ARGS__); \ else if ((level) & dbg_bh & XRADIO_DBG_WARN) \ printk(KERN_ERR "[BH_WRN] " __VA_ARGS__); \ else if ((level) & dbg_bh) \ printk(KERN_ERR "[BH] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[BH_ERR] " __VA_ARGS__); \ } while (0) #define wsm_printk(level, ...) \ do { \ if ((level) & dbg_wsm & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[WSM_ERR] " __VA_ARGS__); \ else if ((level) & dbg_wsm & XRADIO_DBG_WARN) \ printk(KERN_ERR "[WSM_WRN] " __VA_ARGS__); \ else if ((level) & dbg_wsm) \ printk(KERN_ERR "[WSM] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[WSM_ERR] " __VA_ARGS__); \ } while (0) #define sta_printk(level, ...) \ do { \ if ((level) & dbg_sta & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[STA_ERR] " __VA_ARGS__); \ else if ((level) & dbg_sta & XRADIO_DBG_WARN) \ printk(KERN_ERR "[STA_WRN] " __VA_ARGS__); \ else if ((level) & dbg_sta) \ printk(KERN_ERR "[STA] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[STA_ERR] " __VA_ARGS__); \ } while (0) #define scan_printk(level, ...) \ do { \ if ((level) & dbg_scan & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[SCAN_ERR] " __VA_ARGS__); \ else if ((level) & dbg_scan & XRADIO_DBG_WARN) \ printk(KERN_ERR "[SCAN_WRN] " __VA_ARGS__); \ else if ((level) & dbg_scan) \ printk(KERN_ERR "[SCAN] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[SCAN_ERR] " __VA_ARGS__); \ } while (0) #define ap_printk(level, ...) \ do { \ if ((level) & dbg_ap & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[AP_ERR] " __VA_ARGS__); \ else if ((level) & dbg_ap & XRADIO_DBG_WARN) \ printk(KERN_ERR "[AP_WRN] " __VA_ARGS__); \ else if ((level) & dbg_ap) \ printk(KERN_ERR "[AP] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[AP_ERR] " __VA_ARGS__); \ } while (0) #define pm_printk(level, ...) \ do { \ if ((level) & dbg_pm & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[PM_ERR] " __VA_ARGS__); \ else if ((level) & dbg_pm & XRADIO_DBG_WARN) \ printk(KERN_ERR "[PM_WRN] " __VA_ARGS__); \ else if ((level) & dbg_pm) \ printk(KERN_ERR "[PM] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[PM_ERR] " __VA_ARGS__); \ } while (0) #define itp_printk(level, ...) \ do { \ if ((level) & dbg_itp & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[ITP_ERR] " __VA_ARGS__); \ else if ((level) & dbg_itp & XRADIO_DBG_WARN) \ printk(KERN_ERR "[ITP_WRN] " __VA_ARGS__); \ else if ((level) & dbg_itp) \ printk(KERN_ERR "[ITP] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[ITP_ERR] " __VA_ARGS__); \ } while (0) #define etf_printk(level, ...) \ do { \ if ((level) & dbg_etf & XRADIO_DBG_ERROR) \ printk(KERN_ERR "[ETF_ERR] " __VA_ARGS__); \ else if ((level) & dbg_etf & XRADIO_DBG_WARN) \ printk(KERN_ERR "[ETF_WRN] " __VA_ARGS__); \ else if ((level) & dbg_etf) \ printk(KERN_ERR "[ETF] " __VA_ARGS__); \ if ((level) & dbg_logfile) \ LOG_FILE_VARS(((level)&XRADIO_DBG_ERROR), \ "[ETF_ERR] " __VA_ARGS__); \ } while (0) #define DBG_FUN_LINE printk(KERN_ERR "%s,line=%d", __func__, __LINE__) #define PARAM_CHECK_FALSE(p) \ do { \ if (!p) \ DBG_FUN_LINE; \ } while (0) #define PARAM_CHECK_TRUE(p) \ do { \ if (p) \ DBG_FUN_LINE; \ } while (0) /*interfaces to debug packet's information.*/ /*for802.11*/ #define PF_CTRL 0x0001 #define PF_MGMT 0x0002 #define PF_DATA 0x0004 #define PF_SCAN 0x0008 /*for ip data*/ #define PF_TCP 0x0010 #define PF_UDP 0x0020 #define PF_DHCP 0x0040 #define PF_ICMP 0x0080 /*for special frames or info.*/ #define PF_8021X 0x0100 /*action frames*/ #define PF_MAC_SN 0x0200 /*mac seq*/ #define PF_OWNMAC 0x0400 /*TA in Tx, RA in Rx.*/ #define PF_SA_DA 0x0800 /*SA, DA for Ethernet.*/ #define PF_MACADDR 0x1000 /*RA in Tx, TA in Rx.*/ #define PF_IPADDR 0x2000 /*ip address of ip packets.*/ #define PF_UNKNWN 0x4000 /*print frames of unknown flag.*/ #define PF_RX 0x8000 /*0:TX, 1:RX. So, need to add PF_RX in Rx path.*/ void xradio_parse_frame(u8 *mac_data, u8 iv_len, u16 flags, u8 if_id); #if (DGB_XRADIO_HWT) /*hardware test*/ typedef struct HWT_PARAMETERS_S { u16 Msglen; u16 MsgID; u16 TestID; u16 Params; u16 Datalen; u16 Data; } HWT_PARAMETERS; int get_hwt_hif_tx(struct xradio_common *hw_priv, u8 **data, size_t *tx_len, int *burst, int *vif_selected); #endif /*DGB_XRADIO_HWT*/ #else /****************************** release version *******************************/ #define SYS_BUG(c) WARN_ON(c) #define SYS_WARN(c) WARN_ON(c) #define xradio_dbg(level, ...) #define sbus_printk(level, ...) #define txrx_printk(level, ...) #define bh_printk(level, ...) #define wsm_printk(level, ...) #define sta_printk(level, ...) #define scan_printk(level, ...) #define ap_printk(level, ...) #define pm_printk(level, ...) #define itp_printk(level, ...) #define DBG_FUN_LINE #define PARAM_CHECK_FALSE #define PARAM_CHECK_TRUE static inline void xradio_parse_frame(u8 *mac_data, u8 iv_len, u16 flags, u8 if_id) { } #endif /*CONFIG_XRADIO_DEBUG*/ #ifdef CONFIG_XRADIO_DEBUGFS /************************* debugfs version *****************************/ struct xradio_debug_common { struct dentry *debugfs_phy; int tx_cache_miss; int tx_burst; int rx_burst; int ba_cnt; int ba_acc; int ba_cnt_rx; int ba_acc_rx; #ifdef CONFIG_XRADIO_ITP struct xradio_itp itp; #endif /* CONFIG_XRADIO_ITP */ }; struct xradio_debug_priv { struct dentry *debugfs_phy; int tx; int tx_agg; int rx; int rx_agg; int tx_multi; int tx_multi_frames; int tx_align; int tx_ttl; }; #define DBG_INT_ADD(count) (++count) #define DBG_ARRY_ADD(a, i) (++a[i]) #ifdef ERROR_HANG_DRIVER void xradio_hang_driver_for_debug(struct xradio_common *hw_priv, int error); #endif int xradio_debug_init_common(struct xradio_common *hw_priv); int xradio_debug_init_priv(struct xradio_common *hw_priv, struct xradio_vif *priv); void xradio_debug_release_common(struct xradio_common *hw_priv); void xradio_debug_release_priv(struct xradio_vif *priv); void xradio_debug_tx_delay(u32 media_delay, u32 queue_delay); static inline void xradio_debug_txed(struct xradio_vif *priv) { if (!priv->debug) return; ++priv->debug->tx; } static inline void xradio_debug_txed_agg(struct xradio_vif *priv) { if (!priv->debug) return; ++priv->debug->tx_agg; } static inline void xradio_debug_txed_multi(struct xradio_vif *priv, int count) { if (!priv->debug) return; ++priv->debug->tx_multi; priv->debug->tx_multi_frames += count; } static inline void xradio_debug_rxed(struct xradio_vif *priv) { if (!priv->debug) return; ++priv->debug->rx; } static inline void xradio_debug_rxed_agg(struct xradio_vif *priv) { if (!priv->debug) return; ++priv->debug->rx_agg; } static inline void xradio_debug_tx_cache_miss(struct xradio_common *hw_priv) { if (!hw_priv->debug) return; ++hw_priv->debug->tx_cache_miss; } static inline void xradio_debug_tx_align(struct xradio_vif *priv) { if (!priv->debug) return; ++priv->debug->tx_align; } static inline void xradio_debug_tx_ttl(struct xradio_vif *priv) { if (!priv->debug) return; ++priv->debug->tx_ttl; } static inline void xradio_debug_tx_burst(struct xradio_common *hw_priv) { if (!hw_priv->debug) return; ++hw_priv->debug->tx_burst; } static inline void xradio_debug_rx_burst(struct xradio_common *hw_priv) { if (!hw_priv->debug) return; ++hw_priv->debug->rx_burst; } static inline void xradio_debug_ba(struct xradio_common *hw_priv, int ba_cnt, int ba_acc, int ba_cnt_rx, int ba_acc_rx) { if (!hw_priv->debug) return; hw_priv->debug->ba_cnt = ba_cnt; hw_priv->debug->ba_acc = ba_acc; hw_priv->debug->ba_cnt_rx = ba_cnt_rx; hw_priv->debug->ba_acc_rx = ba_acc_rx; } int xradio_print_fw_version(struct xradio_common *hw_priv, u8 *buf, size_t len); int xradio_host_dbg_init(void); void xradio_host_dbg_deinit(void); #else /* CONFIG_XRADIO_DEBUGFS */ /************************ no debugfs version **************************/ #define DBG_INT_ADD(count) #define DBG_ARRY_ADD(a, i) static inline int xradio_debug_init_common(struct xradio_common *hw_priv) { return 0; } static inline int xradio_debug_init_priv(struct xradio_common *hw_priv, struct xradio_vif *priv) { return 0; } static inline void xradio_debug_release_common(struct xradio_common *hw_priv) { } static inline void xradio_debug_release_priv(struct xradio_vif *priv) { } static inline void xradio_debug_txed(struct xradio_vif *priv) { } static inline void xradio_debug_txed_agg(struct xradio_vif *priv) { } static inline void xradio_debug_txed_multi(struct xradio_vif *priv, int count) { } static inline void xradio_debug_rxed(struct xradio_vif *priv) { } static inline void xradio_debug_rxed_agg(struct xradio_vif *priv) { } static inline void xradio_debug_tx_cache_miss(struct xradio_common *hw_priv) { } static inline void xradio_debug_tx_align(struct xradio_vif *priv) { } static inline void xradio_debug_tx_ttl(struct xradio_vif *priv) { } static inline void xradio_debug_tx_burst(struct xradio_common *hw_priv) { } static inline void xradio_debug_rx_burst(struct xradio_common *hw_priv) { } static inline void xradio_debug_ba(struct xradio_common *hw_priv, int ba_cnt, int ba_acc, int ba_cnt_rx, int ba_acc_rx) { } static inline void xradio_debug_tx_delay(u32 media_delay, u32 queue_delay) { } static inline int xradio_print_fw_version(struct xradio_vif *priv, u8 *buf, size_t len) { return 0; } static inline void xradio_hang_driver_for_debug(struct xradio_common *hw_priv, int error) { return 0; } static inline int xradio_host_dbg_init(void) { return 0; } static inline void xradio_host_dbg_deinit(void) { } #endif /* CONFIG_XRADIO_DEBUGFS */ #endif /* XRADIO_DEBUG_H_INCLUDED */