Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
[linux-2.6-block.git] / drivers / staging / csr / io.c
CommitLineData
635d2b00
GKH
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
635d2b00
GKH
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 */
635d2b00 72DEFINE_SEMAPHORE(Unifi_instance_mutex);
635d2b00
GKH
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;
635d2b00
GKH
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;
70128792 96 priv->rxSignalBuffer.rx_buff[i].bufptr = kmalloc(UNIFI_PACKED_SIGBUF_SIZE, GFP_KERNEL);
635d2b00
GKH
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;
4fe9db37 104 kfree(priv->rxSignalBuffer.rx_buff[j].bufptr);
635d2b00
GKH
105 priv->rxSignalBuffer.rx_buff[j].bufptr = NULL;
106 }
635d2b00
GKH
107 return -1;
108 }
109 }
635d2b00
GKH
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;
4fe9db37 121 kfree(priv->rxSignalBuffer.rx_buff[i].bufptr);
635d2b00
GKH
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
635d2b00
GKH
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
635d2b00
GKH
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 */
8c87f69a 311 csrResult = unifi_coredump_init(priv->card, (u16)coredump_max);
635d2b00
GKH
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 */
c4f9e644 325 scnprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance);
635d2b00
GKH
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
95edd09e
GKH
385#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
386 if (log_hip_signals)
387 {
388 uf_register_hip_offline_debug(priv);
389 }
390#endif
391
635d2b00
GKH
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
635d2b00
GKH
412 return priv;
413
414failed4:
95edd09e
GKH
415#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
416if (log_hip_signals)
417{
418 uf_unregister_hip_offline_debug(priv);
419}
420#endif
635d2b00
GKH
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
635d2b00
GKH
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{
635d2b00
GKH
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
635d2b00
GKH
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
635d2b00
GKH
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
95edd09e
GKH
531#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
532 if (log_hip_signals)
533 {
534 uf_unregister_hip_offline_debug(priv);
535 }
536#endif
537
635d2b00
GKH
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
635d2b00
GKH
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);
635d2b00
GKH
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]);
4febd649 637 netif_tx_stop_all_queues(priv->netdev[interfaceTag]);
635d2b00
GKH
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;
95e326c2
GKH
855 s32 remain = UNIFI_DEBUG_TXT_BUFFER;
856 s32 written;
635d2b00
GKH
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
c4f9e644 872 written = scnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n",
635d2b00
GKH
873 CSR_WIFI_VERSION, __DATE__, __TIME__);
874 UNIFI_SNPRINTF_RET(p, remain, written);
875#ifdef CSR_SME_USERSPACE
c4f9e644 876 written = scnprintf(p, remain, "SME: CSR userspace ");
635d2b00
GKH
877 UNIFI_SNPRINTF_RET(p, remain, written);
878#ifdef CSR_SUPPORT_WEXT
c4f9e644 879 written = scnprintf(p, remain, "with WEXT support\n");
635d2b00 880#else
c4f9e644 881 written = scnprintf(p, remain, "\n");
635d2b00
GKH
882#endif /* CSR_SUPPORT_WEXT */
883 UNIFI_SNPRINTF_RET(p, remain, written);
884#endif /* CSR_SME_USERSPACE */
885#ifdef CSR_NATIVE_LINUX
c4f9e644 886 written = scnprintf(p, remain, "SME: native\n");
635d2b00
GKH
887 UNIFI_SNPRINTF_RET(p, remain, written);
888#endif
889
890#ifdef CSR_SUPPORT_SME
c4f9e644
DN
891 written = scnprintf(p, remain,
892 "Firmware (ROM) build:%u, Patch:%u\n",
635d2b00
GKH
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
c4f9e644 899 written = scnprintf(p, remain, "Last dbg str: %s\n",
635d2b00
GKH
900 priv->last_debug_string);
901 UNIFI_SNPRINTF_RET(p, remain, written);
902
c4f9e644 903 written = scnprintf(p, remain, "Last dbg16:");
635d2b00
GKH
904 UNIFI_SNPRINTF_RET(p, remain, written);
905 for (i = 0; i < 8; i++) {
c4f9e644 906 written = scnprintf(p, remain, " %04X",
635d2b00
GKH
907 priv->last_debug_word16[i]);
908 UNIFI_SNPRINTF_RET(p, remain, written);
909 }
c4f9e644 910 written = scnprintf(p, remain, "\n");
635d2b00 911 UNIFI_SNPRINTF_RET(p, remain, written);
c4f9e644 912 written = scnprintf(p, remain, " ");
635d2b00
GKH
913 UNIFI_SNPRINTF_RET(p, remain, written);
914 for (; i < 16; i++) {
c4f9e644 915 written = scnprintf(p, remain, " %04X",
635d2b00
GKH
916 priv->last_debug_word16[i]);
917 UNIFI_SNPRINTF_RET(p, remain, written);
918 }
c4f9e644 919 written = scnprintf(p, remain, "\n");
635d2b00
GKH
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{
f145b4f4 1003 unifi_priv_t *priv;
635d2b00 1004
f145b4f4
DN
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]);
635d2b00 1007
f145b4f4
DN
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 }
635d2b00 1013
f145b4f4 1014 sdio_ctx->driverData = priv;
635d2b00 1015
f145b4f4 1016 CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS);
635d2b00
GKH
1017} /* uf_sdio_inserted() */
1018
1019
1020static void
1021uf_sdio_removed(CsrSdioFunction *sdio_ctx)
1022{
f145b4f4
DN
1023 unregister_unifi_sdio(active_slot);
1024 CsrSdioRemovedAcknowledge(sdio_ctx);
635d2b00
GKH
1025} /* uf_sdio_removed() */
1026
1027
1028static void
1029uf_sdio_dsr_handler(CsrSdioFunction *sdio_ctx)
1030{
f145b4f4 1031 unifi_priv_t *priv = sdio_ctx->driverData;
635d2b00 1032
f145b4f4 1033 unifi_sdio_interrupt_handler(priv->card);
635d2b00
GKH
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{
f145b4f4 1055 return uf_sdio_dsr_handler;
635d2b00
GKH
1056} /* uf_sdio_int_handler() */
1057
1058
1059
1060
1061static CsrSdioFunctionId unifi_ids[] =
1062{
f145b4f4
DN
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 }
635d2b00
GKH
1075};
1076
1077
1078/*
1079 * Structure to register with the glue layer.
1080 */
1081static CsrSdioFunctionDriver unifi_sdioFunction_drv =
1082{
f145b4f4
DN
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])
635d2b00
GKH
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{
f145b4f4 1113 CsrResult csrResult;
635d2b00 1114
f145b4f4
DN
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 }
635d2b00 1120
f145b4f4 1121 return 0;
635d2b00
GKH
1122} /* uf_sdio_load() */
1123
1124
1125
1126void __exit
1127uf_sdio_unload(void)
1128{
f145b4f4 1129 CsrSdioFunctionDriverUnregister(&unifi_sdioFunction_drv);
635d2b00
GKH
1130} /* uf_sdio_unload() */
1131