linux/drivers/net/wireless/realtek/rtlwifi/debug.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2012  Realtek Corporation.*/
   3
   4#include "wifi.h"
   5#include "cam.h"
   6
   7#include <linux/moduleparam.h>
   8#include <linux/vmalloc.h>
   9
  10#ifdef CONFIG_RTLWIFI_DEBUG
  11void _rtl_dbg_print(struct rtl_priv *rtlpriv, u64 comp, int level,
  12                    const char *fmt, ...)
  13{
  14        if (unlikely((comp & rtlpriv->cfg->mod_params->debug_mask) &&
  15                     level <= rtlpriv->cfg->mod_params->debug_level)) {
  16                struct va_format vaf;
  17                va_list args;
  18
  19                va_start(args, fmt);
  20
  21                vaf.fmt = fmt;
  22                vaf.va = &args;
  23
  24                pr_info("%pV", &vaf);
  25
  26                va_end(args);
  27        }
  28}
  29EXPORT_SYMBOL_GPL(_rtl_dbg_print);
  30
  31void _rtl_dbg_print_data(struct rtl_priv *rtlpriv, u64 comp, int level,
  32                         const char *titlestring,
  33                         const void *hexdata, int hexdatalen)
  34{
  35        if (unlikely(((comp) & rtlpriv->cfg->mod_params->debug_mask) &&
  36                     ((level) <= rtlpriv->cfg->mod_params->debug_level))) {
  37                pr_info("In process \"%s\" (pid %i): %s\n",
  38                        current->comm, current->pid, titlestring);
  39                print_hex_dump_bytes("", DUMP_PREFIX_NONE,
  40                                     hexdata, hexdatalen);
  41        }
  42}
  43EXPORT_SYMBOL_GPL(_rtl_dbg_print_data);
  44
  45struct rtl_debugfs_priv {
  46        struct rtl_priv *rtlpriv;
  47        int (*cb_read)(struct seq_file *m, void *v);
  48        ssize_t (*cb_write)(struct file *filp, const char __user *buffer,
  49                            size_t count, loff_t *loff);
  50        u32 cb_data;
  51};
  52
  53static struct dentry *debugfs_topdir;
  54
  55static int rtl_debug_get_common(struct seq_file *m, void *v)
  56{
  57        struct rtl_debugfs_priv *debugfs_priv = m->private;
  58
  59        return debugfs_priv->cb_read(m, v);
  60}
  61
  62static int dl_debug_open_common(struct inode *inode, struct file *file)
  63{
  64        return single_open(file, rtl_debug_get_common, inode->i_private);
  65}
  66
  67static const struct file_operations file_ops_common = {
  68        .open = dl_debug_open_common,
  69        .read = seq_read,
  70        .llseek = seq_lseek,
  71        .release = single_release,
  72};
  73
  74static int rtl_debug_get_mac_page(struct seq_file *m, void *v)
  75{
  76        struct rtl_debugfs_priv *debugfs_priv = m->private;
  77        struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv;
  78        u32 page = debugfs_priv->cb_data;
  79        int i, n;
  80        int max = 0xff;
  81
  82        for (n = 0; n <= max; ) {
  83                seq_printf(m, "\n%8.8x  ", n + page);
  84                for (i = 0; i < 4 && n <= max; i++, n += 4)
  85                        seq_printf(m, "%8.8x    ",
  86                                   rtl_read_dword(rtlpriv, (page | n)));
  87        }
  88        seq_puts(m, "\n");
  89        return 0;
  90}
  91
  92#define RTL_DEBUG_IMPL_MAC_SERIES(page, addr)                   \
  93static struct rtl_debugfs_priv rtl_debug_priv_mac_ ##page = {   \
  94        .cb_read = rtl_debug_get_mac_page,                      \
  95        .cb_data = addr,                                        \
  96}
  97
  98RTL_DEBUG_IMPL_MAC_SERIES(0, 0x0000);
  99RTL_DEBUG_IMPL_MAC_SERIES(1, 0x0100);
 100RTL_DEBUG_IMPL_MAC_SERIES(2, 0x0200);
 101RTL_DEBUG_IMPL_MAC_SERIES(3, 0x0300);
 102RTL_DEBUG_IMPL_MAC_SERIES(4, 0x0400);
 103RTL_DEBUG_IMPL_MAC_SERIES(5, 0x0500);
 104RTL_DEBUG_IMPL_MAC_SERIES(6, 0x0600);
 105RTL_DEBUG_IMPL_MAC_SERIES(7, 0x0700);
 106RTL_DEBUG_IMPL_MAC_SERIES(10, 0x1000);
 107RTL_DEBUG_IMPL_MAC_SERIES(11, 0x1100);
 108RTL_DEBUG_IMPL_MAC_SERIES(12, 0x1200);
 109RTL_DEBUG_IMPL_MAC_SERIES(13, 0x1300);
 110RTL_DEBUG_IMPL_MAC_SERIES(14, 0x1400);
 111RTL_DEBUG_IMPL_MAC_SERIES(15, 0x1500);
 112RTL_DEBUG_IMPL_MAC_SERIES(16, 0x1600);
 113RTL_DEBUG_IMPL_MAC_SERIES(17, 0x1700);
 114
 115static int rtl_debug_get_bb_page(struct seq_file *m, void *v)
 116{
 117        struct rtl_debugfs_priv *debugfs_priv = m->private;
 118        struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv;
 119        struct ieee80211_hw *hw = rtlpriv->hw;
 120        u32 page = debugfs_priv->cb_data;
 121        int i, n;
 122        int max = 0xff;
 123
 124        for (n = 0; n <= max; ) {
 125                seq_printf(m, "\n%8.8x  ", n + page);
 126                for (i = 0; i < 4 && n <= max; i++, n += 4)
 127                        seq_printf(m, "%8.8x    ",
 128                                   rtl_get_bbreg(hw, (page | n), 0xffffffff));
 129        }
 130        seq_puts(m, "\n");
 131        return 0;
 132}
 133
 134#define RTL_DEBUG_IMPL_BB_SERIES(page, addr)                    \
 135static struct rtl_debugfs_priv rtl_debug_priv_bb_ ##page = {    \
 136        .cb_read = rtl_debug_get_bb_page,                       \
 137        .cb_data = addr,                                        \
 138}
 139
 140RTL_DEBUG_IMPL_BB_SERIES(8, 0x0800);
 141RTL_DEBUG_IMPL_BB_SERIES(9, 0x0900);
 142RTL_DEBUG_IMPL_BB_SERIES(a, 0x0a00);
 143RTL_DEBUG_IMPL_BB_SERIES(b, 0x0b00);
 144RTL_DEBUG_IMPL_BB_SERIES(c, 0x0c00);
 145RTL_DEBUG_IMPL_BB_SERIES(d, 0x0d00);
 146RTL_DEBUG_IMPL_BB_SERIES(e, 0x0e00);
 147RTL_DEBUG_IMPL_BB_SERIES(f, 0x0f00);
 148RTL_DEBUG_IMPL_BB_SERIES(18, 0x1800);
 149RTL_DEBUG_IMPL_BB_SERIES(19, 0x1900);
 150RTL_DEBUG_IMPL_BB_SERIES(1a, 0x1a00);
 151RTL_DEBUG_IMPL_BB_SERIES(1b, 0x1b00);
 152RTL_DEBUG_IMPL_BB_SERIES(1c, 0x1c00);
 153RTL_DEBUG_IMPL_BB_SERIES(1d, 0x1d00);
 154RTL_DEBUG_IMPL_BB_SERIES(1e, 0x1e00);
 155RTL_DEBUG_IMPL_BB_SERIES(1f, 0x1f00);
 156
 157static int rtl_debug_get_reg_rf(struct seq_file *m, void *v)
 158{
 159        struct rtl_debugfs_priv *debugfs_priv = m->private;
 160        struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv;
 161        struct ieee80211_hw *hw = rtlpriv->hw;
 162        enum radio_path rfpath = debugfs_priv->cb_data;
 163        int i, n;
 164        int max = 0x40;
 165
 166        if (IS_HARDWARE_TYPE_8822B(rtlpriv))
 167                max = 0xff;
 168
 169        seq_printf(m, "\nPATH(%d)", rfpath);
 170
 171        for (n = 0; n <= max; ) {
 172                seq_printf(m, "\n%8.8x  ", n);
 173                for (i = 0; i < 4 && n <= max; n += 1, i++)
 174                        seq_printf(m, "%8.8x    ",
 175                                   rtl_get_rfreg(hw, rfpath, n, 0xffffffff));
 176        }
 177        seq_puts(m, "\n");
 178        return 0;
 179}
 180
 181#define RTL_DEBUG_IMPL_RF_SERIES(page, addr)                    \
 182static struct rtl_debugfs_priv rtl_debug_priv_rf_ ##page = {    \
 183        .cb_read = rtl_debug_get_reg_rf,                        \
 184        .cb_data = addr,                                        \
 185}
 186
 187RTL_DEBUG_IMPL_RF_SERIES(a, RF90_PATH_A);
 188RTL_DEBUG_IMPL_RF_SERIES(b, RF90_PATH_B);
 189
 190static int rtl_debug_get_cam_register(struct seq_file *m, void *v)
 191{
 192        struct rtl_debugfs_priv *debugfs_priv = m->private;
 193        struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv;
 194        int start = debugfs_priv->cb_data;
 195        u32 target_cmd = 0;
 196        u32 target_val = 0;
 197        u8 entry_i = 0;
 198        u32 ulstatus;
 199        int i = 100, j = 0;
 200        int end = (start + 11 > TOTAL_CAM_ENTRY ? TOTAL_CAM_ENTRY : start + 11);
 201
 202        /* This dump the current register page */
 203        seq_printf(m,
 204                   "\n#################### SECURITY CAM (%d-%d) ##################\n",
 205                   start, end - 1);
 206
 207        for (j = start; j < end; j++) {
 208                seq_printf(m, "\nD:  %2x > ", j);
 209                for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
 210                        /* polling bit, and No Write enable, and address  */
 211                        target_cmd = entry_i + CAM_CONTENT_COUNT * j;
 212                        target_cmd = target_cmd | BIT(31);
 213
 214                        /* Check polling bit is clear */
 215                        while ((i--) >= 0) {
 216                                ulstatus =
 217                                    rtl_read_dword(rtlpriv,
 218                                                   rtlpriv->cfg->maps[RWCAM]);
 219                                if (ulstatus & BIT(31))
 220                                        continue;
 221                                else
 222                                        break;
 223                        }
 224
 225                        rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
 226                                        target_cmd);
 227                        target_val = rtl_read_dword(rtlpriv,
 228                                                    rtlpriv->cfg->maps[RCAMO]);
 229                        seq_printf(m, "%8.8x ", target_val);
 230                }
 231        }
 232        seq_puts(m, "\n");
 233        return 0;
 234}
 235
 236#define RTL_DEBUG_IMPL_CAM_SERIES(page, addr)                   \
 237static struct rtl_debugfs_priv rtl_debug_priv_cam_ ##page = {   \
 238        .cb_read = rtl_debug_get_cam_register,                  \
 239        .cb_data = addr,                                        \
 240}
 241
 242RTL_DEBUG_IMPL_CAM_SERIES(1, 0);
 243RTL_DEBUG_IMPL_CAM_SERIES(2, 11);
 244RTL_DEBUG_IMPL_CAM_SERIES(3, 22);
 245
 246static int rtl_debug_get_btcoex(struct seq_file *m, void *v)
 247{
 248        struct rtl_debugfs_priv *debugfs_priv = m->private;
 249        struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv;
 250
 251        if (rtlpriv->cfg->ops->get_btc_status())
 252                rtlpriv->btcoexist.btc_ops->btc_display_bt_coex_info(rtlpriv,
 253                                                                     m);
 254
 255        seq_puts(m, "\n");
 256
 257        return 0;
 258}
 259
 260static struct rtl_debugfs_priv rtl_debug_priv_btcoex = {
 261        .cb_read = rtl_debug_get_btcoex,
 262        .cb_data = 0,
 263};
 264
 265static ssize_t rtl_debugfs_set_write_reg(struct file *filp,
 266                                         const char __user *buffer,
 267                                         size_t count, loff_t *loff)
 268{
 269        struct rtl_debugfs_priv *debugfs_priv = filp->private_data;
 270        struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv;
 271        char tmp[32 + 1];
 272        int tmp_len;
 273        u32 addr, val, len;
 274        int num;
 275
 276        if (count < 3)
 277                return -EFAULT;
 278
 279        tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count);
 280
 281        if (!buffer || copy_from_user(tmp, buffer, tmp_len))
 282                return count;
 283
 284        tmp[tmp_len] = '\0';
 285
 286        /* write BB/MAC register */
 287        num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
 288
 289        if (num !=  3)
 290                return count;
 291
 292        switch (len) {
 293        case 1:
 294                rtl_write_byte(rtlpriv, addr, (u8)val);
 295                break;
 296        case 2:
 297                rtl_write_word(rtlpriv, addr, (u16)val);
 298                break;
 299        case 4:
 300                rtl_write_dword(rtlpriv, addr, val);
 301                break;
 302        default:
 303                /*printk("error write length=%d", len);*/
 304                break;
 305        }
 306
 307        return count;
 308}
 309
 310static struct rtl_debugfs_priv rtl_debug_priv_write_reg = {
 311        .cb_write = rtl_debugfs_set_write_reg,
 312};
 313
 314static ssize_t rtl_debugfs_set_write_h2c(struct file *filp,
 315                                         const char __user *buffer,
 316                                         size_t count, loff_t *loff)
 317{
 318        struct rtl_debugfs_priv *debugfs_priv = filp->private_data;
 319        struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv;
 320        struct ieee80211_hw *hw = rtlpriv->hw;
 321        char tmp[32 + 1];
 322        int tmp_len;
 323        u8 h2c_len, h2c_data_packed[8];
 324        int h2c_data[8];        /* idx 0: cmd */
 325        int i;
 326
 327        if (count < 3)
 328                return -EFAULT;
 329
 330        tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count);
 331
 332        if (!buffer || copy_from_user(tmp, buffer, tmp_len))
 333                return count;
 334
 335        tmp[tmp_len] = '\0';
 336
 337        h2c_len = sscanf(tmp, "%X %X %X %X %X %X %X %X",
 338                         &h2c_data[0], &h2c_data[1],
 339                         &h2c_data[2], &h2c_data[3],
 340                         &h2c_data[4], &h2c_data[5],
 341                         &h2c_data[6], &h2c_data[7]);
 342
 343        if (h2c_len <= 0)
 344                return count;
 345
 346        for (i = 0; i < h2c_len; i++)
 347                h2c_data_packed[i] = (u8)h2c_data[i];
 348
 349        rtlpriv->cfg->ops->fill_h2c_cmd(hw, h2c_data_packed[0],
 350                                        h2c_len - 1,
 351                                        &h2c_data_packed[1]);
 352
 353        return count;
 354}
 355
 356static struct rtl_debugfs_priv rtl_debug_priv_write_h2c = {
 357        .cb_write = rtl_debugfs_set_write_h2c,
 358};
 359
 360static ssize_t rtl_debugfs_set_write_rfreg(struct file *filp,
 361                                           const char __user *buffer,
 362                                            size_t count, loff_t *loff)
 363{
 364        struct rtl_debugfs_priv *debugfs_priv = filp->private_data;
 365        struct rtl_priv *rtlpriv = debugfs_priv->rtlpriv;
 366        struct ieee80211_hw *hw = rtlpriv->hw;
 367        char tmp[32 + 1];
 368        int tmp_len;
 369        int num;
 370        int path;
 371        u32 addr, bitmask, data;
 372
 373        if (count < 3)
 374                return -EFAULT;
 375
 376        tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count);
 377
 378        if (!buffer || copy_from_user(tmp, buffer, tmp_len))
 379                return count;
 380
 381        tmp[tmp_len] = '\0';
 382
 383        num = sscanf(tmp, "%X %X %X %X",
 384                     &path, &addr, &bitmask, &data);
 385
 386        if (num != 4) {
 387                rtl_dbg(rtlpriv, COMP_ERR, DBG_DMESG,
 388                        "Format is <path> <addr> <mask> <data>\n");
 389                return count;
 390        }
 391
 392        rtl_set_rfreg(hw, path, addr, bitmask, data);
 393
 394        return count;
 395}
 396
 397static struct rtl_debugfs_priv rtl_debug_priv_write_rfreg = {
 398        .cb_write = rtl_debugfs_set_write_rfreg,
 399};
 400
 401static int rtl_debugfs_close(struct inode *inode, struct file *filp)
 402{
 403        return 0;
 404}
 405
 406static ssize_t rtl_debugfs_common_write(struct file *filp,
 407                                        const char __user *buffer,
 408                                        size_t count, loff_t *loff)
 409{
 410        struct rtl_debugfs_priv *debugfs_priv = filp->private_data;
 411
 412        return debugfs_priv->cb_write(filp, buffer, count, loff);
 413}
 414
 415static const struct file_operations file_ops_common_write = {
 416        .owner = THIS_MODULE,
 417        .write = rtl_debugfs_common_write,
 418        .open = simple_open,
 419        .release = rtl_debugfs_close,
 420};
 421
 422#define RTL_DEBUGFS_ADD_CORE(name, mode, fopname)                          \
 423        do {                                                               \
 424                rtl_debug_priv_ ##name.rtlpriv = rtlpriv;                  \
 425                debugfs_create_file(#name, mode, parent,                   \
 426                                    &rtl_debug_priv_ ##name,               \
 427                                    &file_ops_ ##fopname);                 \
 428        } while (0)
 429
 430#define RTL_DEBUGFS_ADD(name)                                              \
 431                RTL_DEBUGFS_ADD_CORE(name, S_IFREG | 0444, common)
 432#define RTL_DEBUGFS_ADD_W(name)                                            \
 433                RTL_DEBUGFS_ADD_CORE(name, S_IFREG | 0222, common_write)
 434
 435void rtl_debug_add_one(struct ieee80211_hw *hw)
 436{
 437        struct rtl_priv *rtlpriv = rtl_priv(hw);
 438        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 439        struct dentry *parent;
 440
 441        snprintf(rtlpriv->dbg.debugfs_name, 18, "%pMF", rtlefuse->dev_addr);
 442
 443        rtlpriv->dbg.debugfs_dir =
 444                debugfs_create_dir(rtlpriv->dbg.debugfs_name, debugfs_topdir);
 445
 446        parent = rtlpriv->dbg.debugfs_dir;
 447
 448        RTL_DEBUGFS_ADD(mac_0);
 449        RTL_DEBUGFS_ADD(mac_1);
 450        RTL_DEBUGFS_ADD(mac_2);
 451        RTL_DEBUGFS_ADD(mac_3);
 452        RTL_DEBUGFS_ADD(mac_4);
 453        RTL_DEBUGFS_ADD(mac_5);
 454        RTL_DEBUGFS_ADD(mac_6);
 455        RTL_DEBUGFS_ADD(mac_7);
 456        RTL_DEBUGFS_ADD(bb_8);
 457        RTL_DEBUGFS_ADD(bb_9);
 458        RTL_DEBUGFS_ADD(bb_a);
 459        RTL_DEBUGFS_ADD(bb_b);
 460        RTL_DEBUGFS_ADD(bb_c);
 461        RTL_DEBUGFS_ADD(bb_d);
 462        RTL_DEBUGFS_ADD(bb_e);
 463        RTL_DEBUGFS_ADD(bb_f);
 464        RTL_DEBUGFS_ADD(mac_10);
 465        RTL_DEBUGFS_ADD(mac_11);
 466        RTL_DEBUGFS_ADD(mac_12);
 467        RTL_DEBUGFS_ADD(mac_13);
 468        RTL_DEBUGFS_ADD(mac_14);
 469        RTL_DEBUGFS_ADD(mac_15);
 470        RTL_DEBUGFS_ADD(mac_16);
 471        RTL_DEBUGFS_ADD(mac_17);
 472        RTL_DEBUGFS_ADD(bb_18);
 473        RTL_DEBUGFS_ADD(bb_19);
 474        RTL_DEBUGFS_ADD(bb_1a);
 475        RTL_DEBUGFS_ADD(bb_1b);
 476        RTL_DEBUGFS_ADD(bb_1c);
 477        RTL_DEBUGFS_ADD(bb_1d);
 478        RTL_DEBUGFS_ADD(bb_1e);
 479        RTL_DEBUGFS_ADD(bb_1f);
 480        RTL_DEBUGFS_ADD(rf_a);
 481        RTL_DEBUGFS_ADD(rf_b);
 482
 483        RTL_DEBUGFS_ADD(cam_1);
 484        RTL_DEBUGFS_ADD(cam_2);
 485        RTL_DEBUGFS_ADD(cam_3);
 486
 487        RTL_DEBUGFS_ADD(btcoex);
 488
 489        RTL_DEBUGFS_ADD_W(write_reg);
 490        RTL_DEBUGFS_ADD_W(write_h2c);
 491        RTL_DEBUGFS_ADD_W(write_rfreg);
 492}
 493EXPORT_SYMBOL_GPL(rtl_debug_add_one);
 494
 495void rtl_debug_remove_one(struct ieee80211_hw *hw)
 496{
 497        struct rtl_priv *rtlpriv = rtl_priv(hw);
 498
 499        debugfs_remove_recursive(rtlpriv->dbg.debugfs_dir);
 500        rtlpriv->dbg.debugfs_dir = NULL;
 501}
 502EXPORT_SYMBOL_GPL(rtl_debug_remove_one);
 503
 504void rtl_debugfs_add_topdir(void)
 505{
 506        debugfs_topdir = debugfs_create_dir("rtlwifi", NULL);
 507}
 508
 509void rtl_debugfs_remove_topdir(void)
 510{
 511        debugfs_remove_recursive(debugfs_topdir);
 512}
 513
 514#endif
 515