1#include <linux/module.h> 2#include <linux/dcache.h> 3#include <linux/debugfs.h> 4#include <linux/delay.h> 5#include <linux/mm.h> 6#include <net/iw_handler.h> 7 8#include "dev.h" 9#include "decl.h" 10#include "host.h" 11#include "debugfs.h" 12 13static struct dentry *libertas_dir = NULL; 14static char *szStates[] = { 15 "Connected", 16 "Disconnected" 17}; 18 19#ifdef PROC_DEBUG 20static void libertas_debug_init(wlan_private * priv, struct net_device *dev); 21#endif 22 23static int open_file_generic(struct inode *inode, struct file *file) 24{ 25 file->private_data = inode->i_private; 26 return 0; 27} 28 29static ssize_t write_file_dummy(struct file *file, const char __user *buf, 30 size_t count, loff_t *ppos) 31{ 32 return -EINVAL; 33} 34 35static const size_t len = PAGE_SIZE; 36 37static ssize_t libertas_dev_info(struct file *file, char __user *userbuf, 38 size_t count, loff_t *ppos) 39{ 40 wlan_private *priv = file->private_data; 41 size_t pos = 0; 42 unsigned long addr = get_zeroed_page(GFP_KERNEL); 43 char *buf = (char *)addr; 44 ssize_t res; 45 46 pos += snprintf(buf+pos, len-pos, "state = %s\n", 47 szStates[priv->adapter->connect_status]); 48 pos += snprintf(buf+pos, len-pos, "region_code = %02x\n", 49 (u32) priv->adapter->regioncode); 50 51 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 52 53 free_page(addr); 54 return res; 55} 56 57 58static ssize_t libertas_getscantable(struct file *file, char __user *userbuf, 59 size_t count, loff_t *ppos) 60{ 61 wlan_private *priv = file->private_data; 62 size_t pos = 0; 63 int numscansdone = 0, res; 64 unsigned long addr = get_zeroed_page(GFP_KERNEL); 65 char *buf = (char *)addr; 66 struct bss_descriptor * iter_bss; 67 68 pos += snprintf(buf+pos, len-pos, 69 "# | ch | ss | bssid | cap | TSF | Qual | SSID \n"); 70 71 mutex_lock(&priv->adapter->lock); 72 list_for_each_entry (iter_bss, &priv->adapter->network_list, list) { 73 u16 cap; 74 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)); 89 90 numscansdone++; 91 } 92 mutex_unlock(&priv->adapter->lock); 93 94 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 95 96 free_page(addr); 97 return res; 98} 99 100static ssize_t libertas_sleepparams_write(struct file *file, 101 const char __user *user_buf, size_t count, 102 loff_t *ppos) 103{ 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; 109 110 buf_size = min(count, len - 1); 111 if (copy_from_user(buf, user_buf, buf_size)) { 112 res = -EFAULT; 113 goto out_unlock; 114 } 115 res = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6); 116 if (res != 6) { 117 res = -EFAULT; 118 goto out_unlock; 119 } 120 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; 126 127 res = libertas_prepare_and_send_command(priv, 128 cmd_802_11_sleep_params, 129 cmd_act_set, 130 cmd_option_waitforrsp, 0, NULL); 131 132 if (!res) 133 res = count; 134 else 135 res = -EINVAL; 136 137out_unlock: 138 free_page(addr); 139 return res; 140} 141 142static ssize_t libertas_sleepparams_read(struct file *file, char __user *userbuf, 143 size_t count, loff_t *ppos) 144{ 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; 151 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; 159 } 160 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); 165 166 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 167 168out_unlock: 169 free_page(addr); 170 return res; 171} 172 173static ssize_t libertas_extscan(struct file *file, const char __user *userbuf, 174 size_t count, loff_t *ppos) 175{ 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; 181 182 buf_size = min(count, len - 1); 183 if (copy_from_user(buf, userbuf, buf_size)) { 184 res = -EFAULT; 185 goto out_unlock; 186 } 187 188 libertas_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0); 189 190 memset(&wrqu, 0, sizeof(union iwreq_data)); 191 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); 192 193out_unlock: 194 free_page(addr); 195 return count; 196} 197 198static int libertas_parse_chan(char *buf, size_t count, 199 struct wlan_ioctl_user_scan_cfg *scan_cfg, int dur) 200{ 201 char *start, *end, *hold, *str; 202 int i = 0; 203 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; 226 227 scan_cfg->chanlist[i].scantime = dur; 228 i++; 229 } 230 231 kfree(hold); 232 return i; 233} 234 235static void libertas_parse_bssid(char *buf, size_t count, 236 struct wlan_ioctl_user_scan_cfg *scan_cfg) 237{ 238 char *hold; 239 unsigned int mac[ETH_ALEN]; 240 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); 247} 248 249static void libertas_parse_ssid(char *buf, size_t count, 250 struct wlan_ioctl_user_scan_cfg *scan_cfg) 251{ 252 char *hold, *end; 253 ssize_t size; 254 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; 262 263 size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold)); 264 strncpy(scan_cfg->ssid, hold, size); 265 266 return; 267} 268 269static int libertas_parse_clear(char *buf, size_t count, const char *tag) 270{ 271 char *hold; 272 int val; 273 274 hold = strstr(buf, tag); 275 if (!hold) 276 return 0; 277 hold += strlen(tag); 278 sscanf(hold, "%d", &val); 279 280 if (val != 0) 281 val = 1; 282 283 return val; 284} 285 286static int libertas_parse_dur(char *buf, size_t count, 287 struct wlan_ioctl_user_scan_cfg *scan_cfg) 288{ 289 char *hold; 290 int val; 291 292 hold = strstr(buf, "dur="); 293 if (!hold) 294 return 0; 295 hold += 4; 296 sscanf(hold, "%d", &val); 297 298 return val; 299} 300 301static void libertas_parse_probes(char *buf, size_t count, 302 struct wlan_ioctl_user_scan_cfg *scan_cfg) 303{ 304 char *hold; 305 int val; 306 307 hold = strstr(buf, "probes="); 308 if (!hold) 309 return; 310 hold += 7; 311 sscanf(hold, "%d", &val); 312 313 scan_cfg->numprobes = val; 314 315 return; 316} 317 318static void libertas_parse_type(char *buf, size_t count, 319 struct wlan_ioctl_user_scan_cfg *scan_cfg) 320{ 321 char *hold; 322 int val; 323 324 hold = strstr(buf, "type="); 325 if (!hold) 326 return; 327 hold += 5; 328 sscanf(hold, "%d", &val); 329 330 /* type=1,2 or 3 */ 331 if (val < 1 || val > 3) 332 return; 333 334 scan_cfg->bsstype = val; 335 336 return; 337} 338 339static ssize_t libertas_setuserscan(struct file *file, 340 const char __user *userbuf, 341 size_t count, loff_t *ppos) 342{ 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; 350 351 scan_cfg = kzalloc(sizeof(struct wlan_ioctl_user_scan_cfg), GFP_KERNEL); 352 if (!scan_cfg) 353 return -ENOMEM; 354 355 buf_size = min(count, len - 1); 356 if (copy_from_user(buf, userbuf, buf_size)) { 357 res = -EFAULT; 358 goto out_unlock; 359 } 360 361 scan_cfg->bsstype = WLAN_SCAN_BSS_TYPE_ANY; 362 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); 371 372 wlan_scan_networks(priv, scan_cfg, 1); 373 wait_event_interruptible(priv->adapter->cmd_pending, 374 !priv->adapter->nr_cmd_pending); 375 376 memset(&wrqu, 0x00, sizeof(union iwreq_data)); 377 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); 378 379out_unlock: 380 free_page(addr); 381 kfree(scan_cfg); 382 return count; 383} 384 385static int libertas_event_initcmd(wlan_private *priv, void **response_buf, 386 struct cmd_ctrl_node **cmdnode, 387 struct cmd_ds_command **cmd) 388{ 389 u16 wait_option = cmd_option_waitforrsp; 390 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; 394 } 395 if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) { 396 lbs_deb_debugfs("failed to allocate response buffer!\n"); 397 return -ENOMEM; 398 } 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; 409} 410 411static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf, 412 size_t count, loff_t *ppos) 413{ 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; 424 425 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 426 if (res < 0) { 427 free_page(addr); 428 return res; 429 } 430 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); 436 437 /* Sleep until response is generated by FW */ 438 wait_event_interruptible(pcmdnode->cmdwait_q, 439 pcmdnode->cmdwaitqwoken); 440 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; 448 } 449 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; 455 } 456 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; 472 } 473 } 474 475 kfree(response_buf); 476 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 477 free_page(addr); 478 return res; 479} 480 481static u16 libertas_get_events_bitmap(wlan_private *priv) 482{ 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; 490 491 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 492 if (res < 0) 493 return res; 494 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); 500 501 /* Sleep until response is generated by FW */ 502 wait_event_interruptible(pcmdnode->cmdwait_q, 503 pcmdnode->cmdwaitqwoken); 504 505 pcmdptr = response_buf; 506 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; 512 } 513 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; 518 } 519 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; 524} 525 526static ssize_t libertas_lowrssi_write(struct file *file, 527 const char __user *userbuf, 528 size_t count, loff_t *ppos) 529{ 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; 543 544 buf_size = min(count, len - 1); 545 if (copy_from_user(buf, userbuf, buf_size)) { 546 res = -EFAULT; 547 goto out_unlock; 548 } 549 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed); 550 if (res != 3) { 551 res = -EFAULT; 552 goto out_unlock; 553 } 554 555 event_bitmap = libertas_get_events_bitmap(priv); 556 557 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 558 if (res < 0) 559 goto out_unlock; 560 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)); 566 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); 576 577 libertas_queue_cmd(adapter, pcmdnode, 1); 578 wake_up_interruptible(&priv->mainthread.waitq); 579 580 /* Sleep until response is generated by FW */ 581 wait_event_interruptible(pcmdnode->cmdwait_q, 582 pcmdnode->cmdwaitqwoken); 583 584 pcmdptr = response_buf; 585 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; 592 } 593 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; 599 } 600 601 res = count; 602out_unlock: 603 free_page(addr); 604 return res; 605} 606 607static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf, 608 size_t count, loff_t *ppos) 609{ 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; 620 621 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 622 if (res < 0) { 623 free_page(addr); 624 return res; 625 } 626 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); 632 633 /* Sleep until response is generated by FW */ 634 wait_event_interruptible(pcmdnode->cmdwait_q, 635 pcmdnode->cmdwaitqwoken); 636 637 pcmdptr = response_buf; 638 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; 645 } 646 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; 652 } 653 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; 669 } 670 } 671 672 kfree(response_buf); 673 674 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 675 free_page(addr); 676 return res; 677} 678 679static ssize_t libertas_lowsnr_write(struct file *file, 680 const char __user *userbuf, 681 size_t count, loff_t *ppos) 682{ 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; 696 697 buf_size = min(count, len - 1); 698 if (copy_from_user(buf, userbuf, buf_size)) { 699 res = -EFAULT; 700 goto out_unlock; 701 } 702 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed); 703 if (res != 3) { 704 res = -EFAULT; 705 goto out_unlock; 706 } 707 708 event_bitmap = libertas_get_events_bitmap(priv); 709 710 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 711 if (res < 0) 712 goto out_unlock; 713 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); 728 729 libertas_queue_cmd(adapter, pcmdnode, 1); 730 wake_up_interruptible(&priv->mainthread.waitq); 731 732 /* Sleep until response is generated by FW */ 733 wait_event_interruptible(pcmdnode->cmdwait_q, 734 pcmdnode->cmdwaitqwoken); 735 736 pcmdptr = response_buf; 737 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; 744 } 745 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; 751 } 752 753 res = count; 754 755out_unlock: 756 free_page(addr); 757 return res; 758} 759 760static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf, 761 size_t count, loff_t *ppos) 762{ 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; 773 774 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 775 if (res < 0) { 776 free_page(addr); 777 return res; 778 } 779 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); 785 786 /* Sleep until response is generated by FW */ 787 wait_event_interruptible(pcmdnode->cmdwait_q, 788 pcmdnode->cmdwaitqwoken); 789 790 pcmdptr = response_buf; 791 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; 798 } 799 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; 805 } 806 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; 822 } 823 } 824 825 kfree(response_buf); 826 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 827 free_page(addr); 828 return res; 829} 830 831static ssize_t libertas_failcount_write(struct file *file, 832 const char __user *userbuf, 833 size_t count, loff_t *ppos) 834{ 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; 848 849 buf_size = min(count, len - 1); 850 if (copy_from_user(buf, userbuf, buf_size)) { 851 res = -EFAULT; 852 goto out_unlock; 853 } 854 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed); 855 if (res != 3) { 856 res = -EFAULT; 857 goto out_unlock; 858 } 859 860 event_bitmap = libertas_get_events_bitmap(priv); 861 862 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 863 if (res < 0) 864 goto out_unlock; 865 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); 880 881 libertas_queue_cmd(adapter, pcmdnode, 1); 882 wake_up_interruptible(&priv->mainthread.waitq); 883 884 /* Sleep until response is generated by FW */ 885 wait_event_interruptible(pcmdnode->cmdwait_q, 886 pcmdnode->cmdwaitqwoken); 887 888 pcmdptr = (struct cmd_ds_command *)response_buf; 889 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; 896 } 897 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; 903 } 904 905 res = count; 906out_unlock: 907 free_page(addr); 908 return res; 909} 910 911static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf, 912 size_t count, loff_t *ppos) 913{ 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; 924 925 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 926 if (res < 0) { 927 free_page(addr); 928 return res; 929 } 930 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); 936 937 /* Sleep until response is generated by FW */ 938 wait_event_interruptible(pcmdnode->cmdwait_q, 939 pcmdnode->cmdwaitqwoken); 940 941 pcmdptr = response_buf; 942 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; 949 } 950 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; 956 } 957 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; 972 } 973 } 974 975 kfree(response_buf); 976 977 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 978 free_page(addr); 979 return res; 980} 981 982static ssize_t libertas_bcnmiss_write(struct file *file, 983 const char __user *userbuf, 984 size_t count, loff_t *ppos) 985{ 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; 999 1000 buf_size = min(count, len - 1); 1001 if (copy_from_user(buf, userbuf, buf_size)) { 1002 res = -EFAULT; 1003 goto out_unlock; 1004 } 1005 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed); 1006 if (res != 3) { 1007 res = -EFAULT; 1008 goto out_unlock; 1009 } 1010 1011 event_bitmap = libertas_get_events_bitmap(priv); 1012 1013 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 1014 if (res < 0) 1015 goto out_unlock; 1016 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); 1030 1031 libertas_queue_cmd(adapter, pcmdnode, 1); 1032 wake_up_interruptible(&priv->mainthread.waitq); 1033 1034 /* Sleep until response is generated by FW */ 1035 wait_event_interruptible(pcmdnode->cmdwait_q, 1036 pcmdnode->cmdwaitqwoken); 1037 1038 pcmdptr = response_buf; 1039 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; 1046 } 1047 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; 1053 } 1054 1055 res = count; 1056out_unlock: 1057 free_page(addr); 1058 return res; 1059} 1060 1061static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf, 1062 size_t count, loff_t *ppos) 1063{ 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; 1074 1075 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 1076 if (res < 0) { 1077 free_page(addr); 1078 return res; 1079 } 1080 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); 1086 1087 /* Sleep until response is generated by FW */ 1088 wait_event_interruptible(pcmdnode->cmdwait_q, 1089 pcmdnode->cmdwaitqwoken); 1090 1091 pcmdptr = response_buf; 1092 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; 1099 } 1100 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; 1106 } 1107 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; 1123 } 1124 } 1125 1126 kfree(response_buf); 1127 1128 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 1129 free_page(addr); 1130 return res; 1131} 1132 1133static ssize_t libertas_highrssi_write(struct file *file, 1134 const char __user *userbuf, 1135 size_t count, loff_t *ppos) 1136{ 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; 1150 1151 buf_size = min(count, len - 1); 1152 if (copy_from_user(buf, userbuf, buf_size)) { 1153 res = -EFAULT; 1154 goto out_unlock; 1155 } 1156 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed); 1157 if (res != 3) { 1158 res = -EFAULT; 1159 goto out_unlock; 1160 } 1161 1162 event_bitmap = libertas_get_events_bitmap(priv); 1163 1164 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 1165 if (res < 0) 1166 goto out_unlock; 1167 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); 1182 1183 libertas_queue_cmd(adapter, pcmdnode, 1); 1184 wake_up_interruptible(&priv->mainthread.waitq); 1185 1186 /* Sleep until response is generated by FW */ 1187 wait_event_interruptible(pcmdnode->cmdwait_q, 1188 pcmdnode->cmdwaitqwoken); 1189 1190 pcmdptr = response_buf; 1191 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; 1197 } 1198 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; 1203 } 1204 1205 res = count; 1206out_unlock: 1207 free_page(addr); 1208 return res; 1209} 1210 1211static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf, 1212 size_t count, loff_t *ppos) 1213{ 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; 1224 1225 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 1226 if (res < 0) { 1227 free_page(addr); 1228 return res; 1229 } 1230 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); 1236 1237 /* Sleep until response is generated by FW */ 1238 wait_event_interruptible(pcmdnode->cmdwait_q, 1239 pcmdnode->cmdwaitqwoken); 1240 1241 pcmdptr = response_buf; 1242 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; 1249 } 1250 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; 1256 } 1257 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; 1273 } 1274 } 1275 1276 kfree(response_buf); 1277 1278 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 1279 free_page(addr); 1280 return res; 1281} 1282 1283static ssize_t libertas_highsnr_write(struct file *file, 1284 const char __user *userbuf, 1285 size_t count, loff_t *ppos) 1286{ 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; 1300 1301 buf_size = min(count, len - 1); 1302 if (copy_from_user(buf, userbuf, buf_size)) { 1303 res = -EFAULT; 1304 goto out_unlock; 1305 } 1306 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed); 1307 if (res != 3) { 1308 res = -EFAULT; 1309 goto out_unlock; 1310 } 1311 1312 event_bitmap = libertas_get_events_bitmap(priv); 1313 1314 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); 1315 if (res < 0) 1316 goto out_unlock; 1317 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); 1332 1333 libertas_queue_cmd(adapter, pcmdnode, 1); 1334 wake_up_interruptible(&priv->mainthread.waitq); 1335 1336 /* Sleep until response is generated by FW */ 1337 wait_event_interruptible(pcmdnode->cmdwait_q, 1338 pcmdnode->cmdwaitqwoken); 1339 1340 pcmdptr = response_buf; 1341 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; 1348 } 1349 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; 1355 } 1356 1357 res = count; 1358out_unlock: 1359 free_page(addr); 1360 return res; 1361} 1362 1363static ssize_t libertas_rdmac_read(struct file *file, char __user *userbuf, 1364 size_t count, loff_t *ppos) 1365{ 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; 1373 1374 offval.offset = priv->mac_offset; 1375 offval.value = 0; 1376 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); 1383 1384 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 1385 free_page(addr); 1386 return ret; 1387} 1388 1389static ssize_t libertas_rdmac_write(struct file *file, 1390 const char __user *userbuf, 1391 size_t count, loff_t *ppos) 1392{ 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; 1397 1398 buf_size = min(count, len - 1); 1399 if (copy_from_user(buf, userbuf, buf_size)) { 1400 res = -EFAULT; 1401 goto out_unlock; 1402 } 1403 priv->mac_offset = simple_strtoul((char *)buf, NULL, 16); 1404 res = count; 1405out_unlock: 1406 free_page(addr); 1407 return res; 1408} 1409 1410static ssize_t libertas_wrmac_write(struct file *file, 1411 const char __user *userbuf, 1412 size_t count, loff_t *ppos) 1413{ 1414 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; 1421 1422 buf_size = min(count, len - 1); 1423 if (copy_from_user(buf, userbuf, buf_size)) { 1424 res = -EFAULT; 1425 goto out_unlock; 1426 } 1427 res = sscanf(buf, "%x %x", &offset, &value); 1428 if (res != 2) { 1429 res = -EFAULT; 1430 goto out_unlock; 1431 } 1432 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); 1439 1440 res = count; 1441out_unlock: 1442 free_page(addr); 1443 return res; 1444} 1445 1446static ssize_t libertas_rdbbp_read(struct file *file, char __user *userbuf, 1447 size_t count, loff_t *ppos) 1448{ 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; 1456 1457 offval.offset = priv->bbp_offset; 1458 offval.value = 0; 1459 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); 1466 1467 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 1468 free_page(addr); 1469 1470 return ret; 1471} 1472 1473static ssize_t libertas_rdbbp_write(struct file *file, 1474 const char __user *userbuf, 1475 size_t count, loff_t *ppos) 1476{ 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; 1481 1482 buf_size = min(count, len - 1); 1483 if (copy_from_user(buf, userbuf, buf_size)) { 1484 res = -EFAULT; 1485 goto out_unlock; 1486 } 1487 priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16); 1488 res = count; 1489out_unlock: 1490 free_page(addr); 1491 return res; 1492} 1493 1494static ssize_t libertas_wrbbp_write(struct file *file, 1495 const char __user *userbuf, 1496 size_t count, loff_t *ppos) 1497{ 1498 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; 1505 1506 buf_size = min(count, len - 1); 1507 if (copy_from_user(buf, userbuf, buf_size)) { 1508 res = -EFAULT; 1509 goto out_unlock; 1510 } 1511 res = sscanf(buf, "%x %x", &offset, &value); 1512 if (res != 2) { 1513 res = -EFAULT; 1514 goto out_unlock; 1515 } 1516 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); 1523 1524 res = count; 1525out_unlock: 1526 free_page(addr); 1527 return res; 1528} 1529 1530static ssize_t libertas_rdrf_read(struct file *file, char __user *userbuf, 1531 size_t count, loff_t *ppos) 1532{ 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; 1540 1541 offval.offset = priv->rf_offset; 1542 offval.value = 0; 1543 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); 1550 1551 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 1552 free_page(addr); 1553 1554 return ret; 1555} 1556 1557static ssize_t libertas_rdrf_write(struct file *file, 1558 const char __user *userbuf, 1559 size_t count, loff_t *ppos) 1560{ 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; 1565 1566 buf_size = min(count, len - 1); 1567 if (copy_from_user(buf, userbuf, buf_size)) { 1568 res = -EFAULT; 1569 goto out_unlock; 1570 } 1571 priv->rf_offset = simple_strtoul((char *)buf, NULL, 16); 1572 res = count; 1573out_unlock: 1574 free_page(addr); 1575 return res; 1576} 1577 1578static ssize_t libertas_wrrf_write(struct file *file, 1579 const char __user *userbuf, 1580 size_t count, loff_t *ppos) 1581{ 1582 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; 1589 1590 buf_size = min(count, len - 1); 1591 if (copy_from_user(buf, userbuf, buf_size)) { 1592 res = -EFAULT; 1593 goto out_unlock; 1594 } 1595 res = sscanf(buf, "%x %x", &offset, &value); 1596 if (res != 2) { 1597 res = -EFAULT; 1598 goto out_unlock; 1599 } 1600 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); 1607 1608 res = count; 1609out_unlock: 1610 free_page(addr); 1611 return res; 1612} 1613 1614#define FOPS(fread, fwrite) { \ 1615 .owner = THIS_MODULE, \ 1616 .open = open_file_generic, \ 1617 .read = (fread), \ 1618 .write = (fwrite), \ 1619} 1620 1621struct libertas_debugfs_files { 1622 char *name; 1623 int perm; 1624 struct file_operations fops; 1625}; 1626 1627static 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), }, 1635}; 1636 1637static 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), }, 1650}; 1651 1652static 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), }, 1659}; 1660 1661void libertas_debugfs_init(void) 1662{ 1663 if (!libertas_dir) 1664 libertas_dir = debugfs_create_dir("libertas_wireless", NULL); 1665 1666 return; 1667} 1668 1669void libertas_debugfs_remove(void) 1670{ 1671 if (libertas_dir) 1672 debugfs_remove(libertas_dir); 1673 return; 1674} 1675 1676void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev) 1677{ 1678 int i; 1679 struct libertas_debugfs_files *files; 1680 if (!libertas_dir) 1681 goto exit; 1682 1683 priv->debugfs_dir = debugfs_create_dir(dev->name, libertas_dir); 1684 if (!priv->debugfs_dir) 1685 goto exit; 1686 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); 1694 } 1695 1696 priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir); 1697 if (!priv->events_dir) 1698 goto exit; 1699 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); 1707 } 1708 1709 priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir); 1710 if (!priv->regs_dir) 1711 goto exit; 1712 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); 1720 } 1721 1722#ifdef PROC_DEBUG 1723 libertas_debug_init(priv, dev); 1724#endif 1725exit: 1726 return; 1727} 1728 1729void libertas_debugfs_remove_one(wlan_private *priv) 1730{ 1731 int i; 1732 1733 for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) 1734 debugfs_remove(priv->debugfs_regs_files[i]); 1735 1736 debugfs_remove(priv->regs_dir); 1737 1738 for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++) 1739 debugfs_remove(priv->debugfs_events_files[i]); 1740 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); 1748} 1749 1750 1751 1752/* debug entry */ 1753 1754#ifdef PROC_DEBUG 1755 1756#define item_size(n) (FIELD_SIZEOF(wlan_adapter, n)) 1757#define item_addr(n) (offsetof(wlan_adapter, n)) 1758 1759 1760struct debug_data { 1761 char name[32]; 1762 u32 size; 1763 size_t addr; 1764}; 1765 1766/* To debug any member of wlan_adapter, simply add one line here. 1767 */ 1768static 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)}, 1772}; 1773 1774static int num_of_items = ARRAY_SIZE(items); 1775 1776/** 1777 * @brief proc read function 1778 * 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 1786 */ 1787static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf, 1788 size_t count, loff_t *ppos) 1789{ 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; 1798 1799 p = buf; 1800 1801 d = (struct debug_data *)file->private_data; 1802 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); 1812 1813 pos += sprintf(p + pos, "%s=%d\n", d[i].name, val); 1814 } 1815 1816 res = simple_read_from_buffer(userbuf, count, ppos, p, pos); 1817 1818 free_page(addr); 1819 return res; 1820} 1821 1822/** 1823 * @brief proc write function 1824 * 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 1830 */ 1831static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf, 1832 size_t cnt, loff_t *ppos) 1833{ 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; 1841 1842 pdata = (char *)kmalloc(cnt, GFP_KERNEL); 1843 if (pdata == NULL) 1844 return 0; 1845 1846 if (copy_from_user(pdata, buf, cnt)) { 1847 lbs_deb_debugfs("Copy from user failed\n"); 1848 kfree(pdata); 1849 return 0; 1850 } 1851 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); 1877 } 1878 kfree(pdata); 1879 1880 return (ssize_t)cnt; 1881} 1882 1883static 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, 1888}; 1889 1890/** 1891 * @brief create debug proc file 1892 * 1893 * @param priv pointer wlan_private 1894 * @param dev pointer net_device 1895 * @return N/A 1896 */ 1897static void libertas_debug_init(wlan_private * priv, struct net_device *dev) 1898{ 1899 int i; 1900 1901 if (!priv->debugfs_dir) 1902 return; 1903 1904 for (i = 0; i < num_of_items; i++) 1905 items[i].addr += (size_t) priv->adapter; 1906 1907 priv->debugfs_debug = debugfs_create_file("debug", 0644, 1908 priv->debugfs_dir, &items[0], 1909 &libertas_debug_fops); 1910} 1911#endif 1912