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.8 1131 lines 32 kB view raw
1/* 2 * --------------------------------------------------------------------------- 3 * FILE: io.c 4 * 5 * PURPOSE: 6 * This file contains routines that the SDIO driver can call when a 7 * UniFi card is first inserted (or detected) and removed. 8 * 9 * When used with sdioemb, the udev scripts (at least on Ubuntu) don't 10 * recognise a UniFi being added to the system. This is because sdioemb 11 * does not register itself as a device_driver, it uses it's own code 12 * to handle insert and remove. 13 * To have Ubuntu recognise UniFi, edit /etc/udev/rules.d/85-ifupdown.rules 14 * to change this line: 15 * SUBSYSTEM=="net", DRIVERS=="?*", GOTO="net_start" 16 * to these: 17 * #SUBSYSTEM=="net", DRIVERS=="?*", GOTO="net_start" 18 * SUBSYSTEM=="net", GOTO="net_start" 19 * 20 * Then you can add a stanza to /etc/network/interfaces like this: 21 * auto eth1 22 * iface eth1 inet dhcp 23 * wpa-conf /etc/wpa_supplicant.conf 24 * This will then automatically associate when a car dis inserted. 25 * 26 * Copyright (C) 2006-2009 by Cambridge Silicon Radio Ltd. 27 * 28 * Refer to LICENSE.txt included with this source code for details on 29 * the license terms. 30 * 31 * --------------------------------------------------------------------------- 32 */ 33#include <linux/proc_fs.h> 34 35#include "csr_wifi_hip_unifi.h" 36#include "csr_wifi_hip_unifiversion.h" 37#include "csr_wifi_hip_unifi_udi.h" /* for unifi_print_status() */ 38#include "unifiio.h" 39#include "unifi_priv.h" 40 41/* 42 * Array of pointers to context structs for unifi devices that are present. 43 * The index in the array corresponds to the wlan interface number 44 * (if "wlan*" is used). If "eth*" is used, the eth* numbers are allocated 45 * after any Ethernet cards. 46 * 47 * The Arasan PCI-SDIO controller card supported by this driver has 2 slots, 48 * hence a max of 2 devices. 49 */ 50static unifi_priv_t *Unifi_instances[MAX_UNIFI_DEVS]; 51 52/* Array of pointers to netdev objects used by the UniFi driver, as there 53 * are now many per instance. This is used to determine which netdev events 54 * are for UniFi as opposed to other net interfaces. 55 */ 56static netInterface_priv_t *Unifi_netdev_instances[MAX_UNIFI_DEVS * CSR_WIFI_NUM_INTERFACES]; 57 58/* 59 * Array to hold the status of each unifi device in each slot. 60 * We only process an insert event when In_use[] for the slot is 61 * UNIFI_DEV_NOT_IN_USE. Otherwise, it means that the slot is in use or 62 * we are in the middle of a cleanup (the action on unplug). 63 */ 64#define UNIFI_DEV_NOT_IN_USE 0 65#define UNIFI_DEV_IN_USE 1 66#define UNIFI_DEV_CLEANUP 2 67static int In_use[MAX_UNIFI_DEVS]; 68/* 69 * Mutex to prevent UDI clients to open the character device before the priv 70 * is created and initialised. 71 */ 72DEFINE_SEMAPHORE(Unifi_instance_mutex); 73/* 74 * When the device is removed, unregister waits on Unifi_cleanup_wq 75 * until all the UDI clients release the character device. 76 */ 77DECLARE_WAIT_QUEUE_HEAD(Unifi_cleanup_wq); 78 79 80static int uf_read_proc(char *page, char **start, off_t offset, int count, 81 int *eof, void *data); 82 83#ifdef CSR_WIFI_RX_PATH_SPLIT 84 85static CsrResult signal_buffer_init(unifi_priv_t * priv, int size) 86{ 87 int i; 88 89 priv->rxSignalBuffer.writePointer = 90 priv->rxSignalBuffer.readPointer = 0; 91 priv->rxSignalBuffer.size = size; 92 /* Allocating Memory for Signal primitive pointer */ 93 for(i=0; i<size; i++) 94 { 95 priv->rxSignalBuffer.rx_buff[i].sig_len=0; 96 priv->rxSignalBuffer.rx_buff[i].bufptr = kmalloc(UNIFI_PACKED_SIGBUF_SIZE, GFP_KERNEL); 97 if (priv->rxSignalBuffer.rx_buff[i].bufptr == NULL) 98 { 99 int j; 100 unifi_error(priv,"signal_buffer_init:Failed to Allocate shared memory for T-H signals \n"); 101 for(j=0;j<i;j++) 102 { 103 priv->rxSignalBuffer.rx_buff[j].sig_len=0; 104 kfree(priv->rxSignalBuffer.rx_buff[j].bufptr); 105 priv->rxSignalBuffer.rx_buff[j].bufptr = NULL; 106 } 107 return -1; 108 } 109 } 110 return 0; 111} 112 113 114static void signal_buffer_free(unifi_priv_t * priv, int size) 115{ 116 int i; 117 118 for(i=0; i<size; i++) 119 { 120 priv->rxSignalBuffer.rx_buff[i].sig_len=0; 121 kfree(priv->rxSignalBuffer.rx_buff[i].bufptr); 122 priv->rxSignalBuffer.rx_buff[i].bufptr = NULL; 123 } 124} 125#endif 126/* 127 * --------------------------------------------------------------------------- 128 * uf_register_netdev 129 * 130 * Registers the network interface, installes the qdisc, 131 * and registers the inet handler. 132 * In the porting exercise, register the driver to the network 133 * stack if necessary. 134 * 135 * Arguments: 136 * priv Pointer to driver context. 137 * 138 * Returns: 139 * O on success, non-zero otherwise. 140 * 141 * Notes: 142 * We will only unregister when the card is ejected, so we must 143 * only do it once. 144 * --------------------------------------------------------------------------- 145 */ 146int 147uf_register_netdev(unifi_priv_t *priv, int interfaceTag) 148{ 149 int r; 150 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; 151 152 if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { 153 unifi_error(priv, "uf_register_netdev bad interfaceTag\n"); 154 return -EINVAL; 155 } 156 157 /* 158 * Allocates a device number and registers device with the network 159 * stack. 160 */ 161 unifi_trace(priv, UDBG5, "uf_register_netdev: netdev %d - 0x%p\n", 162 interfaceTag, priv->netdev[interfaceTag]); 163 r = register_netdev(priv->netdev[interfaceTag]); 164 if (r) { 165 unifi_error(priv, "Failed to register net device\n"); 166 return -EINVAL; 167 } 168 169 /* The device is registed */ 170 interfacePriv->netdev_registered = 1; 171 172#ifdef CSR_SUPPORT_SME 173 /* 174 * Register the inet handler; it notifies us for changes in the IP address. 175 */ 176 uf_register_inet_notifier(); 177#endif /* CSR_SUPPORT_SME */ 178 179 unifi_notice(priv, "unifi%d is %s\n", 180 priv->instance, priv->netdev[interfaceTag]->name); 181 182 return 0; 183} /* uf_register_netdev */ 184 185 186/* 187 * --------------------------------------------------------------------------- 188 * uf_unregister_netdev 189 * 190 * Unregisters the network interface and the inet handler. 191 * 192 * Arguments: 193 * priv Pointer to driver context. 194 * 195 * Returns: 196 * None. 197 * 198 * --------------------------------------------------------------------------- 199 */ 200void 201uf_unregister_netdev(unifi_priv_t *priv) 202{ 203 int i=0; 204 205#ifdef CSR_SUPPORT_SME 206 /* Unregister the inet handler... */ 207 uf_unregister_inet_notifier(); 208#endif /* CSR_SUPPORT_SME */ 209 210 for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) { 211 netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; 212 if (interfacePriv->netdev_registered) { 213 unifi_trace(priv, UDBG5, 214 "uf_unregister_netdev: netdev %d - 0x%p\n", 215 i, priv->netdev[i]); 216 217 /* ... and the netdev */ 218 unregister_netdev(priv->netdev[i]); 219 interfacePriv->netdev_registered = 0; 220 } 221 222 interfacePriv->interfaceMode = 0; 223 224 /* Enable all queues by default */ 225 interfacePriv->queueEnabled[0] = 1; 226 interfacePriv->queueEnabled[1] = 1; 227 interfacePriv->queueEnabled[2] = 1; 228 interfacePriv->queueEnabled[3] = 1; 229 } 230 231 priv->totalInterfaceCount = 0; 232} /* uf_unregister_netdev() */ 233 234 235/* 236 * --------------------------------------------------------------------------- 237 * register_unifi_sdio 238 * 239 * This function is called from the Probe (or equivalent) method of 240 * the SDIO driver when a UniFi card is detected. 241 * We allocate the Linux net_device struct, initialise the HIP core 242 * lib, create the char device nodes and start the userspace helper 243 * to initialise the device. 244 * 245 * Arguments: 246 * sdio_dev Pointer to SDIO context handle to use for all 247 * SDIO ops. 248 * bus_id A small number indicating the SDIO card position on the 249 * bus. Typically this is the slot number, e.g. 0, 1 etc. 250 * Valid values are 0 to MAX_UNIFI_DEVS-1. 251 * dev Pointer to kernel device manager struct. 252 * 253 * Returns: 254 * Pointer to the unifi instance, or NULL on error. 255 * --------------------------------------------------------------------------- 256 */ 257static unifi_priv_t * 258register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev) 259{ 260 unifi_priv_t *priv = NULL; 261 int r = -1; 262 CsrResult csrResult; 263 264 if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { 265 unifi_error(priv, "register_unifi_sdio: invalid device %d\n", 266 bus_id); 267 return NULL; 268 } 269 270 down(&Unifi_instance_mutex); 271 272 if (In_use[bus_id] != UNIFI_DEV_NOT_IN_USE) { 273 unifi_error(priv, "register_unifi_sdio: device %d is already in use\n", 274 bus_id); 275 goto failed0; 276 } 277 278 279 /* Allocate device private and net_device structs */ 280 priv = uf_alloc_netdevice(sdio_dev, bus_id); 281 if (priv == NULL) { 282 unifi_error(priv, "Failed to allocate driver private\n"); 283 goto failed0; 284 } 285 286 priv->unifi_device = dev; 287 288 SET_NETDEV_DEV(priv->netdev[0], dev); 289 290 /* We are not ready to send data yet. */ 291 netif_carrier_off(priv->netdev[0]); 292 293 /* Allocate driver context. */ 294 priv->card = unifi_alloc_card(priv->sdio, priv); 295 if (priv->card == NULL) { 296 unifi_error(priv, "Failed to allocate UniFi driver card struct.\n"); 297 goto failed1; 298 } 299 300 if (Unifi_instances[bus_id]) { 301 unifi_error(priv, "Internal error: instance for slot %d is already taken\n", 302 bus_id); 303 } 304 Unifi_instances[bus_id] = priv; 305 In_use[bus_id] = UNIFI_DEV_IN_USE; 306 307 /* Save the netdev_priv for use by the netdev event callback mechanism */ 308 Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES] = netdev_priv(priv->netdev[0]); 309 310 /* Initialise the mini-coredump capture buffers */ 311 csrResult = unifi_coredump_init(priv->card, (u16)coredump_max); 312 if (csrResult != CSR_RESULT_SUCCESS) { 313 unifi_error(priv, "Couldn't allocate mini-coredump buffers\n"); 314 } 315 316 /* Create the character device nodes */ 317 r = uf_create_device_nodes(priv, bus_id); 318 if (r) { 319 goto failed1; 320 } 321 322 /* 323 * We use the slot number as unifi device index. 324 */ 325 scnprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance); 326 /* 327 * The following complex casting is in place in order to eliminate 64-bit compilation warning 328 * "cast to/from pointer from/to integer of different size" 329 */ 330 if (!create_proc_read_entry(priv->proc_entry_name, 0, 0, 331 uf_read_proc, (void *)(long)priv->instance)) 332 { 333 unifi_error(priv, "unifi: can't create /proc/driver/unifi\n"); 334 } 335 336 /* Allocate the net_device for interfaces other than 0. */ 337 { 338 int i; 339 priv->totalInterfaceCount =0; 340 341 for(i=1;i<CSR_WIFI_NUM_INTERFACES;i++) 342 { 343 if( !uf_alloc_netdevice_for_other_interfaces(priv,i) ) 344 { 345 /* error occured while allocating the net_device for interface[i]. The net_device are 346 * allocated for the interfaces with id<i. Dont worry, all the allocated net_device will 347 * be releasing chen the control goes to the label failed0. 348 */ 349 unifi_error(priv, "Failed to allocate driver private for interface[%d]\n",i); 350 goto failed0; 351 } 352 else 353 { 354 SET_NETDEV_DEV(priv->netdev[i], dev); 355 356 /* We are not ready to send data yet. */ 357 netif_carrier_off(priv->netdev[i]); 358 359 /* Save the netdev_priv for use by the netdev event callback mechanism */ 360 Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES + i] = netdev_priv(priv->netdev[i]); 361 } 362 } 363 364 for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++) 365 { 366 netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; 367 interfacePriv->netdev_registered=0; 368 } 369 } 370 371#ifdef CSR_WIFI_RX_PATH_SPLIT 372 if (signal_buffer_init(priv, CSR_WIFI_RX_SIGNAL_BUFFER_SIZE)) 373 { 374 unifi_error(priv,"Failed to allocate shared memory for T-H signals\n"); 375 goto failed2; 376 } 377 priv->rx_workqueue = create_singlethread_workqueue("rx_workq"); 378 if (priv->rx_workqueue == NULL) { 379 unifi_error(priv,"create_singlethread_workqueue failed \n"); 380 goto failed3; 381 } 382 INIT_WORK(&priv->rx_work_struct, rx_wq_handler); 383#endif 384 385#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 386 if (log_hip_signals) 387 { 388 uf_register_hip_offline_debug(priv); 389 } 390#endif 391 392 /* Initialise the SME related threads and parameters */ 393 r = uf_sme_init(priv); 394 if (r) { 395 unifi_error(priv, "SME initialisation failed.\n"); 396 goto failed4; 397 } 398 399 /* 400 * Run the userspace helper program (unififw) to perform 401 * the device initialisation. 402 */ 403 unifi_trace(priv, UDBG1, "run UniFi helper app...\n"); 404 r = uf_run_unifihelper(priv); 405 if (r) { 406 unifi_notice(priv, "unable to run UniFi helper app\n"); 407 /* Not a fatal error. */ 408 } 409 410 up(&Unifi_instance_mutex); 411 412 return priv; 413 414failed4: 415#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 416if (log_hip_signals) 417{ 418 uf_unregister_hip_offline_debug(priv); 419} 420#endif 421#ifdef CSR_WIFI_RX_PATH_SPLIT 422 flush_workqueue(priv->rx_workqueue); 423 destroy_workqueue(priv->rx_workqueue); 424failed3: 425 signal_buffer_free(priv,CSR_WIFI_RX_SIGNAL_BUFFER_SIZE); 426failed2: 427#endif 428 /* Remove the device nodes */ 429 uf_destroy_device_nodes(priv); 430failed1: 431 /* Deregister priv->netdev_client */ 432 ul_deregister_client(priv->netdev_client); 433 434failed0: 435 if (priv && priv->card) { 436 unifi_coredump_free(priv->card); 437 unifi_free_card(priv->card); 438 } 439 if (priv) { 440 uf_free_netdevice(priv); 441 } 442 443 up(&Unifi_instance_mutex); 444 445 return NULL; 446} /* register_unifi_sdio() */ 447 448 449/* 450 * --------------------------------------------------------------------------- 451 * ask_unifi_sdio_cleanup 452 * 453 * We can not free our private context, until all the char device 454 * clients have closed the file handles. unregister_unifi_sdio() which 455 * is called when a card is removed, waits on Unifi_cleanup_wq until 456 * the reference count becomes zero. It is time to wake it up now. 457 * 458 * Arguments: 459 * priv Pointer to driver context. 460 * 461 * Returns: 462 * None. 463 * --------------------------------------------------------------------------- 464 */ 465static void 466ask_unifi_sdio_cleanup(unifi_priv_t *priv) 467{ 468 469 /* 470 * Now clear the flag that says the old instance is in use. 471 * This is used to prevent a new instance being started before old 472 * one has finshed closing down, for example if bounce makes the card 473 * appear to be ejected and re-inserted quickly. 474 */ 475 In_use[priv->instance] = UNIFI_DEV_CLEANUP; 476 477 unifi_trace(NULL, UDBG5, "ask_unifi_sdio_cleanup: wake up cleanup workqueue.\n"); 478 wake_up(&Unifi_cleanup_wq); 479 480} /* ask_unifi_sdio_cleanup() */ 481 482 483/* 484 * --------------------------------------------------------------------------- 485 * cleanup_unifi_sdio 486 * 487 * Release any resources owned by a unifi instance. 488 * 489 * Arguments: 490 * priv Pointer to the instance to free. 491 * 492 * Returns: 493 * None. 494 * --------------------------------------------------------------------------- 495 */ 496static void 497cleanup_unifi_sdio(unifi_priv_t *priv) 498{ 499 int priv_instance; 500 int i; 501 static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; 502 503 /* Remove the device nodes */ 504 uf_destroy_device_nodes(priv); 505 506 /* Mark this device as gone away by NULLing the entry in Unifi_instances */ 507 Unifi_instances[priv->instance] = NULL; 508 509 unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: remove_proc_entry\n"); 510 /* 511 * Free the children of priv before unifi_free_netdevice() frees 512 * the priv struct 513 */ 514 remove_proc_entry(priv->proc_entry_name, 0); 515 516 517 /* Unregister netdev as a client. */ 518 if (priv->netdev_client) { 519 unifi_trace(priv, UDBG2, "Netdev client (id:%d s:0x%X) is unregistered\n", 520 priv->netdev_client->client_id, priv->netdev_client->sender_id); 521 ul_deregister_client(priv->netdev_client); 522 } 523 524 /* Destroy the SME related threads and parameters */ 525 uf_sme_deinit(priv); 526 527#ifdef CSR_SME_USERSPACE 528 priv->smepriv = NULL; 529#endif 530 531#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE 532 if (log_hip_signals) 533 { 534 uf_unregister_hip_offline_debug(priv); 535 } 536#endif 537 538 /* Free any packets left in the Rx queues */ 539 for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++) 540 { 541 uf_free_pending_rx_packets(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address,i); 542 uf_free_pending_rx_packets(priv, UF_CONTROLLED_PORT_Q, broadcast_address,i); 543 } 544 /* 545 * We need to free the resources held by the core, which include tx skbs, 546 * otherwise we can not call unregister_netdev(). 547 */ 548 if (priv->card) { 549 unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: free card\n"); 550 unifi_coredump_free(priv->card); 551 unifi_free_card(priv->card); 552 priv->card = NULL; 553 } 554 555 /* 556 * Unregister the network device. 557 * We can not unregister the netdev before we release 558 * all pending packets in the core. 559 */ 560 uf_unregister_netdev(priv); 561 priv->totalInterfaceCount = 0; 562 563 /* Clear the table of registered netdev_priv's */ 564 for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { 565 Unifi_netdev_instances[priv->instance * CSR_WIFI_NUM_INTERFACES + i] = NULL; 566 } 567 568 unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: uf_free_netdevice\n"); 569 /* 570 * When uf_free_netdevice() returns, the priv is invalid 571 * so we need to remember the instance to clear the global flag later. 572 */ 573 priv_instance = priv->instance; 574 575#ifdef CSR_WIFI_RX_PATH_SPLIT 576 flush_workqueue(priv->rx_workqueue); 577 destroy_workqueue(priv->rx_workqueue); 578 signal_buffer_free(priv,CSR_WIFI_RX_SIGNAL_BUFFER_SIZE); 579#endif 580 581 /* Priv is freed as part of the net_device */ 582 uf_free_netdevice(priv); 583 584 /* 585 * Now clear the flag that says the old instance is in use. 586 * This is used to prevent a new instance being started before old 587 * one has finshed closing down, for example if bounce makes the card 588 * appear to be ejected and re-inserted quickly. 589 */ 590 In_use[priv_instance] = UNIFI_DEV_NOT_IN_USE; 591 592 unifi_trace(NULL, UDBG5, "cleanup_unifi_sdio: DONE.\n"); 593 594} /* cleanup_unifi_sdio() */ 595 596 597/* 598 * --------------------------------------------------------------------------- 599 * unregister_unifi_sdio 600 * 601 * Call from SDIO driver when it detects that UniFi has been removed. 602 * 603 * Arguments: 604 * bus_id Number of the card that was ejected. 605 * 606 * Returns: 607 * None. 608 * --------------------------------------------------------------------------- 609 */ 610static void 611unregister_unifi_sdio(int bus_id) 612{ 613 unifi_priv_t *priv; 614 int interfaceTag=0; 615 u8 reason = CONFIG_IND_EXIT; 616 617 if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { 618 unifi_error(NULL, "unregister_unifi_sdio: invalid device %d\n", 619 bus_id); 620 return; 621 } 622 623 priv = Unifi_instances[bus_id]; 624 if (priv == NULL) { 625 unifi_error(priv, "unregister_unifi_sdio: device %d is not registered\n", 626 bus_id); 627 return; 628 } 629 630 /* Stop the network traffic before freeing the core. */ 631 for(interfaceTag=0;interfaceTag<priv->totalInterfaceCount;interfaceTag++) 632 { 633 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; 634 if(interfacePriv->netdev_registered) 635 { 636 netif_carrier_off(priv->netdev[interfaceTag]); 637 netif_tx_stop_all_queues(priv->netdev[interfaceTag]); 638 } 639 } 640 641#ifdef CSR_NATIVE_LINUX 642 /* 643 * If the unifi thread was started, signal it to stop. This 644 * should cause any userspace processes with open unifi device to 645 * close them. 646 */ 647 uf_stop_thread(priv, &priv->bh_thread); 648 649 /* Unregister the interrupt handler */ 650 if (csr_sdio_linux_remove_irq(priv->sdio)) { 651 unifi_notice(priv, 652 "csr_sdio_linux_remove_irq failed to talk to card.\n"); 653 } 654 655 /* Ensure no MLME functions are waiting on a the mlme_event semaphore. */ 656 uf_abort_mlme(priv); 657#endif /* CSR_NATIVE_LINUX */ 658 659 ul_log_config_ind(priv, &reason, sizeof(u8)); 660 661 /* Deregister the UDI hook from the core. */ 662 unifi_remove_udi_hook(priv->card, logging_handler); 663 664 uf_put_instance(bus_id); 665 666 /* 667 * Wait until the device is cleaned up. i.e., when all userspace 668 * processes have closed any open unifi devices. 669 */ 670 wait_event(Unifi_cleanup_wq, In_use[bus_id] == UNIFI_DEV_CLEANUP); 671 unifi_trace(NULL, UDBG5, "Received clean up event\n"); 672 673 /* Now we can free the private context and the char device nodes */ 674 cleanup_unifi_sdio(priv); 675 676} /* unregister_unifi_sdio() */ 677 678 679/* 680 * --------------------------------------------------------------------------- 681 * uf_find_instance 682 * 683 * Find the context structure for a given UniFi device instance. 684 * 685 * Arguments: 686 * inst The instance number to look for. 687 * 688 * Returns: 689 * None. 690 * --------------------------------------------------------------------------- 691 */ 692unifi_priv_t * 693uf_find_instance(int inst) 694{ 695 if ((inst < 0) || (inst >= MAX_UNIFI_DEVS)) { 696 return NULL; 697 } 698 return Unifi_instances[inst]; 699} /* uf_find_instance() */ 700 701 702/* 703 * --------------------------------------------------------------------------- 704 * uf_find_priv 705 * 706 * Find the device instance for a given context structure. 707 * 708 * Arguments: 709 * priv The context structure pointer to look for. 710 * 711 * Returns: 712 * index of instance, -1 otherwise. 713 * --------------------------------------------------------------------------- 714 */ 715int 716uf_find_priv(unifi_priv_t *priv) 717{ 718 int inst; 719 720 if (!priv) { 721 return -1; 722 } 723 724 for (inst = 0; inst < MAX_UNIFI_DEVS; inst++) { 725 if (Unifi_instances[inst] == priv) { 726 return inst; 727 } 728 } 729 730 return -1; 731} /* uf_find_priv() */ 732 733/* 734 * --------------------------------------------------------------------------- 735 * uf_find_netdev_priv 736 * 737 * Find the device instance for a given netdev context structure. 738 * 739 * Arguments: 740 * priv The context structure pointer to look for. 741 * 742 * Returns: 743 * index of instance, -1 otherwise. 744 * --------------------------------------------------------------------------- 745 */ 746int 747uf_find_netdev_priv(netInterface_priv_t *priv) 748{ 749 int inst; 750 751 if (!priv) { 752 return -1; 753 } 754 755 for (inst = 0; inst < MAX_UNIFI_DEVS * CSR_WIFI_NUM_INTERFACES; inst++) { 756 if (Unifi_netdev_instances[inst] == priv) { 757 return inst; 758 } 759 } 760 761 return -1; 762} /* uf_find_netdev_priv() */ 763 764/* 765 * --------------------------------------------------------------------------- 766 * uf_get_instance 767 * 768 * Find the context structure for a given UniFi device instance 769 * and increment the reference count. 770 * 771 * Arguments: 772 * inst The instance number to look for. 773 * 774 * Returns: 775 * Pointer to the instance or NULL if no instance exists. 776 * --------------------------------------------------------------------------- 777 */ 778unifi_priv_t * 779uf_get_instance(int inst) 780{ 781 unifi_priv_t *priv; 782 783 down(&Unifi_instance_mutex); 784 785 priv = uf_find_instance(inst); 786 if (priv) { 787 priv->ref_count++; 788 } 789 790 up(&Unifi_instance_mutex); 791 792 return priv; 793} 794 795/* 796 * --------------------------------------------------------------------------- 797 * uf_put_instance 798 * 799 * Decrement the context reference count, freeing resources and 800 * shutting down the driver when the count reaches zero. 801 * 802 * Arguments: 803 * inst The instance number to look for. 804 * 805 * Returns: 806 * Pointer to the instance or NULL if no instance exists. 807 * --------------------------------------------------------------------------- 808 */ 809void 810uf_put_instance(int inst) 811{ 812 unifi_priv_t *priv; 813 814 down(&Unifi_instance_mutex); 815 816 priv = uf_find_instance(inst); 817 if (priv) { 818 priv->ref_count--; 819 if (priv->ref_count == 0) { 820 ask_unifi_sdio_cleanup(priv); 821 } 822 } 823 824 up(&Unifi_instance_mutex); 825} 826 827 828/* 829 * --------------------------------------------------------------------------- 830 * uf_read_proc 831 * 832 * Read method for driver node in /proc/driver/unifi0 833 * 834 * Arguments: 835 * page 836 * start 837 * offset 838 * count 839 * eof 840 * data 841 * 842 * Returns: 843 * None. 844 * --------------------------------------------------------------------------- 845 */ 846#ifdef CONFIG_PROC_FS 847static int 848uf_read_proc(char *page, char **start, off_t offset, int count, 849 int *eof, void *data) 850{ 851#define UNIFI_DEBUG_TXT_BUFFER 8*1024 852 unifi_priv_t *priv; 853 int actual_amount_to_copy; 854 char *p, *orig_p; 855 s32 remain = UNIFI_DEBUG_TXT_BUFFER; 856 s32 written; 857 int i; 858 859 /* 860 * The following complex casting is in place in order to eliminate 64-bit compilation warning 861 * "cast to/from pointer from/to integer of different size" 862 */ 863 priv = uf_find_instance((int)(long)data); 864 if (!priv) { 865 return 0; 866 } 867 868 p = kmalloc( UNIFI_DEBUG_TXT_BUFFER, GFP_KERNEL ); 869 870 orig_p = p; 871 872 written = scnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n", 873 CSR_WIFI_VERSION, __DATE__, __TIME__); 874 UNIFI_SNPRINTF_RET(p, remain, written); 875#ifdef CSR_SME_USERSPACE 876 written = scnprintf(p, remain, "SME: CSR userspace "); 877 UNIFI_SNPRINTF_RET(p, remain, written); 878#ifdef CSR_SUPPORT_WEXT 879 written = scnprintf(p, remain, "with WEXT support\n"); 880#else 881 written = scnprintf(p, remain, "\n"); 882#endif /* CSR_SUPPORT_WEXT */ 883 UNIFI_SNPRINTF_RET(p, remain, written); 884#endif /* CSR_SME_USERSPACE */ 885#ifdef CSR_NATIVE_LINUX 886 written = scnprintf(p, remain, "SME: native\n"); 887 UNIFI_SNPRINTF_RET(p, remain, written); 888#endif 889 890#ifdef CSR_SUPPORT_SME 891 written = scnprintf(p, remain, 892 "Firmware (ROM) build:%u, Patch:%u\n", 893 priv->card_info.fw_build, 894 priv->sme_versions.firmwarePatch); 895 UNIFI_SNPRINTF_RET(p, remain, written); 896#endif 897 p += unifi_print_status(priv->card, p, &remain); 898 899 written = scnprintf(p, remain, "Last dbg str: %s\n", 900 priv->last_debug_string); 901 UNIFI_SNPRINTF_RET(p, remain, written); 902 903 written = scnprintf(p, remain, "Last dbg16:"); 904 UNIFI_SNPRINTF_RET(p, remain, written); 905 for (i = 0; i < 8; i++) { 906 written = scnprintf(p, remain, " %04X", 907 priv->last_debug_word16[i]); 908 UNIFI_SNPRINTF_RET(p, remain, written); 909 } 910 written = scnprintf(p, remain, "\n"); 911 UNIFI_SNPRINTF_RET(p, remain, written); 912 written = scnprintf(p, remain, " "); 913 UNIFI_SNPRINTF_RET(p, remain, written); 914 for (; i < 16; i++) { 915 written = scnprintf(p, remain, " %04X", 916 priv->last_debug_word16[i]); 917 UNIFI_SNPRINTF_RET(p, remain, written); 918 } 919 written = scnprintf(p, remain, "\n"); 920 UNIFI_SNPRINTF_RET(p, remain, written); 921 *start = page; 922 923 written = UNIFI_DEBUG_TXT_BUFFER - remain; 924 925 if( offset >= written ) 926 { 927 *eof = 1; 928 kfree( orig_p ); 929 return(0); 930 } 931 932 if( offset + count > written ) 933 { 934 actual_amount_to_copy = written - offset; 935 *eof = 1; 936 } 937 else 938 { 939 actual_amount_to_copy = count; 940 } 941 942 memcpy( page, &(orig_p[offset]), actual_amount_to_copy ); 943 944 kfree( orig_p ); 945 946 return( actual_amount_to_copy ); 947} /* uf_read_proc() */ 948#endif 949 950 951 952 953static void 954uf_lx_suspend(CsrSdioFunction *sdio_ctx) 955{ 956 unifi_priv_t *priv = sdio_ctx->driverData; 957 unifi_suspend(priv); 958 959 CsrSdioSuspendAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); 960} 961 962static void 963uf_lx_resume(CsrSdioFunction *sdio_ctx) 964{ 965 unifi_priv_t *priv = sdio_ctx->driverData; 966 unifi_resume(priv); 967 968 CsrSdioResumeAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); 969} 970 971static int active_slot = MAX_UNIFI_DEVS; 972static struct device *os_devices[MAX_UNIFI_DEVS]; 973 974void 975uf_add_os_device(int bus_id, struct device *os_device) 976{ 977 if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { 978 unifi_error(NULL, "uf_add_os_device: invalid device %d\n", 979 bus_id); 980 return; 981 } 982 983 active_slot = bus_id; 984 os_devices[bus_id] = os_device; 985} /* uf_add_os_device() */ 986 987void 988uf_remove_os_device(int bus_id) 989{ 990 if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { 991 unifi_error(NULL, "uf_remove_os_device: invalid device %d\n", 992 bus_id); 993 return; 994 } 995 996 active_slot = bus_id; 997 os_devices[bus_id] = NULL; 998} /* uf_remove_os_device() */ 999 1000static void 1001uf_sdio_inserted(CsrSdioFunction *sdio_ctx) 1002{ 1003 unifi_priv_t *priv; 1004 1005 unifi_trace(NULL, UDBG5, "uf_sdio_inserted(0x%p), slot_id=%d, dev=%p\n", 1006 sdio_ctx, active_slot, os_devices[active_slot]); 1007 1008 priv = register_unifi_sdio(sdio_ctx, active_slot, os_devices[active_slot]); 1009 if (priv == NULL) { 1010 CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_FAILURE); 1011 return; 1012 } 1013 1014 sdio_ctx->driverData = priv; 1015 1016 CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); 1017} /* uf_sdio_inserted() */ 1018 1019 1020static void 1021uf_sdio_removed(CsrSdioFunction *sdio_ctx) 1022{ 1023 unregister_unifi_sdio(active_slot); 1024 CsrSdioRemovedAcknowledge(sdio_ctx); 1025} /* uf_sdio_removed() */ 1026 1027 1028static void 1029uf_sdio_dsr_handler(CsrSdioFunction *sdio_ctx) 1030{ 1031 unifi_priv_t *priv = sdio_ctx->driverData; 1032 1033 unifi_sdio_interrupt_handler(priv->card); 1034} /* uf_sdio_dsr_handler() */ 1035 1036/* 1037 * --------------------------------------------------------------------------- 1038 * uf_sdio_int_handler 1039 * 1040 * Interrupt callback function for SDIO interrupts. 1041 * This is called in kernel context (i.e. not interrupt context). 1042 * We retrieve the unifi context pointer and call the main UniFi 1043 * interrupt handler. 1044 * 1045 * Arguments: 1046 * fdev SDIO context pointer 1047 * 1048 * Returns: 1049 * None. 1050 * --------------------------------------------------------------------------- 1051 */ 1052static CsrSdioInterruptDsrCallback 1053uf_sdio_int_handler(CsrSdioFunction *sdio_ctx) 1054{ 1055 return uf_sdio_dsr_handler; 1056} /* uf_sdio_int_handler() */ 1057 1058 1059 1060 1061static CsrSdioFunctionId unifi_ids[] = 1062{ 1063 { 1064 .manfId = SDIO_MANF_ID_CSR, 1065 .cardId = SDIO_CARD_ID_UNIFI_3, 1066 .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_3, 1067 .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE, 1068 }, 1069 { 1070 .manfId = SDIO_MANF_ID_CSR, 1071 .cardId = SDIO_CARD_ID_UNIFI_4, 1072 .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_4, 1073 .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE, 1074 } 1075}; 1076 1077 1078/* 1079 * Structure to register with the glue layer. 1080 */ 1081static CsrSdioFunctionDriver unifi_sdioFunction_drv = 1082{ 1083 .inserted = uf_sdio_inserted, 1084 .removed = uf_sdio_removed, 1085 .intr = uf_sdio_int_handler, 1086 .suspend = uf_lx_suspend, 1087 .resume = uf_lx_resume, 1088 1089 .ids = unifi_ids, 1090 .idsCount = sizeof(unifi_ids) / sizeof(unifi_ids[0]) 1091}; 1092 1093 1094/* 1095 * --------------------------------------------------------------------------- 1096 * uf_sdio_load 1097 * uf_sdio_unload 1098 * 1099 * These functions are called from the main module load and unload 1100 * functions. They perform the appropriate operations for the monolithic 1101 * driver. 1102 * 1103 * Arguments: 1104 * None. 1105 * 1106 * Returns: 1107 * None. 1108 * --------------------------------------------------------------------------- 1109 */ 1110int __init 1111uf_sdio_load(void) 1112{ 1113 CsrResult csrResult; 1114 1115 csrResult = CsrSdioFunctionDriverRegister(&unifi_sdioFunction_drv); 1116 if (csrResult != CSR_RESULT_SUCCESS) { 1117 unifi_error(NULL, "Failed to register UniFi SDIO driver: csrResult=%d\n", csrResult); 1118 return -EIO; 1119 } 1120 1121 return 0; 1122} /* uf_sdio_load() */ 1123 1124 1125 1126void __exit 1127uf_sdio_unload(void) 1128{ 1129 CsrSdioFunctionDriverUnregister(&unifi_sdioFunction_drv); 1130} /* uf_sdio_unload() */ 1131