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