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