root/drivers/net/wireless/broadcom/b43/debugfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fops_to_dfs_file
  2. shm16read__read_file
  3. shm16read__write_file
  4. shm16write__write_file
  5. shm32read__read_file
  6. shm32read__write_file
  7. shm32write__write_file
  8. mmio16read__read_file
  9. mmio16read__write_file
  10. mmio16write__write_file
  11. mmio32read__read_file
  12. mmio32read__write_file
  13. mmio32write__write_file
  14. txstat_read_file
  15. restart_write_file
  16. calc_expire_secs
  17. loctls_read_file
  18. b43_debugfs_read
  19. b43_debugfs_write
  20. b43_debug
  21. b43_remove_dynamic_debug
  22. b43_add_dynamic_debug
  23. b43_debugfs_add_device
  24. b43_debugfs_remove_device
  25. b43_debugfs_log_txstat
  26. b43_debugfs_init
  27. b43_debugfs_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3 
   4   Broadcom B43 wireless driver
   5 
   6   debugfs driver debugging code
   7 
   8   Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
   9 
  10 
  11 */
  12 
  13 #include <linux/fs.h>
  14 #include <linux/debugfs.h>
  15 #include <linux/slab.h>
  16 #include <linux/netdevice.h>
  17 #include <linux/pci.h>
  18 #include <linux/mutex.h>
  19 
  20 #include "b43.h"
  21 #include "main.h"
  22 #include "debugfs.h"
  23 #include "dma.h"
  24 #include "xmit.h"
  25 
  26 
  27 /* The root directory. */
  28 static struct dentry *rootdir;
  29 
  30 struct b43_debugfs_fops {
  31         ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize);
  32         int (*write)(struct b43_wldev *dev, const char *buf, size_t count);
  33         struct file_operations fops;
  34         /* Offset of struct b43_dfs_file in struct b43_dfsentry */
  35         size_t file_struct_offset;
  36 };
  37 
  38 static inline
  39 struct b43_dfs_file *fops_to_dfs_file(struct b43_wldev *dev,
  40                                       const struct b43_debugfs_fops *dfops)
  41 {
  42         void *p;
  43 
  44         p = dev->dfsentry;
  45         p += dfops->file_struct_offset;
  46 
  47         return p;
  48 }
  49 
  50 
  51 #define fappend(fmt, x...)      \
  52         do {                                                    \
  53                 if (bufsize - count)                            \
  54                         count += snprintf(buf + count,          \
  55                                           bufsize - count,      \
  56                                           fmt , ##x);           \
  57                 else                                            \
  58                         printk(KERN_ERR "b43: fappend overflow\n"); \
  59         } while (0)
  60 
  61 
  62 /* The biggest address values for SHM access from the debugfs files. */
  63 #define B43_MAX_SHM_ROUTING     4
  64 #define B43_MAX_SHM_ADDR        0xFFFF
  65 
  66 static ssize_t shm16read__read_file(struct b43_wldev *dev,
  67                                     char *buf, size_t bufsize)
  68 {
  69         ssize_t count = 0;
  70         unsigned int routing, addr;
  71         u16 val;
  72 
  73         routing = dev->dfsentry->shm16read_routing_next;
  74         addr = dev->dfsentry->shm16read_addr_next;
  75         if ((routing > B43_MAX_SHM_ROUTING) ||
  76             (addr > B43_MAX_SHM_ADDR))
  77                 return -EDESTADDRREQ;
  78 
  79         val = b43_shm_read16(dev, routing, addr);
  80         fappend("0x%04X\n", val);
  81 
  82         return count;
  83 }
  84 
  85 static int shm16read__write_file(struct b43_wldev *dev,
  86                                  const char *buf, size_t count)
  87 {
  88         unsigned int routing, addr;
  89         int res;
  90 
  91         res = sscanf(buf, "0x%X 0x%X", &routing, &addr);
  92         if (res != 2)
  93                 return -EINVAL;
  94         if (routing > B43_MAX_SHM_ROUTING)
  95                 return -EADDRNOTAVAIL;
  96         if (addr > B43_MAX_SHM_ADDR)
  97                 return -EADDRNOTAVAIL;
  98         if (routing == B43_SHM_SHARED) {
  99                 if ((addr % 2) != 0)
 100                         return -EADDRNOTAVAIL;
 101         }
 102 
 103         dev->dfsentry->shm16read_routing_next = routing;
 104         dev->dfsentry->shm16read_addr_next = addr;
 105 
 106         return 0;
 107 }
 108 
 109 static int shm16write__write_file(struct b43_wldev *dev,
 110                                   const char *buf, size_t count)
 111 {
 112         unsigned int routing, addr, mask, set;
 113         u16 val;
 114         int res;
 115 
 116         res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
 117                      &routing, &addr, &mask, &set);
 118         if (res != 4)
 119                 return -EINVAL;
 120         if (routing > B43_MAX_SHM_ROUTING)
 121                 return -EADDRNOTAVAIL;
 122         if (addr > B43_MAX_SHM_ADDR)
 123                 return -EADDRNOTAVAIL;
 124         if (routing == B43_SHM_SHARED) {
 125                 if ((addr % 2) != 0)
 126                         return -EADDRNOTAVAIL;
 127         }
 128         if ((mask > 0xFFFF) || (set > 0xFFFF))
 129                 return -E2BIG;
 130 
 131         if (mask == 0)
 132                 val = 0;
 133         else
 134                 val = b43_shm_read16(dev, routing, addr);
 135         val &= mask;
 136         val |= set;
 137         b43_shm_write16(dev, routing, addr, val);
 138 
 139         return 0;
 140 }
 141 
 142 static ssize_t shm32read__read_file(struct b43_wldev *dev,
 143                                     char *buf, size_t bufsize)
 144 {
 145         ssize_t count = 0;
 146         unsigned int routing, addr;
 147         u32 val;
 148 
 149         routing = dev->dfsentry->shm32read_routing_next;
 150         addr = dev->dfsentry->shm32read_addr_next;
 151         if ((routing > B43_MAX_SHM_ROUTING) ||
 152             (addr > B43_MAX_SHM_ADDR))
 153                 return -EDESTADDRREQ;
 154 
 155         val = b43_shm_read32(dev, routing, addr);
 156         fappend("0x%08X\n", val);
 157 
 158         return count;
 159 }
 160 
 161 static int shm32read__write_file(struct b43_wldev *dev,
 162                                  const char *buf, size_t count)
 163 {
 164         unsigned int routing, addr;
 165         int res;
 166 
 167         res = sscanf(buf, "0x%X 0x%X", &routing, &addr);
 168         if (res != 2)
 169                 return -EINVAL;
 170         if (routing > B43_MAX_SHM_ROUTING)
 171                 return -EADDRNOTAVAIL;
 172         if (addr > B43_MAX_SHM_ADDR)
 173                 return -EADDRNOTAVAIL;
 174         if (routing == B43_SHM_SHARED) {
 175                 if ((addr % 2) != 0)
 176                         return -EADDRNOTAVAIL;
 177         }
 178 
 179         dev->dfsentry->shm32read_routing_next = routing;
 180         dev->dfsentry->shm32read_addr_next = addr;
 181 
 182         return 0;
 183 }
 184 
 185 static int shm32write__write_file(struct b43_wldev *dev,
 186                                   const char *buf, size_t count)
 187 {
 188         unsigned int routing, addr, mask, set;
 189         u32 val;
 190         int res;
 191 
 192         res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
 193                      &routing, &addr, &mask, &set);
 194         if (res != 4)
 195                 return -EINVAL;
 196         if (routing > B43_MAX_SHM_ROUTING)
 197                 return -EADDRNOTAVAIL;
 198         if (addr > B43_MAX_SHM_ADDR)
 199                 return -EADDRNOTAVAIL;
 200         if (routing == B43_SHM_SHARED) {
 201                 if ((addr % 2) != 0)
 202                         return -EADDRNOTAVAIL;
 203         }
 204         if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
 205                 return -E2BIG;
 206 
 207         if (mask == 0)
 208                 val = 0;
 209         else
 210                 val = b43_shm_read32(dev, routing, addr);
 211         val &= mask;
 212         val |= set;
 213         b43_shm_write32(dev, routing, addr, val);
 214 
 215         return 0;
 216 }
 217 
 218 /* The biggest MMIO address that we allow access to from the debugfs files. */
 219 #define B43_MAX_MMIO_ACCESS     (0xF00 - 1)
 220 
 221 static ssize_t mmio16read__read_file(struct b43_wldev *dev,
 222                                      char *buf, size_t bufsize)
 223 {
 224         ssize_t count = 0;
 225         unsigned int addr;
 226         u16 val;
 227 
 228         addr = dev->dfsentry->mmio16read_next;
 229         if (addr > B43_MAX_MMIO_ACCESS)
 230                 return -EDESTADDRREQ;
 231 
 232         val = b43_read16(dev, addr);
 233         fappend("0x%04X\n", val);
 234 
 235         return count;
 236 }
 237 
 238 static int mmio16read__write_file(struct b43_wldev *dev,
 239                                   const char *buf, size_t count)
 240 {
 241         unsigned int addr;
 242         int res;
 243 
 244         res = sscanf(buf, "0x%X", &addr);
 245         if (res != 1)
 246                 return -EINVAL;
 247         if (addr > B43_MAX_MMIO_ACCESS)
 248                 return -EADDRNOTAVAIL;
 249         if ((addr % 2) != 0)
 250                 return -EINVAL;
 251 
 252         dev->dfsentry->mmio16read_next = addr;
 253 
 254         return 0;
 255 }
 256 
 257 static int mmio16write__write_file(struct b43_wldev *dev,
 258                                    const char *buf, size_t count)
 259 {
 260         unsigned int addr, mask, set;
 261         int res;
 262         u16 val;
 263 
 264         res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set);
 265         if (res != 3)
 266                 return -EINVAL;
 267         if (addr > B43_MAX_MMIO_ACCESS)
 268                 return -EADDRNOTAVAIL;
 269         if ((mask > 0xFFFF) || (set > 0xFFFF))
 270                 return -E2BIG;
 271         if ((addr % 2) != 0)
 272                 return -EINVAL;
 273 
 274         if (mask == 0)
 275                 val = 0;
 276         else
 277                 val = b43_read16(dev, addr);
 278         val &= mask;
 279         val |= set;
 280         b43_write16(dev, addr, val);
 281 
 282         return 0;
 283 }
 284 
 285 static ssize_t mmio32read__read_file(struct b43_wldev *dev,
 286                                      char *buf, size_t bufsize)
 287 {
 288         ssize_t count = 0;
 289         unsigned int addr;
 290         u32 val;
 291 
 292         addr = dev->dfsentry->mmio32read_next;
 293         if (addr > B43_MAX_MMIO_ACCESS)
 294                 return -EDESTADDRREQ;
 295 
 296         val = b43_read32(dev, addr);
 297         fappend("0x%08X\n", val);
 298 
 299         return count;
 300 }
 301 
 302 static int mmio32read__write_file(struct b43_wldev *dev,
 303                                   const char *buf, size_t count)
 304 {
 305         unsigned int addr;
 306         int res;
 307 
 308         res = sscanf(buf, "0x%X", &addr);
 309         if (res != 1)
 310                 return -EINVAL;
 311         if (addr > B43_MAX_MMIO_ACCESS)
 312                 return -EADDRNOTAVAIL;
 313         if ((addr % 4) != 0)
 314                 return -EINVAL;
 315 
 316         dev->dfsentry->mmio32read_next = addr;
 317 
 318         return 0;
 319 }
 320 
 321 static int mmio32write__write_file(struct b43_wldev *dev,
 322                                    const char *buf, size_t count)
 323 {
 324         unsigned int addr, mask, set;
 325         int res;
 326         u32 val;
 327 
 328         res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set);
 329         if (res != 3)
 330                 return -EINVAL;
 331         if (addr > B43_MAX_MMIO_ACCESS)
 332                 return -EADDRNOTAVAIL;
 333         if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
 334                 return -E2BIG;
 335         if ((addr % 4) != 0)
 336                 return -EINVAL;
 337 
 338         if (mask == 0)
 339                 val = 0;
 340         else
 341                 val = b43_read32(dev, addr);
 342         val &= mask;
 343         val |= set;
 344         b43_write32(dev, addr, val);
 345 
 346         return 0;
 347 }
 348 
 349 static ssize_t txstat_read_file(struct b43_wldev *dev,
 350                                 char *buf, size_t bufsize)
 351 {
 352         struct b43_txstatus_log *log = &dev->dfsentry->txstatlog;
 353         ssize_t count = 0;
 354         int i, idx;
 355         struct b43_txstatus *stat;
 356 
 357         if (log->end < 0) {
 358                 fappend("Nothing transmitted, yet\n");
 359                 goto out;
 360         }
 361         fappend("b43 TX status reports:\n\n"
 362                 "index | cookie | seq | phy_stat | frame_count | "
 363                 "rts_count | supp_reason | pm_indicated | "
 364                 "intermediate | for_ampdu | acked\n" "---\n");
 365         i = log->end + 1;
 366         idx = 0;
 367         while (1) {
 368                 if (i == B43_NR_LOGGED_TXSTATUS)
 369                         i = 0;
 370                 stat = &(log->log[i]);
 371                 if (stat->cookie) {
 372                         fappend("%03d | "
 373                                 "0x%04X | 0x%04X | 0x%02X | "
 374                                 "0x%X | 0x%X | "
 375                                 "%u | %u | "
 376                                 "%u | %u | %u\n",
 377                                 idx,
 378                                 stat->cookie, stat->seq, stat->phy_stat,
 379                                 stat->frame_count, stat->rts_count,
 380                                 stat->supp_reason, stat->pm_indicated,
 381                                 stat->intermediate, stat->for_ampdu,
 382                                 stat->acked);
 383                         idx++;
 384                 }
 385                 if (i == log->end)
 386                         break;
 387                 i++;
 388         }
 389 out:
 390 
 391         return count;
 392 }
 393 
 394 static int restart_write_file(struct b43_wldev *dev,
 395                               const char *buf, size_t count)
 396 {
 397         int err = 0;
 398 
 399         if (count > 0 && buf[0] == '1') {
 400                 b43_controller_restart(dev, "manually restarted");
 401         } else
 402                 err = -EINVAL;
 403 
 404         return err;
 405 }
 406 
 407 static unsigned long calc_expire_secs(unsigned long now,
 408                                       unsigned long time,
 409                                       unsigned long expire)
 410 {
 411         expire = time + expire;
 412 
 413         if (time_after(now, expire))
 414                 return 0; /* expired */
 415         if (expire < now) {
 416                 /* jiffies wrapped */
 417                 expire -= MAX_JIFFY_OFFSET;
 418                 now -= MAX_JIFFY_OFFSET;
 419         }
 420         B43_WARN_ON(expire < now);
 421 
 422         return (expire - now) / HZ;
 423 }
 424 
 425 static ssize_t loctls_read_file(struct b43_wldev *dev,
 426                                 char *buf, size_t bufsize)
 427 {
 428         ssize_t count = 0;
 429         struct b43_txpower_lo_control *lo;
 430         int i, err = 0;
 431         struct b43_lo_calib *cal;
 432         unsigned long now = jiffies;
 433         struct b43_phy *phy = &dev->phy;
 434 
 435         if (phy->type != B43_PHYTYPE_G) {
 436                 fappend("Device is not a G-PHY\n");
 437                 err = -ENODEV;
 438                 goto out;
 439         }
 440         lo = phy->g->lo_control;
 441         fappend("-- Local Oscillator calibration data --\n\n");
 442         fappend("HW-power-control enabled: %d\n",
 443                 dev->phy.hardware_power_control);
 444         fappend("TX Bias: 0x%02X,  TX Magn: 0x%02X  (expire in %lu sec)\n",
 445                 lo->tx_bias, lo->tx_magn,
 446                 calc_expire_secs(now, lo->txctl_measured_time,
 447                                  B43_LO_TXCTL_EXPIRE));
 448         fappend("Power Vector: 0x%08X%08X  (expires in %lu sec)\n",
 449                 (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32),
 450                 (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL),
 451                 calc_expire_secs(now, lo->pwr_vec_read_time,
 452                                  B43_LO_PWRVEC_EXPIRE));
 453 
 454         fappend("\nCalibrated settings:\n");
 455         list_for_each_entry(cal, &lo->calib_list, list) {
 456                 bool active;
 457 
 458                 active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) &&
 459                           b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt));
 460                 fappend("BB(%d), RF(%d,%d)  ->  I=%d, Q=%d  "
 461                         "(expires in %lu sec)%s\n",
 462                         cal->bbatt.att,
 463                         cal->rfatt.att, cal->rfatt.with_padmix,
 464                         cal->ctl.i, cal->ctl.q,
 465                         calc_expire_secs(now, cal->calib_time,
 466                                          B43_LO_CALIB_EXPIRE),
 467                         active ? "  ACTIVE" : "");
 468         }
 469 
 470         fappend("\nUsed RF attenuation values:  Value(WithPadmix flag)\n");
 471         for (i = 0; i < lo->rfatt_list.len; i++) {
 472                 fappend("%u(%d), ",
 473                         lo->rfatt_list.list[i].att,
 474                         lo->rfatt_list.list[i].with_padmix);
 475         }
 476         fappend("\n");
 477         fappend("\nUsed Baseband attenuation values:\n");
 478         for (i = 0; i < lo->bbatt_list.len; i++) {
 479                 fappend("%u, ",
 480                         lo->bbatt_list.list[i].att);
 481         }
 482         fappend("\n");
 483 
 484 out:
 485         return err ? err : count;
 486 }
 487 
 488 #undef fappend
 489 
 490 static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
 491                                 size_t count, loff_t *ppos)
 492 {
 493         struct b43_wldev *dev;
 494         struct b43_debugfs_fops *dfops;
 495         struct b43_dfs_file *dfile;
 496         ssize_t uninitialized_var(ret);
 497         char *buf;
 498         const size_t bufsize = 1024 * 16; /* 16 kiB buffer */
 499         const size_t buforder = get_order(bufsize);
 500         int err = 0;
 501 
 502         if (!count)
 503                 return 0;
 504         dev = file->private_data;
 505         if (!dev)
 506                 return -ENODEV;
 507 
 508         mutex_lock(&dev->wl->mutex);
 509         if (b43_status(dev) < B43_STAT_INITIALIZED) {
 510                 err = -ENODEV;
 511                 goto out_unlock;
 512         }
 513 
 514         dfops = container_of(debugfs_real_fops(file),
 515                              struct b43_debugfs_fops, fops);
 516         if (!dfops->read) {
 517                 err = -ENOSYS;
 518                 goto out_unlock;
 519         }
 520         dfile = fops_to_dfs_file(dev, dfops);
 521 
 522         if (!dfile->buffer) {
 523                 buf = (char *)__get_free_pages(GFP_KERNEL, buforder);
 524                 if (!buf) {
 525                         err = -ENOMEM;
 526                         goto out_unlock;
 527                 }
 528                 memset(buf, 0, bufsize);
 529                 ret = dfops->read(dev, buf, bufsize);
 530                 if (ret <= 0) {
 531                         free_pages((unsigned long)buf, buforder);
 532                         err = ret;
 533                         goto out_unlock;
 534                 }
 535                 dfile->data_len = ret;
 536                 dfile->buffer = buf;
 537         }
 538 
 539         ret = simple_read_from_buffer(userbuf, count, ppos,
 540                                       dfile->buffer,
 541                                       dfile->data_len);
 542         if (*ppos >= dfile->data_len) {
 543                 free_pages((unsigned long)dfile->buffer, buforder);
 544                 dfile->buffer = NULL;
 545                 dfile->data_len = 0;
 546         }
 547 out_unlock:
 548         mutex_unlock(&dev->wl->mutex);
 549 
 550         return err ? err : ret;
 551 }
 552 
 553 static ssize_t b43_debugfs_write(struct file *file,
 554                                  const char __user *userbuf,
 555                                  size_t count, loff_t *ppos)
 556 {
 557         struct b43_wldev *dev;
 558         struct b43_debugfs_fops *dfops;
 559         char *buf;
 560         int err = 0;
 561 
 562         if (!count)
 563                 return 0;
 564         if (count > PAGE_SIZE)
 565                 return -E2BIG;
 566         dev = file->private_data;
 567         if (!dev)
 568                 return -ENODEV;
 569 
 570         mutex_lock(&dev->wl->mutex);
 571         if (b43_status(dev) < B43_STAT_INITIALIZED) {
 572                 err = -ENODEV;
 573                 goto out_unlock;
 574         }
 575 
 576         dfops = container_of(debugfs_real_fops(file),
 577                              struct b43_debugfs_fops, fops);
 578         if (!dfops->write) {
 579                 err = -ENOSYS;
 580                 goto out_unlock;
 581         }
 582 
 583         buf = (char *)get_zeroed_page(GFP_KERNEL);
 584         if (!buf) {
 585                 err = -ENOMEM;
 586                 goto out_unlock;
 587         }
 588         if (copy_from_user(buf, userbuf, count)) {
 589                 err = -EFAULT;
 590                 goto out_freepage;
 591         }
 592         err = dfops->write(dev, buf, count);
 593         if (err)
 594                 goto out_freepage;
 595 
 596 out_freepage:
 597         free_page((unsigned long)buf);
 598 out_unlock:
 599         mutex_unlock(&dev->wl->mutex);
 600 
 601         return err ? err : count;
 602 }
 603 
 604 
 605 #define B43_DEBUGFS_FOPS(name, _read, _write)                   \
 606         static struct b43_debugfs_fops fops_##name = {          \
 607                 .read   = _read,                                \
 608                 .write  = _write,                               \
 609                 .fops   = {                                     \
 610                         .open   = simple_open,                  \
 611                         .read   = b43_debugfs_read,             \
 612                         .write  = b43_debugfs_write,            \
 613                         .llseek = generic_file_llseek,          \
 614                 },                                              \
 615                 .file_struct_offset = offsetof(struct b43_dfsentry, \
 616                                                file_##name),    \
 617         }
 618 
 619 B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file);
 620 B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file);
 621 B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file);
 622 B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file);
 623 B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file);
 624 B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file);
 625 B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file);
 626 B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file);
 627 B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL);
 628 B43_DEBUGFS_FOPS(restart, NULL, restart_write_file);
 629 B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL);
 630 
 631 
 632 bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
 633 {
 634         bool enabled;
 635 
 636         enabled = (dev->dfsentry && dev->dfsentry->dyn_debug[feature]);
 637         if (unlikely(enabled)) {
 638                 /* Force full debugging messages, if the user enabled
 639                  * some dynamic debugging feature. */
 640                 b43_modparam_verbose = B43_VERBOSITY_MAX;
 641         }
 642 
 643         return enabled;
 644 }
 645 
 646 static void b43_remove_dynamic_debug(struct b43_wldev *dev)
 647 {
 648         struct b43_dfsentry *e = dev->dfsentry;
 649         int i;
 650 
 651         for (i = 0; i < __B43_NR_DYNDBG; i++)
 652                 debugfs_remove(e->dyn_debug_dentries[i]);
 653 }
 654 
 655 static void b43_add_dynamic_debug(struct b43_wldev *dev)
 656 {
 657         struct b43_dfsentry *e = dev->dfsentry;
 658 
 659 #define add_dyn_dbg(name, id, initstate) do {                   \
 660         e->dyn_debug[id] = (initstate);                         \
 661         e->dyn_debug_dentries[id] =                             \
 662                 debugfs_create_bool(name, 0600, e->subdir,      \
 663                                 &(e->dyn_debug[id]));           \
 664         } while (0)
 665 
 666         add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, false);
 667         add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, false);
 668         add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, false);
 669         add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, false);
 670         add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, false);
 671         add_dyn_dbg("debug_lo", B43_DBG_LO, false);
 672         add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, false);
 673         add_dyn_dbg("debug_keys", B43_DBG_KEYS, false);
 674         add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, false);
 675 
 676 #undef add_dyn_dbg
 677 }
 678 
 679 void b43_debugfs_add_device(struct b43_wldev *dev)
 680 {
 681         struct b43_dfsentry *e;
 682         struct b43_txstatus_log *log;
 683         char devdir[16];
 684 
 685         B43_WARN_ON(!dev);
 686         e = kzalloc(sizeof(*e), GFP_KERNEL);
 687         if (!e) {
 688                 b43err(dev->wl, "debugfs: add device OOM\n");
 689                 return;
 690         }
 691         e->dev = dev;
 692         log = &e->txstatlog;
 693         log->log = kcalloc(B43_NR_LOGGED_TXSTATUS,
 694                            sizeof(struct b43_txstatus), GFP_KERNEL);
 695         if (!log->log) {
 696                 b43err(dev->wl, "debugfs: add device txstatus OOM\n");
 697                 kfree(e);
 698                 return;
 699         }
 700         log->end = -1;
 701 
 702         dev->dfsentry = e;
 703 
 704         snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy));
 705         e->subdir = debugfs_create_dir(devdir, rootdir);
 706 
 707         e->mmio16read_next = 0xFFFF; /* invalid address */
 708         e->mmio32read_next = 0xFFFF; /* invalid address */
 709         e->shm16read_routing_next = 0xFFFFFFFF; /* invalid routing */
 710         e->shm16read_addr_next = 0xFFFFFFFF; /* invalid address */
 711         e->shm32read_routing_next = 0xFFFFFFFF; /* invalid routing */
 712         e->shm32read_addr_next = 0xFFFFFFFF; /* invalid address */
 713 
 714 #define ADD_FILE(name, mode)    \
 715         do {                                                    \
 716                 e->file_##name.dentry =                         \
 717                         debugfs_create_file(__stringify(name),  \
 718                                         mode, e->subdir, dev,   \
 719                                         &fops_##name.fops);     \
 720         } while (0)
 721 
 722 
 723         ADD_FILE(shm16read, 0600);
 724         ADD_FILE(shm16write, 0200);
 725         ADD_FILE(shm32read, 0600);
 726         ADD_FILE(shm32write, 0200);
 727         ADD_FILE(mmio16read, 0600);
 728         ADD_FILE(mmio16write, 0200);
 729         ADD_FILE(mmio32read, 0600);
 730         ADD_FILE(mmio32write, 0200);
 731         ADD_FILE(txstat, 0400);
 732         ADD_FILE(restart, 0200);
 733         ADD_FILE(loctls, 0400);
 734 
 735 #undef ADD_FILE
 736 
 737         b43_add_dynamic_debug(dev);
 738 }
 739 
 740 void b43_debugfs_remove_device(struct b43_wldev *dev)
 741 {
 742         struct b43_dfsentry *e;
 743 
 744         if (!dev)
 745                 return;
 746         e = dev->dfsentry;
 747         if (!e)
 748                 return;
 749         b43_remove_dynamic_debug(dev);
 750 
 751         debugfs_remove(e->file_shm16read.dentry);
 752         debugfs_remove(e->file_shm16write.dentry);
 753         debugfs_remove(e->file_shm32read.dentry);
 754         debugfs_remove(e->file_shm32write.dentry);
 755         debugfs_remove(e->file_mmio16read.dentry);
 756         debugfs_remove(e->file_mmio16write.dentry);
 757         debugfs_remove(e->file_mmio32read.dentry);
 758         debugfs_remove(e->file_mmio32write.dentry);
 759         debugfs_remove(e->file_txstat.dentry);
 760         debugfs_remove(e->file_restart.dentry);
 761         debugfs_remove(e->file_loctls.dentry);
 762 
 763         debugfs_remove(e->subdir);
 764         kfree(e->txstatlog.log);
 765         kfree(e);
 766 }
 767 
 768 void b43_debugfs_log_txstat(struct b43_wldev *dev,
 769                             const struct b43_txstatus *status)
 770 {
 771         struct b43_dfsentry *e = dev->dfsentry;
 772         struct b43_txstatus_log *log;
 773         struct b43_txstatus *cur;
 774         int i;
 775 
 776         if (!e)
 777                 return;
 778         log = &e->txstatlog;
 779         i = log->end + 1;
 780         if (i == B43_NR_LOGGED_TXSTATUS)
 781                 i = 0;
 782         log->end = i;
 783         cur = &(log->log[i]);
 784         memcpy(cur, status, sizeof(*cur));
 785 }
 786 
 787 void b43_debugfs_init(void)
 788 {
 789         rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
 790 }
 791 
 792 void b43_debugfs_exit(void)
 793 {
 794         debugfs_remove(rootdir);
 795 }

/* [<][>][^][v][top][bottom][index][help] */