1 #include <linux/module.h>
2 #include <linux/dcache.h>
3 #include <linux/debugfs.h>
4 #include <linux/delay.h>
6 #include <linux/string.h>
7 #include <net/iw_handler.h>
8 #include <net/lib80211.h>
16 static struct dentry *lbs_dir;
17 static char *szStates[] = {
23 static void lbs_debug_init(struct lbs_private *priv);
26 static int open_file_generic(struct inode *inode, struct file *file)
28 file->private_data = inode->i_private;
32 static ssize_t write_file_dummy(struct file *file, const char __user *buf,
33 size_t count, loff_t *ppos)
38 static const size_t len = PAGE_SIZE;
40 static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
41 size_t count, loff_t *ppos)
43 struct lbs_private *priv = file->private_data;
45 unsigned long addr = get_zeroed_page(GFP_KERNEL);
46 char *buf = (char *)addr;
51 pos += snprintf(buf+pos, len-pos, "state = %s\n",
52 szStates[priv->connect_status]);
53 pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
54 (u32) priv->regioncode);
56 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
63 static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
64 size_t count, loff_t *ppos)
66 struct lbs_private *priv = file->private_data;
68 int numscansdone = 0, res;
69 unsigned long addr = get_zeroed_page(GFP_KERNEL);
70 char *buf = (char *)addr;
71 DECLARE_SSID_BUF(ssid);
72 struct bss_descriptor * iter_bss;
76 pos += snprintf(buf+pos, len-pos,
77 "# | ch | rssi | bssid | cap | Qual | SSID \n");
79 mutex_lock(&priv->lock);
80 list_for_each_entry (iter_bss, &priv->network_list, list) {
81 u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS);
82 u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
83 u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
85 pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |",
86 numscansdone, iter_bss->channel, iter_bss->rssi,
88 pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
89 pos += snprintf(buf+pos, len-pos, "%c%c%c |",
90 ibss ? 'A' : 'I', privacy ? 'P' : ' ',
91 spectrum_mgmt ? 'S' : ' ');
92 pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi));
93 pos += snprintf(buf+pos, len-pos, " %s\n",
94 print_ssid(ssid, iter_bss->ssid,
99 mutex_unlock(&priv->lock);
101 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
107 static ssize_t lbs_sleepparams_write(struct file *file,
108 const char __user *user_buf, size_t count,
111 struct lbs_private *priv = file->private_data;
112 ssize_t buf_size, ret;
113 struct sleep_params sp;
114 int p1, p2, p3, p4, p5, p6;
115 unsigned long addr = get_zeroed_page(GFP_KERNEL);
116 char *buf = (char *)addr;
120 if (!lbs_is_cmd_allowed(priv)) {
125 buf_size = min(count, len - 1);
126 if (copy_from_user(buf, user_buf, buf_size)) {
130 ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
137 sp.sp_stabletime = p3;
138 sp.sp_calcontrol = p4;
139 sp.sp_extsleepclk = p5;
142 ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
153 static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
154 size_t count, loff_t *ppos)
156 struct lbs_private *priv = file->private_data;
159 struct sleep_params sp;
160 unsigned long addr = get_zeroed_page(GFP_KERNEL);
161 char *buf = (char *)addr;
165 if (!lbs_is_cmd_allowed(priv)) {
170 ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
174 pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error,
175 sp.sp_offset, sp.sp_stabletime,
176 sp.sp_calcontrol, sp.sp_extsleepclk,
179 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
187 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
188 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
189 * firmware. Here's an example:
190 * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
191 * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
192 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
194 * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
195 * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
196 * defined in mrvlietypes_thresholds
198 * This function searches in this TLV data chunk for a given TLV type
199 * and returns a pointer to the first data byte of the TLV, or to NULL
200 * if the TLV hasn't been found.
202 static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
204 struct mrvl_ie_header *tlv_h;
209 tlv_h = (struct mrvl_ie_header *) tlv;
212 if (tlv_h->type == cpu_to_le16(tlv_type))
214 length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
222 static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
223 struct file *file, char __user *userbuf,
224 size_t count, loff_t *ppos)
226 struct cmd_ds_802_11_subscribe_event *subscribed;
227 struct mrvl_ie_thresholds *got;
228 struct lbs_private *priv = file->private_data;
236 if (!lbs_is_cmd_allowed(priv))
239 buf = (char *)get_zeroed_page(GFP_KERNEL);
243 subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL);
249 subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed));
250 subscribed->action = cpu_to_le16(CMD_ACT_GET);
252 ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
256 got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
260 events = le16_to_cpu(subscribed->events);
262 pos += snprintf(buf, len, "%d %d %d\n", value, freq,
263 !!(events & event_mask));
266 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
272 free_page((unsigned long)buf);
277 static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
279 const char __user *userbuf, size_t count,
282 struct cmd_ds_802_11_subscribe_event *events;
283 struct mrvl_ie_thresholds *tlv;
284 struct lbs_private *priv = file->private_data;
286 int value, freq, new_mask;
291 if (!lbs_is_cmd_allowed(priv))
294 buf = (char *)get_zeroed_page(GFP_KERNEL);
298 buf_size = min(count, len - 1);
299 if (copy_from_user(buf, userbuf, buf_size)) {
303 ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
308 events = kzalloc(sizeof(*events), GFP_KERNEL);
314 events->hdr.size = cpu_to_le16(sizeof(*events));
315 events->action = cpu_to_le16(CMD_ACT_GET);
317 ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
321 curr_mask = le16_to_cpu(events->events);
324 new_mask = curr_mask | event_mask;
326 new_mask = curr_mask & ~event_mask;
328 /* Now everything is set and we can send stuff down to the firmware */
330 tlv = (void *)events->tlv;
332 events->action = cpu_to_le16(CMD_ACT_SET);
333 events->events = cpu_to_le16(new_mask);
334 tlv->header.type = cpu_to_le16(tlv_type);
335 tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
337 if (tlv_type != TLV_TYPE_BCNMISS)
340 /* The command header, the action, the event mask, and one TLV */
341 events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));
343 ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
350 free_page((unsigned long)buf);
355 static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
356 size_t count, loff_t *ppos)
358 return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
359 file, userbuf, count, ppos);
363 static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf,
364 size_t count, loff_t *ppos)
366 return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
367 file, userbuf, count, ppos);
371 static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
372 size_t count, loff_t *ppos)
374 return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
375 file, userbuf, count, ppos);
379 static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf,
380 size_t count, loff_t *ppos)
382 return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
383 file, userbuf, count, ppos);
387 static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
388 size_t count, loff_t *ppos)
390 return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
391 file, userbuf, count, ppos);
395 static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf,
396 size_t count, loff_t *ppos)
398 return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
399 file, userbuf, count, ppos);
403 static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
404 size_t count, loff_t *ppos)
406 return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
407 file, userbuf, count, ppos);
411 static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf,
412 size_t count, loff_t *ppos)
414 return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
415 file, userbuf, count, ppos);
419 static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf,
420 size_t count, loff_t *ppos)
422 return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
423 file, userbuf, count, ppos);
427 static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf,
428 size_t count, loff_t *ppos)
430 return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
431 file, userbuf, count, ppos);
434 static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
435 size_t count, loff_t *ppos)
437 return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
438 file, userbuf, count, ppos);
442 static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
443 size_t count, loff_t *ppos)
445 return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
446 file, userbuf, count, ppos);
451 static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
452 size_t count, loff_t *ppos)
454 struct lbs_private *priv = file->private_data;
455 struct lbs_offset_value offval;
458 unsigned long addr = get_zeroed_page(GFP_KERNEL);
459 char *buf = (char *)addr;
463 if (!lbs_is_cmd_allowed(priv)) {
468 offval.offset = priv->mac_offset;
471 ret = lbs_prepare_and_send_command(priv,
472 CMD_MAC_REG_ACCESS, 0,
473 CMD_OPTION_WAITFORRSP, 0, &offval);
475 pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
476 priv->mac_offset, priv->offsetvalue.value);
478 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
483 static ssize_t lbs_rdmac_write(struct file *file,
484 const char __user *userbuf,
485 size_t count, loff_t *ppos)
487 struct lbs_private *priv = file->private_data;
488 ssize_t res, buf_size;
489 unsigned long addr = get_zeroed_page(GFP_KERNEL);
490 char *buf = (char *)addr;
494 buf_size = min(count, len - 1);
495 if (copy_from_user(buf, userbuf, buf_size)) {
499 priv->mac_offset = simple_strtoul((char *)buf, NULL, 16);
506 static ssize_t lbs_wrmac_write(struct file *file,
507 const char __user *userbuf,
508 size_t count, loff_t *ppos)
511 struct lbs_private *priv = file->private_data;
512 ssize_t res, buf_size;
514 struct lbs_offset_value offval;
515 unsigned long addr = get_zeroed_page(GFP_KERNEL);
516 char *buf = (char *)addr;
520 if (!lbs_is_cmd_allowed(priv)) {
525 buf_size = min(count, len - 1);
526 if (copy_from_user(buf, userbuf, buf_size)) {
530 res = sscanf(buf, "%x %x", &offset, &value);
536 offval.offset = offset;
537 offval.value = value;
538 res = lbs_prepare_and_send_command(priv,
539 CMD_MAC_REG_ACCESS, 1,
540 CMD_OPTION_WAITFORRSP, 0, &offval);
549 static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
550 size_t count, loff_t *ppos)
552 struct lbs_private *priv = file->private_data;
553 struct lbs_offset_value offval;
556 unsigned long addr = get_zeroed_page(GFP_KERNEL);
557 char *buf = (char *)addr;
561 if (!lbs_is_cmd_allowed(priv)) {
566 offval.offset = priv->bbp_offset;
569 ret = lbs_prepare_and_send_command(priv,
570 CMD_BBP_REG_ACCESS, 0,
571 CMD_OPTION_WAITFORRSP, 0, &offval);
573 pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
574 priv->bbp_offset, priv->offsetvalue.value);
576 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
582 static ssize_t lbs_rdbbp_write(struct file *file,
583 const char __user *userbuf,
584 size_t count, loff_t *ppos)
586 struct lbs_private *priv = file->private_data;
587 ssize_t res, buf_size;
588 unsigned long addr = get_zeroed_page(GFP_KERNEL);
589 char *buf = (char *)addr;
593 buf_size = min(count, len - 1);
594 if (copy_from_user(buf, userbuf, buf_size)) {
598 priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16);
605 static ssize_t lbs_wrbbp_write(struct file *file,
606 const char __user *userbuf,
607 size_t count, loff_t *ppos)
610 struct lbs_private *priv = file->private_data;
611 ssize_t res, buf_size;
613 struct lbs_offset_value offval;
614 unsigned long addr = get_zeroed_page(GFP_KERNEL);
615 char *buf = (char *)addr;
619 if (!lbs_is_cmd_allowed(priv)) {
624 buf_size = min(count, len - 1);
625 if (copy_from_user(buf, userbuf, buf_size)) {
629 res = sscanf(buf, "%x %x", &offset, &value);
635 offval.offset = offset;
636 offval.value = value;
637 res = lbs_prepare_and_send_command(priv,
638 CMD_BBP_REG_ACCESS, 1,
639 CMD_OPTION_WAITFORRSP, 0, &offval);
648 static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
649 size_t count, loff_t *ppos)
651 struct lbs_private *priv = file->private_data;
652 struct lbs_offset_value offval;
655 unsigned long addr = get_zeroed_page(GFP_KERNEL);
656 char *buf = (char *)addr;
660 if (!lbs_is_cmd_allowed(priv)) {
665 offval.offset = priv->rf_offset;
668 ret = lbs_prepare_and_send_command(priv,
669 CMD_RF_REG_ACCESS, 0,
670 CMD_OPTION_WAITFORRSP, 0, &offval);
672 pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
673 priv->rf_offset, priv->offsetvalue.value);
675 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
681 static ssize_t lbs_rdrf_write(struct file *file,
682 const char __user *userbuf,
683 size_t count, loff_t *ppos)
685 struct lbs_private *priv = file->private_data;
686 ssize_t res, buf_size;
687 unsigned long addr = get_zeroed_page(GFP_KERNEL);
688 char *buf = (char *)addr;
692 buf_size = min(count, len - 1);
693 if (copy_from_user(buf, userbuf, buf_size)) {
697 priv->rf_offset = simple_strtoul(buf, NULL, 16);
704 static ssize_t lbs_wrrf_write(struct file *file,
705 const char __user *userbuf,
706 size_t count, loff_t *ppos)
709 struct lbs_private *priv = file->private_data;
710 ssize_t res, buf_size;
712 struct lbs_offset_value offval;
713 unsigned long addr = get_zeroed_page(GFP_KERNEL);
714 char *buf = (char *)addr;
718 if (!lbs_is_cmd_allowed(priv)) {
723 buf_size = min(count, len - 1);
724 if (copy_from_user(buf, userbuf, buf_size)) {
728 res = sscanf(buf, "%x %x", &offset, &value);
734 offval.offset = offset;
735 offval.value = value;
736 res = lbs_prepare_and_send_command(priv,
737 CMD_RF_REG_ACCESS, 1,
738 CMD_OPTION_WAITFORRSP, 0, &offval);
747 #define FOPS(fread, fwrite) { \
748 .owner = THIS_MODULE, \
749 .open = open_file_generic, \
754 struct lbs_debugfs_files {
757 struct file_operations fops;
760 static const struct lbs_debugfs_files debugfs_files[] = {
761 { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
762 { "getscantable", 0444, FOPS(lbs_getscantable,
763 write_file_dummy), },
764 { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
765 lbs_sleepparams_write), },
768 static const struct lbs_debugfs_files debugfs_events_files[] = {
769 {"low_rssi", 0644, FOPS(lbs_lowrssi_read,
770 lbs_lowrssi_write), },
771 {"low_snr", 0644, FOPS(lbs_lowsnr_read,
772 lbs_lowsnr_write), },
773 {"failure_count", 0644, FOPS(lbs_failcount_read,
774 lbs_failcount_write), },
775 {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read,
776 lbs_bcnmiss_write), },
777 {"high_rssi", 0644, FOPS(lbs_highrssi_read,
778 lbs_highrssi_write), },
779 {"high_snr", 0644, FOPS(lbs_highsnr_read,
780 lbs_highsnr_write), },
783 static const struct lbs_debugfs_files debugfs_regs_files[] = {
784 {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), },
785 {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), },
786 {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), },
787 {"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), },
788 {"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), },
789 {"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), },
792 void lbs_debugfs_init(void)
795 lbs_dir = debugfs_create_dir("lbs_wireless", NULL);
800 void lbs_debugfs_remove(void)
803 debugfs_remove(lbs_dir);
807 void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
810 const struct lbs_debugfs_files *files;
814 priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir);
815 if (!priv->debugfs_dir)
818 for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
819 files = &debugfs_files[i];
820 priv->debugfs_files[i] = debugfs_create_file(files->name,
827 priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
828 if (!priv->events_dir)
831 for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
832 files = &debugfs_events_files[i];
833 priv->debugfs_events_files[i] = debugfs_create_file(files->name,
840 priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
844 for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
845 files = &debugfs_regs_files[i];
846 priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
854 lbs_debug_init(priv);
860 void lbs_debugfs_remove_one(struct lbs_private *priv)
864 for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
865 debugfs_remove(priv->debugfs_regs_files[i]);
867 debugfs_remove(priv->regs_dir);
869 for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
870 debugfs_remove(priv->debugfs_events_files[i]);
872 debugfs_remove(priv->events_dir);
874 debugfs_remove(priv->debugfs_debug);
876 for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
877 debugfs_remove(priv->debugfs_files[i]);
878 debugfs_remove(priv->debugfs_dir);
887 #define item_size(n) (FIELD_SIZEOF(struct lbs_private, n))
888 #define item_addr(n) (offsetof(struct lbs_private, n))
897 /* To debug any member of struct lbs_private, simply add one line here.
899 static struct debug_data items[] = {
900 {"psmode", item_size(psmode), item_addr(psmode)},
901 {"psstate", item_size(psstate), item_addr(psstate)},
904 static int num_of_items = ARRAY_SIZE(items);
907 * @brief proc read function
909 * @param page pointer to buffer
910 * @param s read data starting position
913 * @param eof end of file flag
914 * @param data data to output
915 * @return number of output data
917 static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
918 size_t count, loff_t *ppos)
925 struct debug_data *d;
926 unsigned long addr = get_zeroed_page(GFP_KERNEL);
927 char *buf = (char *)addr;
933 d = (struct debug_data *)file->private_data;
935 for (i = 0; i < num_of_items; i++) {
937 val = *((u8 *) d[i].addr);
938 else if (d[i].size == 2)
939 val = *((u16 *) d[i].addr);
940 else if (d[i].size == 4)
941 val = *((u32 *) d[i].addr);
942 else if (d[i].size == 8)
943 val = *((u64 *) d[i].addr);
945 pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
948 res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
955 * @brief proc write function
957 * @param f file pointer
958 * @param buf pointer to data buffer
959 * @param cnt data number to write
960 * @param data data to write
961 * @return number of data
963 static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
964 size_t cnt, loff_t *ppos)
972 struct debug_data *d = (struct debug_data *)f->private_data;
974 pdata = kmalloc(cnt, GFP_KERNEL);
978 if (copy_from_user(pdata, buf, cnt)) {
979 lbs_deb_debugfs("Copy from user failed\n");
985 for (i = 0; i < num_of_items; i++) {
987 p = strstr(p0, d[i].name);
990 p1 = strchr(p, '\n');
998 r = simple_strtoul(p2, NULL, 0);
1000 *((u8 *) d[i].addr) = (u8) r;
1001 else if (d[i].size == 2)
1002 *((u16 *) d[i].addr) = (u16) r;
1003 else if (d[i].size == 4)
1004 *((u32 *) d[i].addr) = (u32) r;
1005 else if (d[i].size == 8)
1006 *((u64 *) d[i].addr) = (u64) r;
1012 return (ssize_t)cnt;
1015 static const struct file_operations lbs_debug_fops = {
1016 .owner = THIS_MODULE,
1017 .open = open_file_generic,
1018 .write = lbs_debugfs_write,
1019 .read = lbs_debugfs_read,
1023 * @brief create debug proc file
1025 * @param priv pointer struct lbs_private
1026 * @param dev pointer net_device
1029 static void lbs_debug_init(struct lbs_private *priv)
1033 if (!priv->debugfs_dir)
1036 for (i = 0; i < num_of_items; i++)
1037 items[i].addr += (size_t) priv;
1039 priv->debugfs_debug = debugfs_create_file("debug", 0644,
1040 priv->debugfs_dir, &items[0],