sysfs: fix race condition around sd->s_dentry, take#2
[sfrench/cifs-2.6.git] / drivers / net / wireless / libertas / debugfs.c
1 #include <linux/module.h>
2 #include <linux/dcache.h>
3 #include <linux/debugfs.h>
4 #include <linux/delay.h>
5 #include <linux/mm.h>
6 #include <net/iw_handler.h>
7 #include "dev.h"
8 #include "decl.h"
9 #include "host.h"
10 #include "debugfs.h"
11
12 static struct dentry *libertas_dir = NULL;
13 static char *szStates[] = {
14         "Connected",
15         "Disconnected"
16 };
17
18 void libertas_debug_init(wlan_private * priv, struct net_device *dev);
19
20 static int open_file_generic(struct inode *inode, struct file *file)
21 {
22         file->private_data = inode->i_private;
23         return 0;
24 }
25
26 static ssize_t write_file_dummy(struct file *file, const char __user *buf,
27                                 size_t count, loff_t *ppos)
28 {
29         return -EINVAL;
30 }
31
32 static const size_t len = PAGE_SIZE;
33
34 static ssize_t libertas_dev_info(struct file *file, char __user *userbuf,
35                                   size_t count, loff_t *ppos)
36 {
37         wlan_private *priv = file->private_data;
38         size_t pos = 0;
39         unsigned long addr = get_zeroed_page(GFP_KERNEL);
40         char *buf = (char *)addr;
41         ssize_t res;
42
43         pos += snprintf(buf+pos, len-pos, "state = %s\n",
44                                 szStates[priv->adapter->connect_status]);
45         pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
46                                 (u32) priv->adapter->regioncode);
47
48         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
49
50         free_page(addr);
51         return res;
52 }
53
54
55 static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
56                                   size_t count, loff_t *ppos)
57 {
58         wlan_private *priv = file->private_data;
59         size_t pos = 0;
60         int numscansdone = 0, res;
61         unsigned long addr = get_zeroed_page(GFP_KERNEL);
62         char *buf = (char *)addr;
63
64         pos += snprintf(buf+pos, len-pos,
65                         "---------------------------------------");
66         pos += snprintf(buf+pos, len-pos,
67                         "---------------------------------------\n");
68         pos += snprintf(buf+pos, len-pos,
69                 "# | ch  | ss  |       bssid       |   cap    |    TSF   | Qual | SSID \n");
70         pos += snprintf(buf+pos, len-pos,
71                 "---------------------------------------");
72         pos += snprintf(buf+pos, len-pos,
73                 "---------------------------------------\n");
74
75         while (numscansdone < priv->adapter->numinscantable) {
76                 struct bss_descriptor *pbssinfo;
77                 u16 cap;
78
79                 pbssinfo = &priv->adapter->scantable[numscansdone];
80                 memcpy(&cap, &pbssinfo->cap, sizeof(cap));
81                 pos += snprintf(buf+pos, len-pos,
82                         "%02u| %03d | %03ld | %02x:%02x:%02x:%02x:%02x:%02x |",
83                         numscansdone, pbssinfo->channel, pbssinfo->rssi,
84                         pbssinfo->macaddress[0], pbssinfo->macaddress[1],
85                         pbssinfo->macaddress[2], pbssinfo->macaddress[3],
86                         pbssinfo->macaddress[4], pbssinfo->macaddress[5]);
87                 pos += snprintf(buf+pos, len-pos, " %04x-", cap);
88                 pos += snprintf(buf+pos, len-pos, "%c%c%c |",
89                                 pbssinfo->cap.ibss ? 'A' : 'I',
90                                 pbssinfo->cap.privacy ? 'P' : ' ',
91                                 pbssinfo->cap.spectrummgmt ? 'S' : ' ');
92                 pos += snprintf(buf+pos, len-pos, " %08llx |", pbssinfo->networktsf);
93                 pos += snprintf(buf+pos, len-pos, " %d |",
94                         SCAN_RSSI(priv->adapter->scantable[numscansdone].rssi));
95
96                 pos += snprintf(buf+pos, len-pos, " %s\n", pbssinfo->ssid.ssid);
97
98                 numscansdone++;
99         }
100
101         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
102
103         free_page(addr);
104         return res;
105 }
106
107 static ssize_t libertas_sleepparams_write(struct file *file,
108                                 const char __user *user_buf, size_t count,
109                                 loff_t *ppos)
110 {
111         wlan_private *priv = file->private_data;
112         ssize_t buf_size, res;
113         int p1, p2, p3, p4, p5, p6;
114         struct sleep_params sp;
115         unsigned long addr = get_zeroed_page(GFP_KERNEL);
116         char *buf = (char *)addr;
117
118         buf_size = min(count, len - 1);
119         if (copy_from_user(buf, user_buf, buf_size)) {
120                 res = -EFAULT;
121                 goto out_unlock;
122         }
123         res = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
124         if (res != 6) {
125                 res = -EFAULT;
126                 goto out_unlock;
127         }
128         sp.sp_error = p1;
129         sp.sp_offset = p2;
130         sp.sp_stabletime = p3;
131         sp.sp_calcontrol = p4;
132         sp.sp_extsleepclk = p5;
133         sp.sp_reserved = p6;
134
135         memcpy(&priv->adapter->sp, &sp, sizeof(struct sleep_params));
136
137         res = libertas_prepare_and_send_command(priv,
138                                 cmd_802_11_sleep_params,
139                                 cmd_act_set,
140                                 cmd_option_waitforrsp, 0, NULL);
141
142         if (!res)
143                 res = count;
144         else
145                 res = -EINVAL;
146
147 out_unlock:
148         free_page(addr);
149         return res;
150 }
151
152 static ssize_t libertas_sleepparams_read(struct file *file, char __user *userbuf,
153                                   size_t count, loff_t *ppos)
154 {
155         wlan_private *priv = file->private_data;
156         wlan_adapter *adapter = priv->adapter;
157         ssize_t res;
158         size_t pos = 0;
159         unsigned long addr = get_zeroed_page(GFP_KERNEL);
160         char *buf = (char *)addr;
161
162         res = libertas_prepare_and_send_command(priv,
163                                 cmd_802_11_sleep_params,
164                                 cmd_act_get,
165                                 cmd_option_waitforrsp, 0, NULL);
166         if (res) {
167                 res = -EFAULT;
168                 goto out_unlock;
169         }
170
171         pos += snprintf(buf, len, "%d %d %d %d %d %d\n", adapter->sp.sp_error,
172                         adapter->sp.sp_offset, adapter->sp.sp_stabletime,
173                         adapter->sp.sp_calcontrol, adapter->sp.sp_extsleepclk,
174                         adapter->sp.sp_reserved);
175
176         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
177
178 out_unlock:
179         free_page(addr);
180         return res;
181 }
182
183 static ssize_t libertas_extscan(struct file *file, const char __user *userbuf,
184                                   size_t count, loff_t *ppos)
185 {
186         wlan_private *priv = file->private_data;
187         ssize_t res, buf_size;
188         struct WLAN_802_11_SSID extscan_ssid;
189         union iwreq_data wrqu;
190         unsigned long addr = get_zeroed_page(GFP_KERNEL);
191         char *buf = (char *)addr;
192
193         buf_size = min(count, len - 1);
194         if (copy_from_user(buf, userbuf, buf_size)) {
195                 res = -EFAULT;
196                 goto out_unlock;
197         }
198
199         memcpy(&extscan_ssid.ssid, buf, strlen(buf)-1);
200         extscan_ssid.ssidlength = strlen(buf)-1;
201
202         libertas_send_specific_SSID_scan(priv, &extscan_ssid, 1);
203
204         memset(&wrqu, 0, sizeof(union iwreq_data));
205         wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL);
206
207 out_unlock:
208         free_page(addr);
209         return count;
210 }
211
212 static int libertas_parse_chan(char *buf, size_t count,
213                         struct wlan_ioctl_user_scan_cfg *scan_cfg, int dur)
214 {
215         char *start, *end, *hold, *str;
216         int i = 0;
217
218         start = strstr(buf, "chan=");
219         if (!start)
220                 return -EINVAL;
221         start += 5;
222         end = strstr(start, " ");
223         if (!end)
224                 end = buf + count;
225         hold = kzalloc((end - start)+1, GFP_KERNEL);
226         if (!hold)
227                 return -ENOMEM;
228         strncpy(hold, start, end - start);
229         hold[(end-start)+1] = '\0';
230         while(hold && (str = strsep(&hold, ","))) {
231                 int chan;
232                 char band, passive = 0;
233                 sscanf(str, "%d%c%c", &chan, &band, &passive);
234                 scan_cfg->chanlist[i].channumber = chan;
235                 scan_cfg->chanlist[i].scantype = passive ? 1 : 0;
236                 if (band == 'b' || band == 'g')
237                         scan_cfg->chanlist[i].radiotype = 0;
238                 else if (band == 'a')
239                         scan_cfg->chanlist[i].radiotype = 1;
240
241                 scan_cfg->chanlist[i].scantime = dur;
242                 i++;
243         }
244
245         kfree(hold);
246         return i;
247 }
248
249 static void libertas_parse_bssid(char *buf, size_t count,
250                         struct wlan_ioctl_user_scan_cfg *scan_cfg)
251 {
252         char *hold;
253         unsigned int mac[ETH_ALEN];
254         int i;
255
256         hold = strstr(buf, "bssid=");
257         if (!hold)
258                 return;
259         hold += 6;
260         sscanf(hold, "%2x:%2x:%2x:%2x:%2x:%2x", mac, mac+1, mac+2, mac+3,
261                         mac+4, mac+5);
262         for(i=0;i<ETH_ALEN;i++)
263                 scan_cfg->specificBSSID[i] = mac[i];
264 }
265
266 static void libertas_parse_ssid(char *buf, size_t count,
267                         struct wlan_ioctl_user_scan_cfg *scan_cfg)
268 {
269         char *hold, *end;
270         ssize_t size;
271
272         hold = strstr(buf, "ssid=");
273         if (!hold)
274                 return;
275         hold += 5;
276         end = strstr(hold, " ");
277         if (!end)
278                 end = buf + count - 1;
279
280         size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
281         strncpy(scan_cfg->specificSSID, hold, size);
282
283         return;
284 }
285
286 static void libertas_parse_keep(char *buf, size_t count,
287                         struct wlan_ioctl_user_scan_cfg *scan_cfg)
288 {
289         char *hold;
290         int val;
291
292         hold = strstr(buf, "keep=");
293         if (!hold)
294                 return;
295         hold += 5;
296         sscanf(hold, "%d", &val);
297
298         if (val != 0)
299                 val = 1;
300
301         scan_cfg->keeppreviousscan = val;
302         return;
303 }
304
305 static int libertas_parse_dur(char *buf, size_t count,
306                         struct wlan_ioctl_user_scan_cfg *scan_cfg)
307 {
308         char *hold;
309         int val;
310
311         hold = strstr(buf, "dur=");
312         if (!hold)
313                 return 0;
314         hold += 4;
315         sscanf(hold, "%d", &val);
316
317         return val;
318 }
319
320 static void libertas_parse_probes(char *buf, size_t count,
321                         struct wlan_ioctl_user_scan_cfg *scan_cfg)
322 {
323         char *hold;
324         int val;
325
326         hold = strstr(buf, "probes=");
327         if (!hold)
328                 return;
329         hold += 7;
330         sscanf(hold, "%d", &val);
331
332         scan_cfg->numprobes = val;
333
334         return;
335 }
336
337 static void libertas_parse_type(char *buf, size_t count,
338                         struct wlan_ioctl_user_scan_cfg *scan_cfg)
339 {
340         char *hold;
341         int val;
342
343         hold = strstr(buf, "type=");
344         if (!hold)
345                 return;
346         hold += 5;
347         sscanf(hold, "%d", &val);
348
349         /* type=1,2 or 3 */
350         if (val < 1 || val > 3)
351                 return;
352
353         scan_cfg->bsstype = val;
354
355         return;
356 }
357
358 static ssize_t libertas_setuserscan(struct file *file,
359                                     const char __user *userbuf,
360                                     size_t count, loff_t *ppos)
361 {
362         wlan_private *priv = file->private_data;
363         ssize_t res, buf_size;
364         struct wlan_ioctl_user_scan_cfg *scan_cfg;
365         union iwreq_data wrqu;
366         int dur;
367         unsigned long addr = get_zeroed_page(GFP_KERNEL);
368         char *buf = (char *)addr;
369
370         scan_cfg = kzalloc(sizeof(struct wlan_ioctl_user_scan_cfg), GFP_KERNEL);
371         if (!scan_cfg)
372                 return -ENOMEM;
373
374         buf_size = min(count, len - 1);
375         if (copy_from_user(buf, userbuf, buf_size)) {
376                 res = -EFAULT;
377                 goto out_unlock;
378         }
379
380         scan_cfg->bsstype = WLAN_SCAN_BSS_TYPE_ANY;
381
382         dur = libertas_parse_dur(buf, count, scan_cfg);
383         libertas_parse_chan(buf, count, scan_cfg, dur);
384         libertas_parse_bssid(buf, count, scan_cfg);
385         libertas_parse_ssid(buf, count, scan_cfg);
386         libertas_parse_keep(buf, count, scan_cfg);
387         libertas_parse_probes(buf, count, scan_cfg);
388         libertas_parse_type(buf, count, scan_cfg);
389
390         wlan_scan_networks(priv, scan_cfg);
391         wait_event_interruptible(priv->adapter->cmd_pending,
392                                  !priv->adapter->nr_cmd_pending);
393
394         memset(&wrqu, 0x00, sizeof(union iwreq_data));
395         wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL);
396
397 out_unlock:
398         free_page(addr);
399         kfree(scan_cfg);
400         return count;
401 }
402
403 static int libertas_event_initcmd(wlan_private *priv, void **response_buf,
404                         struct cmd_ctrl_node **cmdnode,
405                         struct cmd_ds_command **cmd)
406 {
407         u16 wait_option = cmd_option_waitforrsp;
408
409         if (!(*cmdnode = libertas_get_free_cmd_ctrl_node(priv))) {
410                 lbs_pr_debug(1, "failed libertas_get_free_cmd_ctrl_node\n");
411                 return -ENOMEM;
412         }
413         if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) {
414                 lbs_pr_debug(1, "failed to allocate response buffer!\n");
415                 return -ENOMEM;
416         }
417         libertas_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL);
418         init_waitqueue_head(&(*cmdnode)->cmdwait_q);
419         (*cmdnode)->pdata_buf = *response_buf;
420         (*cmdnode)->cmdflags |= CMD_F_HOSTCMD;
421         (*cmdnode)->cmdwaitqwoken = 0;
422         *cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr;
423         (*cmd)->command = cmd_802_11_subscribe_event;
424         (*cmd)->seqnum = ++priv->adapter->seqnum;
425         (*cmd)->result = 0;
426         return 0;
427 }
428
429 static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf,
430                                   size_t count, loff_t *ppos)
431 {
432         wlan_private *priv = file->private_data;
433         wlan_adapter *adapter = priv->adapter;
434         struct cmd_ctrl_node *pcmdnode;
435         struct cmd_ds_command *pcmdptr;
436         struct cmd_ds_802_11_subscribe_event *event;
437         void *response_buf;
438         int res, cmd_len;
439         ssize_t pos = 0;
440         unsigned long addr = get_zeroed_page(GFP_KERNEL);
441         char *buf = (char *)addr;
442
443         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
444         if (res < 0) {
445                 free_page(addr);
446                 return res;
447         }
448
449         event = &pcmdptr->params.subscribe_event;
450         event->action = cmd_act_get;
451         pcmdptr->size =
452         cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
453         libertas_queue_cmd(adapter, pcmdnode, 1);
454         wake_up_interruptible(&priv->mainthread.waitq);
455
456         /* Sleep until response is generated by FW */
457         wait_event_interruptible(pcmdnode->cmdwait_q,
458                                 pcmdnode->cmdwaitqwoken);
459
460         pcmdptr = response_buf;
461         if (pcmdptr->result) {
462                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
463                         pcmdptr->result);
464                 kfree(response_buf);
465                 free_page(addr);
466                 return 0;
467         }
468
469         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
470                 lbs_pr_err("command response incorrect!\n");
471                 kfree(response_buf);
472                 free_page(addr);
473                 return 0;
474         }
475
476         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
477         event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
478         while (cmd_len < pcmdptr->size) {
479                 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
480                 switch(header->type) {
481                 struct mrvlietypes_rssithreshold  *Lowrssi;
482                 case TLV_TYPE_RSSI_LOW:
483                 Lowrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
484                 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
485                                 Lowrssi->rssivalue,
486                                 Lowrssi->rssifreq,
487                                 (event->events & 0x0001)?1:0);
488                 default:
489                         cmd_len += sizeof(struct mrvlietypes_snrthreshold);
490                         break;
491                 }
492         }
493
494         kfree(response_buf);
495         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
496         free_page(addr);
497         return res;
498 }
499
500 static u16 libertas_get_events_bitmap(wlan_private *priv)
501 {
502         wlan_adapter *adapter = priv->adapter;
503         struct cmd_ctrl_node *pcmdnode;
504         struct cmd_ds_command *pcmdptr;
505         struct cmd_ds_802_11_subscribe_event *event;
506         void *response_buf;
507         int res;
508         u16 event_bitmap;
509
510         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
511         if (res < 0)
512                 return res;
513
514         event = &pcmdptr->params.subscribe_event;
515         event->action = cmd_act_get;
516         pcmdptr->size =
517         cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
518         libertas_queue_cmd(adapter, pcmdnode, 1);
519         wake_up_interruptible(&priv->mainthread.waitq);
520
521         /* Sleep until response is generated by FW */
522         wait_event_interruptible(pcmdnode->cmdwait_q,
523                                 pcmdnode->cmdwaitqwoken);
524
525         pcmdptr = response_buf;
526
527         if (pcmdptr->result) {
528                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
529                         pcmdptr->result);
530                 kfree(response_buf);
531                 return 0;
532         }
533
534         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
535                 lbs_pr_err("command response incorrect!\n");
536                 kfree(response_buf);
537                 return 0;
538         }
539
540         event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
541         event_bitmap = event->events;
542         kfree(response_buf);
543         return event_bitmap;
544 }
545
546 static ssize_t libertas_lowrssi_write(struct file *file,
547                                     const char __user *userbuf,
548                                     size_t count, loff_t *ppos)
549 {
550         wlan_private *priv = file->private_data;
551         wlan_adapter *adapter = priv->adapter;
552         ssize_t res, buf_size;
553         int value, freq, subscribed, cmd_len;
554         struct cmd_ctrl_node *pcmdnode;
555         struct cmd_ds_command *pcmdptr;
556         struct cmd_ds_802_11_subscribe_event *event;
557         struct mrvlietypes_rssithreshold *rssi_threshold;
558         void *response_buf;
559         u16 event_bitmap;
560         u8 *ptr;
561         unsigned long addr = get_zeroed_page(GFP_KERNEL);
562         char *buf = (char *)addr;
563
564         buf_size = min(count, len - 1);
565         if (copy_from_user(buf, userbuf, buf_size)) {
566                 res = -EFAULT;
567                 goto out_unlock;
568         }
569         res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
570         if (res != 3) {
571                 res = -EFAULT;
572                 goto out_unlock;
573         }
574
575         event_bitmap = libertas_get_events_bitmap(priv);
576
577         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
578         if (res < 0)
579                 goto out_unlock;
580
581         event = &pcmdptr->params.subscribe_event;
582         event->action = cmd_act_set;
583         pcmdptr->size = cpu_to_le16(S_DS_GEN +
584                 sizeof(struct cmd_ds_802_11_subscribe_event) +
585                 sizeof(struct mrvlietypes_rssithreshold));
586
587         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
588         ptr = (u8*) pcmdptr+cmd_len;
589         rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
590         rssi_threshold->header.type = cpu_to_le16(0x0104);
591         rssi_threshold->header.len = 2;
592         rssi_threshold->rssivalue = cpu_to_le16(value);
593         rssi_threshold->rssifreq = cpu_to_le16(freq);
594         event_bitmap |= subscribed ? 0x0001 : 0x0;
595         event->events = event_bitmap;
596
597         libertas_queue_cmd(adapter, pcmdnode, 1);
598         wake_up_interruptible(&priv->mainthread.waitq);
599
600         /* Sleep until response is generated by FW */
601         wait_event_interruptible(pcmdnode->cmdwait_q,
602                                 pcmdnode->cmdwaitqwoken);
603
604         pcmdptr = response_buf;
605
606         if (pcmdptr->result) {
607                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
608                         pcmdptr->result);
609                 kfree(response_buf);
610                 free_page(addr);
611                 return 0;
612         }
613
614         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
615                 lbs_pr_err("command response incorrect!\n");
616                 kfree(response_buf);
617                 free_page(addr);
618                 return 0;
619         }
620
621         res = count;
622 out_unlock:
623         free_page(addr);
624         return res;
625 }
626
627 static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf,
628                                   size_t count, loff_t *ppos)
629 {
630         wlan_private *priv = file->private_data;
631         wlan_adapter *adapter = priv->adapter;
632         struct cmd_ctrl_node *pcmdnode;
633         struct cmd_ds_command *pcmdptr;
634         struct cmd_ds_802_11_subscribe_event *event;
635         void *response_buf;
636         int res, cmd_len;
637         ssize_t pos = 0;
638         unsigned long addr = get_zeroed_page(GFP_KERNEL);
639         char *buf = (char *)addr;
640
641         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
642         if (res < 0) {
643                 free_page(addr);
644                 return res;
645         }
646
647         event = &pcmdptr->params.subscribe_event;
648         event->action = cmd_act_get;
649         pcmdptr->size =
650         cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
651         libertas_queue_cmd(adapter, pcmdnode, 1);
652         wake_up_interruptible(&priv->mainthread.waitq);
653
654         /* Sleep until response is generated by FW */
655         wait_event_interruptible(pcmdnode->cmdwait_q,
656                                 pcmdnode->cmdwaitqwoken);
657
658         pcmdptr = response_buf;
659
660         if (pcmdptr->result) {
661                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
662                         pcmdptr->result);
663                 kfree(response_buf);
664                 free_page(addr);
665                 return 0;
666         }
667
668         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
669                 lbs_pr_err("command response incorrect!\n");
670                 kfree(response_buf);
671                 free_page(addr);
672                 return 0;
673         }
674
675         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
676         event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
677         while (cmd_len < pcmdptr->size) {
678                 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
679                 switch(header->type) {
680                 struct mrvlietypes_snrthreshold *LowSnr;
681                 case TLV_TYPE_SNR_LOW:
682                 LowSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
683                 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
684                                 LowSnr->snrvalue,
685                                 LowSnr->snrfreq,
686                                 (event->events & 0x0002)?1:0);
687                 default:
688                         cmd_len += sizeof(struct mrvlietypes_snrthreshold);
689                         break;
690                 }
691         }
692
693         kfree(response_buf);
694
695         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
696         free_page(addr);
697         return res;
698 }
699
700 static ssize_t libertas_lowsnr_write(struct file *file,
701                                     const char __user *userbuf,
702                                     size_t count, loff_t *ppos)
703 {
704         wlan_private *priv = file->private_data;
705         wlan_adapter *adapter = priv->adapter;
706         ssize_t res, buf_size;
707         int value, freq, subscribed, cmd_len;
708         struct cmd_ctrl_node *pcmdnode;
709         struct cmd_ds_command *pcmdptr;
710         struct cmd_ds_802_11_subscribe_event *event;
711         struct mrvlietypes_snrthreshold *snr_threshold;
712         void *response_buf;
713         u16 event_bitmap;
714         u8 *ptr;
715         unsigned long addr = get_zeroed_page(GFP_KERNEL);
716         char *buf = (char *)addr;
717
718         buf_size = min(count, len - 1);
719         if (copy_from_user(buf, userbuf, buf_size)) {
720                 res = -EFAULT;
721                 goto out_unlock;
722         }
723         res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
724         if (res != 3) {
725                 res = -EFAULT;
726                 goto out_unlock;
727         }
728
729         event_bitmap = libertas_get_events_bitmap(priv);
730
731         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
732         if (res < 0)
733                 goto out_unlock;
734
735         event = &pcmdptr->params.subscribe_event;
736         event->action = cmd_act_set;
737         pcmdptr->size = cpu_to_le16(S_DS_GEN +
738                 sizeof(struct cmd_ds_802_11_subscribe_event) +
739                 sizeof(struct mrvlietypes_snrthreshold));
740         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
741         ptr = (u8*) pcmdptr+cmd_len;
742         snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
743         snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW);
744         snr_threshold->header.len = 2;
745         snr_threshold->snrvalue = cpu_to_le16(value);
746         snr_threshold->snrfreq = cpu_to_le16(freq);
747         event_bitmap |= subscribed ? 0x0002 : 0x0;
748         event->events = event_bitmap;
749
750         libertas_queue_cmd(adapter, pcmdnode, 1);
751         wake_up_interruptible(&priv->mainthread.waitq);
752
753         /* Sleep until response is generated by FW */
754         wait_event_interruptible(pcmdnode->cmdwait_q,
755                                 pcmdnode->cmdwaitqwoken);
756
757         pcmdptr = response_buf;
758
759         if (pcmdptr->result) {
760                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
761                         pcmdptr->result);
762                 kfree(response_buf);
763                 free_page(addr);
764                 return 0;
765         }
766
767         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
768                 lbs_pr_err("command response incorrect!\n");
769                 kfree(response_buf);
770                 free_page(addr);
771                 return 0;
772         }
773
774         res = count;
775
776 out_unlock:
777         free_page(addr);
778         return res;
779 }
780
781 static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf,
782                                   size_t count, loff_t *ppos)
783 {
784         wlan_private *priv = file->private_data;
785         wlan_adapter *adapter = priv->adapter;
786         struct cmd_ctrl_node *pcmdnode;
787         struct cmd_ds_command *pcmdptr;
788         struct cmd_ds_802_11_subscribe_event *event;
789         void *response_buf;
790         int res, cmd_len;
791         ssize_t pos = 0;
792         unsigned long addr = get_zeroed_page(GFP_KERNEL);
793         char *buf = (char *)addr;
794
795         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
796         if (res < 0) {
797                 free_page(addr);
798                 return res;
799         }
800
801         event = &pcmdptr->params.subscribe_event;
802         event->action = cmd_act_get;
803         pcmdptr->size =
804         cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
805         libertas_queue_cmd(adapter, pcmdnode, 1);
806         wake_up_interruptible(&priv->mainthread.waitq);
807
808         /* Sleep until response is generated by FW */
809         wait_event_interruptible(pcmdnode->cmdwait_q,
810                                 pcmdnode->cmdwaitqwoken);
811
812         pcmdptr = response_buf;
813
814         if (pcmdptr->result) {
815                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
816                         pcmdptr->result);
817                 kfree(response_buf);
818                 free_page(addr);
819                 return 0;
820         }
821
822         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
823                 lbs_pr_err("command response incorrect!\n");
824                 kfree(response_buf);
825                 free_page(addr);
826                 return 0;
827         }
828
829         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
830         event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
831         while (cmd_len < pcmdptr->size) {
832                 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
833                 switch(header->type) {
834                 struct mrvlietypes_failurecount *failcount;
835                 case TLV_TYPE_FAILCOUNT:
836                 failcount = (struct mrvlietypes_failurecount *)(response_buf + cmd_len);
837                 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
838                                 failcount->failvalue,
839                                 failcount->Failfreq,
840                                 (event->events & 0x0004)?1:0);
841                 default:
842                         cmd_len += sizeof(struct mrvlietypes_failurecount);
843                         break;
844                 }
845         }
846
847         kfree(response_buf);
848         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
849         free_page(addr);
850         return res;
851 }
852
853 static ssize_t libertas_failcount_write(struct file *file,
854                                     const char __user *userbuf,
855                                     size_t count, loff_t *ppos)
856 {
857         wlan_private *priv = file->private_data;
858         wlan_adapter *adapter = priv->adapter;
859         ssize_t res, buf_size;
860         int value, freq, subscribed, cmd_len;
861         struct cmd_ctrl_node *pcmdnode;
862         struct cmd_ds_command *pcmdptr;
863         struct cmd_ds_802_11_subscribe_event *event;
864         struct mrvlietypes_failurecount *failcount;
865         void *response_buf;
866         u16 event_bitmap;
867         u8 *ptr;
868         unsigned long addr = get_zeroed_page(GFP_KERNEL);
869         char *buf = (char *)addr;
870
871         buf_size = min(count, len - 1);
872         if (copy_from_user(buf, userbuf, buf_size)) {
873                 res = -EFAULT;
874                 goto out_unlock;
875         }
876         res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
877         if (res != 3) {
878                 res = -EFAULT;
879                 goto out_unlock;
880         }
881
882         event_bitmap = libertas_get_events_bitmap(priv);
883
884         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
885         if (res < 0)
886                 goto out_unlock;
887
888         event = &pcmdptr->params.subscribe_event;
889         event->action = cmd_act_set;
890         pcmdptr->size = cpu_to_le16(S_DS_GEN +
891                 sizeof(struct cmd_ds_802_11_subscribe_event) +
892                 sizeof(struct mrvlietypes_failurecount));
893         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
894         ptr = (u8*) pcmdptr+cmd_len;
895         failcount = (struct mrvlietypes_failurecount *)(ptr);
896         failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
897         failcount->header.len = 2;
898         failcount->failvalue = cpu_to_le16(value);
899         failcount->Failfreq = cpu_to_le16(freq);
900         event_bitmap |= subscribed ? 0x0004 : 0x0;
901         event->events = event_bitmap;
902
903         libertas_queue_cmd(adapter, pcmdnode, 1);
904         wake_up_interruptible(&priv->mainthread.waitq);
905
906         /* Sleep until response is generated by FW */
907         wait_event_interruptible(pcmdnode->cmdwait_q,
908                                 pcmdnode->cmdwaitqwoken);
909
910         pcmdptr = (struct cmd_ds_command *)response_buf;
911
912         if (pcmdptr->result) {
913                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
914                         pcmdptr->result);
915                 kfree(response_buf);
916                 free_page(addr);
917                 return 0;
918         }
919
920         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
921                 lbs_pr_err("command response incorrect!\n");
922                 kfree(response_buf);
923                 free_page(addr);
924                 return 0;
925         }
926
927         res = count;
928 out_unlock:
929         free_page(addr);
930         return res;
931 }
932
933 static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf,
934                                   size_t count, loff_t *ppos)
935 {
936         wlan_private *priv = file->private_data;
937         wlan_adapter *adapter = priv->adapter;
938         struct cmd_ctrl_node *pcmdnode;
939         struct cmd_ds_command *pcmdptr;
940         struct cmd_ds_802_11_subscribe_event *event;
941         void *response_buf;
942         int res, cmd_len;
943         ssize_t pos = 0;
944         unsigned long addr = get_zeroed_page(GFP_KERNEL);
945         char *buf = (char *)addr;
946
947         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
948         if (res < 0) {
949                 free_page(addr);
950                 return res;
951         }
952
953         event = &pcmdptr->params.subscribe_event;
954         event->action = cmd_act_get;
955         pcmdptr->size =
956         cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
957         libertas_queue_cmd(adapter, pcmdnode, 1);
958         wake_up_interruptible(&priv->mainthread.waitq);
959
960         /* Sleep until response is generated by FW */
961         wait_event_interruptible(pcmdnode->cmdwait_q,
962                                 pcmdnode->cmdwaitqwoken);
963
964         pcmdptr = response_buf;
965
966         if (pcmdptr->result) {
967                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
968                         pcmdptr->result);
969                 free_page(addr);
970                 kfree(response_buf);
971                 return 0;
972         }
973
974         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
975                 lbs_pr_err("command response incorrect!\n");
976                 free_page(addr);
977                 kfree(response_buf);
978                 return 0;
979         }
980
981         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
982         event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
983         while (cmd_len < pcmdptr->size) {
984                 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
985                 switch(header->type) {
986                 struct mrvlietypes_beaconsmissed *bcnmiss;
987                 case TLV_TYPE_BCNMISS:
988                 bcnmiss = (struct mrvlietypes_beaconsmissed *)(response_buf + cmd_len);
989                 pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
990                                 bcnmiss->beaconmissed,
991                                 (event->events & 0x0008)?1:0);
992                 default:
993                         cmd_len += sizeof(struct mrvlietypes_beaconsmissed);
994                         break;
995                 }
996         }
997
998         kfree(response_buf);
999
1000         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1001         free_page(addr);
1002         return res;
1003 }
1004
1005 static ssize_t libertas_bcnmiss_write(struct file *file,
1006                                     const char __user *userbuf,
1007                                     size_t count, loff_t *ppos)
1008 {
1009         wlan_private *priv = file->private_data;
1010         wlan_adapter *adapter = priv->adapter;
1011         ssize_t res, buf_size;
1012         int value, freq, subscribed, cmd_len;
1013         struct cmd_ctrl_node *pcmdnode;
1014         struct cmd_ds_command *pcmdptr;
1015         struct cmd_ds_802_11_subscribe_event *event;
1016         struct mrvlietypes_beaconsmissed *bcnmiss;
1017         void *response_buf;
1018         u16 event_bitmap;
1019         u8 *ptr;
1020         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1021         char *buf = (char *)addr;
1022
1023         buf_size = min(count, len - 1);
1024         if (copy_from_user(buf, userbuf, buf_size)) {
1025                 res = -EFAULT;
1026                 goto out_unlock;
1027         }
1028         res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1029         if (res != 3) {
1030                 res = -EFAULT;
1031                 goto out_unlock;
1032         }
1033
1034         event_bitmap = libertas_get_events_bitmap(priv);
1035
1036         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1037         if (res < 0)
1038                 goto out_unlock;
1039
1040         event = &pcmdptr->params.subscribe_event;
1041         event->action = cmd_act_set;
1042         pcmdptr->size = cpu_to_le16(S_DS_GEN +
1043                 sizeof(struct cmd_ds_802_11_subscribe_event) +
1044                 sizeof(struct mrvlietypes_beaconsmissed));
1045         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1046         ptr = (u8*) pcmdptr+cmd_len;
1047         bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr);
1048         bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS);
1049         bcnmiss->header.len = 2;
1050         bcnmiss->beaconmissed = cpu_to_le16(value);
1051         event_bitmap |= subscribed ? 0x0008 : 0x0;
1052         event->events = event_bitmap;
1053
1054         libertas_queue_cmd(adapter, pcmdnode, 1);
1055         wake_up_interruptible(&priv->mainthread.waitq);
1056
1057         /* Sleep until response is generated by FW */
1058         wait_event_interruptible(pcmdnode->cmdwait_q,
1059                                 pcmdnode->cmdwaitqwoken);
1060
1061         pcmdptr = response_buf;
1062
1063         if (pcmdptr->result) {
1064                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1065                         pcmdptr->result);
1066                 kfree(response_buf);
1067                 free_page(addr);
1068                 return 0;
1069         }
1070
1071         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1072                 lbs_pr_err("command response incorrect!\n");
1073                 free_page(addr);
1074                 kfree(response_buf);
1075                 return 0;
1076         }
1077
1078         res = count;
1079 out_unlock:
1080         free_page(addr);
1081         return res;
1082 }
1083
1084 static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf,
1085                                   size_t count, loff_t *ppos)
1086 {
1087         wlan_private *priv = file->private_data;
1088         wlan_adapter *adapter = priv->adapter;
1089         struct cmd_ctrl_node *pcmdnode;
1090         struct cmd_ds_command *pcmdptr;
1091         struct cmd_ds_802_11_subscribe_event *event;
1092         void *response_buf;
1093         int res, cmd_len;
1094         ssize_t pos = 0;
1095         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1096         char *buf = (char *)addr;
1097
1098         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1099         if (res < 0) {
1100                 free_page(addr);
1101                 return res;
1102         }
1103
1104         event = &pcmdptr->params.subscribe_event;
1105         event->action = cmd_act_get;
1106         pcmdptr->size =
1107         cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
1108         libertas_queue_cmd(adapter, pcmdnode, 1);
1109         wake_up_interruptible(&priv->mainthread.waitq);
1110
1111         /* Sleep until response is generated by FW */
1112         wait_event_interruptible(pcmdnode->cmdwait_q,
1113                                 pcmdnode->cmdwaitqwoken);
1114
1115         pcmdptr = response_buf;
1116
1117         if (pcmdptr->result) {
1118                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1119                         pcmdptr->result);
1120                 kfree(response_buf);
1121                 free_page(addr);
1122                 return 0;
1123         }
1124
1125         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1126                 lbs_pr_err("command response incorrect!\n");
1127                 kfree(response_buf);
1128                 free_page(addr);
1129                 return 0;
1130         }
1131
1132         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1133         event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
1134         while (cmd_len < pcmdptr->size) {
1135                 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
1136                 switch(header->type) {
1137                 struct mrvlietypes_rssithreshold  *Highrssi;
1138                 case TLV_TYPE_RSSI_HIGH:
1139                 Highrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
1140                 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
1141                                 Highrssi->rssivalue,
1142                                 Highrssi->rssifreq,
1143                                 (event->events & 0x0010)?1:0);
1144                 default:
1145                         cmd_len += sizeof(struct mrvlietypes_snrthreshold);
1146                         break;
1147                 }
1148         }
1149
1150         kfree(response_buf);
1151
1152         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1153         free_page(addr);
1154         return res;
1155 }
1156
1157 static ssize_t libertas_highrssi_write(struct file *file,
1158                                     const char __user *userbuf,
1159                                     size_t count, loff_t *ppos)
1160 {
1161         wlan_private *priv = file->private_data;
1162         wlan_adapter *adapter = priv->adapter;
1163         ssize_t res, buf_size;
1164         int value, freq, subscribed, cmd_len;
1165         struct cmd_ctrl_node *pcmdnode;
1166         struct cmd_ds_command *pcmdptr;
1167         struct cmd_ds_802_11_subscribe_event *event;
1168         struct mrvlietypes_rssithreshold *rssi_threshold;
1169         void *response_buf;
1170         u16 event_bitmap;
1171         u8 *ptr;
1172         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1173         char *buf = (char *)addr;
1174
1175         buf_size = min(count, len - 1);
1176         if (copy_from_user(buf, userbuf, buf_size)) {
1177                 res = -EFAULT;
1178                 goto out_unlock;
1179         }
1180         res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1181         if (res != 3) {
1182                 res = -EFAULT;
1183                 goto out_unlock;
1184         }
1185
1186         event_bitmap = libertas_get_events_bitmap(priv);
1187
1188         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1189         if (res < 0)
1190                 goto out_unlock;
1191
1192         event = &pcmdptr->params.subscribe_event;
1193         event->action = cmd_act_set;
1194         pcmdptr->size = cpu_to_le16(S_DS_GEN +
1195                 sizeof(struct cmd_ds_802_11_subscribe_event) +
1196                 sizeof(struct mrvlietypes_rssithreshold));
1197         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1198         ptr = (u8*) pcmdptr+cmd_len;
1199         rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
1200         rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
1201         rssi_threshold->header.len = 2;
1202         rssi_threshold->rssivalue = cpu_to_le16(value);
1203         rssi_threshold->rssifreq = cpu_to_le16(freq);
1204         event_bitmap |= subscribed ? 0x0010 : 0x0;
1205         event->events = event_bitmap;
1206
1207         libertas_queue_cmd(adapter, pcmdnode, 1);
1208         wake_up_interruptible(&priv->mainthread.waitq);
1209
1210         /* Sleep until response is generated by FW */
1211         wait_event_interruptible(pcmdnode->cmdwait_q,
1212                                 pcmdnode->cmdwaitqwoken);
1213
1214         pcmdptr = response_buf;
1215
1216         if (pcmdptr->result) {
1217                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1218                         pcmdptr->result);
1219                 kfree(response_buf);
1220                 return 0;
1221         }
1222
1223         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1224                 lbs_pr_err("command response incorrect!\n");
1225                 kfree(response_buf);
1226                 return 0;
1227         }
1228
1229         res = count;
1230 out_unlock:
1231         free_page(addr);
1232         return res;
1233 }
1234
1235 static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf,
1236                                   size_t count, loff_t *ppos)
1237 {
1238         wlan_private *priv = file->private_data;
1239         wlan_adapter *adapter = priv->adapter;
1240         struct cmd_ctrl_node *pcmdnode;
1241         struct cmd_ds_command *pcmdptr;
1242         struct cmd_ds_802_11_subscribe_event *event;
1243         void *response_buf;
1244         int res, cmd_len;
1245         ssize_t pos = 0;
1246         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1247         char *buf = (char *)addr;
1248
1249         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1250         if (res < 0) {
1251                 free_page(addr);
1252                 return res;
1253         }
1254
1255         event = &pcmdptr->params.subscribe_event;
1256         event->action = cmd_act_get;
1257         pcmdptr->size =
1258         cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
1259         libertas_queue_cmd(adapter, pcmdnode, 1);
1260         wake_up_interruptible(&priv->mainthread.waitq);
1261
1262         /* Sleep until response is generated by FW */
1263         wait_event_interruptible(pcmdnode->cmdwait_q,
1264                                 pcmdnode->cmdwaitqwoken);
1265
1266         pcmdptr = response_buf;
1267
1268         if (pcmdptr->result) {
1269                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1270                         pcmdptr->result);
1271                 kfree(response_buf);
1272                 free_page(addr);
1273                 return 0;
1274         }
1275
1276         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1277                 lbs_pr_err("command response incorrect!\n");
1278                 kfree(response_buf);
1279                 free_page(addr);
1280                 return 0;
1281         }
1282
1283         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1284         event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
1285         while (cmd_len < pcmdptr->size) {
1286                 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
1287                 switch(header->type) {
1288                 struct mrvlietypes_snrthreshold *HighSnr;
1289                 case TLV_TYPE_SNR_HIGH:
1290                 HighSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
1291                 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
1292                                 HighSnr->snrvalue,
1293                                 HighSnr->snrfreq,
1294                                 (event->events & 0x0020)?1:0);
1295                 default:
1296                         cmd_len += sizeof(struct mrvlietypes_snrthreshold);
1297                         break;
1298                 }
1299         }
1300
1301         kfree(response_buf);
1302
1303         res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1304         free_page(addr);
1305         return res;
1306 }
1307
1308 static ssize_t libertas_highsnr_write(struct file *file,
1309                                     const char __user *userbuf,
1310                                     size_t count, loff_t *ppos)
1311 {
1312         wlan_private *priv = file->private_data;
1313         wlan_adapter *adapter = priv->adapter;
1314         ssize_t res, buf_size;
1315         int value, freq, subscribed, cmd_len;
1316         struct cmd_ctrl_node *pcmdnode;
1317         struct cmd_ds_command *pcmdptr;
1318         struct cmd_ds_802_11_subscribe_event *event;
1319         struct mrvlietypes_snrthreshold *snr_threshold;
1320         void *response_buf;
1321         u16 event_bitmap;
1322         u8 *ptr;
1323         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1324         char *buf = (char *)addr;
1325
1326         buf_size = min(count, len - 1);
1327         if (copy_from_user(buf, userbuf, buf_size)) {
1328                 res = -EFAULT;
1329                 goto out_unlock;
1330         }
1331         res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1332         if (res != 3) {
1333                 res = -EFAULT;
1334                 goto out_unlock;
1335         }
1336
1337         event_bitmap = libertas_get_events_bitmap(priv);
1338
1339         res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1340         if (res < 0)
1341                 goto out_unlock;
1342
1343         event = &pcmdptr->params.subscribe_event;
1344         event->action = cmd_act_set;
1345         pcmdptr->size = cpu_to_le16(S_DS_GEN +
1346                 sizeof(struct cmd_ds_802_11_subscribe_event) +
1347                 sizeof(struct mrvlietypes_snrthreshold));
1348         cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1349         ptr = (u8*) pcmdptr+cmd_len;
1350         snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
1351         snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH);
1352         snr_threshold->header.len = 2;
1353         snr_threshold->snrvalue = cpu_to_le16(value);
1354         snr_threshold->snrfreq = cpu_to_le16(freq);
1355         event_bitmap |= subscribed ? 0x0020 : 0x0;
1356         event->events = event_bitmap;
1357
1358         libertas_queue_cmd(adapter, pcmdnode, 1);
1359         wake_up_interruptible(&priv->mainthread.waitq);
1360
1361         /* Sleep until response is generated by FW */
1362         wait_event_interruptible(pcmdnode->cmdwait_q,
1363                                 pcmdnode->cmdwaitqwoken);
1364
1365         pcmdptr = response_buf;
1366
1367         if (pcmdptr->result) {
1368                 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1369                         pcmdptr->result);
1370                 kfree(response_buf);
1371                 free_page(addr);
1372                 return 0;
1373         }
1374
1375         if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1376                 lbs_pr_err("command response incorrect!\n");
1377                 kfree(response_buf);
1378                 free_page(addr);
1379                 return 0;
1380         }
1381
1382         res = count;
1383 out_unlock:
1384         free_page(addr);
1385         return res;
1386 }
1387
1388 static ssize_t libertas_rdmac_read(struct file *file, char __user *userbuf,
1389                                   size_t count, loff_t *ppos)
1390 {
1391         wlan_private *priv = file->private_data;
1392         wlan_adapter *adapter = priv->adapter;
1393         struct wlan_offset_value offval;
1394         ssize_t pos = 0;
1395         int ret;
1396         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1397         char *buf = (char *)addr;
1398
1399         offval.offset = priv->mac_offset;
1400         offval.value = 0;
1401
1402         ret = libertas_prepare_and_send_command(priv,
1403                                 cmd_mac_reg_access, 0,
1404                                 cmd_option_waitforrsp, 0, &offval);
1405         mdelay(10);
1406         pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
1407                                 priv->mac_offset, adapter->offsetvalue.value);
1408
1409         ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1410         free_page(addr);
1411         return ret;
1412 }
1413
1414 static ssize_t libertas_rdmac_write(struct file *file,
1415                                     const char __user *userbuf,
1416                                     size_t count, loff_t *ppos)
1417 {
1418         wlan_private *priv = file->private_data;
1419         ssize_t res, buf_size;
1420         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1421         char *buf = (char *)addr;
1422
1423         buf_size = min(count, len - 1);
1424         if (copy_from_user(buf, userbuf, buf_size)) {
1425                 res = -EFAULT;
1426                 goto out_unlock;
1427         }
1428         priv->mac_offset = simple_strtoul((char *)buf, NULL, 16);
1429         res = count;
1430 out_unlock:
1431         free_page(addr);
1432         return res;
1433 }
1434
1435 static ssize_t libertas_wrmac_write(struct file *file,
1436                                     const char __user *userbuf,
1437                                     size_t count, loff_t *ppos)
1438 {
1439
1440         wlan_private *priv = file->private_data;
1441         ssize_t res, buf_size;
1442         u32 offset, value;
1443         struct wlan_offset_value offval;
1444         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1445         char *buf = (char *)addr;
1446
1447         buf_size = min(count, len - 1);
1448         if (copy_from_user(buf, userbuf, buf_size)) {
1449                 res = -EFAULT;
1450                 goto out_unlock;
1451         }
1452         res = sscanf(buf, "%x %x", &offset, &value);
1453         if (res != 2) {
1454                 res = -EFAULT;
1455                 goto out_unlock;
1456         }
1457
1458         offval.offset = offset;
1459         offval.value = value;
1460         res = libertas_prepare_and_send_command(priv,
1461                                 cmd_mac_reg_access, 1,
1462                                 cmd_option_waitforrsp, 0, &offval);
1463         mdelay(10);
1464
1465         res = count;
1466 out_unlock:
1467         free_page(addr);
1468         return res;
1469 }
1470
1471 static ssize_t libertas_rdbbp_read(struct file *file, char __user *userbuf,
1472                                   size_t count, loff_t *ppos)
1473 {
1474         wlan_private *priv = file->private_data;
1475         wlan_adapter *adapter = priv->adapter;
1476         struct wlan_offset_value offval;
1477         ssize_t pos = 0;
1478         int ret;
1479         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1480         char *buf = (char *)addr;
1481
1482         offval.offset = priv->bbp_offset;
1483         offval.value = 0;
1484
1485         ret = libertas_prepare_and_send_command(priv,
1486                                 cmd_bbp_reg_access, 0,
1487                                 cmd_option_waitforrsp, 0, &offval);
1488         mdelay(10);
1489         pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
1490                                 priv->bbp_offset, adapter->offsetvalue.value);
1491
1492         ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1493         free_page(addr);
1494
1495         return ret;
1496 }
1497
1498 static ssize_t libertas_rdbbp_write(struct file *file,
1499                                     const char __user *userbuf,
1500                                     size_t count, loff_t *ppos)
1501 {
1502         wlan_private *priv = file->private_data;
1503         ssize_t res, buf_size;
1504         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1505         char *buf = (char *)addr;
1506
1507         buf_size = min(count, len - 1);
1508         if (copy_from_user(buf, userbuf, buf_size)) {
1509                 res = -EFAULT;
1510                 goto out_unlock;
1511         }
1512         priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16);
1513         res = count;
1514 out_unlock:
1515         free_page(addr);
1516         return res;
1517 }
1518
1519 static ssize_t libertas_wrbbp_write(struct file *file,
1520                                     const char __user *userbuf,
1521                                     size_t count, loff_t *ppos)
1522 {
1523
1524         wlan_private *priv = file->private_data;
1525         ssize_t res, buf_size;
1526         u32 offset, value;
1527         struct wlan_offset_value offval;
1528         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1529         char *buf = (char *)addr;
1530
1531         buf_size = min(count, len - 1);
1532         if (copy_from_user(buf, userbuf, buf_size)) {
1533                 res = -EFAULT;
1534                 goto out_unlock;
1535         }
1536         res = sscanf(buf, "%x %x", &offset, &value);
1537         if (res != 2) {
1538                 res = -EFAULT;
1539                 goto out_unlock;
1540         }
1541
1542         offval.offset = offset;
1543         offval.value = value;
1544         res = libertas_prepare_and_send_command(priv,
1545                                 cmd_bbp_reg_access, 1,
1546                                 cmd_option_waitforrsp, 0, &offval);
1547         mdelay(10);
1548
1549         res = count;
1550 out_unlock:
1551         free_page(addr);
1552         return res;
1553 }
1554
1555 static ssize_t libertas_rdrf_read(struct file *file, char __user *userbuf,
1556                                   size_t count, loff_t *ppos)
1557 {
1558         wlan_private *priv = file->private_data;
1559         wlan_adapter *adapter = priv->adapter;
1560         struct wlan_offset_value offval;
1561         ssize_t pos = 0;
1562         int ret;
1563         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1564         char *buf = (char *)addr;
1565
1566         offval.offset = priv->rf_offset;
1567         offval.value = 0;
1568
1569         ret = libertas_prepare_and_send_command(priv,
1570                                 cmd_rf_reg_access, 0,
1571                                 cmd_option_waitforrsp, 0, &offval);
1572         mdelay(10);
1573         pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
1574                                 priv->rf_offset, adapter->offsetvalue.value);
1575
1576         ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1577         free_page(addr);
1578
1579         return ret;
1580 }
1581
1582 static ssize_t libertas_rdrf_write(struct file *file,
1583                                     const char __user *userbuf,
1584                                     size_t count, loff_t *ppos)
1585 {
1586         wlan_private *priv = file->private_data;
1587         ssize_t res, buf_size;
1588         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1589         char *buf = (char *)addr;
1590
1591         buf_size = min(count, len - 1);
1592         if (copy_from_user(buf, userbuf, buf_size)) {
1593                 res = -EFAULT;
1594                 goto out_unlock;
1595         }
1596         priv->rf_offset = simple_strtoul((char *)buf, NULL, 16);
1597         res = count;
1598 out_unlock:
1599         free_page(addr);
1600         return res;
1601 }
1602
1603 static ssize_t libertas_wrrf_write(struct file *file,
1604                                     const char __user *userbuf,
1605                                     size_t count, loff_t *ppos)
1606 {
1607
1608         wlan_private *priv = file->private_data;
1609         ssize_t res, buf_size;
1610         u32 offset, value;
1611         struct wlan_offset_value offval;
1612         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1613         char *buf = (char *)addr;
1614
1615         buf_size = min(count, len - 1);
1616         if (copy_from_user(buf, userbuf, buf_size)) {
1617                 res = -EFAULT;
1618                 goto out_unlock;
1619         }
1620         res = sscanf(buf, "%x %x", &offset, &value);
1621         if (res != 2) {
1622                 res = -EFAULT;
1623                 goto out_unlock;
1624         }
1625
1626         offval.offset = offset;
1627         offval.value = value;
1628         res = libertas_prepare_and_send_command(priv,
1629                                 cmd_rf_reg_access, 1,
1630                                 cmd_option_waitforrsp, 0, &offval);
1631         mdelay(10);
1632
1633         res = count;
1634 out_unlock:
1635         free_page(addr);
1636         return res;
1637 }
1638
1639 #define FOPS(fread, fwrite) { \
1640         .owner = THIS_MODULE, \
1641         .open = open_file_generic, \
1642         .read = (fread), \
1643         .write = (fwrite), \
1644 }
1645
1646 struct libertas_debugfs_files {
1647         char *name;
1648         int perm;
1649         struct file_operations fops;
1650 };
1651
1652 static struct libertas_debugfs_files debugfs_files[] = {
1653         { "info", 0444, FOPS(libertas_dev_info, write_file_dummy), },
1654         { "getscantable", 0444, FOPS(libertas_getscantable,
1655                                         write_file_dummy), },
1656         { "sleepparams", 0644, FOPS(libertas_sleepparams_read,
1657                                 libertas_sleepparams_write), },
1658         { "extscan", 0600, FOPS(NULL, libertas_extscan), },
1659         { "setuserscan", 0600, FOPS(NULL, libertas_setuserscan), },
1660 };
1661
1662 static struct libertas_debugfs_files debugfs_events_files[] = {
1663         {"low_rssi", 0644, FOPS(libertas_lowrssi_read,
1664                                 libertas_lowrssi_write), },
1665         {"low_snr", 0644, FOPS(libertas_lowsnr_read,
1666                                 libertas_lowsnr_write), },
1667         {"failure_count", 0644, FOPS(libertas_failcount_read,
1668                                 libertas_failcount_write), },
1669         {"beacon_missed", 0644, FOPS(libertas_bcnmiss_read,
1670                                 libertas_bcnmiss_write), },
1671         {"high_rssi", 0644, FOPS(libertas_highrssi_read,
1672                                 libertas_highrssi_write), },
1673         {"high_snr", 0644, FOPS(libertas_highsnr_read,
1674                                 libertas_highsnr_write), },
1675 };
1676
1677 static struct libertas_debugfs_files debugfs_regs_files[] = {
1678         {"rdmac", 0644, FOPS(libertas_rdmac_read, libertas_rdmac_write), },
1679         {"wrmac", 0600, FOPS(NULL, libertas_wrmac_write), },
1680         {"rdbbp", 0644, FOPS(libertas_rdbbp_read, libertas_rdbbp_write), },
1681         {"wrbbp", 0600, FOPS(NULL, libertas_wrbbp_write), },
1682         {"rdrf", 0644, FOPS(libertas_rdrf_read, libertas_rdrf_write), },
1683         {"wrrf", 0600, FOPS(NULL, libertas_wrrf_write), },
1684 };
1685
1686 void libertas_debugfs_init(void)
1687 {
1688         if (!libertas_dir)
1689                 libertas_dir = debugfs_create_dir("libertas_wireless", NULL);
1690
1691         return;
1692 }
1693
1694 void libertas_debugfs_remove(void)
1695 {
1696         if (libertas_dir)
1697                  debugfs_remove(libertas_dir);
1698         return;
1699 }
1700
1701 void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev)
1702 {
1703         int i;
1704         struct libertas_debugfs_files *files;
1705         if (!libertas_dir)
1706                 goto exit;
1707
1708         priv->debugfs_dir = debugfs_create_dir(dev->name, libertas_dir);
1709         if (!priv->debugfs_dir)
1710                 goto exit;
1711
1712         for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
1713                 files = &debugfs_files[i];
1714                 priv->debugfs_files[i] = debugfs_create_file(files->name,
1715                                                              files->perm,
1716                                                              priv->debugfs_dir,
1717                                                              priv,
1718                                                              &files->fops);
1719         }
1720
1721         priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
1722         if (!priv->events_dir)
1723                 goto exit;
1724
1725         for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
1726                 files = &debugfs_events_files[i];
1727                 priv->debugfs_events_files[i] = debugfs_create_file(files->name,
1728                                                              files->perm,
1729                                                              priv->events_dir,
1730                                                              priv,
1731                                                              &files->fops);
1732         }
1733
1734         priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
1735         if (!priv->regs_dir)
1736                 goto exit;
1737
1738         for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
1739                 files = &debugfs_regs_files[i];
1740                 priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
1741                                                              files->perm,
1742                                                              priv->regs_dir,
1743                                                              priv,
1744                                                              &files->fops);
1745         }
1746
1747 #ifdef PROC_DEBUG
1748         libertas_debug_init(priv, dev);
1749 #endif
1750 exit:
1751         return;
1752 }
1753
1754 void libertas_debugfs_remove_one(wlan_private *priv)
1755 {
1756         int i;
1757
1758         for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
1759                 debugfs_remove(priv->debugfs_regs_files[i]);
1760
1761         debugfs_remove(priv->regs_dir);
1762
1763         for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
1764                 debugfs_remove(priv->debugfs_events_files[i]);
1765
1766         debugfs_remove(priv->events_dir);
1767 #ifdef PROC_DEBUG
1768         debugfs_remove(priv->debugfs_debug);
1769 #endif
1770         for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
1771                 debugfs_remove(priv->debugfs_files[i]);
1772 }
1773
1774 /* debug entry */
1775
1776 #define item_size(n)    (FIELD_SIZEOF(wlan_adapter, n))
1777 #define item_addr(n)    (offsetof(wlan_adapter, n))
1778
1779 struct debug_data {
1780         char name[32];
1781         u32 size;
1782         size_t addr;
1783 };
1784
1785 /* To debug any member of wlan_adapter, simply add one line here.
1786  */
1787 static struct debug_data items[] = {
1788         {"intcounter", item_size(intcounter), item_addr(intcounter)},
1789         {"psmode", item_size(psmode), item_addr(psmode)},
1790         {"psstate", item_size(psstate), item_addr(psstate)},
1791 };
1792
1793 static int num_of_items = ARRAY_SIZE(items);
1794
1795 /**
1796  *  @brief proc read function
1797  *
1798  *  @param page    pointer to buffer
1799  *  @param s       read data starting position
1800  *  @param off     offset
1801  *  @param cnt     counter
1802  *  @param eof     end of file flag
1803  *  @param data    data to output
1804  *  @return        number of output data
1805  */
1806 static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf,
1807                         size_t count, loff_t *ppos)
1808 {
1809         int val = 0;
1810         size_t pos = 0;
1811         ssize_t res;
1812         char *p;
1813         int i;
1814         struct debug_data *d;
1815         unsigned long addr = get_zeroed_page(GFP_KERNEL);
1816         char *buf = (char *)addr;
1817
1818         p = buf;
1819
1820         d = (struct debug_data *)file->private_data;
1821
1822         for (i = 0; i < num_of_items; i++) {
1823                 if (d[i].size == 1)
1824                         val = *((u8 *) d[i].addr);
1825                 else if (d[i].size == 2)
1826                         val = *((u16 *) d[i].addr);
1827                 else if (d[i].size == 4)
1828                         val = *((u32 *) d[i].addr);
1829                 else if (d[i].size == 8)
1830                         val = *((u64 *) d[i].addr);
1831
1832                 pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
1833         }
1834
1835         res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
1836
1837         free_page(addr);
1838         return res;
1839 }
1840
1841 /**
1842  *  @brief proc write function
1843  *
1844  *  @param f       file pointer
1845  *  @param buf     pointer to data buffer
1846  *  @param cnt     data number to write
1847  *  @param data    data to write
1848  *  @return        number of data
1849  */
1850 static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf,
1851                             size_t cnt, loff_t *ppos)
1852 {
1853         int r, i;
1854         char *pdata;
1855         char *p;
1856         char *p0;
1857         char *p1;
1858         char *p2;
1859         struct debug_data *d = (struct debug_data *)f->private_data;
1860
1861         pdata = (char *)kmalloc(cnt, GFP_KERNEL);
1862         if (pdata == NULL)
1863                 return 0;
1864
1865         if (copy_from_user(pdata, buf, cnt)) {
1866                 lbs_pr_debug(1, "Copy from user failed\n");
1867                 kfree(pdata);
1868                 return 0;
1869         }
1870
1871         p0 = pdata;
1872         for (i = 0; i < num_of_items; i++) {
1873                 do {
1874                         p = strstr(p0, d[i].name);
1875                         if (p == NULL)
1876                                 break;
1877                         p1 = strchr(p, '\n');
1878                         if (p1 == NULL)
1879                                 break;
1880                         p0 = p1++;
1881                         p2 = strchr(p, '=');
1882                         if (!p2)
1883                                 break;
1884                         p2++;
1885                         r = simple_strtoul(p2, NULL, 0);
1886                         if (d[i].size == 1)
1887                                 *((u8 *) d[i].addr) = (u8) r;
1888                         else if (d[i].size == 2)
1889                                 *((u16 *) d[i].addr) = (u16) r;
1890                         else if (d[i].size == 4)
1891                                 *((u32 *) d[i].addr) = (u32) r;
1892                         else if (d[i].size == 8)
1893                                 *((u64 *) d[i].addr) = (u64) r;
1894                         break;
1895                 } while (1);
1896         }
1897         kfree(pdata);
1898
1899         return (ssize_t)cnt;
1900 }
1901
1902 static struct file_operations libertas_debug_fops = {
1903         .owner = THIS_MODULE,
1904         .open = open_file_generic,
1905         .write = wlan_debugfs_write,
1906         .read = wlan_debugfs_read,
1907 };
1908
1909 /**
1910  *  @brief create debug proc file
1911  *
1912  *  @param priv    pointer wlan_private
1913  *  @param dev     pointer net_device
1914  *  @return        N/A
1915  */
1916 void libertas_debug_init(wlan_private * priv, struct net_device *dev)
1917 {
1918         int i;
1919
1920         if (!priv->debugfs_dir)
1921                 return;
1922
1923         for (i = 0; i < num_of_items; i++)
1924                 items[i].addr += (size_t) priv->adapter;
1925
1926         priv->debugfs_debug = debugfs_create_file("debug", 0644,
1927                                                   priv->debugfs_dir, &items[0],
1928                                                   &libertas_debug_fops);
1929 }
1930