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