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