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