allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / drivers / net / wireless / libertas / debugfs.c
blob715cbdaa1d4bcf17170717b6148d409e4907ef8d
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>
8 #include "dev.h"
9 #include "decl.h"
10 #include "host.h"
11 #include "debugfs.h"
13 static struct dentry *libertas_dir = NULL;
14 static char *szStates[] = {
15 "Connected",
16 "Disconnected"
19 #ifdef PROC_DEBUG
20 static void libertas_debug_init(wlan_private * priv, struct net_device *dev);
21 #endif
23 static int open_file_generic(struct inode *inode, struct file *file)
25 file->private_data = inode->i_private;
26 return 0;
29 static ssize_t write_file_dummy(struct file *file, const char __user *buf,
30 size_t count, loff_t *ppos)
32 return -EINVAL;
35 static const size_t len = PAGE_SIZE;
37 static ssize_t libertas_dev_info(struct file *file, char __user *userbuf,
38 size_t count, loff_t *ppos)
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;
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);
51 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
53 free_page(addr);
54 return res;
58 static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
59 size_t count, loff_t *ppos)
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 struct bss_descriptor * iter_bss;
68 pos += snprintf(buf+pos, len-pos,
69 "# | ch | ss | bssid | cap | TSF | Qual | SSID \n");
71 mutex_lock(&priv->adapter->lock);
72 list_for_each_entry (iter_bss, &priv->adapter->network_list, list) {
73 u16 cap;
75 memcpy(&cap, &iter_bss->cap, sizeof(cap));
76 pos += snprintf(buf+pos, len-pos,
77 "%02u| %03d | %03ld | " MAC_FMT " |",
78 numscansdone, iter_bss->channel, iter_bss->rssi,
79 MAC_ARG(iter_bss->bssid));
80 pos += snprintf(buf+pos, len-pos, " %04x-", cap);
81 pos += snprintf(buf+pos, len-pos, "%c%c%c |",
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",
88 escape_essid(iter_bss->ssid, iter_bss->ssid_len));
90 numscansdone++;
92 mutex_unlock(&priv->adapter->lock);
94 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
96 free_page(addr);
97 return res;
100 static ssize_t libertas_sleepparams_write(struct file *file,
101 const char __user *user_buf, size_t count,
102 loff_t *ppos)
104 wlan_private *priv = file->private_data;
105 ssize_t buf_size, res;
106 int p1, p2, p3, p4, p5, p6;
107 unsigned long addr = get_zeroed_page(GFP_KERNEL);
108 char *buf = (char *)addr;
110 buf_size = min(count, len - 1);
111 if (copy_from_user(buf, user_buf, buf_size)) {
112 res = -EFAULT;
113 goto out_unlock;
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;
120 priv->adapter->sp.sp_error = p1;
121 priv->adapter->sp.sp_offset = p2;
122 priv->adapter->sp.sp_stabletime = p3;
123 priv->adapter->sp.sp_calcontrol = p4;
124 priv->adapter->sp.sp_extsleepclk = p5;
125 priv->adapter->sp.sp_reserved = p6;
127 res = libertas_prepare_and_send_command(priv,
128 cmd_802_11_sleep_params,
129 cmd_act_set,
130 cmd_option_waitforrsp, 0, NULL);
132 if (!res)
133 res = count;
134 else
135 res = -EINVAL;
137 out_unlock:
138 free_page(addr);
139 return res;
142 static ssize_t libertas_sleepparams_read(struct file *file, char __user *userbuf,
143 size_t count, loff_t *ppos)
145 wlan_private *priv = file->private_data;
146 wlan_adapter *adapter = priv->adapter;
147 ssize_t res;
148 size_t pos = 0;
149 unsigned long addr = get_zeroed_page(GFP_KERNEL);
150 char *buf = (char *)addr;
152 res = libertas_prepare_and_send_command(priv,
153 cmd_802_11_sleep_params,
154 cmd_act_get,
155 cmd_option_waitforrsp, 0, NULL);
156 if (res) {
157 res = -EFAULT;
158 goto out_unlock;
161 pos += snprintf(buf, len, "%d %d %d %d %d %d\n", adapter->sp.sp_error,
162 adapter->sp.sp_offset, adapter->sp.sp_stabletime,
163 adapter->sp.sp_calcontrol, adapter->sp.sp_extsleepclk,
164 adapter->sp.sp_reserved);
166 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
168 out_unlock:
169 free_page(addr);
170 return res;
173 static ssize_t libertas_extscan(struct file *file, const char __user *userbuf,
174 size_t count, loff_t *ppos)
176 wlan_private *priv = file->private_data;
177 ssize_t res, buf_size;
178 union iwreq_data wrqu;
179 unsigned long addr = get_zeroed_page(GFP_KERNEL);
180 char *buf = (char *)addr;
182 buf_size = min(count, len - 1);
183 if (copy_from_user(buf, userbuf, buf_size)) {
184 res = -EFAULT;
185 goto out_unlock;
188 libertas_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
190 memset(&wrqu, 0, sizeof(union iwreq_data));
191 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
193 out_unlock:
194 free_page(addr);
195 return count;
198 static int libertas_parse_chan(char *buf, size_t count,
199 struct wlan_ioctl_user_scan_cfg *scan_cfg, int dur)
201 char *start, *end, *hold, *str;
202 int i = 0;
204 start = strstr(buf, "chan=");
205 if (!start)
206 return -EINVAL;
207 start += 5;
208 end = strstr(start, " ");
209 if (!end)
210 end = buf + count;
211 hold = kzalloc((end - start)+1, GFP_KERNEL);
212 if (!hold)
213 return -ENOMEM;
214 strncpy(hold, start, end - start);
215 hold[(end-start)+1] = '\0';
216 while(hold && (str = strsep(&hold, ","))) {
217 int chan;
218 char band, passive = 0;
219 sscanf(str, "%d%c%c", &chan, &band, &passive);
220 scan_cfg->chanlist[i].channumber = chan;
221 scan_cfg->chanlist[i].scantype = passive ? 1 : 0;
222 if (band == 'b' || band == 'g')
223 scan_cfg->chanlist[i].radiotype = 0;
224 else if (band == 'a')
225 scan_cfg->chanlist[i].radiotype = 1;
227 scan_cfg->chanlist[i].scantime = dur;
228 i++;
231 kfree(hold);
232 return i;
235 static void libertas_parse_bssid(char *buf, size_t count,
236 struct wlan_ioctl_user_scan_cfg *scan_cfg)
238 char *hold;
239 unsigned int mac[ETH_ALEN];
241 hold = strstr(buf, "bssid=");
242 if (!hold)
243 return;
244 hold += 6;
245 sscanf(hold, MAC_FMT, mac, mac+1, mac+2, mac+3, mac+4, mac+5);
246 memcpy(scan_cfg->bssid, mac, ETH_ALEN);
249 static void libertas_parse_ssid(char *buf, size_t count,
250 struct wlan_ioctl_user_scan_cfg *scan_cfg)
252 char *hold, *end;
253 ssize_t size;
255 hold = strstr(buf, "ssid=");
256 if (!hold)
257 return;
258 hold += 5;
259 end = strstr(hold, " ");
260 if (!end)
261 end = buf + count - 1;
263 size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
264 strncpy(scan_cfg->ssid, hold, size);
266 return;
269 static int libertas_parse_clear(char *buf, size_t count, const char *tag)
271 char *hold;
272 int val;
274 hold = strstr(buf, tag);
275 if (!hold)
276 return 0;
277 hold += strlen(tag);
278 sscanf(hold, "%d", &val);
280 if (val != 0)
281 val = 1;
283 return val;
286 static int libertas_parse_dur(char *buf, size_t count,
287 struct wlan_ioctl_user_scan_cfg *scan_cfg)
289 char *hold;
290 int val;
292 hold = strstr(buf, "dur=");
293 if (!hold)
294 return 0;
295 hold += 4;
296 sscanf(hold, "%d", &val);
298 return val;
301 static void libertas_parse_probes(char *buf, size_t count,
302 struct wlan_ioctl_user_scan_cfg *scan_cfg)
304 char *hold;
305 int val;
307 hold = strstr(buf, "probes=");
308 if (!hold)
309 return;
310 hold += 7;
311 sscanf(hold, "%d", &val);
313 scan_cfg->numprobes = val;
315 return;
318 static void libertas_parse_type(char *buf, size_t count,
319 struct wlan_ioctl_user_scan_cfg *scan_cfg)
321 char *hold;
322 int val;
324 hold = strstr(buf, "type=");
325 if (!hold)
326 return;
327 hold += 5;
328 sscanf(hold, "%d", &val);
330 /* type=1,2 or 3 */
331 if (val < 1 || val > 3)
332 return;
334 scan_cfg->bsstype = val;
336 return;
339 static ssize_t libertas_setuserscan(struct file *file,
340 const char __user *userbuf,
341 size_t count, loff_t *ppos)
343 wlan_private *priv = file->private_data;
344 ssize_t res, buf_size;
345 struct wlan_ioctl_user_scan_cfg *scan_cfg;
346 union iwreq_data wrqu;
347 int dur;
348 unsigned long addr = get_zeroed_page(GFP_KERNEL);
349 char *buf = (char *)addr;
351 scan_cfg = kzalloc(sizeof(struct wlan_ioctl_user_scan_cfg), GFP_KERNEL);
352 if (!scan_cfg)
353 return -ENOMEM;
355 buf_size = min(count, len - 1);
356 if (copy_from_user(buf, userbuf, buf_size)) {
357 res = -EFAULT;
358 goto out_unlock;
361 scan_cfg->bsstype = WLAN_SCAN_BSS_TYPE_ANY;
363 dur = libertas_parse_dur(buf, count, scan_cfg);
364 libertas_parse_chan(buf, count, scan_cfg, dur);
365 libertas_parse_bssid(buf, count, scan_cfg);
366 scan_cfg->clear_bssid = libertas_parse_clear(buf, count, "clear_bssid=");
367 libertas_parse_ssid(buf, count, scan_cfg);
368 scan_cfg->clear_ssid = libertas_parse_clear(buf, count, "clear_ssid=");
369 libertas_parse_probes(buf, count, scan_cfg);
370 libertas_parse_type(buf, count, scan_cfg);
372 wlan_scan_networks(priv, scan_cfg, 1);
373 wait_event_interruptible(priv->adapter->cmd_pending,
374 !priv->adapter->nr_cmd_pending);
376 memset(&wrqu, 0x00, sizeof(union iwreq_data));
377 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
379 out_unlock:
380 free_page(addr);
381 kfree(scan_cfg);
382 return count;
385 static int libertas_event_initcmd(wlan_private *priv, void **response_buf,
386 struct cmd_ctrl_node **cmdnode,
387 struct cmd_ds_command **cmd)
389 u16 wait_option = cmd_option_waitforrsp;
391 if (!(*cmdnode = libertas_get_free_cmd_ctrl_node(priv))) {
392 lbs_deb_debugfs("failed libertas_get_free_cmd_ctrl_node\n");
393 return -ENOMEM;
395 if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) {
396 lbs_deb_debugfs("failed to allocate response buffer!\n");
397 return -ENOMEM;
399 libertas_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL);
400 init_waitqueue_head(&(*cmdnode)->cmdwait_q);
401 (*cmdnode)->pdata_buf = *response_buf;
402 (*cmdnode)->cmdflags |= CMD_F_HOSTCMD;
403 (*cmdnode)->cmdwaitqwoken = 0;
404 *cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr;
405 (*cmd)->command = cpu_to_le16(cmd_802_11_subscribe_event);
406 (*cmd)->seqnum = cpu_to_le16(++priv->adapter->seqnum);
407 (*cmd)->result = 0;
408 return 0;
411 static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf,
412 size_t count, loff_t *ppos)
414 wlan_private *priv = file->private_data;
415 wlan_adapter *adapter = priv->adapter;
416 struct cmd_ctrl_node *pcmdnode;
417 struct cmd_ds_command *pcmdptr;
418 struct cmd_ds_802_11_subscribe_event *event;
419 void *response_buf;
420 int res, cmd_len;
421 ssize_t pos = 0;
422 unsigned long addr = get_zeroed_page(GFP_KERNEL);
423 char *buf = (char *)addr;
425 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
426 if (res < 0) {
427 free_page(addr);
428 return res;
431 event = &pcmdptr->params.subscribe_event;
432 event->action = cpu_to_le16(cmd_act_get);
433 pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
434 libertas_queue_cmd(adapter, pcmdnode, 1);
435 wake_up_interruptible(&priv->mainthread.waitq);
437 /* Sleep until response is generated by FW */
438 wait_event_interruptible(pcmdnode->cmdwait_q,
439 pcmdnode->cmdwaitqwoken);
441 pcmdptr = response_buf;
442 if (pcmdptr->result) {
443 lbs_pr_err("%s: fail, result=%d\n", __func__,
444 le16_to_cpu(pcmdptr->result));
445 kfree(response_buf);
446 free_page(addr);
447 return 0;
450 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
451 lbs_pr_err("command response incorrect!\n");
452 kfree(response_buf);
453 free_page(addr);
454 return 0;
457 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
458 event = (void *)(response_buf + S_DS_GEN);
459 while (cmd_len < le16_to_cpu(pcmdptr->size)) {
460 struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
461 switch (header->type) {
462 struct mrvlietypes_rssithreshold *Lowrssi;
463 case __constant_cpu_to_le16(TLV_TYPE_RSSI_LOW):
464 Lowrssi = (void *)(response_buf + cmd_len);
465 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
466 Lowrssi->rssivalue,
467 Lowrssi->rssifreq,
468 (event->events & cpu_to_le16(0x0001))?1:0);
469 default:
470 cmd_len += sizeof(struct mrvlietypes_snrthreshold);
471 break;
475 kfree(response_buf);
476 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
477 free_page(addr);
478 return res;
481 static u16 libertas_get_events_bitmap(wlan_private *priv)
483 wlan_adapter *adapter = priv->adapter;
484 struct cmd_ctrl_node *pcmdnode;
485 struct cmd_ds_command *pcmdptr;
486 struct cmd_ds_802_11_subscribe_event *event;
487 void *response_buf;
488 int res;
489 u16 event_bitmap;
491 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
492 if (res < 0)
493 return res;
495 event = &pcmdptr->params.subscribe_event;
496 event->action = cpu_to_le16(cmd_act_get);
497 pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
498 libertas_queue_cmd(adapter, pcmdnode, 1);
499 wake_up_interruptible(&priv->mainthread.waitq);
501 /* Sleep until response is generated by FW */
502 wait_event_interruptible(pcmdnode->cmdwait_q,
503 pcmdnode->cmdwaitqwoken);
505 pcmdptr = response_buf;
507 if (pcmdptr->result) {
508 lbs_pr_err("%s: fail, result=%d\n", __func__,
509 le16_to_cpu(pcmdptr->result));
510 kfree(response_buf);
511 return 0;
514 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
515 lbs_pr_err("command response incorrect!\n");
516 kfree(response_buf);
517 return 0;
520 event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
521 event_bitmap = le16_to_cpu(event->events);
522 kfree(response_buf);
523 return event_bitmap;
526 static ssize_t libertas_lowrssi_write(struct file *file,
527 const char __user *userbuf,
528 size_t count, loff_t *ppos)
530 wlan_private *priv = file->private_data;
531 wlan_adapter *adapter = priv->adapter;
532 ssize_t res, buf_size;
533 int value, freq, subscribed, cmd_len;
534 struct cmd_ctrl_node *pcmdnode;
535 struct cmd_ds_command *pcmdptr;
536 struct cmd_ds_802_11_subscribe_event *event;
537 struct mrvlietypes_rssithreshold *rssi_threshold;
538 void *response_buf;
539 u16 event_bitmap;
540 u8 *ptr;
541 unsigned long addr = get_zeroed_page(GFP_KERNEL);
542 char *buf = (char *)addr;
544 buf_size = min(count, len - 1);
545 if (copy_from_user(buf, userbuf, buf_size)) {
546 res = -EFAULT;
547 goto out_unlock;
549 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
550 if (res != 3) {
551 res = -EFAULT;
552 goto out_unlock;
555 event_bitmap = libertas_get_events_bitmap(priv);
557 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
558 if (res < 0)
559 goto out_unlock;
561 event = &pcmdptr->params.subscribe_event;
562 event->action = cpu_to_le16(cmd_act_set);
563 pcmdptr->size = cpu_to_le16(S_DS_GEN +
564 sizeof(struct cmd_ds_802_11_subscribe_event) +
565 sizeof(struct mrvlietypes_rssithreshold));
567 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
568 ptr = (u8*) pcmdptr+cmd_len;
569 rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
570 rssi_threshold->header.type = cpu_to_le16(0x0104);
571 rssi_threshold->header.len = cpu_to_le16(2);
572 rssi_threshold->rssivalue = value;
573 rssi_threshold->rssifreq = freq;
574 event_bitmap |= subscribed ? 0x0001 : 0x0;
575 event->events = cpu_to_le16(event_bitmap);
577 libertas_queue_cmd(adapter, pcmdnode, 1);
578 wake_up_interruptible(&priv->mainthread.waitq);
580 /* Sleep until response is generated by FW */
581 wait_event_interruptible(pcmdnode->cmdwait_q,
582 pcmdnode->cmdwaitqwoken);
584 pcmdptr = response_buf;
586 if (pcmdptr->result) {
587 lbs_pr_err("%s: fail, result=%d\n", __func__,
588 le16_to_cpu(pcmdptr->result));
589 kfree(response_buf);
590 free_page(addr);
591 return 0;
594 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
595 lbs_pr_err("command response incorrect!\n");
596 kfree(response_buf);
597 free_page(addr);
598 return 0;
601 res = count;
602 out_unlock:
603 free_page(addr);
604 return res;
607 static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf,
608 size_t count, loff_t *ppos)
610 wlan_private *priv = file->private_data;
611 wlan_adapter *adapter = priv->adapter;
612 struct cmd_ctrl_node *pcmdnode;
613 struct cmd_ds_command *pcmdptr;
614 struct cmd_ds_802_11_subscribe_event *event;
615 void *response_buf;
616 int res, cmd_len;
617 ssize_t pos = 0;
618 unsigned long addr = get_zeroed_page(GFP_KERNEL);
619 char *buf = (char *)addr;
621 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
622 if (res < 0) {
623 free_page(addr);
624 return res;
627 event = &pcmdptr->params.subscribe_event;
628 event->action = cpu_to_le16(cmd_act_get);
629 pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
630 libertas_queue_cmd(adapter, pcmdnode, 1);
631 wake_up_interruptible(&priv->mainthread.waitq);
633 /* Sleep until response is generated by FW */
634 wait_event_interruptible(pcmdnode->cmdwait_q,
635 pcmdnode->cmdwaitqwoken);
637 pcmdptr = response_buf;
639 if (pcmdptr->result) {
640 lbs_pr_err("%s: fail, result=%d\n", __func__,
641 le16_to_cpu(pcmdptr->result));
642 kfree(response_buf);
643 free_page(addr);
644 return 0;
647 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
648 lbs_pr_err("command response incorrect!\n");
649 kfree(response_buf);
650 free_page(addr);
651 return 0;
654 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
655 event = (void *)(response_buf + S_DS_GEN);
656 while (cmd_len < le16_to_cpu(pcmdptr->size)) {
657 struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
658 switch (header->type) {
659 struct mrvlietypes_snrthreshold *LowSnr;
660 case __constant_cpu_to_le16(TLV_TYPE_SNR_LOW):
661 LowSnr = (void *)(response_buf + cmd_len);
662 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
663 LowSnr->snrvalue,
664 LowSnr->snrfreq,
665 (event->events & cpu_to_le16(0x0002))?1:0);
666 default:
667 cmd_len += sizeof(struct mrvlietypes_snrthreshold);
668 break;
672 kfree(response_buf);
674 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
675 free_page(addr);
676 return res;
679 static ssize_t libertas_lowsnr_write(struct file *file,
680 const char __user *userbuf,
681 size_t count, loff_t *ppos)
683 wlan_private *priv = file->private_data;
684 wlan_adapter *adapter = priv->adapter;
685 ssize_t res, buf_size;
686 int value, freq, subscribed, cmd_len;
687 struct cmd_ctrl_node *pcmdnode;
688 struct cmd_ds_command *pcmdptr;
689 struct cmd_ds_802_11_subscribe_event *event;
690 struct mrvlietypes_snrthreshold *snr_threshold;
691 void *response_buf;
692 u16 event_bitmap;
693 u8 *ptr;
694 unsigned long addr = get_zeroed_page(GFP_KERNEL);
695 char *buf = (char *)addr;
697 buf_size = min(count, len - 1);
698 if (copy_from_user(buf, userbuf, buf_size)) {
699 res = -EFAULT;
700 goto out_unlock;
702 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
703 if (res != 3) {
704 res = -EFAULT;
705 goto out_unlock;
708 event_bitmap = libertas_get_events_bitmap(priv);
710 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
711 if (res < 0)
712 goto out_unlock;
714 event = &pcmdptr->params.subscribe_event;
715 event->action = cpu_to_le16(cmd_act_set);
716 pcmdptr->size = cpu_to_le16(S_DS_GEN +
717 sizeof(struct cmd_ds_802_11_subscribe_event) +
718 sizeof(struct mrvlietypes_snrthreshold));
719 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
720 ptr = (u8*) pcmdptr+cmd_len;
721 snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
722 snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW);
723 snr_threshold->header.len = cpu_to_le16(2);
724 snr_threshold->snrvalue = value;
725 snr_threshold->snrfreq = freq;
726 event_bitmap |= subscribed ? 0x0002 : 0x0;
727 event->events = cpu_to_le16(event_bitmap);
729 libertas_queue_cmd(adapter, pcmdnode, 1);
730 wake_up_interruptible(&priv->mainthread.waitq);
732 /* Sleep until response is generated by FW */
733 wait_event_interruptible(pcmdnode->cmdwait_q,
734 pcmdnode->cmdwaitqwoken);
736 pcmdptr = response_buf;
738 if (pcmdptr->result) {
739 lbs_pr_err("%s: fail, result=%d\n", __func__,
740 le16_to_cpu(pcmdptr->result));
741 kfree(response_buf);
742 free_page(addr);
743 return 0;
746 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
747 lbs_pr_err("command response incorrect!\n");
748 kfree(response_buf);
749 free_page(addr);
750 return 0;
753 res = count;
755 out_unlock:
756 free_page(addr);
757 return res;
760 static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf,
761 size_t count, loff_t *ppos)
763 wlan_private *priv = file->private_data;
764 wlan_adapter *adapter = priv->adapter;
765 struct cmd_ctrl_node *pcmdnode;
766 struct cmd_ds_command *pcmdptr;
767 struct cmd_ds_802_11_subscribe_event *event;
768 void *response_buf;
769 int res, cmd_len;
770 ssize_t pos = 0;
771 unsigned long addr = get_zeroed_page(GFP_KERNEL);
772 char *buf = (char *)addr;
774 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
775 if (res < 0) {
776 free_page(addr);
777 return res;
780 event = &pcmdptr->params.subscribe_event;
781 event->action = cpu_to_le16(cmd_act_get);
782 pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
783 libertas_queue_cmd(adapter, pcmdnode, 1);
784 wake_up_interruptible(&priv->mainthread.waitq);
786 /* Sleep until response is generated by FW */
787 wait_event_interruptible(pcmdnode->cmdwait_q,
788 pcmdnode->cmdwaitqwoken);
790 pcmdptr = response_buf;
792 if (pcmdptr->result) {
793 lbs_pr_err("%s: fail, result=%d\n", __func__,
794 le16_to_cpu(pcmdptr->result));
795 kfree(response_buf);
796 free_page(addr);
797 return 0;
800 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
801 lbs_pr_err("command response incorrect!\n");
802 kfree(response_buf);
803 free_page(addr);
804 return 0;
807 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
808 event = (void *)(response_buf + S_DS_GEN);
809 while (cmd_len < le16_to_cpu(pcmdptr->size)) {
810 struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
811 switch (header->type) {
812 struct mrvlietypes_failurecount *failcount;
813 case __constant_cpu_to_le16(TLV_TYPE_FAILCOUNT):
814 failcount = (void *)(response_buf + cmd_len);
815 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
816 failcount->failvalue,
817 failcount->Failfreq,
818 (event->events & cpu_to_le16(0x0004))?1:0);
819 default:
820 cmd_len += sizeof(struct mrvlietypes_failurecount);
821 break;
825 kfree(response_buf);
826 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
827 free_page(addr);
828 return res;
831 static ssize_t libertas_failcount_write(struct file *file,
832 const char __user *userbuf,
833 size_t count, loff_t *ppos)
835 wlan_private *priv = file->private_data;
836 wlan_adapter *adapter = priv->adapter;
837 ssize_t res, buf_size;
838 int value, freq, subscribed, cmd_len;
839 struct cmd_ctrl_node *pcmdnode;
840 struct cmd_ds_command *pcmdptr;
841 struct cmd_ds_802_11_subscribe_event *event;
842 struct mrvlietypes_failurecount *failcount;
843 void *response_buf;
844 u16 event_bitmap;
845 u8 *ptr;
846 unsigned long addr = get_zeroed_page(GFP_KERNEL);
847 char *buf = (char *)addr;
849 buf_size = min(count, len - 1);
850 if (copy_from_user(buf, userbuf, buf_size)) {
851 res = -EFAULT;
852 goto out_unlock;
854 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
855 if (res != 3) {
856 res = -EFAULT;
857 goto out_unlock;
860 event_bitmap = libertas_get_events_bitmap(priv);
862 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
863 if (res < 0)
864 goto out_unlock;
866 event = &pcmdptr->params.subscribe_event;
867 event->action = cpu_to_le16(cmd_act_set);
868 pcmdptr->size = cpu_to_le16(S_DS_GEN +
869 sizeof(struct cmd_ds_802_11_subscribe_event) +
870 sizeof(struct mrvlietypes_failurecount));
871 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
872 ptr = (u8*) pcmdptr+cmd_len;
873 failcount = (struct mrvlietypes_failurecount *)(ptr);
874 failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
875 failcount->header.len = cpu_to_le16(2);
876 failcount->failvalue = value;
877 failcount->Failfreq = freq;
878 event_bitmap |= subscribed ? 0x0004 : 0x0;
879 event->events = cpu_to_le16(event_bitmap);
881 libertas_queue_cmd(adapter, pcmdnode, 1);
882 wake_up_interruptible(&priv->mainthread.waitq);
884 /* Sleep until response is generated by FW */
885 wait_event_interruptible(pcmdnode->cmdwait_q,
886 pcmdnode->cmdwaitqwoken);
888 pcmdptr = (struct cmd_ds_command *)response_buf;
890 if (pcmdptr->result) {
891 lbs_pr_err("%s: fail, result=%d\n", __func__,
892 le16_to_cpu(pcmdptr->result));
893 kfree(response_buf);
894 free_page(addr);
895 return 0;
898 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
899 lbs_pr_err("command response incorrect!\n");
900 kfree(response_buf);
901 free_page(addr);
902 return 0;
905 res = count;
906 out_unlock:
907 free_page(addr);
908 return res;
911 static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf,
912 size_t count, loff_t *ppos)
914 wlan_private *priv = file->private_data;
915 wlan_adapter *adapter = priv->adapter;
916 struct cmd_ctrl_node *pcmdnode;
917 struct cmd_ds_command *pcmdptr;
918 struct cmd_ds_802_11_subscribe_event *event;
919 void *response_buf;
920 int res, cmd_len;
921 ssize_t pos = 0;
922 unsigned long addr = get_zeroed_page(GFP_KERNEL);
923 char *buf = (char *)addr;
925 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
926 if (res < 0) {
927 free_page(addr);
928 return res;
931 event = &pcmdptr->params.subscribe_event;
932 event->action = cpu_to_le16(cmd_act_get);
933 pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
934 libertas_queue_cmd(adapter, pcmdnode, 1);
935 wake_up_interruptible(&priv->mainthread.waitq);
937 /* Sleep until response is generated by FW */
938 wait_event_interruptible(pcmdnode->cmdwait_q,
939 pcmdnode->cmdwaitqwoken);
941 pcmdptr = response_buf;
943 if (pcmdptr->result) {
944 lbs_pr_err("%s: fail, result=%d\n", __func__,
945 le16_to_cpu(pcmdptr->result));
946 free_page(addr);
947 kfree(response_buf);
948 return 0;
951 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
952 lbs_pr_err("command response incorrect!\n");
953 free_page(addr);
954 kfree(response_buf);
955 return 0;
958 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
959 event = (void *)(response_buf + S_DS_GEN);
960 while (cmd_len < le16_to_cpu(pcmdptr->size)) {
961 struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
962 switch (header->type) {
963 struct mrvlietypes_beaconsmissed *bcnmiss;
964 case __constant_cpu_to_le16(TLV_TYPE_BCNMISS):
965 bcnmiss = (void *)(response_buf + cmd_len);
966 pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
967 bcnmiss->beaconmissed,
968 (event->events & cpu_to_le16(0x0008))?1:0);
969 default:
970 cmd_len += sizeof(struct mrvlietypes_beaconsmissed);
971 break;
975 kfree(response_buf);
977 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
978 free_page(addr);
979 return res;
982 static ssize_t libertas_bcnmiss_write(struct file *file,
983 const char __user *userbuf,
984 size_t count, loff_t *ppos)
986 wlan_private *priv = file->private_data;
987 wlan_adapter *adapter = priv->adapter;
988 ssize_t res, buf_size;
989 int value, freq, subscribed, cmd_len;
990 struct cmd_ctrl_node *pcmdnode;
991 struct cmd_ds_command *pcmdptr;
992 struct cmd_ds_802_11_subscribe_event *event;
993 struct mrvlietypes_beaconsmissed *bcnmiss;
994 void *response_buf;
995 u16 event_bitmap;
996 u8 *ptr;
997 unsigned long addr = get_zeroed_page(GFP_KERNEL);
998 char *buf = (char *)addr;
1000 buf_size = min(count, len - 1);
1001 if (copy_from_user(buf, userbuf, buf_size)) {
1002 res = -EFAULT;
1003 goto out_unlock;
1005 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1006 if (res != 3) {
1007 res = -EFAULT;
1008 goto out_unlock;
1011 event_bitmap = libertas_get_events_bitmap(priv);
1013 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1014 if (res < 0)
1015 goto out_unlock;
1017 event = &pcmdptr->params.subscribe_event;
1018 event->action = cpu_to_le16(cmd_act_set);
1019 pcmdptr->size = cpu_to_le16(S_DS_GEN +
1020 sizeof(struct cmd_ds_802_11_subscribe_event) +
1021 sizeof(struct mrvlietypes_beaconsmissed));
1022 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1023 ptr = (u8*) pcmdptr+cmd_len;
1024 bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr);
1025 bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS);
1026 bcnmiss->header.len = cpu_to_le16(2);
1027 bcnmiss->beaconmissed = value;
1028 event_bitmap |= subscribed ? 0x0008 : 0x0;
1029 event->events = cpu_to_le16(event_bitmap);
1031 libertas_queue_cmd(adapter, pcmdnode, 1);
1032 wake_up_interruptible(&priv->mainthread.waitq);
1034 /* Sleep until response is generated by FW */
1035 wait_event_interruptible(pcmdnode->cmdwait_q,
1036 pcmdnode->cmdwaitqwoken);
1038 pcmdptr = response_buf;
1040 if (pcmdptr->result) {
1041 lbs_pr_err("%s: fail, result=%d\n", __func__,
1042 le16_to_cpu(pcmdptr->result));
1043 kfree(response_buf);
1044 free_page(addr);
1045 return 0;
1048 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
1049 lbs_pr_err("command response incorrect!\n");
1050 free_page(addr);
1051 kfree(response_buf);
1052 return 0;
1055 res = count;
1056 out_unlock:
1057 free_page(addr);
1058 return res;
1061 static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf,
1062 size_t count, loff_t *ppos)
1064 wlan_private *priv = file->private_data;
1065 wlan_adapter *adapter = priv->adapter;
1066 struct cmd_ctrl_node *pcmdnode;
1067 struct cmd_ds_command *pcmdptr;
1068 struct cmd_ds_802_11_subscribe_event *event;
1069 void *response_buf;
1070 int res, cmd_len;
1071 ssize_t pos = 0;
1072 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1073 char *buf = (char *)addr;
1075 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1076 if (res < 0) {
1077 free_page(addr);
1078 return res;
1081 event = &pcmdptr->params.subscribe_event;
1082 event->action = cpu_to_le16(cmd_act_get);
1083 pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
1084 libertas_queue_cmd(adapter, pcmdnode, 1);
1085 wake_up_interruptible(&priv->mainthread.waitq);
1087 /* Sleep until response is generated by FW */
1088 wait_event_interruptible(pcmdnode->cmdwait_q,
1089 pcmdnode->cmdwaitqwoken);
1091 pcmdptr = response_buf;
1093 if (pcmdptr->result) {
1094 lbs_pr_err("%s: fail, result=%d\n", __func__,
1095 le16_to_cpu(pcmdptr->result));
1096 kfree(response_buf);
1097 free_page(addr);
1098 return 0;
1101 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
1102 lbs_pr_err("command response incorrect!\n");
1103 kfree(response_buf);
1104 free_page(addr);
1105 return 0;
1108 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1109 event = (void *)(response_buf + S_DS_GEN);
1110 while (cmd_len < le16_to_cpu(pcmdptr->size)) {
1111 struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
1112 switch (header->type) {
1113 struct mrvlietypes_rssithreshold *Highrssi;
1114 case __constant_cpu_to_le16(TLV_TYPE_RSSI_HIGH):
1115 Highrssi = (void *)(response_buf + cmd_len);
1116 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
1117 Highrssi->rssivalue,
1118 Highrssi->rssifreq,
1119 (event->events & cpu_to_le16(0x0010))?1:0);
1120 default:
1121 cmd_len += sizeof(struct mrvlietypes_snrthreshold);
1122 break;
1126 kfree(response_buf);
1128 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1129 free_page(addr);
1130 return res;
1133 static ssize_t libertas_highrssi_write(struct file *file,
1134 const char __user *userbuf,
1135 size_t count, loff_t *ppos)
1137 wlan_private *priv = file->private_data;
1138 wlan_adapter *adapter = priv->adapter;
1139 ssize_t res, buf_size;
1140 int value, freq, subscribed, cmd_len;
1141 struct cmd_ctrl_node *pcmdnode;
1142 struct cmd_ds_command *pcmdptr;
1143 struct cmd_ds_802_11_subscribe_event *event;
1144 struct mrvlietypes_rssithreshold *rssi_threshold;
1145 void *response_buf;
1146 u16 event_bitmap;
1147 u8 *ptr;
1148 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1149 char *buf = (char *)addr;
1151 buf_size = min(count, len - 1);
1152 if (copy_from_user(buf, userbuf, buf_size)) {
1153 res = -EFAULT;
1154 goto out_unlock;
1156 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1157 if (res != 3) {
1158 res = -EFAULT;
1159 goto out_unlock;
1162 event_bitmap = libertas_get_events_bitmap(priv);
1164 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1165 if (res < 0)
1166 goto out_unlock;
1168 event = &pcmdptr->params.subscribe_event;
1169 event->action = cpu_to_le16(cmd_act_set);
1170 pcmdptr->size = cpu_to_le16(S_DS_GEN +
1171 sizeof(struct cmd_ds_802_11_subscribe_event) +
1172 sizeof(struct mrvlietypes_rssithreshold));
1173 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1174 ptr = (u8*) pcmdptr+cmd_len;
1175 rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
1176 rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
1177 rssi_threshold->header.len = cpu_to_le16(2);
1178 rssi_threshold->rssivalue = value;
1179 rssi_threshold->rssifreq = freq;
1180 event_bitmap |= subscribed ? 0x0010 : 0x0;
1181 event->events = cpu_to_le16(event_bitmap);
1183 libertas_queue_cmd(adapter, pcmdnode, 1);
1184 wake_up_interruptible(&priv->mainthread.waitq);
1186 /* Sleep until response is generated by FW */
1187 wait_event_interruptible(pcmdnode->cmdwait_q,
1188 pcmdnode->cmdwaitqwoken);
1190 pcmdptr = response_buf;
1192 if (pcmdptr->result) {
1193 lbs_pr_err("%s: fail, result=%d\n", __func__,
1194 le16_to_cpu(pcmdptr->result));
1195 kfree(response_buf);
1196 return 0;
1199 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
1200 lbs_pr_err("command response incorrect!\n");
1201 kfree(response_buf);
1202 return 0;
1205 res = count;
1206 out_unlock:
1207 free_page(addr);
1208 return res;
1211 static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf,
1212 size_t count, loff_t *ppos)
1214 wlan_private *priv = file->private_data;
1215 wlan_adapter *adapter = priv->adapter;
1216 struct cmd_ctrl_node *pcmdnode;
1217 struct cmd_ds_command *pcmdptr;
1218 struct cmd_ds_802_11_subscribe_event *event;
1219 void *response_buf;
1220 int res, cmd_len;
1221 ssize_t pos = 0;
1222 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1223 char *buf = (char *)addr;
1225 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1226 if (res < 0) {
1227 free_page(addr);
1228 return res;
1231 event = &pcmdptr->params.subscribe_event;
1232 event->action = cpu_to_le16(cmd_act_get);
1233 pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
1234 libertas_queue_cmd(adapter, pcmdnode, 1);
1235 wake_up_interruptible(&priv->mainthread.waitq);
1237 /* Sleep until response is generated by FW */
1238 wait_event_interruptible(pcmdnode->cmdwait_q,
1239 pcmdnode->cmdwaitqwoken);
1241 pcmdptr = response_buf;
1243 if (pcmdptr->result) {
1244 lbs_pr_err("%s: fail, result=%d\n", __func__,
1245 le16_to_cpu(pcmdptr->result));
1246 kfree(response_buf);
1247 free_page(addr);
1248 return 0;
1251 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
1252 lbs_pr_err("command response incorrect!\n");
1253 kfree(response_buf);
1254 free_page(addr);
1255 return 0;
1258 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1259 event = (void *)(response_buf + S_DS_GEN);
1260 while (cmd_len < le16_to_cpu(pcmdptr->size)) {
1261 struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
1262 switch (header->type) {
1263 struct mrvlietypes_snrthreshold *HighSnr;
1264 case __constant_cpu_to_le16(TLV_TYPE_SNR_HIGH):
1265 HighSnr = (void *)(response_buf + cmd_len);
1266 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
1267 HighSnr->snrvalue,
1268 HighSnr->snrfreq,
1269 (event->events & cpu_to_le16(0x0020))?1:0);
1270 default:
1271 cmd_len += sizeof(struct mrvlietypes_snrthreshold);
1272 break;
1276 kfree(response_buf);
1278 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1279 free_page(addr);
1280 return res;
1283 static ssize_t libertas_highsnr_write(struct file *file,
1284 const char __user *userbuf,
1285 size_t count, loff_t *ppos)
1287 wlan_private *priv = file->private_data;
1288 wlan_adapter *adapter = priv->adapter;
1289 ssize_t res, buf_size;
1290 int value, freq, subscribed, cmd_len;
1291 struct cmd_ctrl_node *pcmdnode;
1292 struct cmd_ds_command *pcmdptr;
1293 struct cmd_ds_802_11_subscribe_event *event;
1294 struct mrvlietypes_snrthreshold *snr_threshold;
1295 void *response_buf;
1296 u16 event_bitmap;
1297 u8 *ptr;
1298 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1299 char *buf = (char *)addr;
1301 buf_size = min(count, len - 1);
1302 if (copy_from_user(buf, userbuf, buf_size)) {
1303 res = -EFAULT;
1304 goto out_unlock;
1306 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1307 if (res != 3) {
1308 res = -EFAULT;
1309 goto out_unlock;
1312 event_bitmap = libertas_get_events_bitmap(priv);
1314 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1315 if (res < 0)
1316 goto out_unlock;
1318 event = &pcmdptr->params.subscribe_event;
1319 event->action = cpu_to_le16(cmd_act_set);
1320 pcmdptr->size = cpu_to_le16(S_DS_GEN +
1321 sizeof(struct cmd_ds_802_11_subscribe_event) +
1322 sizeof(struct mrvlietypes_snrthreshold));
1323 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1324 ptr = (u8*) pcmdptr+cmd_len;
1325 snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
1326 snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH);
1327 snr_threshold->header.len = cpu_to_le16(2);
1328 snr_threshold->snrvalue = value;
1329 snr_threshold->snrfreq = freq;
1330 event_bitmap |= subscribed ? 0x0020 : 0x0;
1331 event->events = cpu_to_le16(event_bitmap);
1333 libertas_queue_cmd(adapter, pcmdnode, 1);
1334 wake_up_interruptible(&priv->mainthread.waitq);
1336 /* Sleep until response is generated by FW */
1337 wait_event_interruptible(pcmdnode->cmdwait_q,
1338 pcmdnode->cmdwaitqwoken);
1340 pcmdptr = response_buf;
1342 if (pcmdptr->result) {
1343 lbs_pr_err("%s: fail, result=%d\n", __func__,
1344 le16_to_cpu(pcmdptr->result));
1345 kfree(response_buf);
1346 free_page(addr);
1347 return 0;
1350 if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
1351 lbs_pr_err("command response incorrect!\n");
1352 kfree(response_buf);
1353 free_page(addr);
1354 return 0;
1357 res = count;
1358 out_unlock:
1359 free_page(addr);
1360 return res;
1363 static ssize_t libertas_rdmac_read(struct file *file, char __user *userbuf,
1364 size_t count, loff_t *ppos)
1366 wlan_private *priv = file->private_data;
1367 wlan_adapter *adapter = priv->adapter;
1368 struct wlan_offset_value offval;
1369 ssize_t pos = 0;
1370 int ret;
1371 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1372 char *buf = (char *)addr;
1374 offval.offset = priv->mac_offset;
1375 offval.value = 0;
1377 ret = libertas_prepare_and_send_command(priv,
1378 cmd_mac_reg_access, 0,
1379 cmd_option_waitforrsp, 0, &offval);
1380 mdelay(10);
1381 pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
1382 priv->mac_offset, adapter->offsetvalue.value);
1384 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1385 free_page(addr);
1386 return ret;
1389 static ssize_t libertas_rdmac_write(struct file *file,
1390 const char __user *userbuf,
1391 size_t count, loff_t *ppos)
1393 wlan_private *priv = file->private_data;
1394 ssize_t res, buf_size;
1395 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1396 char *buf = (char *)addr;
1398 buf_size = min(count, len - 1);
1399 if (copy_from_user(buf, userbuf, buf_size)) {
1400 res = -EFAULT;
1401 goto out_unlock;
1403 priv->mac_offset = simple_strtoul((char *)buf, NULL, 16);
1404 res = count;
1405 out_unlock:
1406 free_page(addr);
1407 return res;
1410 static ssize_t libertas_wrmac_write(struct file *file,
1411 const char __user *userbuf,
1412 size_t count, loff_t *ppos)
1415 wlan_private *priv = file->private_data;
1416 ssize_t res, buf_size;
1417 u32 offset, value;
1418 struct wlan_offset_value offval;
1419 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1420 char *buf = (char *)addr;
1422 buf_size = min(count, len - 1);
1423 if (copy_from_user(buf, userbuf, buf_size)) {
1424 res = -EFAULT;
1425 goto out_unlock;
1427 res = sscanf(buf, "%x %x", &offset, &value);
1428 if (res != 2) {
1429 res = -EFAULT;
1430 goto out_unlock;
1433 offval.offset = offset;
1434 offval.value = value;
1435 res = libertas_prepare_and_send_command(priv,
1436 cmd_mac_reg_access, 1,
1437 cmd_option_waitforrsp, 0, &offval);
1438 mdelay(10);
1440 res = count;
1441 out_unlock:
1442 free_page(addr);
1443 return res;
1446 static ssize_t libertas_rdbbp_read(struct file *file, char __user *userbuf,
1447 size_t count, loff_t *ppos)
1449 wlan_private *priv = file->private_data;
1450 wlan_adapter *adapter = priv->adapter;
1451 struct wlan_offset_value offval;
1452 ssize_t pos = 0;
1453 int ret;
1454 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1455 char *buf = (char *)addr;
1457 offval.offset = priv->bbp_offset;
1458 offval.value = 0;
1460 ret = libertas_prepare_and_send_command(priv,
1461 cmd_bbp_reg_access, 0,
1462 cmd_option_waitforrsp, 0, &offval);
1463 mdelay(10);
1464 pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
1465 priv->bbp_offset, adapter->offsetvalue.value);
1467 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1468 free_page(addr);
1470 return ret;
1473 static ssize_t libertas_rdbbp_write(struct file *file,
1474 const char __user *userbuf,
1475 size_t count, loff_t *ppos)
1477 wlan_private *priv = file->private_data;
1478 ssize_t res, buf_size;
1479 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1480 char *buf = (char *)addr;
1482 buf_size = min(count, len - 1);
1483 if (copy_from_user(buf, userbuf, buf_size)) {
1484 res = -EFAULT;
1485 goto out_unlock;
1487 priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16);
1488 res = count;
1489 out_unlock:
1490 free_page(addr);
1491 return res;
1494 static ssize_t libertas_wrbbp_write(struct file *file,
1495 const char __user *userbuf,
1496 size_t count, loff_t *ppos)
1499 wlan_private *priv = file->private_data;
1500 ssize_t res, buf_size;
1501 u32 offset, value;
1502 struct wlan_offset_value offval;
1503 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1504 char *buf = (char *)addr;
1506 buf_size = min(count, len - 1);
1507 if (copy_from_user(buf, userbuf, buf_size)) {
1508 res = -EFAULT;
1509 goto out_unlock;
1511 res = sscanf(buf, "%x %x", &offset, &value);
1512 if (res != 2) {
1513 res = -EFAULT;
1514 goto out_unlock;
1517 offval.offset = offset;
1518 offval.value = value;
1519 res = libertas_prepare_and_send_command(priv,
1520 cmd_bbp_reg_access, 1,
1521 cmd_option_waitforrsp, 0, &offval);
1522 mdelay(10);
1524 res = count;
1525 out_unlock:
1526 free_page(addr);
1527 return res;
1530 static ssize_t libertas_rdrf_read(struct file *file, char __user *userbuf,
1531 size_t count, loff_t *ppos)
1533 wlan_private *priv = file->private_data;
1534 wlan_adapter *adapter = priv->adapter;
1535 struct wlan_offset_value offval;
1536 ssize_t pos = 0;
1537 int ret;
1538 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1539 char *buf = (char *)addr;
1541 offval.offset = priv->rf_offset;
1542 offval.value = 0;
1544 ret = libertas_prepare_and_send_command(priv,
1545 cmd_rf_reg_access, 0,
1546 cmd_option_waitforrsp, 0, &offval);
1547 mdelay(10);
1548 pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
1549 priv->rf_offset, adapter->offsetvalue.value);
1551 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1552 free_page(addr);
1554 return ret;
1557 static ssize_t libertas_rdrf_write(struct file *file,
1558 const char __user *userbuf,
1559 size_t count, loff_t *ppos)
1561 wlan_private *priv = file->private_data;
1562 ssize_t res, buf_size;
1563 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1564 char *buf = (char *)addr;
1566 buf_size = min(count, len - 1);
1567 if (copy_from_user(buf, userbuf, buf_size)) {
1568 res = -EFAULT;
1569 goto out_unlock;
1571 priv->rf_offset = simple_strtoul((char *)buf, NULL, 16);
1572 res = count;
1573 out_unlock:
1574 free_page(addr);
1575 return res;
1578 static ssize_t libertas_wrrf_write(struct file *file,
1579 const char __user *userbuf,
1580 size_t count, loff_t *ppos)
1583 wlan_private *priv = file->private_data;
1584 ssize_t res, buf_size;
1585 u32 offset, value;
1586 struct wlan_offset_value offval;
1587 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1588 char *buf = (char *)addr;
1590 buf_size = min(count, len - 1);
1591 if (copy_from_user(buf, userbuf, buf_size)) {
1592 res = -EFAULT;
1593 goto out_unlock;
1595 res = sscanf(buf, "%x %x", &offset, &value);
1596 if (res != 2) {
1597 res = -EFAULT;
1598 goto out_unlock;
1601 offval.offset = offset;
1602 offval.value = value;
1603 res = libertas_prepare_and_send_command(priv,
1604 cmd_rf_reg_access, 1,
1605 cmd_option_waitforrsp, 0, &offval);
1606 mdelay(10);
1608 res = count;
1609 out_unlock:
1610 free_page(addr);
1611 return res;
1614 #define FOPS(fread, fwrite) { \
1615 .owner = THIS_MODULE, \
1616 .open = open_file_generic, \
1617 .read = (fread), \
1618 .write = (fwrite), \
1621 struct libertas_debugfs_files {
1622 char *name;
1623 int perm;
1624 struct file_operations fops;
1627 static struct libertas_debugfs_files debugfs_files[] = {
1628 { "info", 0444, FOPS(libertas_dev_info, write_file_dummy), },
1629 { "getscantable", 0444, FOPS(libertas_getscantable,
1630 write_file_dummy), },
1631 { "sleepparams", 0644, FOPS(libertas_sleepparams_read,
1632 libertas_sleepparams_write), },
1633 { "extscan", 0600, FOPS(NULL, libertas_extscan), },
1634 { "setuserscan", 0600, FOPS(NULL, libertas_setuserscan), },
1637 static struct libertas_debugfs_files debugfs_events_files[] = {
1638 {"low_rssi", 0644, FOPS(libertas_lowrssi_read,
1639 libertas_lowrssi_write), },
1640 {"low_snr", 0644, FOPS(libertas_lowsnr_read,
1641 libertas_lowsnr_write), },
1642 {"failure_count", 0644, FOPS(libertas_failcount_read,
1643 libertas_failcount_write), },
1644 {"beacon_missed", 0644, FOPS(libertas_bcnmiss_read,
1645 libertas_bcnmiss_write), },
1646 {"high_rssi", 0644, FOPS(libertas_highrssi_read,
1647 libertas_highrssi_write), },
1648 {"high_snr", 0644, FOPS(libertas_highsnr_read,
1649 libertas_highsnr_write), },
1652 static struct libertas_debugfs_files debugfs_regs_files[] = {
1653 {"rdmac", 0644, FOPS(libertas_rdmac_read, libertas_rdmac_write), },
1654 {"wrmac", 0600, FOPS(NULL, libertas_wrmac_write), },
1655 {"rdbbp", 0644, FOPS(libertas_rdbbp_read, libertas_rdbbp_write), },
1656 {"wrbbp", 0600, FOPS(NULL, libertas_wrbbp_write), },
1657 {"rdrf", 0644, FOPS(libertas_rdrf_read, libertas_rdrf_write), },
1658 {"wrrf", 0600, FOPS(NULL, libertas_wrrf_write), },
1661 void libertas_debugfs_init(void)
1663 if (!libertas_dir)
1664 libertas_dir = debugfs_create_dir("libertas_wireless", NULL);
1666 return;
1669 void libertas_debugfs_remove(void)
1671 if (libertas_dir)
1672 debugfs_remove(libertas_dir);
1673 return;
1676 void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev)
1678 int i;
1679 struct libertas_debugfs_files *files;
1680 if (!libertas_dir)
1681 goto exit;
1683 priv->debugfs_dir = debugfs_create_dir(dev->name, libertas_dir);
1684 if (!priv->debugfs_dir)
1685 goto exit;
1687 for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
1688 files = &debugfs_files[i];
1689 priv->debugfs_files[i] = debugfs_create_file(files->name,
1690 files->perm,
1691 priv->debugfs_dir,
1692 priv,
1693 &files->fops);
1696 priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
1697 if (!priv->events_dir)
1698 goto exit;
1700 for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
1701 files = &debugfs_events_files[i];
1702 priv->debugfs_events_files[i] = debugfs_create_file(files->name,
1703 files->perm,
1704 priv->events_dir,
1705 priv,
1706 &files->fops);
1709 priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
1710 if (!priv->regs_dir)
1711 goto exit;
1713 for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
1714 files = &debugfs_regs_files[i];
1715 priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
1716 files->perm,
1717 priv->regs_dir,
1718 priv,
1719 &files->fops);
1722 #ifdef PROC_DEBUG
1723 libertas_debug_init(priv, dev);
1724 #endif
1725 exit:
1726 return;
1729 void libertas_debugfs_remove_one(wlan_private *priv)
1731 int i;
1733 for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
1734 debugfs_remove(priv->debugfs_regs_files[i]);
1736 debugfs_remove(priv->regs_dir);
1738 for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
1739 debugfs_remove(priv->debugfs_events_files[i]);
1741 debugfs_remove(priv->events_dir);
1742 #ifdef PROC_DEBUG
1743 debugfs_remove(priv->debugfs_debug);
1744 #endif
1745 for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
1746 debugfs_remove(priv->debugfs_files[i]);
1747 debugfs_remove(priv->debugfs_dir);
1752 /* debug entry */
1754 #ifdef PROC_DEBUG
1756 #define item_size(n) (FIELD_SIZEOF(wlan_adapter, n))
1757 #define item_addr(n) (offsetof(wlan_adapter, n))
1760 struct debug_data {
1761 char name[32];
1762 u32 size;
1763 size_t addr;
1766 /* To debug any member of wlan_adapter, simply add one line here.
1768 static struct debug_data items[] = {
1769 {"intcounter", item_size(intcounter), item_addr(intcounter)},
1770 {"psmode", item_size(psmode), item_addr(psmode)},
1771 {"psstate", item_size(psstate), item_addr(psstate)},
1774 static int num_of_items = ARRAY_SIZE(items);
1777 * @brief proc read function
1779 * @param page pointer to buffer
1780 * @param s read data starting position
1781 * @param off offset
1782 * @param cnt counter
1783 * @param eof end of file flag
1784 * @param data data to output
1785 * @return number of output data
1787 static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf,
1788 size_t count, loff_t *ppos)
1790 int val = 0;
1791 size_t pos = 0;
1792 ssize_t res;
1793 char *p;
1794 int i;
1795 struct debug_data *d;
1796 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1797 char *buf = (char *)addr;
1799 p = buf;
1801 d = (struct debug_data *)file->private_data;
1803 for (i = 0; i < num_of_items; i++) {
1804 if (d[i].size == 1)
1805 val = *((u8 *) d[i].addr);
1806 else if (d[i].size == 2)
1807 val = *((u16 *) d[i].addr);
1808 else if (d[i].size == 4)
1809 val = *((u32 *) d[i].addr);
1810 else if (d[i].size == 8)
1811 val = *((u64 *) d[i].addr);
1813 pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
1816 res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
1818 free_page(addr);
1819 return res;
1823 * @brief proc write function
1825 * @param f file pointer
1826 * @param buf pointer to data buffer
1827 * @param cnt data number to write
1828 * @param data data to write
1829 * @return number of data
1831 static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf,
1832 size_t cnt, loff_t *ppos)
1834 int r, i;
1835 char *pdata;
1836 char *p;
1837 char *p0;
1838 char *p1;
1839 char *p2;
1840 struct debug_data *d = (struct debug_data *)f->private_data;
1842 pdata = (char *)kmalloc(cnt, GFP_KERNEL);
1843 if (pdata == NULL)
1844 return 0;
1846 if (copy_from_user(pdata, buf, cnt)) {
1847 lbs_deb_debugfs("Copy from user failed\n");
1848 kfree(pdata);
1849 return 0;
1852 p0 = pdata;
1853 for (i = 0; i < num_of_items; i++) {
1854 do {
1855 p = strstr(p0, d[i].name);
1856 if (p == NULL)
1857 break;
1858 p1 = strchr(p, '\n');
1859 if (p1 == NULL)
1860 break;
1861 p0 = p1++;
1862 p2 = strchr(p, '=');
1863 if (!p2)
1864 break;
1865 p2++;
1866 r = simple_strtoul(p2, NULL, 0);
1867 if (d[i].size == 1)
1868 *((u8 *) d[i].addr) = (u8) r;
1869 else if (d[i].size == 2)
1870 *((u16 *) d[i].addr) = (u16) r;
1871 else if (d[i].size == 4)
1872 *((u32 *) d[i].addr) = (u32) r;
1873 else if (d[i].size == 8)
1874 *((u64 *) d[i].addr) = (u64) r;
1875 break;
1876 } while (1);
1878 kfree(pdata);
1880 return (ssize_t)cnt;
1883 static struct file_operations libertas_debug_fops = {
1884 .owner = THIS_MODULE,
1885 .open = open_file_generic,
1886 .write = wlan_debugfs_write,
1887 .read = wlan_debugfs_read,
1891 * @brief create debug proc file
1893 * @param priv pointer wlan_private
1894 * @param dev pointer net_device
1895 * @return N/A
1897 static void libertas_debug_init(wlan_private * priv, struct net_device *dev)
1899 int i;
1901 if (!priv->debugfs_dir)
1902 return;
1904 for (i = 0; i < num_of_items; i++)
1905 items[i].addr += (size_t) priv->adapter;
1907 priv->debugfs_debug = debugfs_create_file("debug", 0644,
1908 priv->debugfs_dir, &items[0],
1909 &libertas_debug_fops);
1911 #endif