Root/drivers/staging/csr/io.c

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

Archive Download this file



interactive