Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9-rc8 2193 lines 70 kB view raw
1/* 2 * --------------------------------------------------------------------------- 3 * FILE: drv.c 4 * 5 * PURPOSE: 6 * Conventional device interface for debugging/monitoring of the 7 * driver and h/w using unicli. This interface is also being used 8 * by the SME linux implementation and the helper apps. 9 * 10 * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. 11 * 12 * Refer to LICENSE.txt included with this source code for details on 13 * the license terms. 14 * 15 * --------------------------------------------------------------------------- 16 */ 17 18/* 19 * Porting Notes: 20 * Part of this file contains an example for how to glue the OS layer 21 * with the HIP core lib, the SDIO glue layer, and the SME. 22 * 23 * When the unifi_sdio.ko modules loads, the linux kernel calls unifi_load(). 24 * unifi_load() calls uf_sdio_load() which is exported by the SDIO glue 25 * layer. uf_sdio_load() registers this driver with the underlying SDIO driver. 26 * When a card is detected, the SDIO glue layer calls register_unifi_sdio() 27 * to pass the SDIO function context and ask the OS layer to initialise 28 * the card. register_unifi_sdio() allocates all the private data of the OS 29 * layer and calls uf_run_unifihelper() to start the SME. The SME calls 30 * unifi_sys_wifi_on_req() which uses the HIP core lib to initialise the card. 31 */ 32 33#include <linux/init.h> 34#include <linux/slab.h> 35#include <linux/poll.h> 36#include <asm/uaccess.h> 37#include <linux/jiffies.h> 38#include <linux/version.h> 39 40#include "csr_wifi_hip_unifiversion.h" 41#include "unifi_priv.h" 42#include "csr_wifi_hip_conversions.h" 43#include "unifi_native.h" 44 45/* Module parameter variables */ 46int buswidth = 0; /* 0 means use default, values 1,4 */ 47int sdio_clock = 50000; /* kHz */ 48int unifi_debug = 0; 49/* fw_init prevents f/w initialisation on error. */ 50int fw_init[MAX_UNIFI_DEVS] = {-1, -1}; 51int use_5g = 0; 52int led_mask = 0; /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */ 53int disable_hw_reset = 0; 54int disable_power_control = 0; 55int enable_wol = UNIFI_WOL_OFF; /* 0 for none, 1 for SDIO IRQ, 2 for PIO */ 56#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) 57int tl_80211d = (int)CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB; 58#endif 59int sdio_block_size = -1; /* Override SDIO block size */ 60int sdio_byte_mode = 0; /* 0 for block mode + padding, 1 for byte mode */ 61int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS; 62int run_bh_once = -1; /* Set for scheduled interrupt mode, -1 = default */ 63int bh_priority = -1; 64#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 65#define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA (1 << 1) 66#define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP (1 << 2) 67int log_hip_signals = 0; 68#endif 69 70MODULE_DESCRIPTION("CSR UniFi (SDIO)"); 71 72module_param(buswidth, int, S_IRUGO|S_IWUSR); 73module_param(sdio_clock, int, S_IRUGO|S_IWUSR); 74module_param(unifi_debug, int, S_IRUGO|S_IWUSR); 75module_param_array(fw_init, int, NULL, S_IRUGO|S_IWUSR); 76module_param(use_5g, int, S_IRUGO|S_IWUSR); 77module_param(led_mask, int, S_IRUGO|S_IWUSR); 78module_param(disable_hw_reset, int, S_IRUGO|S_IWUSR); 79module_param(disable_power_control, int, S_IRUGO|S_IWUSR); 80module_param(enable_wol, int, S_IRUGO|S_IWUSR); 81#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) 82module_param(tl_80211d, int, S_IRUGO|S_IWUSR); 83#endif 84module_param(sdio_block_size, int, S_IRUGO|S_IWUSR); 85module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR); 86module_param(coredump_max, int, S_IRUGO|S_IWUSR); 87module_param(run_bh_once, int, S_IRUGO|S_IWUSR); 88module_param(bh_priority, int, S_IRUGO|S_IWUSR); 89#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 90module_param(log_hip_signals, int, S_IRUGO|S_IWUSR); 91#endif 92 93MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode"); 94MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)"); 95MODULE_PARM_DESC(unifi_debug, "Diagnostic reporting level"); 96MODULE_PARM_DESC(fw_init, "Set to 0 to prevent f/w initialization on error"); 97MODULE_PARM_DESC(use_5g, "Use the 5G (802.11a) radio band"); 98MODULE_PARM_DESC(led_mask, "LED mask flags"); 99MODULE_PARM_DESC(disable_hw_reset, "Set to 1 to disable hardware reset"); 100MODULE_PARM_DESC(disable_power_control, "Set to 1 to disable SDIO power control"); 101MODULE_PARM_DESC(enable_wol, "Enable wake-on-wlan function 0=off, 1=SDIO, 2=PIO"); 102#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) 103MODULE_PARM_DESC(tl_80211d, "802.11d Trust Level (1-6, default = 5)"); 104#endif 105MODULE_PARM_DESC(sdio_block_size, "Set to override SDIO block size"); 106MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO"); 107MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate"); 108MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts"); 109MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority"); 110#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 111MODULE_PARM_DESC(log_hip_signals, "Set to 1 to enable HIP signal offline logging"); 112#endif 113 114 115/* Callback for event logging to UDI clients */ 116static void udi_log_event(ul_client_t *client, 117 const u8 *signal, int signal_len, 118 const bulk_data_param_t *bulkdata, 119 int dir); 120 121static void udi_set_log_filter(ul_client_t *pcli, 122 unifiio_filter_t *udi_filter); 123 124 125/* Mutex to protect access to priv->sme_cli */ 126DEFINE_SEMAPHORE(udi_mutex); 127 128s32 CsrHipResultToStatus(CsrResult csrResult) 129{ 130 s32 r = -EIO; 131 132 switch (csrResult) 133 { 134 case CSR_RESULT_SUCCESS: 135 r = 0; 136 break; 137 case CSR_WIFI_HIP_RESULT_RANGE: 138 r = -ERANGE; 139 break; 140 case CSR_WIFI_HIP_RESULT_NO_DEVICE: 141 r = -ENODEV; 142 break; 143 case CSR_WIFI_HIP_RESULT_INVALID_VALUE: 144 r = -EINVAL; 145 break; 146 case CSR_WIFI_HIP_RESULT_NOT_FOUND: 147 r = -ENOENT; 148 break; 149 case CSR_WIFI_HIP_RESULT_NO_SPACE: 150 r = -ENOSPC; 151 break; 152 case CSR_WIFI_HIP_RESULT_NO_MEMORY: 153 r = -ENOMEM; 154 break; 155 case CSR_RESULT_FAILURE: 156 r = -EIO; 157 break; 158 default: 159 /*unifi_warning(card->ospriv, "CsrHipResultToStatus: Unrecognised csrResult error code: %d\n", csrResult);*/ 160 r = -EIO; 161 } 162 return r; 163} 164 165 166static const char* 167trace_putest_cmdid(unifi_putest_command_t putest_cmd) 168{ 169 switch (putest_cmd) { 170 case UNIFI_PUTEST_START: 171 return "START"; 172 case UNIFI_PUTEST_STOP: 173 return "STOP"; 174 case UNIFI_PUTEST_SET_SDIO_CLOCK: 175 return "SET CLOCK"; 176 case UNIFI_PUTEST_CMD52_READ: 177 return "CMD52R"; 178 case UNIFI_PUTEST_CMD52_BLOCK_READ: 179 return "CMD52BR"; 180 case UNIFI_PUTEST_CMD52_WRITE: 181 return "CMD52W"; 182 case UNIFI_PUTEST_DL_FW: 183 return "D/L FW"; 184 case UNIFI_PUTEST_DL_FW_BUFF: 185 return "D/L FW BUFFER"; 186 case UNIFI_PUTEST_COREDUMP_PREPARE: 187 return "PREPARE COREDUMP"; 188 case UNIFI_PUTEST_GP_READ16: 189 return "GP16R"; 190 case UNIFI_PUTEST_GP_WRITE16: 191 return "GP16W"; 192 default: 193 return "ERROR: unrecognised command"; 194 } 195 } 196 197#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 198int uf_register_hip_offline_debug(unifi_priv_t *priv) 199{ 200 ul_client_t *udi_cli; 201 int i; 202 203 udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event); 204 if (udi_cli == NULL) { 205 /* Too many clients already using this device */ 206 unifi_error(priv, "Too many UDI clients already open\n"); 207 return -ENOSPC; 208 } 209 unifi_trace(priv, UDBG1, "Offline HIP client is registered\n"); 210 211 down(&priv->udi_logging_mutex); 212 udi_cli->event_hook = udi_log_event; 213 unifi_set_udi_hook(priv->card, logging_handler); 214 /* Log all signals by default */ 215 for (i = 0; i < SIG_FILTER_SIZE; i++) { 216 udi_cli->signal_filter[i] = 0xFFFF; 217 } 218 priv->logging_client = udi_cli; 219 up(&priv->udi_logging_mutex); 220 221 return 0; 222} 223 224int uf_unregister_hip_offline_debug(unifi_priv_t *priv) 225{ 226 ul_client_t *udi_cli = priv->logging_client; 227 if (udi_cli == NULL) 228 { 229 unifi_error(priv, "Unknown HIP client unregister request\n"); 230 return -ERANGE; 231 } 232 233 unifi_trace(priv, UDBG1, "Offline HIP client is unregistered\n"); 234 235 down(&priv->udi_logging_mutex); 236 priv->logging_client = NULL; 237 udi_cli->event_hook = NULL; 238 up(&priv->udi_logging_mutex); 239 240 ul_deregister_client(udi_cli); 241 242 return 0; 243} 244#endif 245 246 247/* 248 * --------------------------------------------------------------------------- 249 * unifi_open 250 * unifi_release 251 * 252 * Open and release entry points for the UniFi debug driver. 253 * 254 * Arguments: 255 * Normal linux driver args. 256 * 257 * Returns: 258 * Linux error code. 259 * --------------------------------------------------------------------------- 260 */ 261static int 262unifi_open(struct inode *inode, struct file *file) 263{ 264 int devno; 265 unifi_priv_t *priv; 266 ul_client_t *udi_cli; 267 268 devno = MINOR(inode->i_rdev) >> 1; 269 270 /* 271 * Increase the ref_count for the char device clients. 272 * Make sure you call uf_put_instance() to decreace it if 273 * unifi_open returns an error. 274 */ 275 priv = uf_get_instance(devno); 276 if (priv == NULL) { 277 unifi_error(NULL, "unifi_open: No device present\n"); 278 return -ENODEV; 279 } 280 281 /* Register this instance in the client's list. */ 282 /* The minor number determines the nature of the client (Unicli or SME). */ 283 if (MINOR(inode->i_rdev) & 0x1) { 284 udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event); 285 if (udi_cli == NULL) { 286 /* Too many clients already using this device */ 287 unifi_error(priv, "Too many clients already open\n"); 288 uf_put_instance(devno); 289 return -ENOSPC; 290 } 291 unifi_trace(priv, UDBG1, "Client is registered to /dev/unifiudi%d\n", devno); 292 } else { 293 /* 294 * Even-numbered device nodes are the control application. 295 * This is the userspace helper containing SME or 296 * unifi_manager. 297 */ 298 299 down(&udi_mutex); 300 301#ifdef CSR_SME_USERSPACE 302 /* Check if a config client is already attached */ 303 if (priv->sme_cli) { 304 up(&udi_mutex); 305 uf_put_instance(devno); 306 307 unifi_info(priv, "There is already a configuration client using the character device\n"); 308 return -EBUSY; 309 } 310#endif /* CSR_SME_USERSPACE */ 311 312#ifdef CSR_SUPPORT_SME 313 udi_cli = ul_register_client(priv, 314 CLI_USING_WIRE_FORMAT | CLI_SME_USERSPACE, 315 sme_log_event); 316#else 317 /* Config client for native driver */ 318 udi_cli = ul_register_client(priv, 319 0, 320 sme_native_log_event); 321#endif 322 if (udi_cli == NULL) { 323 /* Too many clients already using this device */ 324 up(&udi_mutex); 325 uf_put_instance(devno); 326 327 unifi_error(priv, "Too many clients already open\n"); 328 return -ENOSPC; 329 } 330 331 /* 332 * Fill-in the pointer to the configuration client. 333 * This is the SME userspace helper or unifi_manager. 334 * Not used in the SME embedded version. 335 */ 336 unifi_trace(priv, UDBG1, "SME client (id:%d s:0x%X) is registered\n", 337 udi_cli->client_id, udi_cli->sender_id); 338 /* Store the SME UniFi Linux Client */ 339 if (priv->sme_cli == NULL) { 340 priv->sme_cli = udi_cli; 341 } 342 343 up(&udi_mutex); 344 } 345 346 347 /* 348 * Store the pointer to the client. 349 * All char driver's entry points will pass this pointer. 350 */ 351 file->private_data = udi_cli; 352 353 return 0; 354} /* unifi_open() */ 355 356 357static int 358unifi_release(struct inode *inode, struct file *filp) 359{ 360 ul_client_t *udi_cli = (void*)filp->private_data; 361 int devno; 362 unifi_priv_t *priv; 363 364 priv = uf_find_instance(udi_cli->instance); 365 if (!priv) { 366 unifi_error(priv, "unifi_close: instance for device not found\n"); 367 return -ENODEV; 368 } 369 370 devno = MINOR(inode->i_rdev) >> 1; 371 372 /* Even device nodes are the config client (i.e. SME or unifi_manager) */ 373 if ((MINOR(inode->i_rdev) & 0x1) == 0) { 374 375 if (priv->sme_cli != udi_cli) { 376 unifi_notice(priv, "Surprise closing config device: not the sme client\n"); 377 } 378 unifi_notice(priv, "SME client close (unifi%d)\n", devno); 379 380 /* 381 * Clear sme_cli before calling unifi_sys_... so it doesn't try to 382 * queue a reply to the (now gone) SME. 383 */ 384 down(&udi_mutex); 385 priv->sme_cli = NULL; 386 up(&udi_mutex); 387 388#ifdef CSR_SME_USERSPACE 389 /* Power-down when config client closes */ 390 { 391 CsrWifiRouterCtrlWifiOffReq req = {{CSR_WIFI_ROUTER_CTRL_HIP_REQ, 0, 0, 0, NULL}}; 392 CsrWifiRouterCtrlWifiOffReqHandler(priv, &req.common); 393 } 394 395 uf_sme_deinit(priv); 396 397 /* It is possible that a blocking SME request was made from another process 398 * which did not get read by the SME before the WifiOffReq. 399 * So check for a pending request which will go unanswered and cancel 400 * the wait for event. As only one blocking request can be in progress at 401 * a time, up to one event should be completed. 402 */ 403 uf_sme_cancel_request(priv, 0); 404 405#endif /* CSR_SME_USERSPACE */ 406 } else { 407 408 unifi_trace(priv, UDBG2, "UDI client close (unifiudi%d)\n", devno); 409 410 /* If the pointer matches the logging client, stop logging. */ 411 down(&priv->udi_logging_mutex); 412 if (udi_cli == priv->logging_client) { 413 priv->logging_client = NULL; 414 } 415 up(&priv->udi_logging_mutex); 416 417 if (udi_cli == priv->amp_client) { 418 priv->amp_client = NULL; 419 } 420 } 421 422 /* Deregister this instance from the client's list. */ 423 ul_deregister_client(udi_cli); 424 425 uf_put_instance(devno); 426 427 return 0; 428} /* unifi_release() */ 429 430 431 432/* 433 * --------------------------------------------------------------------------- 434 * unifi_read 435 * 436 * The read() driver entry point. 437 * 438 * Arguments: 439 * filp The file descriptor returned by unifi_open() 440 * p The user space buffer to copy the read data 441 * len The size of the p buffer 442 * poff 443 * 444 * Returns: 445 * number of bytes read or an error code on failure 446 * --------------------------------------------------------------------------- 447 */ 448static ssize_t 449unifi_read(struct file *filp, char *p, size_t len, loff_t *poff) 450{ 451 ul_client_t *pcli = (void*)filp->private_data; 452 unifi_priv_t *priv; 453 udi_log_t *logptr = NULL; 454 udi_msg_t *msgptr; 455 struct list_head *l; 456 int msglen; 457 458 priv = uf_find_instance(pcli->instance); 459 if (!priv) { 460 unifi_error(priv, "invalid priv\n"); 461 return -ENODEV; 462 } 463 464 if (!pcli->udi_enabled) { 465 unifi_error(priv, "unifi_read: unknown client."); 466 return -EINVAL; 467 } 468 469 if (list_empty(&pcli->udi_log)) { 470 if (filp->f_flags & O_NONBLOCK) { 471 /* Non-blocking - just return if the udi_log is empty */ 472 return 0; 473 } else { 474 /* Blocking - wait on the UDI wait queue */ 475 if (wait_event_interruptible(pcli->udi_wq, 476 !list_empty(&pcli->udi_log))) 477 { 478 unifi_error(priv, "unifi_read: wait_event_interruptible failed."); 479 return -ERESTARTSYS; 480 } 481 } 482 } 483 484 /* Read entry from list head and remove it from the list */ 485 if (down_interruptible(&pcli->udi_sem)) { 486 return -ERESTARTSYS; 487 } 488 l = pcli->udi_log.next; 489 list_del(l); 490 up(&pcli->udi_sem); 491 492 /* Get a pointer to whole struct */ 493 logptr = list_entry(l, udi_log_t, q); 494 if (logptr == NULL) { 495 unifi_error(priv, "unifi_read: failed to get event.\n"); 496 return -EINVAL; 497 } 498 499 /* Get the real message */ 500 msgptr = &logptr->msg; 501 msglen = msgptr->length; 502 if (msglen > len) { 503 printk(KERN_WARNING "truncated read to %d actual msg len is %lu\n", msglen, (long unsigned int)len); 504 msglen = len; 505 } 506 507 /* and pass it to the client (SME or Unicli). */ 508 if (copy_to_user(p, msgptr, msglen)) 509 { 510 printk(KERN_ERR "Failed to copy UDI log to user\n"); 511 kfree(logptr); 512 return -EFAULT; 513 } 514 515 /* It is our resposibility to free the message buffer. */ 516 kfree(logptr); 517 518 return msglen; 519 520} /* unifi_read() */ 521 522 523 524/* 525 * --------------------------------------------------------------------------- 526 * udi_send_signal_unpacked 527 * 528 * Sends an unpacked signal to UniFi. 529 * 530 * Arguments: 531 * priv Pointer to private context struct 532 * data Pointer to request structure and data to send 533 * data_len Length of data in data pointer. 534 * 535 * Returns: 536 * Number of bytes written, error otherwise. 537 * 538 * Notes: 539 * All clients that use this function to send a signal to the unifi 540 * must use the host formatted structures. 541 * --------------------------------------------------------------------------- 542 */ 543static int 544udi_send_signal_unpacked(unifi_priv_t *priv, unsigned char* data, uint data_len) 545{ 546 CSR_SIGNAL *sigptr = (CSR_SIGNAL*)data; 547 CSR_DATAREF *datarefptr; 548 bulk_data_param_t bulk_data; 549 uint signal_size, i; 550 uint bulk_data_offset = 0; 551 int bytecount, r; 552 CsrResult csrResult; 553 554 /* Number of bytes in the signal */ 555 signal_size = SigGetSize(sigptr); 556 if (!signal_size || (signal_size > data_len)) { 557 unifi_error(priv, "unifi_sme_mlme_req - Invalid signal 0x%x size should be %d bytes\n", 558 sigptr->SignalPrimitiveHeader.SignalId, 559 signal_size); 560 return -EINVAL; 561 } 562 bytecount = signal_size; 563 564 /* Get a pointer to the information of the first data reference */ 565 datarefptr = (CSR_DATAREF*)&sigptr->u; 566 567 /* Initialize the offset in the data buffer, bulk data is right after the signal. */ 568 bulk_data_offset = signal_size; 569 570 /* store the references and the size of the bulk data to the bulkdata structure */ 571 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { 572 /* the length of the bulk data is in the signal */ 573 if ((datarefptr+i)->DataLength) { 574 void *dest; 575 576 csrResult = unifi_net_data_malloc(priv, &bulk_data.d[i], (datarefptr+i)->DataLength); 577 if (csrResult != CSR_RESULT_SUCCESS) { 578 unifi_error(priv, "udi_send_signal_unpacked: failed to allocate request_data.\n"); 579 return -EIO; 580 } 581 582 dest = (void*)bulk_data.d[i].os_data_ptr; 583 memcpy(dest, data + bulk_data_offset, bulk_data.d[i].data_length); 584 } else { 585 bulk_data.d[i].data_length = 0; 586 } 587 588 bytecount += bulk_data.d[i].data_length; 589 /* advance the offset, to point the next bulk data */ 590 bulk_data_offset += bulk_data.d[i].data_length; 591 } 592 593 594 unifi_trace(priv, UDBG3, "SME Send: signal 0x%.4X\n", sigptr->SignalPrimitiveHeader.SignalId); 595 596 /* Send the signal. */ 597 r = ul_send_signal_unpacked(priv, sigptr, &bulk_data); 598 if (r < 0) { 599 unifi_error(priv, "udi_send_signal_unpacked: send failed (%d)\n", r); 600 for(i=0;i<UNIFI_MAX_DATA_REFERENCES;i++) { 601 if(bulk_data.d[i].data_length != 0) { 602 unifi_net_data_free(priv, &bulk_data.d[i]); 603 } 604 } 605 return -EIO; 606 } 607 608 return bytecount; 609} /* udi_send_signal_unpacked() */ 610 611 612 613/* 614 * --------------------------------------------------------------------------- 615 * udi_send_signal_raw 616 * 617 * Sends a packed signal to UniFi. 618 * 619 * Arguments: 620 * priv Pointer to private context struct 621 * buf Pointer to request structure and data to send 622 * buflen Length of data in data pointer. 623 * 624 * Returns: 625 * Number of bytes written, error otherwise. 626 * 627 * Notes: 628 * All clients that use this function to send a signal to the unifi 629 * must use the wire formatted structures. 630 * --------------------------------------------------------------------------- 631 */ 632static int 633udi_send_signal_raw(unifi_priv_t *priv, unsigned char *buf, int buflen) 634{ 635 int signal_size; 636 int sig_id; 637 bulk_data_param_t data_ptrs; 638 int i, r; 639 unsigned int num_data_refs; 640 int bytecount; 641 CsrResult csrResult; 642 643 /* 644 * The signal is the first thing in buf, the signal id is the 645 * first 16 bits of the signal. 646 */ 647 /* Number of bytes in the signal */ 648 sig_id = GET_SIGNAL_ID(buf); 649 signal_size = buflen; 650 signal_size -= GET_PACKED_DATAREF_LEN(buf, 0); 651 signal_size -= GET_PACKED_DATAREF_LEN(buf, 1); 652 if ((signal_size <= 0) || (signal_size > buflen)) { 653 unifi_error(priv, "udi_send_signal_raw - Couldn't find length of signal 0x%x\n", 654 sig_id); 655 return -EINVAL; 656 } 657 unifi_trace(priv, UDBG2, "udi_send_signal_raw: signal 0x%.4X len:%d\n", 658 sig_id, signal_size); 659 /* Zero the data ref arrays */ 660 memset(&data_ptrs, 0, sizeof(data_ptrs)); 661 662 /* 663 * Find the number of associated bulk data packets. Scan through 664 * the data refs to check that we have enough data and pick out 665 * pointers to appended bulk data. 666 */ 667 num_data_refs = 0; 668 bytecount = signal_size; 669 670 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) 671 { 672 unsigned int len = GET_PACKED_DATAREF_LEN(buf, i); 673 unifi_trace(priv, UDBG3, "udi_send_signal_raw: data_ref length = %d\n", len); 674 675 if (len != 0) { 676 void *dest; 677 678 csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[i], len); 679 if (csrResult != CSR_RESULT_SUCCESS) { 680 unifi_error(priv, "udi_send_signal_raw: failed to allocate request_data.\n"); 681 return -EIO; 682 } 683 684 dest = (void*)data_ptrs.d[i].os_data_ptr; 685 memcpy(dest, buf + bytecount, len); 686 687 bytecount += len; 688 num_data_refs++; 689 } 690 data_ptrs.d[i].data_length = len; 691 } 692 693 unifi_trace(priv, UDBG3, "Queueing signal 0x%.4X from UDI with %u data refs\n", 694 sig_id, 695 num_data_refs); 696 697 if (bytecount > buflen) { 698 unifi_error(priv, "udi_send_signal_raw: Not enough data (%d instead of %d)\n", buflen, bytecount); 699 return -EINVAL; 700 } 701 702 /* Send the signal calling the function that uses the wire-formatted signals. */ 703 r = ul_send_signal_raw(priv, buf, signal_size, &data_ptrs); 704 if (r < 0) { 705 unifi_error(priv, "udi_send_signal_raw: send failed (%d)\n", r); 706 return -EIO; 707 } 708 709#ifdef CSR_NATIVE_LINUX 710 if (sig_id == CSR_MLME_POWERMGT_REQUEST_ID) { 711 int power_mode = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((buf + 712 SIZEOF_SIGNAL_HEADER + (UNIFI_MAX_DATA_REFERENCES*SIZEOF_DATAREF))); 713#ifdef CSR_SUPPORT_WEXT 714 /* Overide the wext power mode to the new value */ 715 priv->wext_conf.power_mode = power_mode; 716#endif 717 /* Configure deep sleep signaling */ 718 if (power_mode || (priv->interfacePriv[0]->connected == UnifiNotConnected)) { 719 csrResult = unifi_configure_low_power_mode(priv->card, 720 UNIFI_LOW_POWER_ENABLED, 721 UNIFI_PERIODIC_WAKE_HOST_DISABLED); 722 } else { 723 csrResult = unifi_configure_low_power_mode(priv->card, 724 UNIFI_LOW_POWER_DISABLED, 725 UNIFI_PERIODIC_WAKE_HOST_DISABLED); 726 } 727 } 728#endif 729 730 return bytecount; 731} /* udi_send_signal_raw */ 732 733/* 734 * --------------------------------------------------------------------------- 735 * unifi_write 736 * 737 * The write() driver entry point. 738 * A UniFi Debug Interface client such as unicli can write a signal 739 * plus bulk data to the driver for sending to the UniFi chip. 740 * 741 * Only one signal may be sent per write operation. 742 * 743 * Arguments: 744 * filp The file descriptor returned by unifi_open() 745 * p The user space buffer to get the data from 746 * len The size of the p buffer 747 * poff 748 * 749 * Returns: 750 * number of bytes written or an error code on failure 751 * --------------------------------------------------------------------------- 752 */ 753static ssize_t 754unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff) 755{ 756 ul_client_t *pcli = (ul_client_t*)filp->private_data; 757 unifi_priv_t *priv; 758 unsigned char *buf; 759 unsigned char *bufptr; 760 int remaining; 761 int bytes_written; 762 int r; 763 bulk_data_param_t bulkdata; 764 CsrResult csrResult; 765 766 priv = uf_find_instance(pcli->instance); 767 if (!priv) { 768 unifi_error(priv, "invalid priv\n"); 769 return -ENODEV; 770 } 771 772 unifi_trace(priv, UDBG5, "unifi_write: len = %d\n", len); 773 774 if (!pcli->udi_enabled) { 775 unifi_error(priv, "udi disabled\n"); 776 return -EINVAL; 777 } 778 779 /* 780 * AMP client sends only one signal at a time, so we can use 781 * unifi_net_data_malloc to save the extra copy. 782 */ 783 if (pcli == priv->amp_client) { 784 int signal_size; 785 int sig_id; 786 unsigned char *signal_buf; 787 char *user_data_buf; 788 789 csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], len); 790 if (csrResult != CSR_RESULT_SUCCESS) { 791 unifi_error(priv, "unifi_write: failed to allocate request_data.\n"); 792 return -ENOMEM; 793 } 794 795 user_data_buf = (char*)bulkdata.d[0].os_data_ptr; 796 797 /* Get the data from the AMP client. */ 798 if (copy_from_user((void*)user_data_buf, p, len)) { 799 unifi_error(priv, "unifi_write: copy from user failed\n"); 800 unifi_net_data_free(priv, &bulkdata.d[0]); 801 return -EFAULT; 802 } 803 804 bulkdata.d[1].os_data_ptr = NULL; 805 bulkdata.d[1].data_length = 0; 806 807 /* Number of bytes in the signal */ 808 sig_id = GET_SIGNAL_ID(bulkdata.d[0].os_data_ptr); 809 signal_size = len; 810 signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 0); 811 signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 1); 812 if ((signal_size <= 0) || (signal_size > len)) { 813 unifi_error(priv, "unifi_write - Couldn't find length of signal 0x%x\n", 814 sig_id); 815 unifi_net_data_free(priv, &bulkdata.d[0]); 816 return -EINVAL; 817 } 818 819 unifi_trace(priv, UDBG2, "unifi_write: signal 0x%.4X len:%d\n", 820 sig_id, signal_size); 821 822 /* Allocate a buffer for the signal */ 823 signal_buf = kmemdup(bulkdata.d[0].os_data_ptr, signal_size, 824 GFP_KERNEL); 825 if (!signal_buf) { 826 unifi_net_data_free(priv, &bulkdata.d[0]); 827 return -ENOMEM; 828 } 829 830 /* Get the signal from the os_data_ptr */ 831 signal_buf[5] = (pcli->sender_id >> 8) & 0xff; 832 833 if (signal_size < len) { 834 /* Remove the signal from the os_data_ptr */ 835 bulkdata.d[0].data_length -= signal_size; 836 bulkdata.d[0].os_data_ptr += signal_size; 837 } else { 838 bulkdata.d[0].data_length = 0; 839 bulkdata.d[0].os_data_ptr = NULL; 840 } 841 842 /* Send the signal calling the function that uses the wire-formatted signals. */ 843 r = ul_send_signal_raw(priv, signal_buf, signal_size, &bulkdata); 844 if (r < 0) { 845 unifi_error(priv, "unifi_write: send failed (%d)\n", r); 846 if (bulkdata.d[0].os_data_ptr != NULL) { 847 unifi_net_data_free(priv, &bulkdata.d[0]); 848 } 849 } 850 851 /* Free the signal buffer and return */ 852 kfree(signal_buf); 853 return len; 854 } 855 856 buf = kmalloc(len, GFP_KERNEL); 857 if (!buf) { 858 return -ENOMEM; 859 } 860 861 /* Get the data from the client (SME or Unicli). */ 862 if (copy_from_user((void*)buf, p, len)) { 863 unifi_error(priv, "copy from user failed\n"); 864 kfree(buf); 865 return -EFAULT; 866 } 867 868 /* 869 * In SME userspace build read() contains a SYS or MGT message. 870 * Note that even though the SME sends one signal at a time, we can not 871 * use unifi_net_data_malloc because in the early stages, before having 872 * initialised the core, it will fail since the I/O block size is unknown. 873 */ 874#ifdef CSR_SME_USERSPACE 875 if (pcli->configuration & CLI_SME_USERSPACE) { 876 CsrWifiRouterTransportRecv(priv, buf, len); 877 kfree(buf); 878 return len; 879 } 880#endif 881 882 /* ul_send_signal_raw will do a sanity check of len against signal content */ 883 884 /* 885 * udi_send_signal_raw() and udi_send_signal_unpacked() return the number of bytes consumed. 886 * A write call can pass multiple signal concatenated together. 887 */ 888 bytes_written = 0; 889 remaining = len; 890 bufptr = buf; 891 while (remaining > 0) 892 { 893 int r; 894 895 /* 896 * Set the SenderProcessId. 897 * The SignalPrimitiveHeader is the first 3 16-bit words of the signal, 898 * the SenderProcessId is bytes 4,5. 899 * The MSB of the sender ID needs to be set to the client ID. 900 * The LSB is controlled by the SME. 901 */ 902 bufptr[5] = (pcli->sender_id >> 8) & 0xff; 903 904 /* use the appropriate interface, depending on the clients' configuration */ 905 if (pcli->configuration & CLI_USING_WIRE_FORMAT) { 906 unifi_trace(priv, UDBG1, "unifi_write: call udi_send_signal().\n"); 907 r = udi_send_signal_raw(priv, bufptr, remaining); 908 } else { 909 r = udi_send_signal_unpacked(priv, bufptr, remaining); 910 } 911 if (r < 0) { 912 /* Set the return value to the error code */ 913 unifi_error(priv, "unifi_write: (udi or sme)_send_signal() returns %d\n", r); 914 bytes_written = r; 915 break; 916 } 917 bufptr += r; 918 remaining -= r; 919 bytes_written += r; 920 } 921 922 kfree(buf); 923 924 return bytes_written; 925} /* unifi_write() */ 926 927 928static const char* build_type_to_string(unsigned char build_type) 929{ 930 switch (build_type) 931 { 932 case UNIFI_BUILD_NME: return "NME"; 933 case UNIFI_BUILD_WEXT: return "WEXT"; 934 case UNIFI_BUILD_AP: return "AP"; 935 } 936 return "unknown"; 937} 938 939 940/* 941 * ---------------------------------------------------------------- 942 * unifi_ioctl 943 * 944 * Ioctl handler for unifi driver. 945 * 946 * Arguments: 947 * inodep Pointer to inode structure. 948 * filp Pointer to file structure. 949 * cmd Ioctl cmd passed by user. 950 * arg Ioctl arg passed by user. 951 * 952 * Returns: 953 * 0 on success, -ve error code on error. 954 * ---------------------------------------------------------------- 955 */ 956static long 957unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 958{ 959 ul_client_t *pcli = (ul_client_t*)filp->private_data; 960 unifi_priv_t *priv; 961 struct net_device *dev; 962 int r = 0; 963 int int_param, i; 964 u8* buf; 965 CsrResult csrResult; 966#if (defined CSR_SUPPORT_SME) 967 unifi_cfg_command_t cfg_cmd; 968#if (defined CSR_SUPPORT_WEXT) 969 CsrWifiSmeCoexConfig coex_config; 970 unsigned char uchar_param; 971 unsigned char varbind[MAX_VARBIND_LENGTH]; 972 int vblen; 973#endif 974#endif 975 unifi_putest_command_t putest_cmd; 976 977 priv = uf_find_instance(pcli->instance); 978 if (!priv) { 979 unifi_error(priv, "ioctl error: unknown instance=%d\n", pcli->instance); 980 r = -ENODEV; 981 goto out; 982 } 983 unifi_trace(priv, UDBG5, "unifi_ioctl: cmd=0x%X, arg=0x%lX\n", cmd, arg); 984 985 switch (cmd) { 986 987 case UNIFI_GET_UDI_ENABLE: 988 unifi_trace(priv, UDBG4, "UniFi Get UDI Enable\n"); 989 990 down(&priv->udi_logging_mutex); 991 int_param = (priv->logging_client == NULL) ? 0 : 1; 992 up(&priv->udi_logging_mutex); 993 994 if (put_user(int_param, (int*)arg)) 995 { 996 unifi_error(priv, "UNIFI_GET_UDI_ENABLE: Failed to copy to user\n"); 997 r = -EFAULT; 998 goto out; 999 } 1000 break; 1001 1002 case UNIFI_SET_UDI_ENABLE: 1003 unifi_trace(priv, UDBG4, "UniFi Set UDI Enable\n"); 1004 if (get_user(int_param, (int*)arg)) 1005 { 1006 unifi_error(priv, "UNIFI_SET_UDI_ENABLE: Failed to copy from user\n"); 1007 r = -EFAULT; 1008 goto out; 1009 } 1010 1011#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 1012 if (log_hip_signals) { 1013 unifi_error(priv, "omnicli cannot be used when log_hip_signals is used\n"); 1014 r = -EFAULT; 1015 goto out; 1016 } 1017#endif 1018 1019 down(&priv->udi_logging_mutex); 1020 if (int_param) { 1021 pcli->event_hook = udi_log_event; 1022 unifi_set_udi_hook(priv->card, logging_handler); 1023 /* Log all signals by default */ 1024 for (i = 0; i < SIG_FILTER_SIZE; i++) { 1025 pcli->signal_filter[i] = 0xFFFF; 1026 } 1027 priv->logging_client = pcli; 1028 1029 } else { 1030 priv->logging_client = NULL; 1031 pcli->event_hook = NULL; 1032 } 1033 up(&priv->udi_logging_mutex); 1034 1035 break; 1036 1037 case UNIFI_SET_MIB: 1038 unifi_trace(priv, UDBG4, "UniFi Set MIB\n"); 1039#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) 1040 /* Read first 2 bytes and check length */ 1041 if (copy_from_user((void*)varbind, (void*)arg, 2)) { 1042 unifi_error(priv, 1043 "UNIFI_SET_MIB: Failed to copy in varbind header\n"); 1044 r = -EFAULT; 1045 goto out; 1046 } 1047 vblen = varbind[1]; 1048 if ((vblen + 2) > MAX_VARBIND_LENGTH) { 1049 unifi_error(priv, 1050 "UNIFI_SET_MIB: Varbind too long (%d, limit %d)\n", 1051 (vblen+2), MAX_VARBIND_LENGTH); 1052 r = -EINVAL; 1053 goto out; 1054 } 1055 /* Read rest of varbind */ 1056 if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) { 1057 unifi_error(priv, "UNIFI_SET_MIB: Failed to copy in varbind\n"); 1058 r = -EFAULT; 1059 goto out; 1060 } 1061 1062 /* send to SME */ 1063 vblen += 2; 1064 r = sme_mgt_mib_set(priv, varbind, vblen); 1065 if (r) { 1066 goto out; 1067 } 1068#else 1069 unifi_notice(priv, "UNIFI_SET_MIB: Unsupported.\n"); 1070#endif /* CSR_SUPPORT_WEXT */ 1071 break; 1072 1073 case UNIFI_GET_MIB: 1074 unifi_trace(priv, UDBG4, "UniFi Get MIB\n"); 1075#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) 1076 /* Read first 2 bytes and check length */ 1077 if (copy_from_user((void*)varbind, (void*)arg, 2)) { 1078 unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind header\n"); 1079 r = -EFAULT; 1080 goto out; 1081 } 1082 vblen = varbind[1]; 1083 if ((vblen+2) > MAX_VARBIND_LENGTH) { 1084 unifi_error(priv, "UNIFI_GET_MIB: Varbind too long (%d, limit %d)\n", 1085 (vblen+2), MAX_VARBIND_LENGTH); 1086 r = -EINVAL; 1087 goto out; 1088 } 1089 /* Read rest of varbind */ 1090 if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) { 1091 unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind\n"); 1092 r = -EFAULT; 1093 goto out; 1094 } 1095 1096 vblen += 2; 1097 r = sme_mgt_mib_get(priv, varbind, &vblen); 1098 if (r) { 1099 goto out; 1100 } 1101 /* copy out varbind */ 1102 if (vblen > MAX_VARBIND_LENGTH) { 1103 unifi_error(priv, 1104 "UNIFI_GET_MIB: Varbind result too long (%d, limit %d)\n", 1105 vblen, MAX_VARBIND_LENGTH); 1106 r = -EINVAL; 1107 goto out; 1108 } 1109 if (copy_to_user((void*)arg, varbind, vblen)) { 1110 r = -EFAULT; 1111 goto out; 1112 } 1113#else 1114 unifi_notice(priv, "UNIFI_GET_MIB: Unsupported.\n"); 1115#endif /* CSR_SUPPORT_WEXT */ 1116 break; 1117 1118 case UNIFI_CFG: 1119#if (defined CSR_SUPPORT_SME) 1120 if (get_user(cfg_cmd, (unifi_cfg_command_t*)arg)) 1121 { 1122 unifi_error(priv, "UNIFI_CFG: Failed to get the command\n"); 1123 r = -EFAULT; 1124 goto out; 1125 } 1126 1127 unifi_trace(priv, UDBG1, "UNIFI_CFG: Command is %d (t=%u) sz=%d\n", 1128 cfg_cmd, jiffies_to_msecs(jiffies), sizeof(unifi_cfg_command_t)); 1129 switch (cfg_cmd) { 1130 case UNIFI_CFG_POWER: 1131 r = unifi_cfg_power(priv, (unsigned char*)arg); 1132 break; 1133 case UNIFI_CFG_POWERSAVE: 1134 r = unifi_cfg_power_save(priv, (unsigned char*)arg); 1135 break; 1136 case UNIFI_CFG_POWERSUPPLY: 1137 r = unifi_cfg_power_supply(priv, (unsigned char*)arg); 1138 break; 1139 case UNIFI_CFG_FILTER: 1140 r = unifi_cfg_packet_filters(priv, (unsigned char*)arg); 1141 break; 1142 case UNIFI_CFG_GET: 1143 r = unifi_cfg_get_info(priv, (unsigned char*)arg); 1144 break; 1145 case UNIFI_CFG_WMM_QOSINFO: 1146 r = unifi_cfg_wmm_qos_info(priv, (unsigned char*)arg); 1147 break; 1148 case UNIFI_CFG_WMM_ADDTS: 1149 r = unifi_cfg_wmm_addts(priv, (unsigned char*)arg); 1150 break; 1151 case UNIFI_CFG_WMM_DELTS: 1152 r = unifi_cfg_wmm_delts(priv, (unsigned char*)arg); 1153 break; 1154 case UNIFI_CFG_STRICT_DRAFT_N: 1155 r = unifi_cfg_strict_draft_n(priv, (unsigned char*)arg); 1156 break; 1157 case UNIFI_CFG_ENABLE_OKC: 1158 r = unifi_cfg_enable_okc(priv, (unsigned char*)arg); 1159 break; 1160#ifdef CSR_SUPPORT_SME 1161 case UNIFI_CFG_CORE_DUMP: 1162 CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,CSR_WIFI_SME_CONTROL_INDICATION_ERROR); 1163 unifi_trace(priv, UDBG2, "UNIFI_CFG_CORE_DUMP: sent wifi off indication\n"); 1164 break; 1165#endif 1166#ifdef CSR_SUPPORT_WEXT_AP 1167 case UNIFI_CFG_SET_AP_CONFIG: 1168 r= unifi_cfg_set_ap_config(priv,(unsigned char*)arg); 1169 break; 1170#endif 1171 default: 1172 unifi_error(priv, "UNIFI_CFG: Unknown Command (%d)\n", cfg_cmd); 1173 r = -EINVAL; 1174 goto out; 1175 } 1176#endif 1177 1178 break; 1179 1180 case UNIFI_PUTEST: 1181 if (get_user(putest_cmd, (unifi_putest_command_t*)arg)) 1182 { 1183 unifi_error(priv, "UNIFI_PUTEST: Failed to get the command\n"); 1184 r = -EFAULT; 1185 goto out; 1186 } 1187 1188 unifi_trace(priv, UDBG1, "UNIFI_PUTEST: Command is %s\n", 1189 trace_putest_cmdid(putest_cmd)); 1190 switch (putest_cmd) { 1191 case UNIFI_PUTEST_START: 1192 r = unifi_putest_start(priv, (unsigned char*)arg); 1193 break; 1194 case UNIFI_PUTEST_STOP: 1195 r = unifi_putest_stop(priv, (unsigned char*)arg); 1196 break; 1197 case UNIFI_PUTEST_SET_SDIO_CLOCK: 1198 r = unifi_putest_set_sdio_clock(priv, (unsigned char*)arg); 1199 break; 1200 case UNIFI_PUTEST_CMD52_READ: 1201 r = unifi_putest_cmd52_read(priv, (unsigned char*)arg); 1202 break; 1203 case UNIFI_PUTEST_CMD52_BLOCK_READ: 1204 r = unifi_putest_cmd52_block_read(priv, (unsigned char*)arg); 1205 break; 1206 case UNIFI_PUTEST_CMD52_WRITE: 1207 r = unifi_putest_cmd52_write(priv, (unsigned char*)arg); 1208 break; 1209 case UNIFI_PUTEST_DL_FW: 1210 r = unifi_putest_dl_fw(priv, (unsigned char*)arg); 1211 break; 1212 case UNIFI_PUTEST_DL_FW_BUFF: 1213 r = unifi_putest_dl_fw_buff(priv, (unsigned char*)arg); 1214 break; 1215 case UNIFI_PUTEST_COREDUMP_PREPARE: 1216 r = unifi_putest_coredump_prepare(priv, (unsigned char*)arg); 1217 break; 1218 case UNIFI_PUTEST_GP_READ16: 1219 r = unifi_putest_gp_read16(priv, (unsigned char*)arg); 1220 break; 1221 case UNIFI_PUTEST_GP_WRITE16: 1222 r = unifi_putest_gp_write16(priv, (unsigned char*)arg); 1223 break; 1224 default: 1225 unifi_error(priv, "UNIFI_PUTEST: Unknown Command (%d)\n", putest_cmd); 1226 r = -EINVAL; 1227 goto out; 1228 } 1229 1230 break; 1231 case UNIFI_BUILD_TYPE: 1232 unifi_trace(priv, UDBG2, "UNIFI_BUILD_TYPE userspace=%s\n", build_type_to_string(*(unsigned char*)arg)); 1233#ifndef CSR_SUPPORT_WEXT_AP 1234 if (UNIFI_BUILD_AP == *(unsigned char*)arg) 1235 { 1236 unifi_error(priv, "Userspace has AP support, which is incompatible\n"); 1237 } 1238#endif 1239 1240#ifndef CSR_SUPPORT_WEXT 1241 if (UNIFI_BUILD_WEXT == *(unsigned char*)arg) 1242 { 1243 unifi_error(priv, "Userspace has WEXT support, which is incompatible\n"); 1244 } 1245#endif 1246 break; 1247 case UNIFI_INIT_HW: 1248 unifi_trace(priv, UDBG2, "UNIFI_INIT_HW.\n"); 1249 priv->init_progress = UNIFI_INIT_NONE; 1250 1251#if defined(CSR_SUPPORT_WEXT) || defined (CSR_NATIVE_LINUX) 1252 /* At this point we are ready to start the SME. */ 1253 r = sme_mgt_wifi_on(priv); 1254 if (r) { 1255 goto out; 1256 } 1257#endif 1258 1259 break; 1260 1261 case UNIFI_INIT_NETDEV: 1262 { 1263 /* get the proper interfaceTagId */ 1264 u16 interfaceTag=0; 1265 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; 1266 1267 dev = priv->netdev[interfaceTag]; 1268 unifi_trace(priv, UDBG2, "UNIFI_INIT_NETDEV.\n"); 1269 1270 if (copy_from_user((void*)dev->dev_addr, (void*)arg, 6)) { 1271 r = -EFAULT; 1272 goto out; 1273 } 1274 1275 /* Attach the network device to the stack */ 1276 if (!interfacePriv->netdev_registered) 1277 { 1278 r = uf_register_netdev(priv,interfaceTag); 1279 if (r) { 1280 unifi_error(priv, "Failed to register the network device.\n"); 1281 goto out; 1282 } 1283 } 1284 1285 /* Apply scheduled interrupt mode, if requested by module param */ 1286 if (run_bh_once != -1) { 1287 unifi_set_interrupt_mode(priv->card, (u32)run_bh_once); 1288 } 1289 1290 priv->init_progress = UNIFI_INIT_COMPLETED; 1291 1292 /* Firmware initialisation is complete, so let the SDIO bus 1293 * clock be raised when convienent to the core. 1294 */ 1295 unifi_request_max_sdio_clock(priv->card); 1296 1297#ifdef CSR_SUPPORT_WEXT 1298 /* Notify the Android wpa_supplicant that we are ready */ 1299 wext_send_started_event(priv); 1300#endif 1301 1302 unifi_info(priv, "UniFi ready\n"); 1303 1304#ifdef ANDROID_BUILD 1305 /* Release the wakelock */ 1306 unifi_trace(priv, UDBG1, "netdev_init: release wake lock\n"); 1307 wake_unlock(&unifi_sdio_wake_lock); 1308#endif 1309#ifdef CSR_NATIVE_SOFTMAC /* For softmac dev, force-enable the network interface rather than wait for a connected-ind */ 1310 { 1311 struct net_device *dev = priv->netdev[interfaceTag]; 1312#ifdef CSR_SUPPORT_WEXT 1313 interfacePriv->wait_netdev_change = TRUE; 1314#endif 1315 netif_carrier_on(dev); 1316 } 1317#endif 1318 } 1319 break; 1320 case UNIFI_GET_INIT_STATUS: 1321 unifi_trace(priv, UDBG2, "UNIFI_GET_INIT_STATUS.\n"); 1322 if (put_user(priv->init_progress, (int*)arg)) 1323 { 1324 printk(KERN_ERR "UNIFI_GET_INIT_STATUS: Failed to copy to user\n"); 1325 r = -EFAULT; 1326 goto out; 1327 } 1328 break; 1329 1330 case UNIFI_KICK: 1331 unifi_trace(priv, UDBG4, "Kick UniFi\n"); 1332 unifi_sdio_interrupt_handler(priv->card); 1333 break; 1334 1335 case UNIFI_SET_DEBUG: 1336 unifi_debug = arg; 1337 unifi_trace(priv, UDBG4, "unifi_debug set to %d\n", unifi_debug); 1338 break; 1339 1340 case UNIFI_SET_TRACE: 1341 /* no longer supported */ 1342 r = -EINVAL; 1343 break; 1344 1345 1346 case UNIFI_SET_UDI_LOG_MASK: 1347 { 1348 unifiio_filter_t udi_filter; 1349 uint16_t *sig_ids_addr; 1350#define UF_MAX_SIG_IDS 128 /* Impose a sensible limit */ 1351 1352 if (copy_from_user((void*)(&udi_filter), (void*)arg, sizeof(udi_filter))) { 1353 r = -EFAULT; 1354 goto out; 1355 } 1356 if ((udi_filter.action < UfSigFil_AllOn) || 1357 (udi_filter.action > UfSigFil_SelectOff)) 1358 { 1359 printk(KERN_WARNING 1360 "UNIFI_SET_UDI_LOG_MASK: Bad action value: %d\n", 1361 udi_filter.action); 1362 r = -EINVAL; 1363 goto out; 1364 } 1365 /* No signal list for "All" actions */ 1366 if ((udi_filter.action == UfSigFil_AllOn) || 1367 (udi_filter.action == UfSigFil_AllOff)) 1368 { 1369 udi_filter.num_sig_ids = 0; 1370 } 1371 1372 if (udi_filter.num_sig_ids > UF_MAX_SIG_IDS) { 1373 printk(KERN_WARNING 1374 "UNIFI_SET_UDI_LOG_MASK: too many signal ids (%d, max %d)\n", 1375 udi_filter.num_sig_ids, UF_MAX_SIG_IDS); 1376 r = -EINVAL; 1377 goto out; 1378 } 1379 1380 /* Copy in signal id list if given */ 1381 if (udi_filter.num_sig_ids > 0) { 1382 /* Preserve userspace address of sig_ids array */ 1383 sig_ids_addr = udi_filter.sig_ids; 1384 /* Allocate kernel memory for sig_ids and copy to it */ 1385 udi_filter.sig_ids = 1386 kmalloc(udi_filter.num_sig_ids * sizeof(uint16_t), GFP_KERNEL); 1387 if (!udi_filter.sig_ids) { 1388 r = -ENOMEM; 1389 goto out; 1390 } 1391 if (copy_from_user((void*)udi_filter.sig_ids, 1392 (void*)sig_ids_addr, 1393 udi_filter.num_sig_ids * sizeof(uint16_t))) 1394 { 1395 kfree(udi_filter.sig_ids); 1396 r = -EFAULT; 1397 goto out; 1398 } 1399 } 1400 1401 udi_set_log_filter(pcli, &udi_filter); 1402 1403 if (udi_filter.num_sig_ids > 0) { 1404 kfree(udi_filter.sig_ids); 1405 } 1406 } 1407 break; 1408 1409 case UNIFI_SET_AMP_ENABLE: 1410 unifi_trace(priv, UDBG4, "UniFi Set AMP Enable\n"); 1411 if (get_user(int_param, (int*)arg)) 1412 { 1413 unifi_error(priv, "UNIFI_SET_AMP_ENABLE: Failed to copy from user\n"); 1414 r = -EFAULT; 1415 goto out; 1416 } 1417 1418 if (int_param) { 1419 priv->amp_client = pcli; 1420 } else { 1421 priv->amp_client = NULL; 1422 } 1423 1424 int_param = 0; 1425 buf = (u8*)&int_param; 1426 buf[0] = UNIFI_SOFT_COMMAND_Q_LENGTH - 1; 1427 buf[1] = UNIFI_SOFT_TRAFFIC_Q_LENGTH - 1; 1428 if (copy_to_user((void*)arg, &int_param, sizeof(int))) { 1429 r = -EFAULT; 1430 goto out; 1431 } 1432 break; 1433 1434 case UNIFI_SET_UDI_SNAP_MASK: 1435 { 1436 unifiio_snap_filter_t snap_filter; 1437 1438 if (copy_from_user((void*)(&snap_filter), (void*)arg, sizeof(snap_filter))) { 1439 r = -EFAULT; 1440 goto out; 1441 } 1442 1443 if (pcli->snap_filter.count) { 1444 pcli->snap_filter.count = 0; 1445 kfree(pcli->snap_filter.protocols); 1446 } 1447 1448 if (snap_filter.count == 0) { 1449 break; 1450 } 1451 1452 pcli->snap_filter.protocols = kmalloc(snap_filter.count * sizeof(u16), GFP_KERNEL); 1453 if (!pcli->snap_filter.protocols) { 1454 r = -ENOMEM; 1455 goto out; 1456 } 1457 if (copy_from_user((void*)pcli->snap_filter.protocols, 1458 (void*)snap_filter.protocols, 1459 snap_filter.count * sizeof(u16))) 1460 { 1461 kfree(pcli->snap_filter.protocols); 1462 r = -EFAULT; 1463 goto out; 1464 } 1465 1466 pcli->snap_filter.count = snap_filter.count; 1467 1468 } 1469 break; 1470 1471 case UNIFI_SME_PRESENT: 1472 { 1473 u8 ind; 1474 unifi_trace(priv, UDBG4, "UniFi SME Present IOCTL.\n"); 1475 if (copy_from_user((void*)(&int_param), (void*)arg, sizeof(int))) 1476 { 1477 printk(KERN_ERR "UNIFI_SME_PRESENT: Failed to copy from user\n"); 1478 r = -EFAULT; 1479 goto out; 1480 } 1481 1482 priv->sme_is_present = int_param; 1483 if (priv->sme_is_present == 1) { 1484 ind = CONFIG_SME_PRESENT; 1485 } else { 1486 ind = CONFIG_SME_NOT_PRESENT; 1487 } 1488 /* Send an indication to the helper app. */ 1489 ul_log_config_ind(priv, &ind, sizeof(u8)); 1490 } 1491 break; 1492 1493 case UNIFI_CFG_PERIOD_TRAFFIC: 1494 { 1495#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) 1496 CsrWifiSmeCoexConfig coexConfig; 1497#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ 1498 unifi_trace(priv, UDBG4, "UniFi Configure Periodic Traffic.\n"); 1499#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) 1500 if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) { 1501 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n"); 1502 r = -EFAULT; 1503 goto out; 1504 } 1505 1506 if (uchar_param == 0) { 1507 r = sme_mgt_coex_config_get(priv, &coexConfig); 1508 if (r) { 1509 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Get unifi_CoexInfoValue failed.\n"); 1510 goto out; 1511 } 1512 if (copy_to_user((void*)(arg + 1), 1513 (void*)&coexConfig, 1514 sizeof(CsrWifiSmeCoexConfig))) { 1515 r = -EFAULT; 1516 goto out; 1517 } 1518 goto out; 1519 } 1520 1521 if (copy_from_user((void*)(&coex_config), (void*)(arg + 1), sizeof(CsrWifiSmeCoexConfig))) 1522 { 1523 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n"); 1524 r = -EFAULT; 1525 goto out; 1526 } 1527 1528 coexConfig = coex_config; 1529 r = sme_mgt_coex_config_set(priv, &coexConfig); 1530 if (r) { 1531 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Set unifi_CoexInfoValue failed.\n"); 1532 goto out; 1533 } 1534 1535#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ 1536 break; 1537 } 1538 case UNIFI_CFG_UAPSD_TRAFFIC: 1539 unifi_trace(priv, UDBG4, "UniFi Configure U-APSD Mask.\n"); 1540#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) 1541 if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) { 1542 unifi_error(priv, "UNIFI_CFG_UAPSD_TRAFFIC: Failed to copy from user\n"); 1543 r = -EFAULT; 1544 goto out; 1545 } 1546 unifi_trace(priv, UDBG4, "New U-APSD Mask: 0x%x\n", uchar_param); 1547#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ 1548 break; 1549 1550#ifndef UNIFI_DISABLE_COREDUMP 1551 case UNIFI_COREDUMP_GET_REG: 1552 unifi_trace(priv, UDBG4, "Mini-coredump data request\n"); 1553 { 1554 unifiio_coredump_req_t dump_req; /* Public OS layer structure */ 1555 unifi_coredump_req_t priv_req; /* Private HIP structure */ 1556 1557 if (copy_from_user((void*)(&dump_req), (void*)arg, sizeof(dump_req))) { 1558 r = -EFAULT; 1559 goto out; 1560 } 1561 memset(&priv_req, 0, sizeof(priv_req)); 1562 priv_req.index = dump_req.index; 1563 priv_req.offset = dump_req.offset; 1564 1565 /* Convert OS-layer's XAP memory space ID to HIP's ID in case they differ */ 1566 switch (dump_req.space) { 1567 case UNIFIIO_COREDUMP_MAC_REG: priv_req.space = UNIFI_COREDUMP_MAC_REG; break; 1568 case UNIFIIO_COREDUMP_PHY_REG: priv_req.space = UNIFI_COREDUMP_PHY_REG; break; 1569 case UNIFIIO_COREDUMP_SH_DMEM: priv_req.space = UNIFI_COREDUMP_SH_DMEM; break; 1570 case UNIFIIO_COREDUMP_MAC_DMEM: priv_req.space = UNIFI_COREDUMP_MAC_DMEM; break; 1571 case UNIFIIO_COREDUMP_PHY_DMEM: priv_req.space = UNIFI_COREDUMP_PHY_DMEM; break; 1572 case UNIFIIO_COREDUMP_TRIGGER_MAGIC: priv_req.space = UNIFI_COREDUMP_TRIGGER_MAGIC; break; 1573 default: 1574 r = -EINVAL; 1575 goto out; 1576 } 1577 1578 if (priv_req.space == UNIFI_COREDUMP_TRIGGER_MAGIC) { 1579 /* Force a coredump grab now */ 1580 unifi_trace(priv, UDBG2, "UNIFI_COREDUMP_GET_REG: Force capture\n"); 1581 csrResult = unifi_coredump_capture(priv->card, &priv_req); 1582 r = CsrHipResultToStatus(csrResult); 1583 unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: status %d\n", r); 1584 } else { 1585 /* Retrieve the appropriate register entry */ 1586 csrResult = unifi_coredump_get_value(priv->card, &priv_req); 1587 r = CsrHipResultToStatus(csrResult); 1588 if (r) { 1589 unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: Status %d\n", r); 1590 goto out; 1591 } 1592 /* Update the OS-layer structure with values returned in the private */ 1593 dump_req.value = priv_req.value; 1594 dump_req.timestamp = priv_req.timestamp; 1595 dump_req.requestor = priv_req.requestor; 1596 dump_req.serial = priv_req.serial; 1597 dump_req.chip_ver = priv_req.chip_ver; 1598 dump_req.fw_ver = priv_req.fw_ver; 1599 dump_req.drv_build = 0; 1600 1601 unifi_trace(priv, UDBG6, 1602 "Dump: %d (seq %d): V:0x%04x (%d) @0x%02x:%04x = 0x%04x\n", 1603 dump_req.index, dump_req.serial, 1604 dump_req.chip_ver, dump_req.drv_build, 1605 dump_req.space, dump_req.offset, dump_req.value); 1606 } 1607 if (copy_to_user((void*)arg, (void*)&dump_req, sizeof(dump_req))) { 1608 r = -EFAULT; 1609 goto out; 1610 } 1611 } 1612 break; 1613#endif 1614 default: 1615 r = -EINVAL; 1616 } 1617 1618out: 1619 return (long)r; 1620} /* unifi_ioctl() */ 1621 1622 1623 1624static unsigned int 1625unifi_poll(struct file *filp, poll_table *wait) 1626{ 1627 ul_client_t *pcli = (ul_client_t*)filp->private_data; 1628 unsigned int mask = 0; 1629 int ready; 1630 1631 ready = !list_empty(&pcli->udi_log); 1632 1633 poll_wait(filp, &pcli->udi_wq, wait); 1634 1635 if (ready) { 1636 mask |= POLLIN | POLLRDNORM; /* readable */ 1637 } 1638 1639 return mask; 1640} /* unifi_poll() */ 1641 1642 1643 1644/* 1645 * --------------------------------------------------------------------------- 1646 * udi_set_log_filter 1647 * 1648 * Configure the bit mask that determines which signal primitives are 1649 * passed to the logging process. 1650 * 1651 * Arguments: 1652 * pcli Pointer to the client to configure. 1653 * udi_filter Pointer to a unifiio_filter_t containing instructions. 1654 * 1655 * Returns: 1656 * None. 1657 * 1658 * Notes: 1659 * SigGetFilterPos() returns a 32-bit value that contains an index and a 1660 * mask for accessing a signal_filter array. The top 16 bits specify an 1661 * index into a signal_filter, the bottom 16 bits specify a mask to 1662 * apply. 1663 * --------------------------------------------------------------------------- 1664 */ 1665static void 1666udi_set_log_filter(ul_client_t *pcli, unifiio_filter_t *udi_filter) 1667{ 1668 u32 filter_pos; 1669 int i; 1670 1671 if (udi_filter->action == UfSigFil_AllOn) 1672 { 1673 for (i = 0; i < SIG_FILTER_SIZE; i++) { 1674 pcli->signal_filter[i] = 0xFFFF; 1675 } 1676 } 1677 else if (udi_filter->action == UfSigFil_AllOff) 1678 { 1679 for (i = 0; i < SIG_FILTER_SIZE; i++) { 1680 pcli->signal_filter[i] = 0; 1681 } 1682 } 1683 else if (udi_filter->action == UfSigFil_SelectOn) 1684 { 1685 for (i = 0; i < udi_filter->num_sig_ids; i++) { 1686 filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]); 1687 if (filter_pos == 0xFFFFFFFF) 1688 { 1689 printk(KERN_WARNING 1690 "Unrecognised signal id (0x%X) specifed in logging filter\n", 1691 udi_filter->sig_ids[i]); 1692 } else { 1693 pcli->signal_filter[filter_pos >> 16] |= (filter_pos & 0xFFFF); 1694 } 1695 } 1696 } 1697 else if (udi_filter->action == UfSigFil_SelectOff) 1698 { 1699 for (i = 0; i < udi_filter->num_sig_ids; i++) { 1700 filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]); 1701 if (filter_pos == 0xFFFFFFFF) 1702 { 1703 printk(KERN_WARNING 1704 "Unrecognised signal id (0x%X) specifed in logging filter\n", 1705 udi_filter->sig_ids[i]); 1706 } else { 1707 pcli->signal_filter[filter_pos >> 16] &= ~(filter_pos & 0xFFFF); 1708 } 1709 } 1710 } 1711 1712} /* udi_set_log_filter() */ 1713 1714 1715/* 1716 * --------------------------------------------------------------------------- 1717 * udi_log_event 1718 * 1719 * Callback function to be registered as the UDI hook callback. 1720 * Copies the signal content into a new udi_log_t struct and adds 1721 * it to the read queue for this UDI client. 1722 * 1723 * Arguments: 1724 * pcli A pointer to the client instance. 1725 * signal Pointer to the received signal. 1726 * signal_len Size of the signal structure in bytes. 1727 * bulkdata Pointers to any associated bulk data. 1728 * dir Direction of the signal. Zero means from host, 1729 * non-zero means to host. 1730 * 1731 * Returns: 1732 * None. 1733 * --------------------------------------------------------------------------- 1734 */ 1735void 1736udi_log_event(ul_client_t *pcli, 1737 const u8 *signal, int signal_len, 1738 const bulk_data_param_t *bulkdata, 1739 int dir) 1740{ 1741 udi_log_t *logptr; 1742 u8 *p; 1743 int i; 1744 int total_len; 1745 udi_msg_t *msgptr; 1746 u32 filter_pos; 1747#ifdef OMNICLI_LINUX_EXTRA_LOG 1748 static volatile unsigned int printk_cpu = UINT_MAX; 1749 unsigned long long t; 1750 unsigned long nanosec_rem; 1751 unsigned long n_1000; 1752#endif 1753 1754 /* Just a sanity check */ 1755 if ((signal == NULL) || (signal_len <= 0)) { 1756 return; 1757 } 1758 1759#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 1760 /* When HIP offline signal logging is enabled, omnicli cannot run */ 1761 if (log_hip_signals) 1762 { 1763 /* Add timestamp */ 1764 if (log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP) 1765 { 1766 int timestamp = jiffies_to_msecs(jiffies); 1767 unifi_debug_log_to_buf("T:"); 1768 unifi_debug_log_to_buf("%04X%04X ", *(((u16*)&timestamp) + 1), 1769 *(u16*)&timestamp); 1770 } 1771 1772 /* Add signal */ 1773 unifi_debug_log_to_buf("S%s:%04X R:%04X D:%04X ", 1774 dir ? "T" : "F", 1775 *(u16*)signal, 1776 *(u16*)(signal + 2), 1777 *(u16*)(signal + 4)); 1778 unifi_debug_hex_to_buf(signal + 6, signal_len - 6); 1779 1780 /* Add bulk data (assume 1 bulk data per signal) */ 1781 if ((log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA) && 1782 (bulkdata->d[0].data_length > 0)) 1783 { 1784 unifi_debug_log_to_buf("\nD:"); 1785 unifi_debug_hex_to_buf(bulkdata->d[0].os_data_ptr, bulkdata->d[0].data_length); 1786 } 1787 unifi_debug_log_to_buf("\n"); 1788 1789 return; 1790 } 1791#endif 1792 1793#ifdef CSR_NATIVE_LINUX 1794 uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir); 1795#endif 1796 1797 /* 1798 * Apply the logging filter - only report signals that have their 1799 * bit set in the filter mask. 1800 */ 1801 filter_pos = SigGetFilterPos(GET_SIGNAL_ID(signal)); 1802 1803 if ((filter_pos != 0xFFFFFFFF) && 1804 ((pcli->signal_filter[filter_pos >> 16] & (filter_pos & 0xFFFF)) == 0)) 1805 { 1806 /* Signal is not wanted by client */ 1807 return; 1808 } 1809 1810 1811 /* Calculate the buffer we need to store signal plus bulk data */ 1812 total_len = signal_len; 1813 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { 1814 total_len += bulkdata->d[i].data_length; 1815 } 1816 1817 /* Allocate log structure plus actual signal. */ 1818 logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL); 1819 1820 if (logptr == NULL) { 1821 printk(KERN_ERR 1822 "Failed to allocate %lu bytes for a UDI log record\n", 1823 (long unsigned int)(sizeof(udi_log_t) + total_len)); 1824 return; 1825 } 1826 1827 /* Fill in udi_log struct */ 1828 INIT_LIST_HEAD(&logptr->q); 1829 msgptr = &logptr->msg; 1830 msgptr->length = sizeof(udi_msg_t) + total_len; 1831#ifdef OMNICLI_LINUX_EXTRA_LOG 1832 t = cpu_clock(printk_cpu); 1833 nanosec_rem = do_div(t, 1000000000); 1834 n_1000 = nanosec_rem/1000; 1835 msgptr->timestamp = (t <<10 ) | ((unsigned long)(n_1000 >> 10) & 0x3ff); 1836#else 1837 msgptr->timestamp = jiffies_to_msecs(jiffies); 1838#endif 1839 msgptr->direction = dir; 1840 msgptr->signal_length = signal_len; 1841 1842 /* Copy signal and bulk data to the log */ 1843 p = (u8 *)(msgptr + 1); 1844 memcpy(p, signal, signal_len); 1845 p += signal_len; 1846 1847 /* Append any bulk data */ 1848 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { 1849 int len = bulkdata->d[i].data_length; 1850 1851 /* 1852 * Len here might not be the same as the length in the bulk data slot. 1853 * The slot length will always be even, but len could be odd. 1854 */ 1855 if (len > 0) { 1856 if (bulkdata->d[i].os_data_ptr) { 1857 memcpy(p, bulkdata->d[i].os_data_ptr, len); 1858 } else { 1859 memset(p, 0, len); 1860 } 1861 p += len; 1862 } 1863 } 1864 1865 /* Add to tail of log queue */ 1866 if (down_interruptible(&pcli->udi_sem)) { 1867 printk(KERN_WARNING "udi_log_event_q: Failed to get udi sem\n"); 1868 kfree(logptr); 1869 return; 1870 } 1871 list_add_tail(&logptr->q, &pcli->udi_log); 1872 up(&pcli->udi_sem); 1873 1874 /* Wake any waiting user process */ 1875 wake_up_interruptible(&pcli->udi_wq); 1876 1877} /* udi_log_event() */ 1878 1879#ifdef CSR_SME_USERSPACE 1880int 1881uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length) 1882{ 1883 udi_log_t *logptr; 1884 udi_msg_t *msgptr; 1885 u8 *p; 1886 1887 /* Just a sanity check */ 1888 if ((buffer == NULL) || (length <= 0)) { 1889 return -EINVAL; 1890 } 1891 1892 /* Allocate log structure plus actual signal. */ 1893 logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC); 1894 if (logptr == NULL) { 1895 unifi_error(priv, "Failed to allocate %d bytes for an SME message\n", 1896 sizeof(udi_log_t) + length); 1897 kfree(buffer); 1898 return -ENOMEM; 1899 } 1900 1901 /* Fill in udi_log struct */ 1902 INIT_LIST_HEAD(&logptr->q); 1903 msgptr = &logptr->msg; 1904 msgptr->length = sizeof(udi_msg_t) + length; 1905 msgptr->signal_length = length; 1906 1907 /* Copy signal and bulk data to the log */ 1908 p = (u8 *)(msgptr + 1); 1909 memcpy(p, buffer, length); 1910 1911 /* Add to tail of log queue */ 1912 down(&udi_mutex); 1913 if (priv->sme_cli == NULL) { 1914 kfree(logptr); 1915 kfree(buffer); 1916 up(&udi_mutex); 1917 unifi_info(priv, "Message for the SME dropped, SME has gone away\n"); 1918 return 0; 1919 } 1920 1921 down(&priv->sme_cli->udi_sem); 1922 list_add_tail(&logptr->q, &priv->sme_cli->udi_log); 1923 up(&priv->sme_cli->udi_sem); 1924 1925 /* Wake any waiting user process */ 1926 wake_up_interruptible(&priv->sme_cli->udi_wq); 1927 up(&udi_mutex); 1928 1929 /* It is our responsibility to free the buffer allocated in build_packed_*() */ 1930 kfree(buffer); 1931 1932 return 0; 1933 1934} /* uf_sme_queue_message() */ 1935#endif 1936 1937/* 1938 **************************************************************************** 1939 * 1940 * Driver instantiation 1941 * 1942 **************************************************************************** 1943 */ 1944static struct file_operations unifi_fops = { 1945 .owner = THIS_MODULE, 1946 .open = unifi_open, 1947 .release = unifi_release, 1948 .read = unifi_read, 1949 .write = unifi_write, 1950 .unlocked_ioctl = unifi_ioctl, 1951 .poll = unifi_poll, 1952}; 1953 1954static dev_t unifi_first_devno; 1955static struct class *unifi_class; 1956 1957 1958int uf_create_device_nodes(unifi_priv_t *priv, int bus_id) 1959{ 1960 dev_t devno; 1961 int r; 1962 1963 cdev_init(&priv->unifi_cdev, &unifi_fops); 1964 1965 /* cdev_init() should set the cdev owner, but it does not */ 1966 priv->unifi_cdev.owner = THIS_MODULE; 1967 1968 devno = MKDEV(MAJOR(unifi_first_devno), 1969 MINOR(unifi_first_devno) + (bus_id * 2)); 1970 r = cdev_add(&priv->unifi_cdev, devno, 1); 1971 if (r) { 1972 return r; 1973 } 1974 1975#ifdef SDIO_EXPORTS_STRUCT_DEVICE 1976 if (!device_create(unifi_class, priv->unifi_device, 1977 devno, priv, "unifi%d", bus_id)) { 1978#else 1979 priv->unifi_device = device_create(unifi_class, NULL, 1980 devno, priv, "unifi%d", bus_id); 1981 if (priv->unifi_device == NULL) { 1982#endif /* SDIO_EXPORTS_STRUCT_DEVICE */ 1983 1984 cdev_del(&priv->unifi_cdev); 1985 return -EINVAL; 1986 } 1987 1988 cdev_init(&priv->unifiudi_cdev, &unifi_fops); 1989 1990 /* cdev_init() should set the cdev owner, but it does not */ 1991 priv->unifiudi_cdev.owner = THIS_MODULE; 1992 1993 devno = MKDEV(MAJOR(unifi_first_devno), 1994 MINOR(unifi_first_devno) + (bus_id * 2) + 1); 1995 r = cdev_add(&priv->unifiudi_cdev, devno, 1); 1996 if (r) { 1997 device_destroy(unifi_class, priv->unifi_cdev.dev); 1998 cdev_del(&priv->unifi_cdev); 1999 return r; 2000 } 2001 2002 if (!device_create(unifi_class, 2003#ifdef SDIO_EXPORTS_STRUCT_DEVICE 2004 priv->unifi_device, 2005#else 2006 NULL, 2007#endif /* SDIO_EXPORTS_STRUCT_DEVICE */ 2008 devno, priv, "unifiudi%d", bus_id)) { 2009 device_destroy(unifi_class, priv->unifi_cdev.dev); 2010 cdev_del(&priv->unifiudi_cdev); 2011 cdev_del(&priv->unifi_cdev); 2012 return -EINVAL; 2013 } 2014 2015 return 0; 2016} 2017 2018 2019void uf_destroy_device_nodes(unifi_priv_t *priv) 2020{ 2021 device_destroy(unifi_class, priv->unifiudi_cdev.dev); 2022 device_destroy(unifi_class, priv->unifi_cdev.dev); 2023 cdev_del(&priv->unifiudi_cdev); 2024 cdev_del(&priv->unifi_cdev); 2025} 2026 2027 2028 2029/* 2030 * ---------------------------------------------------------------- 2031 * uf_create_debug_device 2032 * 2033 * Allocates device numbers for unifi character device nodes 2034 * and creates a unifi class in sysfs 2035 * 2036 * Arguments: 2037 * fops Pointer to the char device operations structure. 2038 * 2039 * Returns: 2040 * 0 on success, -ve error code on error. 2041 * ---------------------------------------------------------------- 2042 */ 2043static int 2044uf_create_debug_device(struct file_operations *fops) 2045{ 2046 int ret; 2047 2048 /* Allocate two device numbers for each device. */ 2049 ret = alloc_chrdev_region(&unifi_first_devno, 0, MAX_UNIFI_DEVS*2, UNIFI_NAME); 2050 if (ret) { 2051 unifi_error(NULL, "Failed to add alloc dev numbers: %d\n", ret); 2052 return ret; 2053 } 2054 2055 /* Create a UniFi class */ 2056 unifi_class = class_create(THIS_MODULE, UNIFI_NAME); 2057 if (IS_ERR(unifi_class)) { 2058 unifi_error(NULL, "Failed to create UniFi class\n"); 2059 2060 /* Release device numbers */ 2061 unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2); 2062 unifi_first_devno = 0; 2063 return -EINVAL; 2064 } 2065 2066 return 0; 2067} /* uf_create_debug_device() */ 2068 2069 2070/* 2071 * ---------------------------------------------------------------- 2072 * uf_remove_debug_device 2073 * 2074 * Destroys the unifi class and releases the allocated 2075 * device numbers for unifi character device nodes. 2076 * 2077 * Arguments: 2078 * 2079 * Returns: 2080 * ---------------------------------------------------------------- 2081 */ 2082static void 2083uf_remove_debug_device(void) 2084{ 2085 /* Destroy the UniFi class */ 2086 class_destroy(unifi_class); 2087 2088 /* Release device numbers */ 2089 unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2); 2090 unifi_first_devno = 0; 2091 2092} /* uf_remove_debug_device() */ 2093 2094 2095/* 2096 * --------------------------------------------------------------------------- 2097 * 2098 * Module loading. 2099 * 2100 * --------------------------------------------------------------------------- 2101 */ 2102int __init 2103unifi_load(void) 2104{ 2105 int r; 2106 2107 printk("UniFi SDIO Driver: %s %s %s\n", 2108 CSR_WIFI_VERSION, 2109 __DATE__, __TIME__); 2110 2111#ifdef CSR_SME_USERSPACE 2112#ifdef CSR_SUPPORT_WEXT 2113 printk("CSR SME with WEXT support\n"); 2114#else 2115 printk("CSR SME no WEXT support\n"); 2116#endif /* CSR_SUPPORT_WEXT */ 2117#endif /* CSR_SME_USERSPACE */ 2118 2119#ifdef CSR_NATIVE_LINUX 2120#ifdef CSR_SUPPORT_WEXT 2121#error WEXT unsupported in the native driver 2122#endif 2123 printk("CSR native no WEXT support\n"); 2124#endif 2125#ifdef CSR_WIFI_SPLIT_PATCH 2126 printk("Split patch support\n"); 2127#endif 2128 printk("Kernel %d.%d.%d\n", 2129 ((LINUX_VERSION_CODE) >> 16) & 0xff, 2130 ((LINUX_VERSION_CODE) >> 8) & 0xff, 2131 (LINUX_VERSION_CODE) & 0xff); 2132 /* 2133 * Instantiate the /dev/unifi* device nodes. 2134 * We must do this before registering with the SDIO driver because it 2135 * will immediately call the "insert" callback if the card is 2136 * already present. 2137 */ 2138 r = uf_create_debug_device(&unifi_fops); 2139 if (r) { 2140 return r; 2141 } 2142 2143 /* Now register with the SDIO driver */ 2144 r = uf_sdio_load(); 2145 if (r) { 2146 uf_remove_debug_device(); 2147 return r; 2148 } 2149 2150 if (sdio_block_size > -1) { 2151 unifi_info(NULL, "sdio_block_size %d\n", sdio_block_size); 2152 } 2153 2154 if (sdio_byte_mode) { 2155 unifi_info(NULL, "sdio_byte_mode\n"); 2156 } 2157 2158 if (disable_power_control) { 2159 unifi_info(NULL, "disable_power_control\n"); 2160 } 2161 2162 if (disable_hw_reset) { 2163 unifi_info(NULL, "disable_hw_reset\n"); 2164 } 2165 2166 if (enable_wol) { 2167 unifi_info(NULL, "enable_wol %d\n", enable_wol); 2168 } 2169 2170 if (run_bh_once != -1) { 2171 unifi_info(NULL, "run_bh_once %d\n", run_bh_once); 2172 } 2173 2174 return 0; 2175} /* unifi_load() */ 2176 2177 2178void __exit 2179unifi_unload(void) 2180{ 2181 /* The SDIO remove hook will call unifi_disconnect(). */ 2182 uf_sdio_unload(); 2183 2184 uf_remove_debug_device(); 2185 2186} /* unifi_unload() */ 2187 2188module_init(unifi_load); 2189module_exit(unifi_unload); 2190 2191MODULE_DESCRIPTION("UniFi Device driver"); 2192MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); 2193MODULE_LICENSE("GPL and additional rights");