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