1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
4 * Copyright(c) 2009-2012 Realtek Corporation.
7 * wlanfae <wlanfae@realtek.com>
8 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
11 * Larry Finger <Larry.Finger@lwfinger.net>
12 *****************************************************************************/
17 #include <linux/moduleparam.h>
18 #include <linux/vmalloc.h>
20 #ifdef CONFIG_RTLWIFI_DEBUG_ST
21 void _rtl_dbg_trace(struct rtl_priv
*rtlpriv
, u64 comp
, int level
,
24 if (unlikely((comp
& rtlpriv
->cfg
->mod_params
->debug_mask
) &&
25 level
<= rtlpriv
->cfg
->mod_params
->debug_level
)) {
34 pr_info(":<%lx> %pV", in_interrupt(), &vaf
);
40 void _rtl_dbg_print(struct rtl_priv
*rtlpriv
, u64 comp
, int level
,
43 if (unlikely((comp
& rtlpriv
->cfg
->mod_params
->debug_mask
) &&
44 level
<= rtlpriv
->cfg
->mod_params
->debug_level
)) {
59 void _rtl_dbg_print_data(struct rtl_priv
*rtlpriv
, u64 comp
, int level
,
60 const char *titlestring
,
61 const void *hexdata
, int hexdatalen
)
63 if (unlikely(((comp
) & rtlpriv
->cfg
->mod_params
->debug_mask
) &&
64 ((level
) <= rtlpriv
->cfg
->mod_params
->debug_level
))) {
65 pr_info("In process \"%s\" (pid %i): %s\n",
66 current
->comm
, current
->pid
, titlestring
);
67 print_hex_dump_bytes("", DUMP_PREFIX_NONE
,
72 struct rtl_debugfs_priv
{
73 struct rtl_priv
*rtlpriv
;
74 int (*cb_read
)(struct seq_file
*m
, void *v
);
75 ssize_t (*cb_write
)(struct file
*filp
, const char __user
*buffer
,
76 size_t count
, loff_t
*loff
);
80 static struct dentry
*debugfs_topdir
;
82 static int rtl_debug_get_common(struct seq_file
*m
, void *v
)
84 struct rtl_debugfs_priv
*debugfs_priv
= m
->private;
86 return debugfs_priv
->cb_read(m
, v
);
89 static int dl_debug_open_common(struct inode
*inode
, struct file
*file
)
91 return single_open(file
, rtl_debug_get_common
, inode
->i_private
);
94 static const struct file_operations file_ops_common
= {
95 .open
= dl_debug_open_common
,
98 .release
= single_release
,
101 static int rtl_debug_get_mac_page(struct seq_file
*m
, void *v
)
103 struct rtl_debugfs_priv
*debugfs_priv
= m
->private;
104 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
105 u32 page
= debugfs_priv
->cb_data
;
109 for (n
= 0; n
<= max
; ) {
110 seq_printf(m
, "\n%8.8x ", n
+ page
);
111 for (i
= 0; i
< 4 && n
<= max
; i
++, n
+= 4)
112 seq_printf(m
, "%8.8x ",
113 rtl_read_dword(rtlpriv
, (page
| n
)));
119 #define RTL_DEBUG_IMPL_MAC_SERIES(page, addr) \
120 static struct rtl_debugfs_priv rtl_debug_priv_mac_ ##page = { \
121 .cb_read = rtl_debug_get_mac_page, \
125 RTL_DEBUG_IMPL_MAC_SERIES(0, 0x0000);
126 RTL_DEBUG_IMPL_MAC_SERIES(1, 0x0100);
127 RTL_DEBUG_IMPL_MAC_SERIES(2, 0x0200);
128 RTL_DEBUG_IMPL_MAC_SERIES(3, 0x0300);
129 RTL_DEBUG_IMPL_MAC_SERIES(4, 0x0400);
130 RTL_DEBUG_IMPL_MAC_SERIES(5, 0x0500);
131 RTL_DEBUG_IMPL_MAC_SERIES(6, 0x0600);
132 RTL_DEBUG_IMPL_MAC_SERIES(7, 0x0700);
133 RTL_DEBUG_IMPL_MAC_SERIES(10, 0x1000);
134 RTL_DEBUG_IMPL_MAC_SERIES(11, 0x1100);
135 RTL_DEBUG_IMPL_MAC_SERIES(12, 0x1200);
136 RTL_DEBUG_IMPL_MAC_SERIES(13, 0x1300);
137 RTL_DEBUG_IMPL_MAC_SERIES(14, 0x1400);
138 RTL_DEBUG_IMPL_MAC_SERIES(15, 0x1500);
139 RTL_DEBUG_IMPL_MAC_SERIES(16, 0x1600);
140 RTL_DEBUG_IMPL_MAC_SERIES(17, 0x1700);
142 static int rtl_debug_get_bb_page(struct seq_file
*m
, void *v
)
144 struct rtl_debugfs_priv
*debugfs_priv
= m
->private;
145 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
146 struct ieee80211_hw
*hw
= rtlpriv
->hw
;
147 u32 page
= debugfs_priv
->cb_data
;
151 for (n
= 0; n
<= max
; ) {
152 seq_printf(m
, "\n%8.8x ", n
+ page
);
153 for (i
= 0; i
< 4 && n
<= max
; i
++, n
+= 4)
154 seq_printf(m
, "%8.8x ",
155 rtl_get_bbreg(hw
, (page
| n
), 0xffffffff));
161 #define RTL_DEBUG_IMPL_BB_SERIES(page, addr) \
162 static struct rtl_debugfs_priv rtl_debug_priv_bb_ ##page = { \
163 .cb_read = rtl_debug_get_bb_page, \
167 RTL_DEBUG_IMPL_BB_SERIES(8, 0x0800);
168 RTL_DEBUG_IMPL_BB_SERIES(9, 0x0900);
169 RTL_DEBUG_IMPL_BB_SERIES(a
, 0x0a00);
170 RTL_DEBUG_IMPL_BB_SERIES(b
, 0x0b00);
171 RTL_DEBUG_IMPL_BB_SERIES(c
, 0x0c00);
172 RTL_DEBUG_IMPL_BB_SERIES(d
, 0x0d00);
173 RTL_DEBUG_IMPL_BB_SERIES(e
, 0x0e00);
174 RTL_DEBUG_IMPL_BB_SERIES(f
, 0x0f00);
175 RTL_DEBUG_IMPL_BB_SERIES(18, 0x1800);
176 RTL_DEBUG_IMPL_BB_SERIES(19, 0x1900);
177 RTL_DEBUG_IMPL_BB_SERIES(1a
, 0x1a00);
178 RTL_DEBUG_IMPL_BB_SERIES(1b
, 0x1b00);
179 RTL_DEBUG_IMPL_BB_SERIES(1c
, 0x1c00);
180 RTL_DEBUG_IMPL_BB_SERIES(1d
, 0x1d00);
181 RTL_DEBUG_IMPL_BB_SERIES(1e
, 0x1e00);
182 RTL_DEBUG_IMPL_BB_SERIES(1f
, 0x1f00);
184 static int rtl_debug_get_reg_rf(struct seq_file
*m
, void *v
)
186 struct rtl_debugfs_priv
*debugfs_priv
= m
->private;
187 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
188 struct ieee80211_hw
*hw
= rtlpriv
->hw
;
189 enum radio_path rfpath
= debugfs_priv
->cb_data
;
193 if (IS_HARDWARE_TYPE_8822B(rtlpriv
))
196 seq_printf(m
, "\nPATH(%d)", rfpath
);
198 for (n
= 0; n
<= max
; ) {
199 seq_printf(m
, "\n%8.8x ", n
);
200 for (i
= 0; i
< 4 && n
<= max
; n
+= 1, i
++)
201 seq_printf(m
, "%8.8x ",
202 rtl_get_rfreg(hw
, rfpath
, n
, 0xffffffff));
208 #define RTL_DEBUG_IMPL_RF_SERIES(page, addr) \
209 static struct rtl_debugfs_priv rtl_debug_priv_rf_ ##page = { \
210 .cb_read = rtl_debug_get_reg_rf, \
214 RTL_DEBUG_IMPL_RF_SERIES(a
, RF90_PATH_A
);
215 RTL_DEBUG_IMPL_RF_SERIES(b
, RF90_PATH_B
);
217 static int rtl_debug_get_cam_register(struct seq_file
*m
, void *v
)
219 struct rtl_debugfs_priv
*debugfs_priv
= m
->private;
220 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
221 int start
= debugfs_priv
->cb_data
;
227 int end
= (start
+ 11 > TOTAL_CAM_ENTRY
? TOTAL_CAM_ENTRY
: start
+ 11);
229 /* This dump the current register page */
231 "\n#################### SECURITY CAM (%d-%d) ##################\n",
234 for (j
= start
; j
< end
; j
++) {
235 seq_printf(m
, "\nD: %2x > ", j
);
236 for (entry_i
= 0; entry_i
< CAM_CONTENT_COUNT
; entry_i
++) {
237 /* polling bit, and No Write enable, and address */
238 target_cmd
= entry_i
+ CAM_CONTENT_COUNT
* j
;
239 target_cmd
= target_cmd
| BIT(31);
241 /* Check polling bit is clear */
243 ulstatus
= rtl_read_dword(
245 rtlpriv
->cfg
->maps
[RWCAM
]);
246 if (ulstatus
& BIT(31))
252 rtl_write_dword(rtlpriv
, rtlpriv
->cfg
->maps
[RWCAM
],
254 target_val
= rtl_read_dword(rtlpriv
,
255 rtlpriv
->cfg
->maps
[RCAMO
]);
256 seq_printf(m
, "%8.8x ", target_val
);
263 #define RTL_DEBUG_IMPL_CAM_SERIES(page, addr) \
264 static struct rtl_debugfs_priv rtl_debug_priv_cam_ ##page = { \
265 .cb_read = rtl_debug_get_cam_register, \
269 RTL_DEBUG_IMPL_CAM_SERIES(1, 0);
270 RTL_DEBUG_IMPL_CAM_SERIES(2, 11);
271 RTL_DEBUG_IMPL_CAM_SERIES(3, 22);
273 static int rtl_debug_get_btcoex(struct seq_file
*m
, void *v
)
275 struct rtl_debugfs_priv
*debugfs_priv
= m
->private;
276 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
278 if (rtlpriv
->cfg
->ops
->get_btc_status())
279 rtlpriv
->btcoexist
.btc_ops
->btc_display_bt_coex_info(rtlpriv
,
287 static struct rtl_debugfs_priv rtl_debug_priv_btcoex
= {
288 .cb_read
= rtl_debug_get_btcoex
,
292 static ssize_t
rtl_debugfs_set_write_reg(struct file
*filp
,
293 const char __user
*buffer
,
294 size_t count
, loff_t
*loff
)
296 struct rtl_debugfs_priv
*debugfs_priv
= filp
->private_data
;
297 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
306 tmp_len
= (count
> sizeof(tmp
) - 1 ? sizeof(tmp
) - 1 : count
);
308 if (!buffer
|| copy_from_user(tmp
, buffer
, tmp_len
))
313 /* write BB/MAC register */
314 num
= sscanf(tmp
, "%x %x %x", &addr
, &val
, &len
);
321 rtl_write_byte(rtlpriv
, addr
, (u8
)val
);
324 rtl_write_word(rtlpriv
, addr
, (u16
)val
);
327 rtl_write_dword(rtlpriv
, addr
, val
);
330 /*printk("error write length=%d", len);*/
337 static struct rtl_debugfs_priv rtl_debug_priv_write_reg
= {
338 .cb_write
= rtl_debugfs_set_write_reg
,
341 static ssize_t
rtl_debugfs_set_write_h2c(struct file
*filp
,
342 const char __user
*buffer
,
343 size_t count
, loff_t
*loff
)
345 struct rtl_debugfs_priv
*debugfs_priv
= filp
->private_data
;
346 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
347 struct ieee80211_hw
*hw
= rtlpriv
->hw
;
350 u8 h2c_len
, h2c_data_packed
[8];
351 int h2c_data
[8]; /* idx 0: cmd */
357 tmp_len
= (count
> sizeof(tmp
) - 1 ? sizeof(tmp
) - 1 : count
);
359 if (!buffer
|| copy_from_user(tmp
, buffer
, tmp_len
))
364 h2c_len
= sscanf(tmp
, "%X %X %X %X %X %X %X %X",
365 &h2c_data
[0], &h2c_data
[1],
366 &h2c_data
[2], &h2c_data
[3],
367 &h2c_data
[4], &h2c_data
[5],
368 &h2c_data
[6], &h2c_data
[7]);
373 for (i
= 0; i
< h2c_len
; i
++)
374 h2c_data_packed
[i
] = (u8
)h2c_data
[i
];
376 rtlpriv
->cfg
->ops
->fill_h2c_cmd(hw
, h2c_data_packed
[0],
378 &h2c_data_packed
[1]);
383 static struct rtl_debugfs_priv rtl_debug_priv_write_h2c
= {
384 .cb_write
= rtl_debugfs_set_write_h2c
,
387 static ssize_t
rtl_debugfs_set_write_rfreg(struct file
*filp
,
388 const char __user
*buffer
,
389 size_t count
, loff_t
*loff
)
391 struct rtl_debugfs_priv
*debugfs_priv
= filp
->private_data
;
392 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
393 struct ieee80211_hw
*hw
= rtlpriv
->hw
;
398 u32 addr
, bitmask
, data
;
403 tmp_len
= (count
> sizeof(tmp
) - 1 ? sizeof(tmp
) - 1 : count
);
405 if (!buffer
|| copy_from_user(tmp
, buffer
, tmp_len
))
410 num
= sscanf(tmp
, "%X %X %X %X",
411 &path
, &addr
, &bitmask
, &data
);
414 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_DMESG
,
415 "Format is <path> <addr> <mask> <data>\n");
419 rtl_set_rfreg(hw
, path
, addr
, bitmask
, data
);
424 static struct rtl_debugfs_priv rtl_debug_priv_write_rfreg
= {
425 .cb_write
= rtl_debugfs_set_write_rfreg
,
428 static int rtl_debugfs_close(struct inode
*inode
, struct file
*filp
)
433 static ssize_t
rtl_debugfs_common_write(struct file
*filp
,
434 const char __user
*buffer
,
435 size_t count
, loff_t
*loff
)
437 struct rtl_debugfs_priv
*debugfs_priv
= filp
->private_data
;
439 return debugfs_priv
->cb_write(filp
, buffer
, count
, loff
);
442 static const struct file_operations file_ops_common_write
= {
443 .owner
= THIS_MODULE
,
444 .write
= rtl_debugfs_common_write
,
446 .release
= rtl_debugfs_close
,
449 static ssize_t
rtl_debugfs_phydm_cmd(struct file
*filp
,
450 const char __user
*buffer
,
451 size_t count
, loff_t
*loff
)
453 struct rtl_debugfs_priv
*debugfs_priv
= filp
->private_data
;
454 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
458 if (!rtlpriv
->dbg
.msg_buf
)
461 if (!rtlpriv
->phydm
.ops
)
464 if (buffer
&& !copy_from_user(tmp
, buffer
, sizeof(tmp
))) {
467 rtlpriv
->phydm
.ops
->phydm_debug_cmd(rtlpriv
, tmp
, count
,
468 rtlpriv
->dbg
.msg_buf
,
475 static int rtl_debug_get_phydm_cmd(struct seq_file
*m
, void *v
)
477 struct rtl_debugfs_priv
*debugfs_priv
= m
->private;
478 struct rtl_priv
*rtlpriv
= debugfs_priv
->rtlpriv
;
480 if (rtlpriv
->dbg
.msg_buf
)
481 seq_puts(m
, rtlpriv
->dbg
.msg_buf
);
486 static int rtl_debugfs_open_rw(struct inode
*inode
, struct file
*filp
)
490 if (filp
->f_mode
& FMODE_READ
)
491 ret
= single_open(filp
, rtl_debug_get_common
, inode
->i_private
);
493 filp
->private_data
= inode
->i_private
;
498 static int rtl_debugfs_close_rw(struct inode
*inode
, struct file
*filp
)
500 if (filp
->f_mode
== FMODE_READ
)
501 single_release(inode
, filp
);
506 static struct rtl_debugfs_priv rtl_debug_priv_phydm_cmd
= {
507 .cb_read
= rtl_debug_get_phydm_cmd
,
508 .cb_write
= rtl_debugfs_phydm_cmd
,
512 static const struct file_operations file_ops_common_rw
= {
513 .owner
= THIS_MODULE
,
514 .open
= rtl_debugfs_open_rw
,
515 .release
= rtl_debugfs_close_rw
,
518 .write
= rtl_debugfs_common_write
,
521 #define RTL_DEBUGFS_ADD_CORE(name, mode, fopname) \
523 rtl_debug_priv_ ##name.rtlpriv = rtlpriv; \
524 debugfs_create_file(#name, mode, parent, \
525 &rtl_debug_priv_ ##name, \
526 &file_ops_ ##fopname); \
529 #define RTL_DEBUGFS_ADD(name) \
530 RTL_DEBUGFS_ADD_CORE(name, S_IFREG | 0444, common)
531 #define RTL_DEBUGFS_ADD_W(name) \
532 RTL_DEBUGFS_ADD_CORE(name, S_IFREG | 0222, common_write)
533 #define RTL_DEBUGFS_ADD_RW(name) \
534 RTL_DEBUGFS_ADD_CORE(name, S_IFREG | 0666, common_rw)
536 void rtl_debug_add_one(struct ieee80211_hw
*hw
)
538 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
539 struct rtl_efuse
*rtlefuse
= rtl_efuse(rtl_priv(hw
));
540 struct dentry
*parent
;
542 rtlpriv
->dbg
.msg_buf
= vzalloc(80 * 25);
544 snprintf(rtlpriv
->dbg
.debugfs_name
, 18, "%pMF", rtlefuse
->dev_addr
);
546 rtlpriv
->dbg
.debugfs_dir
=
547 debugfs_create_dir(rtlpriv
->dbg
.debugfs_name
, debugfs_topdir
);
548 if (!rtlpriv
->dbg
.debugfs_dir
) {
549 pr_err("Unable to init debugfs:/%s/%s\n", rtlpriv
->cfg
->name
,
550 rtlpriv
->dbg
.debugfs_name
);
554 parent
= rtlpriv
->dbg
.debugfs_dir
;
556 RTL_DEBUGFS_ADD(mac_0
);
557 RTL_DEBUGFS_ADD(mac_1
);
558 RTL_DEBUGFS_ADD(mac_2
);
559 RTL_DEBUGFS_ADD(mac_3
);
560 RTL_DEBUGFS_ADD(mac_4
);
561 RTL_DEBUGFS_ADD(mac_5
);
562 RTL_DEBUGFS_ADD(mac_6
);
563 RTL_DEBUGFS_ADD(mac_7
);
564 RTL_DEBUGFS_ADD(bb_8
);
565 RTL_DEBUGFS_ADD(bb_9
);
566 RTL_DEBUGFS_ADD(bb_a
);
567 RTL_DEBUGFS_ADD(bb_b
);
568 RTL_DEBUGFS_ADD(bb_c
);
569 RTL_DEBUGFS_ADD(bb_d
);
570 RTL_DEBUGFS_ADD(bb_e
);
571 RTL_DEBUGFS_ADD(bb_f
);
572 RTL_DEBUGFS_ADD(mac_10
);
573 RTL_DEBUGFS_ADD(mac_11
);
574 RTL_DEBUGFS_ADD(mac_12
);
575 RTL_DEBUGFS_ADD(mac_13
);
576 RTL_DEBUGFS_ADD(mac_14
);
577 RTL_DEBUGFS_ADD(mac_15
);
578 RTL_DEBUGFS_ADD(mac_16
);
579 RTL_DEBUGFS_ADD(mac_17
);
580 RTL_DEBUGFS_ADD(bb_18
);
581 RTL_DEBUGFS_ADD(bb_19
);
582 RTL_DEBUGFS_ADD(bb_1a
);
583 RTL_DEBUGFS_ADD(bb_1b
);
584 RTL_DEBUGFS_ADD(bb_1c
);
585 RTL_DEBUGFS_ADD(bb_1d
);
586 RTL_DEBUGFS_ADD(bb_1e
);
587 RTL_DEBUGFS_ADD(bb_1f
);
588 RTL_DEBUGFS_ADD(rf_a
);
589 RTL_DEBUGFS_ADD(rf_b
);
591 RTL_DEBUGFS_ADD(cam_1
);
592 RTL_DEBUGFS_ADD(cam_2
);
593 RTL_DEBUGFS_ADD(cam_3
);
595 RTL_DEBUGFS_ADD(btcoex
);
597 RTL_DEBUGFS_ADD_W(write_reg
);
598 RTL_DEBUGFS_ADD_W(write_h2c
);
599 RTL_DEBUGFS_ADD_W(write_rfreg
);
601 RTL_DEBUGFS_ADD_RW(phydm_cmd
);
604 void rtl_debug_remove_one(struct ieee80211_hw
*hw
)
606 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
608 debugfs_remove_recursive(rtlpriv
->dbg
.debugfs_dir
);
609 rtlpriv
->dbg
.debugfs_dir
= NULL
;
611 vfree(rtlpriv
->dbg
.msg_buf
);
614 void rtl_debugfs_add_topdir(void)
616 debugfs_topdir
= debugfs_create_dir("rtlwifi", NULL
);
619 void rtl_debugfs_remove_topdir(void)
621 debugfs_remove_recursive(debugfs_topdir
);