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