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