1d27a76faSLarry Finger // SPDX-License-Identifier: GPL-2.0 2d27a76faSLarry Finger /* Copyright(c) 2009-2012 Realtek Corporation.*/ 3f1d2b4d3SLarry Finger 4f1d2b4d3SLarry Finger #include "wifi.h" 5610247f4SPing-Ke Shih #include "cam.h" 6f1d2b4d3SLarry Finger 7f1d2b4d3SLarry Finger #include <linux/moduleparam.h> 8610247f4SPing-Ke Shih #include <linux/vmalloc.h> 9f1d2b4d3SLarry Finger 109ce22191SJoe Perches #ifdef CONFIG_RTLWIFI_DEBUG 11102e295eSLarry Finger void _rtl_dbg_print(struct rtl_priv *rtlpriv, u64 comp, int level, 12102e295eSLarry Finger const char *fmt, ...) 13102e295eSLarry Finger { 14c34df318SLarry Finger if (unlikely((comp & rtlpriv->cfg->mod_params->debug_mask) && 15d63589cbSFrank A. Cancio Bello level <= rtlpriv->cfg->mod_params->debug_level)) { 16102e295eSLarry Finger struct va_format vaf; 17102e295eSLarry Finger va_list args; 18102e295eSLarry Finger 19102e295eSLarry Finger va_start(args, fmt); 20102e295eSLarry Finger 21102e295eSLarry Finger vaf.fmt = fmt; 22102e295eSLarry Finger vaf.va = &args; 23102e295eSLarry Finger 24c34df318SLarry Finger pr_info("%pV", &vaf); 25102e295eSLarry Finger 26102e295eSLarry Finger va_end(args); 27102e295eSLarry Finger } 28102e295eSLarry Finger } 29102e295eSLarry Finger EXPORT_SYMBOL_GPL(_rtl_dbg_print); 30102e295eSLarry Finger 31102e295eSLarry Finger void _rtl_dbg_print_data(struct rtl_priv *rtlpriv, u64 comp, int level, 32102e295eSLarry Finger const char *titlestring, 33102e295eSLarry Finger const void *hexdata, int hexdatalen) 34102e295eSLarry Finger { 35c34df318SLarry Finger if (unlikely(((comp) & rtlpriv->cfg->mod_params->debug_mask) && 36c34df318SLarry Finger ((level) <= rtlpriv->cfg->mod_params->debug_level))) { 37c34df318SLarry Finger pr_info("In process \"%s\" (pid %i): %s\n", 38102e295eSLarry Finger current->comm, current->pid, titlestring); 39102e295eSLarry Finger print_hex_dump_bytes("", DUMP_PREFIX_NONE, 40102e295eSLarry Finger hexdata, hexdatalen); 41102e295eSLarry Finger } 42102e295eSLarry Finger } 43102e295eSLarry Finger EXPORT_SYMBOL_GPL(_rtl_dbg_print_data); 44102e295eSLarry Finger 45610247f4SPing-Ke Shih struct rtl_debugfs_priv { 46610247f4SPing-Ke Shih struct rtl_priv *rtlpriv; 47610247f4SPing-Ke Shih int (*cb_read)(struct seq_file *m, void *v); 48610247f4SPing-Ke Shih ssize_t (*cb_write)(struct file *filp, const char __user *buffer, 49610247f4SPing-Ke Shih size_t count, loff_t *loff); 50610247f4SPing-Ke Shih u32 cb_data; 51610247f4SPing-Ke Shih }; 52610247f4SPing-Ke Shih 53610247f4SPing-Ke Shih static struct dentry *debugfs_topdir; 54610247f4SPing-Ke Shih 55610247f4SPing-Ke Shih static int rtl_debug_get_common(struct seq_file *m, void *v) 56610247f4SPing-Ke Shih { 57610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = m->private; 58610247f4SPing-Ke Shih 59610247f4SPing-Ke Shih return debugfs_priv->cb_read(m, v); 60610247f4SPing-Ke Shih } 61610247f4SPing-Ke Shih 62610247f4SPing-Ke Shih static int dl_debug_open_common(struct inode *inode, struct file *file) 63610247f4SPing-Ke Shih { 64610247f4SPing-Ke Shih return single_open(file, rtl_debug_get_common, inode->i_private); 65610247f4SPing-Ke Shih } 66610247f4SPing-Ke Shih 67610247f4SPing-Ke Shih static const struct file_operations file_ops_common = { 68610247f4SPing-Ke Shih .open = dl_debug_open_common, 69610247f4SPing-Ke Shih .read = seq_read, 70610247f4SPing-Ke Shih .llseek = seq_lseek, 714c3e4879SWei Yongjun .release = single_release, 72610247f4SPing-Ke Shih }; 73610247f4SPing-Ke Shih 74610247f4SPing-Ke Shih static int rtl_debug_get_mac_page(struct seq_file *m, void *v) 75610247f4SPing-Ke Shih { 76610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = m->private; 77610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv; 78610247f4SPing-Ke Shih u32 page = debugfs_priv->cb_data; 79610247f4SPing-Ke Shih int i, n; 80610247f4SPing-Ke Shih int max = 0xff; 81610247f4SPing-Ke Shih 82610247f4SPing-Ke Shih for (n = 0; n <= max; ) { 83610247f4SPing-Ke Shih seq_printf(m, "\n%8.8x ", n + page); 84610247f4SPing-Ke Shih for (i = 0; i < 4 && n <= max; i++, n += 4) 85610247f4SPing-Ke Shih seq_printf(m, "%8.8x ", 86610247f4SPing-Ke Shih rtl_read_dword(rtlpriv, (page | n))); 87610247f4SPing-Ke Shih } 88610247f4SPing-Ke Shih seq_puts(m, "\n"); 89610247f4SPing-Ke Shih return 0; 90610247f4SPing-Ke Shih } 91610247f4SPing-Ke Shih 92610247f4SPing-Ke Shih #define RTL_DEBUG_IMPL_MAC_SERIES(page, addr) \ 93610247f4SPing-Ke Shih static struct rtl_debugfs_priv rtl_debug_priv_mac_ ##page = { \ 94610247f4SPing-Ke Shih .cb_read = rtl_debug_get_mac_page, \ 95610247f4SPing-Ke Shih .cb_data = addr, \ 96610247f4SPing-Ke Shih } 97610247f4SPing-Ke Shih 98610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(0, 0x0000); 99610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(1, 0x0100); 100610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(2, 0x0200); 101610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(3, 0x0300); 102610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(4, 0x0400); 103610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(5, 0x0500); 104610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(6, 0x0600); 105610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(7, 0x0700); 106610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(10, 0x1000); 107610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(11, 0x1100); 108610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(12, 0x1200); 109610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(13, 0x1300); 110610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(14, 0x1400); 111610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(15, 0x1500); 112610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(16, 0x1600); 113610247f4SPing-Ke Shih RTL_DEBUG_IMPL_MAC_SERIES(17, 0x1700); 114610247f4SPing-Ke Shih 115610247f4SPing-Ke Shih static int rtl_debug_get_bb_page(struct seq_file *m, void *v) 116610247f4SPing-Ke Shih { 117610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = m->private; 118610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv; 119610247f4SPing-Ke Shih struct ieee80211_hw *hw = rtlpriv->hw; 120610247f4SPing-Ke Shih u32 page = debugfs_priv->cb_data; 121610247f4SPing-Ke Shih int i, n; 122610247f4SPing-Ke Shih int max = 0xff; 123610247f4SPing-Ke Shih 124610247f4SPing-Ke Shih for (n = 0; n <= max; ) { 125610247f4SPing-Ke Shih seq_printf(m, "\n%8.8x ", n + page); 126610247f4SPing-Ke Shih for (i = 0; i < 4 && n <= max; i++, n += 4) 127610247f4SPing-Ke Shih seq_printf(m, "%8.8x ", 128610247f4SPing-Ke Shih rtl_get_bbreg(hw, (page | n), 0xffffffff)); 129610247f4SPing-Ke Shih } 130610247f4SPing-Ke Shih seq_puts(m, "\n"); 131610247f4SPing-Ke Shih return 0; 132610247f4SPing-Ke Shih } 133610247f4SPing-Ke Shih 134610247f4SPing-Ke Shih #define RTL_DEBUG_IMPL_BB_SERIES(page, addr) \ 135610247f4SPing-Ke Shih static struct rtl_debugfs_priv rtl_debug_priv_bb_ ##page = { \ 136610247f4SPing-Ke Shih .cb_read = rtl_debug_get_bb_page, \ 137610247f4SPing-Ke Shih .cb_data = addr, \ 138610247f4SPing-Ke Shih } 139610247f4SPing-Ke Shih 140610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(8, 0x0800); 141610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(9, 0x0900); 142610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(a, 0x0a00); 143610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(b, 0x0b00); 144610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(c, 0x0c00); 145610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(d, 0x0d00); 146610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(e, 0x0e00); 147610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(f, 0x0f00); 148610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(18, 0x1800); 149610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(19, 0x1900); 150610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(1a, 0x1a00); 151610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(1b, 0x1b00); 152610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(1c, 0x1c00); 153610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(1d, 0x1d00); 154610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(1e, 0x1e00); 155610247f4SPing-Ke Shih RTL_DEBUG_IMPL_BB_SERIES(1f, 0x1f00); 156610247f4SPing-Ke Shih 157610247f4SPing-Ke Shih static int rtl_debug_get_reg_rf(struct seq_file *m, void *v) 158610247f4SPing-Ke Shih { 159610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = m->private; 160610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv; 161610247f4SPing-Ke Shih struct ieee80211_hw *hw = rtlpriv->hw; 162610247f4SPing-Ke Shih enum radio_path rfpath = debugfs_priv->cb_data; 163610247f4SPing-Ke Shih int i, n; 164610247f4SPing-Ke Shih int max = 0x40; 165610247f4SPing-Ke Shih 166610247f4SPing-Ke Shih if (IS_HARDWARE_TYPE_8822B(rtlpriv)) 167610247f4SPing-Ke Shih max = 0xff; 168610247f4SPing-Ke Shih 169610247f4SPing-Ke Shih seq_printf(m, "\nPATH(%d)", rfpath); 170610247f4SPing-Ke Shih 171610247f4SPing-Ke Shih for (n = 0; n <= max; ) { 172610247f4SPing-Ke Shih seq_printf(m, "\n%8.8x ", n); 173610247f4SPing-Ke Shih for (i = 0; i < 4 && n <= max; n += 1, i++) 174610247f4SPing-Ke Shih seq_printf(m, "%8.8x ", 175610247f4SPing-Ke Shih rtl_get_rfreg(hw, rfpath, n, 0xffffffff)); 176610247f4SPing-Ke Shih } 177610247f4SPing-Ke Shih seq_puts(m, "\n"); 178610247f4SPing-Ke Shih return 0; 179610247f4SPing-Ke Shih } 180610247f4SPing-Ke Shih 181610247f4SPing-Ke Shih #define RTL_DEBUG_IMPL_RF_SERIES(page, addr) \ 182610247f4SPing-Ke Shih static struct rtl_debugfs_priv rtl_debug_priv_rf_ ##page = { \ 183610247f4SPing-Ke Shih .cb_read = rtl_debug_get_reg_rf, \ 184610247f4SPing-Ke Shih .cb_data = addr, \ 185610247f4SPing-Ke Shih } 186610247f4SPing-Ke Shih 187610247f4SPing-Ke Shih RTL_DEBUG_IMPL_RF_SERIES(a, RF90_PATH_A); 188610247f4SPing-Ke Shih RTL_DEBUG_IMPL_RF_SERIES(b, RF90_PATH_B); 189610247f4SPing-Ke Shih 190610247f4SPing-Ke Shih static int rtl_debug_get_cam_register(struct seq_file *m, void *v) 191610247f4SPing-Ke Shih { 192610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = m->private; 193610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv; 194610247f4SPing-Ke Shih int start = debugfs_priv->cb_data; 195610247f4SPing-Ke Shih u32 target_cmd = 0; 196610247f4SPing-Ke Shih u32 target_val = 0; 197610247f4SPing-Ke Shih u8 entry_i = 0; 198610247f4SPing-Ke Shih u32 ulstatus; 199610247f4SPing-Ke Shih int i = 100, j = 0; 200610247f4SPing-Ke Shih int end = (start + 11 > TOTAL_CAM_ENTRY ? TOTAL_CAM_ENTRY : start + 11); 201610247f4SPing-Ke Shih 202610247f4SPing-Ke Shih /* This dump the current register page */ 203610247f4SPing-Ke Shih seq_printf(m, 204610247f4SPing-Ke Shih "\n#################### SECURITY CAM (%d-%d) ##################\n", 205610247f4SPing-Ke Shih start, end - 1); 206610247f4SPing-Ke Shih 207610247f4SPing-Ke Shih for (j = start; j < end; j++) { 208610247f4SPing-Ke Shih seq_printf(m, "\nD: %2x > ", j); 209610247f4SPing-Ke Shih for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { 210610247f4SPing-Ke Shih /* polling bit, and No Write enable, and address */ 211610247f4SPing-Ke Shih target_cmd = entry_i + CAM_CONTENT_COUNT * j; 212610247f4SPing-Ke Shih target_cmd = target_cmd | BIT(31); 213610247f4SPing-Ke Shih 214610247f4SPing-Ke Shih /* Check polling bit is clear */ 215610247f4SPing-Ke Shih while ((i--) >= 0) { 216610247f4SPing-Ke Shih ulstatus = 217610247f4SPing-Ke Shih rtl_read_dword(rtlpriv, 218610247f4SPing-Ke Shih rtlpriv->cfg->maps[RWCAM]); 219610247f4SPing-Ke Shih if (ulstatus & BIT(31)) 220610247f4SPing-Ke Shih continue; 221610247f4SPing-Ke Shih else 222610247f4SPing-Ke Shih break; 223610247f4SPing-Ke Shih } 224610247f4SPing-Ke Shih 225610247f4SPing-Ke Shih rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], 226610247f4SPing-Ke Shih target_cmd); 227610247f4SPing-Ke Shih target_val = rtl_read_dword(rtlpriv, 228610247f4SPing-Ke Shih rtlpriv->cfg->maps[RCAMO]); 229610247f4SPing-Ke Shih seq_printf(m, "%8.8x ", target_val); 230610247f4SPing-Ke Shih } 231610247f4SPing-Ke Shih } 232610247f4SPing-Ke Shih seq_puts(m, "\n"); 233610247f4SPing-Ke Shih return 0; 234610247f4SPing-Ke Shih } 235610247f4SPing-Ke Shih 236610247f4SPing-Ke Shih #define RTL_DEBUG_IMPL_CAM_SERIES(page, addr) \ 237610247f4SPing-Ke Shih static struct rtl_debugfs_priv rtl_debug_priv_cam_ ##page = { \ 238610247f4SPing-Ke Shih .cb_read = rtl_debug_get_cam_register, \ 239610247f4SPing-Ke Shih .cb_data = addr, \ 240610247f4SPing-Ke Shih } 241610247f4SPing-Ke Shih 242610247f4SPing-Ke Shih RTL_DEBUG_IMPL_CAM_SERIES(1, 0); 243610247f4SPing-Ke Shih RTL_DEBUG_IMPL_CAM_SERIES(2, 11); 244610247f4SPing-Ke Shih RTL_DEBUG_IMPL_CAM_SERIES(3, 22); 245610247f4SPing-Ke Shih 246610247f4SPing-Ke Shih static int rtl_debug_get_btcoex(struct seq_file *m, void *v) 247610247f4SPing-Ke Shih { 248610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = m->private; 249610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv; 250610247f4SPing-Ke Shih 251610247f4SPing-Ke Shih if (rtlpriv->cfg->ops->get_btc_status()) 252610247f4SPing-Ke Shih rtlpriv->btcoexist.btc_ops->btc_display_bt_coex_info(rtlpriv, 253610247f4SPing-Ke Shih m); 254610247f4SPing-Ke Shih 255610247f4SPing-Ke Shih seq_puts(m, "\n"); 256610247f4SPing-Ke Shih 257610247f4SPing-Ke Shih return 0; 258610247f4SPing-Ke Shih } 259610247f4SPing-Ke Shih 260610247f4SPing-Ke Shih static struct rtl_debugfs_priv rtl_debug_priv_btcoex = { 261610247f4SPing-Ke Shih .cb_read = rtl_debug_get_btcoex, 262610247f4SPing-Ke Shih .cb_data = 0, 263610247f4SPing-Ke Shih }; 264610247f4SPing-Ke Shih 265610247f4SPing-Ke Shih static ssize_t rtl_debugfs_set_write_reg(struct file *filp, 266610247f4SPing-Ke Shih const char __user *buffer, 267610247f4SPing-Ke Shih size_t count, loff_t *loff) 268610247f4SPing-Ke Shih { 269610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = filp->private_data; 270610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv; 271610247f4SPing-Ke Shih char tmp[32 + 1]; 272610247f4SPing-Ke Shih int tmp_len; 273610247f4SPing-Ke Shih u32 addr, val, len; 274610247f4SPing-Ke Shih int num; 275610247f4SPing-Ke Shih 276610247f4SPing-Ke Shih if (count < 3) 277610247f4SPing-Ke Shih return -EFAULT; 278610247f4SPing-Ke Shih 279610247f4SPing-Ke Shih tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count); 280610247f4SPing-Ke Shih 281*5dbe1f8eSWei Chen if (copy_from_user(tmp, buffer, tmp_len)) 282*5dbe1f8eSWei Chen return -EFAULT; 283610247f4SPing-Ke Shih 284610247f4SPing-Ke Shih tmp[tmp_len] = '\0'; 285610247f4SPing-Ke Shih 286610247f4SPing-Ke Shih /* write BB/MAC register */ 287610247f4SPing-Ke Shih num = sscanf(tmp, "%x %x %x", &addr, &val, &len); 288610247f4SPing-Ke Shih 289610247f4SPing-Ke Shih if (num != 3) 290*5dbe1f8eSWei Chen return -EINVAL; 291610247f4SPing-Ke Shih 292610247f4SPing-Ke Shih switch (len) { 293610247f4SPing-Ke Shih case 1: 294610247f4SPing-Ke Shih rtl_write_byte(rtlpriv, addr, (u8)val); 295610247f4SPing-Ke Shih break; 296610247f4SPing-Ke Shih case 2: 297610247f4SPing-Ke Shih rtl_write_word(rtlpriv, addr, (u16)val); 298610247f4SPing-Ke Shih break; 299610247f4SPing-Ke Shih case 4: 300610247f4SPing-Ke Shih rtl_write_dword(rtlpriv, addr, val); 301610247f4SPing-Ke Shih break; 302610247f4SPing-Ke Shih default: 303610247f4SPing-Ke Shih /*printk("error write length=%d", len);*/ 304610247f4SPing-Ke Shih break; 305610247f4SPing-Ke Shih } 306610247f4SPing-Ke Shih 307610247f4SPing-Ke Shih return count; 308610247f4SPing-Ke Shih } 309610247f4SPing-Ke Shih 310610247f4SPing-Ke Shih static struct rtl_debugfs_priv rtl_debug_priv_write_reg = { 311610247f4SPing-Ke Shih .cb_write = rtl_debugfs_set_write_reg, 312610247f4SPing-Ke Shih }; 313610247f4SPing-Ke Shih 314610247f4SPing-Ke Shih static ssize_t rtl_debugfs_set_write_h2c(struct file *filp, 315610247f4SPing-Ke Shih const char __user *buffer, 316610247f4SPing-Ke Shih size_t count, loff_t *loff) 317610247f4SPing-Ke Shih { 318610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = filp->private_data; 319610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv; 320610247f4SPing-Ke Shih struct ieee80211_hw *hw = rtlpriv->hw; 321610247f4SPing-Ke Shih char tmp[32 + 1]; 322610247f4SPing-Ke Shih int tmp_len; 323610247f4SPing-Ke Shih u8 h2c_len, h2c_data_packed[8]; 324610247f4SPing-Ke Shih int h2c_data[8]; /* idx 0: cmd */ 325610247f4SPing-Ke Shih int i; 326610247f4SPing-Ke Shih 327610247f4SPing-Ke Shih if (count < 3) 328610247f4SPing-Ke Shih return -EFAULT; 329610247f4SPing-Ke Shih 330610247f4SPing-Ke Shih tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count); 331610247f4SPing-Ke Shih 332b88d2814SDan Carpenter if (copy_from_user(tmp, buffer, tmp_len)) 333b88d2814SDan Carpenter return -EFAULT; 334610247f4SPing-Ke Shih 335610247f4SPing-Ke Shih tmp[tmp_len] = '\0'; 336610247f4SPing-Ke Shih 337610247f4SPing-Ke Shih h2c_len = sscanf(tmp, "%X %X %X %X %X %X %X %X", 338610247f4SPing-Ke Shih &h2c_data[0], &h2c_data[1], 339610247f4SPing-Ke Shih &h2c_data[2], &h2c_data[3], 340610247f4SPing-Ke Shih &h2c_data[4], &h2c_data[5], 341610247f4SPing-Ke Shih &h2c_data[6], &h2c_data[7]); 342610247f4SPing-Ke Shih 343b88d2814SDan Carpenter if (h2c_len == 0) 344b88d2814SDan Carpenter return -EINVAL; 345610247f4SPing-Ke Shih 346610247f4SPing-Ke Shih for (i = 0; i < h2c_len; i++) 347610247f4SPing-Ke Shih h2c_data_packed[i] = (u8)h2c_data[i]; 348610247f4SPing-Ke Shih 349610247f4SPing-Ke Shih rtlpriv->cfg->ops->fill_h2c_cmd(hw, h2c_data_packed[0], 350610247f4SPing-Ke Shih h2c_len - 1, 351610247f4SPing-Ke Shih &h2c_data_packed[1]); 352610247f4SPing-Ke Shih 353610247f4SPing-Ke Shih return count; 354610247f4SPing-Ke Shih } 355610247f4SPing-Ke Shih 356610247f4SPing-Ke Shih static struct rtl_debugfs_priv rtl_debug_priv_write_h2c = { 357610247f4SPing-Ke Shih .cb_write = rtl_debugfs_set_write_h2c, 358610247f4SPing-Ke Shih }; 359610247f4SPing-Ke Shih 360610247f4SPing-Ke Shih static ssize_t rtl_debugfs_set_write_rfreg(struct file *filp, 361610247f4SPing-Ke Shih const char __user *buffer, 362610247f4SPing-Ke Shih size_t count, loff_t *loff) 363610247f4SPing-Ke Shih { 364610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = filp->private_data; 365610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv; 366610247f4SPing-Ke Shih struct ieee80211_hw *hw = rtlpriv->hw; 367610247f4SPing-Ke Shih char tmp[32 + 1]; 368610247f4SPing-Ke Shih int tmp_len; 369610247f4SPing-Ke Shih int num; 370610247f4SPing-Ke Shih int path; 371610247f4SPing-Ke Shih u32 addr, bitmask, data; 372610247f4SPing-Ke Shih 373610247f4SPing-Ke Shih if (count < 3) 374610247f4SPing-Ke Shih return -EFAULT; 375610247f4SPing-Ke Shih 376610247f4SPing-Ke Shih tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count); 377610247f4SPing-Ke Shih 378905a9241SWei Chen if (copy_from_user(tmp, buffer, tmp_len)) 379905a9241SWei Chen return -EFAULT; 380610247f4SPing-Ke Shih 381610247f4SPing-Ke Shih tmp[tmp_len] = '\0'; 382610247f4SPing-Ke Shih 383610247f4SPing-Ke Shih num = sscanf(tmp, "%X %X %X %X", 384610247f4SPing-Ke Shih &path, &addr, &bitmask, &data); 385610247f4SPing-Ke Shih 386610247f4SPing-Ke Shih if (num != 4) { 387f108a420SLarry Finger rtl_dbg(rtlpriv, COMP_ERR, DBG_DMESG, 388610247f4SPing-Ke Shih "Format is <path> <addr> <mask> <data>\n"); 389905a9241SWei Chen return -EINVAL; 390610247f4SPing-Ke Shih } 391610247f4SPing-Ke Shih 392610247f4SPing-Ke Shih rtl_set_rfreg(hw, path, addr, bitmask, data); 393610247f4SPing-Ke Shih 394610247f4SPing-Ke Shih return count; 395610247f4SPing-Ke Shih } 396610247f4SPing-Ke Shih 397610247f4SPing-Ke Shih static struct rtl_debugfs_priv rtl_debug_priv_write_rfreg = { 398610247f4SPing-Ke Shih .cb_write = rtl_debugfs_set_write_rfreg, 399610247f4SPing-Ke Shih }; 400610247f4SPing-Ke Shih 401610247f4SPing-Ke Shih static int rtl_debugfs_close(struct inode *inode, struct file *filp) 402610247f4SPing-Ke Shih { 403610247f4SPing-Ke Shih return 0; 404610247f4SPing-Ke Shih } 405610247f4SPing-Ke Shih 406610247f4SPing-Ke Shih static ssize_t rtl_debugfs_common_write(struct file *filp, 407610247f4SPing-Ke Shih const char __user *buffer, 408610247f4SPing-Ke Shih size_t count, loff_t *loff) 409610247f4SPing-Ke Shih { 410610247f4SPing-Ke Shih struct rtl_debugfs_priv *debugfs_priv = filp->private_data; 411610247f4SPing-Ke Shih 412610247f4SPing-Ke Shih return debugfs_priv->cb_write(filp, buffer, count, loff); 413610247f4SPing-Ke Shih } 414610247f4SPing-Ke Shih 415610247f4SPing-Ke Shih static const struct file_operations file_ops_common_write = { 416610247f4SPing-Ke Shih .owner = THIS_MODULE, 417610247f4SPing-Ke Shih .write = rtl_debugfs_common_write, 418610247f4SPing-Ke Shih .open = simple_open, 419610247f4SPing-Ke Shih .release = rtl_debugfs_close, 420610247f4SPing-Ke Shih }; 421610247f4SPing-Ke Shih 422610247f4SPing-Ke Shih #define RTL_DEBUGFS_ADD_CORE(name, mode, fopname) \ 423610247f4SPing-Ke Shih do { \ 424610247f4SPing-Ke Shih rtl_debug_priv_ ##name.rtlpriv = rtlpriv; \ 4253059785bSGreg Kroah-Hartman debugfs_create_file(#name, mode, parent, \ 4263059785bSGreg Kroah-Hartman &rtl_debug_priv_ ##name, \ 4273059785bSGreg Kroah-Hartman &file_ops_ ##fopname); \ 428610247f4SPing-Ke Shih } while (0) 429610247f4SPing-Ke Shih 430610247f4SPing-Ke Shih #define RTL_DEBUGFS_ADD(name) \ 431610247f4SPing-Ke Shih RTL_DEBUGFS_ADD_CORE(name, S_IFREG | 0444, common) 432610247f4SPing-Ke Shih #define RTL_DEBUGFS_ADD_W(name) \ 433610247f4SPing-Ke Shih RTL_DEBUGFS_ADD_CORE(name, S_IFREG | 0222, common_write) 434610247f4SPing-Ke Shih 435610247f4SPing-Ke Shih void rtl_debug_add_one(struct ieee80211_hw *hw) 436610247f4SPing-Ke Shih { 437610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = rtl_priv(hw); 438610247f4SPing-Ke Shih struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 439610247f4SPing-Ke Shih struct dentry *parent; 440610247f4SPing-Ke Shih 441610247f4SPing-Ke Shih snprintf(rtlpriv->dbg.debugfs_name, 18, "%pMF", rtlefuse->dev_addr); 442610247f4SPing-Ke Shih 443610247f4SPing-Ke Shih rtlpriv->dbg.debugfs_dir = 444610247f4SPing-Ke Shih debugfs_create_dir(rtlpriv->dbg.debugfs_name, debugfs_topdir); 445610247f4SPing-Ke Shih 446610247f4SPing-Ke Shih parent = rtlpriv->dbg.debugfs_dir; 447610247f4SPing-Ke Shih 448610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_0); 449610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_1); 450610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_2); 451610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_3); 452610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_4); 453610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_5); 454610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_6); 455610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_7); 456610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_8); 457610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_9); 458610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_a); 459610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_b); 460610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_c); 461610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_d); 462610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_e); 463610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_f); 464610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_10); 465610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_11); 466610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_12); 467610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_13); 468610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_14); 469610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_15); 470610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_16); 471610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(mac_17); 472610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_18); 473610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_19); 474610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_1a); 475610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_1b); 476610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_1c); 477610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_1d); 478610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_1e); 479610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(bb_1f); 480610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(rf_a); 481610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(rf_b); 482610247f4SPing-Ke Shih 483610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(cam_1); 484610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(cam_2); 485610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(cam_3); 486610247f4SPing-Ke Shih 487610247f4SPing-Ke Shih RTL_DEBUGFS_ADD(btcoex); 488610247f4SPing-Ke Shih 489610247f4SPing-Ke Shih RTL_DEBUGFS_ADD_W(write_reg); 490610247f4SPing-Ke Shih RTL_DEBUGFS_ADD_W(write_h2c); 491610247f4SPing-Ke Shih RTL_DEBUGFS_ADD_W(write_rfreg); 492610247f4SPing-Ke Shih } 493610247f4SPing-Ke Shih EXPORT_SYMBOL_GPL(rtl_debug_add_one); 494610247f4SPing-Ke Shih 495610247f4SPing-Ke Shih void rtl_debug_remove_one(struct ieee80211_hw *hw) 496610247f4SPing-Ke Shih { 497610247f4SPing-Ke Shih struct rtl_priv *rtlpriv = rtl_priv(hw); 498610247f4SPing-Ke Shih 499610247f4SPing-Ke Shih debugfs_remove_recursive(rtlpriv->dbg.debugfs_dir); 500610247f4SPing-Ke Shih rtlpriv->dbg.debugfs_dir = NULL; 501610247f4SPing-Ke Shih } 502610247f4SPing-Ke Shih EXPORT_SYMBOL_GPL(rtl_debug_remove_one); 503610247f4SPing-Ke Shih 504610247f4SPing-Ke Shih void rtl_debugfs_add_topdir(void) 505610247f4SPing-Ke Shih { 506610247f4SPing-Ke Shih debugfs_topdir = debugfs_create_dir("rtlwifi", NULL); 507610247f4SPing-Ke Shih } 508610247f4SPing-Ke Shih 509610247f4SPing-Ke Shih void rtl_debugfs_remove_topdir(void) 510610247f4SPing-Ke Shih { 511610247f4SPing-Ke Shih debugfs_remove_recursive(debugfs_topdir); 512610247f4SPing-Ke Shih } 513610247f4SPing-Ke Shih 5149ce22191SJoe Perches #endif 515