root/drivers/net/wireless/marvell/libertas/debugfs.c

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

DEFINITIONS

This source file includes following definitions.
  1. write_file_dummy
  2. lbs_dev_info
  3. lbs_sleepparams_write
  4. lbs_sleepparams_read
  5. lbs_host_sleep_write
  6. lbs_host_sleep_read
  7. lbs_tlv_find
  8. lbs_threshold_read
  9. lbs_threshold_write
  10. lbs_lowrssi_read
  11. lbs_lowrssi_write
  12. lbs_lowsnr_read
  13. lbs_lowsnr_write
  14. lbs_failcount_read
  15. lbs_failcount_write
  16. lbs_highrssi_read
  17. lbs_highrssi_write
  18. lbs_highsnr_read
  19. lbs_highsnr_write
  20. lbs_bcnmiss_read
  21. lbs_bcnmiss_write
  22. lbs_rdmac_read
  23. lbs_rdmac_write
  24. lbs_wrmac_write
  25. lbs_rdbbp_read
  26. lbs_rdbbp_write
  27. lbs_wrbbp_write
  28. lbs_rdrf_read
  29. lbs_rdrf_write
  30. lbs_wrrf_write
  31. lbs_debugfs_init
  32. lbs_debugfs_remove
  33. lbs_debugfs_init_one
  34. lbs_debugfs_remove_one
  35. lbs_debugfs_read
  36. lbs_debugfs_write
  37. lbs_debug_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/dcache.h>
   3 #include <linux/debugfs.h>
   4 #include <linux/delay.h>
   5 #include <linux/hardirq.h>
   6 #include <linux/mm.h>
   7 #include <linux/string.h>
   8 #include <linux/slab.h>
   9 #include <linux/export.h>
  10 
  11 #include "decl.h"
  12 #include "cmd.h"
  13 #include "debugfs.h"
  14 
  15 static struct dentry *lbs_dir;
  16 static char *szStates[] = {
  17         "Connected",
  18         "Disconnected"
  19 };
  20 
  21 #ifdef PROC_DEBUG
  22 static void lbs_debug_init(struct lbs_private *priv);
  23 #endif
  24 
  25 static ssize_t write_file_dummy(struct file *file, const char __user *buf,
  26                                 size_t count, loff_t *ppos)
  27 {
  28         return -EINVAL;
  29 }
  30 
  31 static const size_t len = PAGE_SIZE;
  32 
  33 static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
  34                                   size_t count, loff_t *ppos)
  35 {
  36         struct lbs_private *priv = file->private_data;
  37         size_t pos = 0;
  38         unsigned long addr = get_zeroed_page(GFP_KERNEL);
  39         char *buf = (char *)addr;
  40         ssize_t res;
  41         if (!buf)
  42                 return -ENOMEM;
  43 
  44         pos += snprintf(buf+pos, len-pos, "state = %s\n",
  45                                 szStates[priv->connect_status]);
  46         pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
  47                                 (u32) priv->regioncode);
  48 
  49         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
  50 
  51         free_page(addr);
  52         return res;
  53 }
  54 
  55 static ssize_t lbs_sleepparams_write(struct file *file,
  56                                 const char __user *user_buf, size_t count,
  57                                 loff_t *ppos)
  58 {
  59         struct lbs_private *priv = file->private_data;
  60         ssize_t ret;
  61         struct sleep_params sp;
  62         int p1, p2, p3, p4, p5, p6;
  63         char *buf;
  64 
  65         buf = memdup_user_nul(user_buf, min(count, len - 1));
  66         if (IS_ERR(buf))
  67                 return PTR_ERR(buf);
  68 
  69         ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
  70         if (ret != 6) {
  71                 ret = -EINVAL;
  72                 goto out_unlock;
  73         }
  74         sp.sp_error = p1;
  75         sp.sp_offset = p2;
  76         sp.sp_stabletime = p3;
  77         sp.sp_calcontrol = p4;
  78         sp.sp_extsleepclk = p5;
  79         sp.sp_reserved = p6;
  80 
  81         ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
  82         if (!ret)
  83                 ret = count;
  84         else if (ret > 0)
  85                 ret = -EINVAL;
  86 
  87 out_unlock:
  88         kfree(buf);
  89         return ret;
  90 }
  91 
  92 static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
  93                                   size_t count, loff_t *ppos)
  94 {
  95         struct lbs_private *priv = file->private_data;
  96         ssize_t ret;
  97         size_t pos = 0;
  98         struct sleep_params sp;
  99         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 100         char *buf = (char *)addr;
 101         if (!buf)
 102                 return -ENOMEM;
 103 
 104         ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
 105         if (ret)
 106                 goto out_unlock;
 107 
 108         pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error,
 109                         sp.sp_offset, sp.sp_stabletime,
 110                         sp.sp_calcontrol, sp.sp_extsleepclk,
 111                         sp.sp_reserved);
 112 
 113         ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 114 
 115 out_unlock:
 116         free_page(addr);
 117         return ret;
 118 }
 119 
 120 static ssize_t lbs_host_sleep_write(struct file *file,
 121                                 const char __user *user_buf, size_t count,
 122                                 loff_t *ppos)
 123 {
 124         struct lbs_private *priv = file->private_data;
 125         ssize_t ret;
 126         int host_sleep;
 127         char *buf;
 128 
 129         buf = memdup_user_nul(user_buf, min(count, len - 1));
 130         if (IS_ERR(buf))
 131                 return PTR_ERR(buf);
 132 
 133         ret = sscanf(buf, "%d", &host_sleep);
 134         if (ret != 1) {
 135                 ret = -EINVAL;
 136                 goto out_unlock;
 137         }
 138 
 139         if (host_sleep == 0)
 140                 ret = lbs_set_host_sleep(priv, 0);
 141         else if (host_sleep == 1) {
 142                 if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
 143                         netdev_info(priv->dev,
 144                                     "wake parameters not configured\n");
 145                         ret = -EINVAL;
 146                         goto out_unlock;
 147                 }
 148                 ret = lbs_set_host_sleep(priv, 1);
 149         } else {
 150                 netdev_err(priv->dev, "invalid option\n");
 151                 ret = -EINVAL;
 152         }
 153 
 154         if (!ret)
 155                 ret = count;
 156 
 157 out_unlock:
 158         kfree(buf);
 159         return ret;
 160 }
 161 
 162 static ssize_t lbs_host_sleep_read(struct file *file, char __user *userbuf,
 163                                   size_t count, loff_t *ppos)
 164 {
 165         struct lbs_private *priv = file->private_data;
 166         ssize_t ret;
 167         size_t pos = 0;
 168         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 169         char *buf = (char *)addr;
 170         if (!buf)
 171                 return -ENOMEM;
 172 
 173         pos += snprintf(buf, len, "%d\n", priv->is_host_sleep_activated);
 174 
 175         ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 176 
 177         free_page(addr);
 178         return ret;
 179 }
 180 
 181 /*
 182  * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
 183  * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
 184  * firmware. Here's an example:
 185  *      04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
 186  *      00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
 187  *      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 188  *
 189  * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
 190  * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
 191  * defined in mrvlietypes_thresholds
 192  *
 193  * This function searches in this TLV data chunk for a given TLV type
 194  * and returns a pointer to the first data byte of the TLV, or to NULL
 195  * if the TLV hasn't been found.
 196  */
 197 static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
 198 {
 199         struct mrvl_ie_header *tlv_h;
 200         uint16_t length;
 201         ssize_t pos = 0;
 202 
 203         while (pos < size) {
 204                 tlv_h = (struct mrvl_ie_header *) tlv;
 205                 if (!tlv_h->len)
 206                         return NULL;
 207                 if (tlv_h->type == cpu_to_le16(tlv_type))
 208                         return tlv_h;
 209                 length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
 210                 pos += length;
 211                 tlv += length;
 212         }
 213         return NULL;
 214 }
 215 
 216 
 217 static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
 218                                   struct file *file, char __user *userbuf,
 219                                   size_t count, loff_t *ppos)
 220 {
 221         struct cmd_ds_802_11_subscribe_event *subscribed;
 222         struct mrvl_ie_thresholds *got;
 223         struct lbs_private *priv = file->private_data;
 224         ssize_t ret = 0;
 225         size_t pos = 0;
 226         char *buf;
 227         u8 value;
 228         u8 freq;
 229         int events = 0;
 230 
 231         buf = (char *)get_zeroed_page(GFP_KERNEL);
 232         if (!buf)
 233                 return -ENOMEM;
 234 
 235         subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL);
 236         if (!subscribed) {
 237                 ret = -ENOMEM;
 238                 goto out_page;
 239         }
 240 
 241         subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed));
 242         subscribed->action = cpu_to_le16(CMD_ACT_GET);
 243 
 244         ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
 245         if (ret)
 246                 goto out_cmd;
 247 
 248         got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
 249         if (got) {
 250                 value = got->value;
 251                 freq  = got->freq;
 252                 events = le16_to_cpu(subscribed->events);
 253 
 254                 pos += snprintf(buf, len, "%d %d %d\n", value, freq,
 255                                 !!(events & event_mask));
 256         }
 257 
 258         ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 259 
 260  out_cmd:
 261         kfree(subscribed);
 262 
 263  out_page:
 264         free_page((unsigned long)buf);
 265         return ret;
 266 }
 267 
 268 
 269 static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
 270                                    struct file *file,
 271                                    const char __user *userbuf, size_t count,
 272                                    loff_t *ppos)
 273 {
 274         struct cmd_ds_802_11_subscribe_event *events;
 275         struct mrvl_ie_thresholds *tlv;
 276         struct lbs_private *priv = file->private_data;
 277         int value, freq, new_mask;
 278         uint16_t curr_mask;
 279         char *buf;
 280         int ret;
 281 
 282         buf = memdup_user_nul(userbuf, min(count, len - 1));
 283         if (IS_ERR(buf))
 284                 return PTR_ERR(buf);
 285 
 286         ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
 287         if (ret != 3) {
 288                 ret = -EINVAL;
 289                 goto out_page;
 290         }
 291         events = kzalloc(sizeof(*events), GFP_KERNEL);
 292         if (!events) {
 293                 ret = -ENOMEM;
 294                 goto out_page;
 295         }
 296 
 297         events->hdr.size = cpu_to_le16(sizeof(*events));
 298         events->action = cpu_to_le16(CMD_ACT_GET);
 299 
 300         ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
 301         if (ret)
 302                 goto out_events;
 303 
 304         curr_mask = le16_to_cpu(events->events);
 305 
 306         if (new_mask)
 307                 new_mask = curr_mask | event_mask;
 308         else
 309                 new_mask = curr_mask & ~event_mask;
 310 
 311         /* Now everything is set and we can send stuff down to the firmware */
 312 
 313         tlv = (void *)events->tlv;
 314 
 315         events->action = cpu_to_le16(CMD_ACT_SET);
 316         events->events = cpu_to_le16(new_mask);
 317         tlv->header.type = cpu_to_le16(tlv_type);
 318         tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
 319         tlv->value = value;
 320         if (tlv_type != TLV_TYPE_BCNMISS)
 321                 tlv->freq = freq;
 322 
 323         /* The command header, the action, the event mask, and one TLV */
 324         events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));
 325 
 326         ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
 327 
 328         if (!ret)
 329                 ret = count;
 330  out_events:
 331         kfree(events);
 332  out_page:
 333         kfree(buf);
 334         return ret;
 335 }
 336 
 337 
 338 static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
 339                                 size_t count, loff_t *ppos)
 340 {
 341         return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
 342                                   file, userbuf, count, ppos);
 343 }
 344 
 345 
 346 static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf,
 347                                  size_t count, loff_t *ppos)
 348 {
 349         return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
 350                                    file, userbuf, count, ppos);
 351 }
 352 
 353 
 354 static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
 355                                size_t count, loff_t *ppos)
 356 {
 357         return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
 358                                   file, userbuf, count, ppos);
 359 }
 360 
 361 
 362 static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf,
 363                                 size_t count, loff_t *ppos)
 364 {
 365         return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
 366                                    file, userbuf, count, ppos);
 367 }
 368 
 369 
 370 static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
 371                                   size_t count, loff_t *ppos)
 372 {
 373         return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
 374                                   file, userbuf, count, ppos);
 375 }
 376 
 377 
 378 static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf,
 379                                    size_t count, loff_t *ppos)
 380 {
 381         return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
 382                                    file, userbuf, count, ppos);
 383 }
 384 
 385 
 386 static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
 387                                  size_t count, loff_t *ppos)
 388 {
 389         return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
 390                                   file, userbuf, count, ppos);
 391 }
 392 
 393 
 394 static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf,
 395                                   size_t count, loff_t *ppos)
 396 {
 397         return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
 398                                    file, userbuf, count, ppos);
 399 }
 400 
 401 
 402 static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf,
 403                                 size_t count, loff_t *ppos)
 404 {
 405         return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
 406                                   file, userbuf, count, ppos);
 407 }
 408 
 409 
 410 static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf,
 411                                  size_t count, loff_t *ppos)
 412 {
 413         return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
 414                                    file, userbuf, count, ppos);
 415 }
 416 
 417 static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
 418                                 size_t count, loff_t *ppos)
 419 {
 420         return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
 421                                   file, userbuf, count, ppos);
 422 }
 423 
 424 
 425 static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
 426                                  size_t count, loff_t *ppos)
 427 {
 428         return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
 429                                    file, userbuf, count, ppos);
 430 }
 431 
 432 
 433 static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
 434                                   size_t count, loff_t *ppos)
 435 {
 436         struct lbs_private *priv = file->private_data;
 437         ssize_t pos = 0;
 438         int ret;
 439         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 440         char *buf = (char *)addr;
 441         u32 val = 0;
 442 
 443         if (!buf)
 444                 return -ENOMEM;
 445 
 446         ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val);
 447         mdelay(10);
 448         if (!ret) {
 449                 pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n",
 450                                 priv->mac_offset, val);
 451                 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 452         }
 453         free_page(addr);
 454         return ret;
 455 }
 456 
 457 static ssize_t lbs_rdmac_write(struct file *file,
 458                                     const char __user *userbuf,
 459                                     size_t count, loff_t *ppos)
 460 {
 461         struct lbs_private *priv = file->private_data;
 462         char *buf;
 463 
 464         buf = memdup_user_nul(userbuf, min(count, len - 1));
 465         if (IS_ERR(buf))
 466                 return PTR_ERR(buf);
 467 
 468         priv->mac_offset = simple_strtoul(buf, NULL, 16);
 469         kfree(buf);
 470         return count;
 471 }
 472 
 473 static ssize_t lbs_wrmac_write(struct file *file,
 474                                     const char __user *userbuf,
 475                                     size_t count, loff_t *ppos)
 476 {
 477 
 478         struct lbs_private *priv = file->private_data;
 479         ssize_t res;
 480         u32 offset, value;
 481         char *buf;
 482 
 483         buf = memdup_user_nul(userbuf, min(count, len - 1));
 484         if (IS_ERR(buf))
 485                 return PTR_ERR(buf);
 486 
 487         res = sscanf(buf, "%x %x", &offset, &value);
 488         if (res != 2) {
 489                 res = -EFAULT;
 490                 goto out_unlock;
 491         }
 492 
 493         res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value);
 494         mdelay(10);
 495 
 496         if (!res)
 497                 res = count;
 498 out_unlock:
 499         kfree(buf);
 500         return res;
 501 }
 502 
 503 static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
 504                                   size_t count, loff_t *ppos)
 505 {
 506         struct lbs_private *priv = file->private_data;
 507         ssize_t pos = 0;
 508         int ret;
 509         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 510         char *buf = (char *)addr;
 511         u32 val;
 512 
 513         if (!buf)
 514                 return -ENOMEM;
 515 
 516         ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val);
 517         mdelay(10);
 518         if (!ret) {
 519                 pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n",
 520                                 priv->bbp_offset, val);
 521                 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 522         }
 523         free_page(addr);
 524 
 525         return ret;
 526 }
 527 
 528 static ssize_t lbs_rdbbp_write(struct file *file,
 529                                     const char __user *userbuf,
 530                                     size_t count, loff_t *ppos)
 531 {
 532         struct lbs_private *priv = file->private_data;
 533         char *buf;
 534 
 535         buf = memdup_user_nul(userbuf, min(count, len - 1));
 536         if (IS_ERR(buf))
 537                 return PTR_ERR(buf);
 538 
 539         priv->bbp_offset = simple_strtoul(buf, NULL, 16);
 540         kfree(buf);
 541 
 542         return count;
 543 }
 544 
 545 static ssize_t lbs_wrbbp_write(struct file *file,
 546                                     const char __user *userbuf,
 547                                     size_t count, loff_t *ppos)
 548 {
 549 
 550         struct lbs_private *priv = file->private_data;
 551         ssize_t res;
 552         u32 offset, value;
 553         char *buf;
 554 
 555         buf = memdup_user_nul(userbuf, min(count, len - 1));
 556         if (IS_ERR(buf))
 557                 return PTR_ERR(buf);
 558 
 559         res = sscanf(buf, "%x %x", &offset, &value);
 560         if (res != 2) {
 561                 res = -EFAULT;
 562                 goto out_unlock;
 563         }
 564 
 565         res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value);
 566         mdelay(10);
 567 
 568         if (!res)
 569                 res = count;
 570 out_unlock:
 571         kfree(buf);
 572         return res;
 573 }
 574 
 575 static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
 576                                   size_t count, loff_t *ppos)
 577 {
 578         struct lbs_private *priv = file->private_data;
 579         ssize_t pos = 0;
 580         int ret;
 581         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 582         char *buf = (char *)addr;
 583         u32 val;
 584 
 585         if (!buf)
 586                 return -ENOMEM;
 587 
 588         ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val);
 589         mdelay(10);
 590         if (!ret) {
 591                 pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n",
 592                                 priv->rf_offset, val);
 593                 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 594         }
 595         free_page(addr);
 596 
 597         return ret;
 598 }
 599 
 600 static ssize_t lbs_rdrf_write(struct file *file,
 601                                     const char __user *userbuf,
 602                                     size_t count, loff_t *ppos)
 603 {
 604         struct lbs_private *priv = file->private_data;
 605         char *buf;
 606 
 607         buf = memdup_user_nul(userbuf, min(count, len - 1));
 608         if (IS_ERR(buf))
 609                 return PTR_ERR(buf);
 610 
 611         priv->rf_offset = simple_strtoul(buf, NULL, 16);
 612         kfree(buf);
 613         return count;
 614 }
 615 
 616 static ssize_t lbs_wrrf_write(struct file *file,
 617                                     const char __user *userbuf,
 618                                     size_t count, loff_t *ppos)
 619 {
 620 
 621         struct lbs_private *priv = file->private_data;
 622         ssize_t res;
 623         u32 offset, value;
 624         char *buf;
 625 
 626         buf = memdup_user_nul(userbuf, min(count, len - 1));
 627         if (IS_ERR(buf))
 628                 return PTR_ERR(buf);
 629 
 630         res = sscanf(buf, "%x %x", &offset, &value);
 631         if (res != 2) {
 632                 res = -EFAULT;
 633                 goto out_unlock;
 634         }
 635 
 636         res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value);
 637         mdelay(10);
 638 
 639         if (!res)
 640                 res = count;
 641 out_unlock:
 642         kfree(buf);
 643         return res;
 644 }
 645 
 646 #define FOPS(fread, fwrite) { \
 647         .owner = THIS_MODULE, \
 648         .open = simple_open, \
 649         .read = (fread), \
 650         .write = (fwrite), \
 651         .llseek = generic_file_llseek, \
 652 }
 653 
 654 struct lbs_debugfs_files {
 655         const char *name;
 656         umode_t perm;
 657         struct file_operations fops;
 658 };
 659 
 660 static const struct lbs_debugfs_files debugfs_files[] = {
 661         { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
 662         { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
 663                                 lbs_sleepparams_write), },
 664         { "hostsleep", 0644, FOPS(lbs_host_sleep_read,
 665                                 lbs_host_sleep_write), },
 666 };
 667 
 668 static const struct lbs_debugfs_files debugfs_events_files[] = {
 669         {"low_rssi", 0644, FOPS(lbs_lowrssi_read,
 670                                 lbs_lowrssi_write), },
 671         {"low_snr", 0644, FOPS(lbs_lowsnr_read,
 672                                 lbs_lowsnr_write), },
 673         {"failure_count", 0644, FOPS(lbs_failcount_read,
 674                                 lbs_failcount_write), },
 675         {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read,
 676                                 lbs_bcnmiss_write), },
 677         {"high_rssi", 0644, FOPS(lbs_highrssi_read,
 678                                 lbs_highrssi_write), },
 679         {"high_snr", 0644, FOPS(lbs_highsnr_read,
 680                                 lbs_highsnr_write), },
 681 };
 682 
 683 static const struct lbs_debugfs_files debugfs_regs_files[] = {
 684         {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), },
 685         {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), },
 686         {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), },
 687         {"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), },
 688         {"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), },
 689         {"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), },
 690 };
 691 
 692 void lbs_debugfs_init(void)
 693 {
 694         if (!lbs_dir)
 695                 lbs_dir = debugfs_create_dir("lbs_wireless", NULL);
 696 }
 697 
 698 void lbs_debugfs_remove(void)
 699 {
 700         debugfs_remove(lbs_dir);
 701 }
 702 
 703 void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
 704 {
 705         int i;
 706         const struct lbs_debugfs_files *files;
 707         if (!lbs_dir)
 708                 goto exit;
 709 
 710         priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir);
 711 
 712         for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
 713                 files = &debugfs_files[i];
 714                 priv->debugfs_files[i] = debugfs_create_file(files->name,
 715                                                              files->perm,
 716                                                              priv->debugfs_dir,
 717                                                              priv,
 718                                                              &files->fops);
 719         }
 720 
 721         priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
 722 
 723         for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
 724                 files = &debugfs_events_files[i];
 725                 priv->debugfs_events_files[i] = debugfs_create_file(files->name,
 726                                                              files->perm,
 727                                                              priv->events_dir,
 728                                                              priv,
 729                                                              &files->fops);
 730         }
 731 
 732         priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
 733 
 734         for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
 735                 files = &debugfs_regs_files[i];
 736                 priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
 737                                                              files->perm,
 738                                                              priv->regs_dir,
 739                                                              priv,
 740                                                              &files->fops);
 741         }
 742 
 743 #ifdef PROC_DEBUG
 744         lbs_debug_init(priv);
 745 #endif
 746 exit:
 747         return;
 748 }
 749 
 750 void lbs_debugfs_remove_one(struct lbs_private *priv)
 751 {
 752         int i;
 753 
 754         for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
 755                 debugfs_remove(priv->debugfs_regs_files[i]);
 756 
 757         debugfs_remove(priv->regs_dir);
 758 
 759         for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
 760                 debugfs_remove(priv->debugfs_events_files[i]);
 761 
 762         debugfs_remove(priv->events_dir);
 763 #ifdef PROC_DEBUG
 764         debugfs_remove(priv->debugfs_debug);
 765 #endif
 766         for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
 767                 debugfs_remove(priv->debugfs_files[i]);
 768         debugfs_remove(priv->debugfs_dir);
 769 }
 770 
 771 
 772 
 773 /* debug entry */
 774 
 775 #ifdef PROC_DEBUG
 776 
 777 #define item_size(n)    (FIELD_SIZEOF(struct lbs_private, n))
 778 #define item_addr(n)    (offsetof(struct lbs_private, n))
 779 
 780 
 781 struct debug_data {
 782         char name[32];
 783         u32 size;
 784         size_t addr;
 785 };
 786 
 787 /* To debug any member of struct lbs_private, simply add one line here.
 788  */
 789 static struct debug_data items[] = {
 790         {"psmode", item_size(psmode), item_addr(psmode)},
 791         {"psstate", item_size(psstate), item_addr(psstate)},
 792 };
 793 
 794 static int num_of_items = ARRAY_SIZE(items);
 795 
 796 /**
 797  * lbs_debugfs_read - proc read function
 798  *
 799  * @file:       file to read
 800  * @userbuf:    pointer to buffer
 801  * @count:      number of bytes to read
 802  * @ppos:       read data starting position
 803  *
 804  * returns:     amount of data read or negative error code
 805  */
 806 static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
 807                         size_t count, loff_t *ppos)
 808 {
 809         int val = 0;
 810         size_t pos = 0;
 811         ssize_t res;
 812         char *p;
 813         int i;
 814         struct debug_data *d;
 815         unsigned long addr = get_zeroed_page(GFP_KERNEL);
 816         char *buf = (char *)addr;
 817         if (!buf)
 818                 return -ENOMEM;
 819 
 820         p = buf;
 821 
 822         d = file->private_data;
 823 
 824         for (i = 0; i < num_of_items; i++) {
 825                 if (d[i].size == 1)
 826                         val = *((u8 *) d[i].addr);
 827                 else if (d[i].size == 2)
 828                         val = *((u16 *) d[i].addr);
 829                 else if (d[i].size == 4)
 830                         val = *((u32 *) d[i].addr);
 831                 else if (d[i].size == 8)
 832                         val = *((u64 *) d[i].addr);
 833 
 834                 pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
 835         }
 836 
 837         res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
 838 
 839         free_page(addr);
 840         return res;
 841 }
 842 
 843 /**
 844  * lbs_debugfs_write - proc write function
 845  *
 846  * @f:          file pointer
 847  * @buf:        pointer to data buffer
 848  * @cnt:        data number to write
 849  * @ppos:       file position
 850  *
 851  * returns:     amount of data written
 852  */
 853 static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
 854                             size_t cnt, loff_t *ppos)
 855 {
 856         int r, i;
 857         char *pdata;
 858         char *p;
 859         char *p0;
 860         char *p1;
 861         char *p2;
 862         struct debug_data *d = f->private_data;
 863 
 864         if (cnt == 0)
 865                 return 0;
 866 
 867         pdata = memdup_user_nul(buf, cnt);
 868         if (IS_ERR(pdata))
 869                 return PTR_ERR(pdata);
 870 
 871         p0 = pdata;
 872         for (i = 0; i < num_of_items; i++) {
 873                 do {
 874                         p = strstr(p0, d[i].name);
 875                         if (p == NULL)
 876                                 break;
 877                         p1 = strchr(p, '\n');
 878                         if (p1 == NULL)
 879                                 break;
 880                         p0 = p1++;
 881                         p2 = strchr(p, '=');
 882                         if (!p2)
 883                                 break;
 884                         p2++;
 885                         r = simple_strtoul(p2, NULL, 0);
 886                         if (d[i].size == 1)
 887                                 *((u8 *) d[i].addr) = (u8) r;
 888                         else if (d[i].size == 2)
 889                                 *((u16 *) d[i].addr) = (u16) r;
 890                         else if (d[i].size == 4)
 891                                 *((u32 *) d[i].addr) = (u32) r;
 892                         else if (d[i].size == 8)
 893                                 *((u64 *) d[i].addr) = (u64) r;
 894                         break;
 895                 } while (1);
 896         }
 897         kfree(pdata);
 898 
 899         return (ssize_t)cnt;
 900 }
 901 
 902 static const struct file_operations lbs_debug_fops = {
 903         .owner = THIS_MODULE,
 904         .open = simple_open,
 905         .write = lbs_debugfs_write,
 906         .read = lbs_debugfs_read,
 907         .llseek = default_llseek,
 908 };
 909 
 910 /**
 911  * lbs_debug_init - create debug proc file
 912  *
 913  * @priv:       pointer to &struct lbs_private
 914  *
 915  * returns:     N/A
 916  */
 917 static void lbs_debug_init(struct lbs_private *priv)
 918 {
 919         int i;
 920 
 921         if (!priv->debugfs_dir)
 922                 return;
 923 
 924         for (i = 0; i < num_of_items; i++)
 925                 items[i].addr += (size_t) priv;
 926 
 927         priv->debugfs_debug = debugfs_create_file("debug", 0644,
 928                                                   priv->debugfs_dir, &items[0],
 929                                                   &lbs_debug_fops);
 930 }
 931 #endif

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