2 * ---------------------------------------------------------------------------
6 * This file contains routines that the SDIO driver can call when a
7 * UniFi card is first inserted (or detected) and removed.
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"
17 * #SUBSYSTEM=="net", DRIVERS=="?*", GOTO="net_start"
18 * SUBSYSTEM=="net", GOTO="net_start"
20 * Then you can add a stanza to /etc/network/interfaces like this:
22 * iface eth1 inet dhcp
23 * wpa-conf /etc/wpa_supplicant.conf
24 * This will then automatically associate when a car dis inserted.
26 * Copyright (C) 2006-2009 by Cambridge Silicon Radio Ltd.
28 * Refer to LICENSE.txt included with this source code for details on
31 * ---------------------------------------------------------------------------
33 #include <linux/proc_fs.h>
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() */
39 #include "unifi_priv.h"
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.
47 * The Arasan PCI-SDIO controller card supported by this driver has 2 slots,
48 * hence a max of 2 devices.
50 static unifi_priv_t *Unifi_instances[MAX_UNIFI_DEVS];
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.
56 static netInterface_priv_t *Unifi_netdev_instances[MAX_UNIFI_DEVS * CSR_WIFI_NUM_INTERFACES];
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).
64 #define UNIFI_DEV_NOT_IN_USE 0
65 #define UNIFI_DEV_IN_USE 1
66 #define UNIFI_DEV_CLEANUP 2
67 static int In_use[MAX_UNIFI_DEVS];
69 * Mutex to prevent UDI clients to open the character device before the priv
70 * is created and initialised.
72 DEFINE_SEMAPHORE(Unifi_instance_mutex);
74 * When the device is removed, unregister waits on Unifi_cleanup_wq
75 * until all the UDI clients release the character device.
77 DECLARE_WAIT_QUEUE_HEAD(Unifi_cleanup_wq);
80 static int uf_read_proc(char *page, char **start, off_t offset, int count,
81 int *eof, void *data);
83 #ifdef CSR_WIFI_RX_PATH_SPLIT
85 static CsrResult signal_buffer_init(unifi_priv_t * priv, int size)
90 priv->rxSignalBuffer.writePointer =
91 priv->rxSignalBuffer.readPointer = 0;
92 priv->rxSignalBuffer.size = size;
93 /* Allocating Memory for Signal primitive pointer */
96 priv->rxSignalBuffer.rx_buff[i].sig_len=0;
97 priv->rxSignalBuffer.rx_buff[i].bufptr = kmalloc(UNIFI_PACKED_SIGBUF_SIZE, GFP_KERNEL);
98 if (priv->rxSignalBuffer.rx_buff[i].bufptr == NULL)
101 unifi_error(priv,"signal_buffer_init:Failed to Allocate shared memory for T-H signals \n");
104 priv->rxSignalBuffer.rx_buff[j].sig_len=0;
105 kfree(priv->rxSignalBuffer.rx_buff[j].bufptr);
106 priv->rxSignalBuffer.rx_buff[j].bufptr = NULL;
117 static void signal_buffer_free(unifi_priv_t * priv, int size)
121 for(i=0; i<size; i++)
123 priv->rxSignalBuffer.rx_buff[i].sig_len=0;
124 kfree(priv->rxSignalBuffer.rx_buff[i].bufptr);
125 priv->rxSignalBuffer.rx_buff[i].bufptr = NULL;
130 * ---------------------------------------------------------------------------
133 * Registers the network interface, installes the qdisc,
134 * and registers the inet handler.
135 * In the porting exercise, register the driver to the network
136 * stack if necessary.
139 * priv Pointer to driver context.
142 * O on success, non-zero otherwise.
145 * We will only unregister when the card is ejected, so we must
147 * ---------------------------------------------------------------------------
150 uf_register_netdev(unifi_priv_t *priv, int interfaceTag)
153 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
155 if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
156 unifi_error(priv, "uf_register_netdev bad interfaceTag\n");
161 * Allocates a device number and registers device with the network
164 unifi_trace(priv, UDBG5, "uf_register_netdev: netdev %d - 0x%p\n",
165 interfaceTag, priv->netdev[interfaceTag]);
166 r = register_netdev(priv->netdev[interfaceTag]);
168 unifi_error(priv, "Failed to register net device\n");
172 /* The device is registed */
173 interfacePriv->netdev_registered = 1;
175 #ifdef CSR_SUPPORT_SME
177 * Register the inet handler; it notifies us for changes in the IP address.
179 uf_register_inet_notifier();
180 #endif /* CSR_SUPPORT_SME */
182 unifi_notice(priv, "unifi%d is %s\n",
183 priv->instance, priv->netdev[interfaceTag]->name);
186 } /* uf_register_netdev */
190 * ---------------------------------------------------------------------------
191 * uf_unregister_netdev
193 * Unregisters the network interface and the inet handler.
196 * priv Pointer to driver context.
201 * ---------------------------------------------------------------------------
204 uf_unregister_netdev(unifi_priv_t *priv)
208 #ifdef CSR_SUPPORT_SME
209 /* Unregister the inet handler... */
210 uf_unregister_inet_notifier();
211 #endif /* CSR_SUPPORT_SME */
213 for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
214 netInterface_priv_t *interfacePriv = priv->interfacePriv[i];
215 if (interfacePriv->netdev_registered) {
216 unifi_trace(priv, UDBG5,
217 "uf_unregister_netdev: netdev %d - 0x%p\n",
220 /* ... and the netdev */
221 unregister_netdev(priv->netdev[i]);
222 interfacePriv->netdev_registered = 0;
225 interfacePriv->interfaceMode = 0;
227 /* Enable all queues by default */
228 interfacePriv->queueEnabled[0] = 1;
229 interfacePriv->queueEnabled[1] = 1;
230 interfacePriv->queueEnabled[2] = 1;
231 interfacePriv->queueEnabled[3] = 1;
234 priv->totalInterfaceCount = 0;
235 } /* uf_unregister_netdev() */
239 * ---------------------------------------------------------------------------
240 * register_unifi_sdio
242 * This function is called from the Probe (or equivalent) method of
243 * the SDIO driver when a UniFi card is detected.
244 * We allocate the Linux net_device struct, initialise the HIP core
245 * lib, create the char device nodes and start the userspace helper
246 * to initialise the device.
249 * sdio_dev Pointer to SDIO context handle to use for all
251 * bus_id A small number indicating the SDIO card position on the
252 * bus. Typically this is the slot number, e.g. 0, 1 etc.
253 * Valid values are 0 to MAX_UNIFI_DEVS-1.
254 * dev Pointer to kernel device manager struct.
257 * Pointer to the unifi instance, or NULL on error.
258 * ---------------------------------------------------------------------------
260 static unifi_priv_t *
261 register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev)
263 unifi_priv_t *priv = NULL;
269 if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) {
270 unifi_error(priv, "register_unifi_sdio: invalid device %d\n",
275 down(&Unifi_instance_mutex);
277 if (In_use[bus_id] != UNIFI_DEV_NOT_IN_USE) {
278 unifi_error(priv, "register_unifi_sdio: device %d is already in use\n",
284 /* Allocate device private and net_device structs */
285 priv = uf_alloc_netdevice(sdio_dev, bus_id);
287 unifi_error(priv, "Failed to allocate driver private\n");
291 priv->unifi_device = dev;
293 SET_NETDEV_DEV(priv->netdev[0], dev);
295 /* We are not ready to send data yet. */
296 netif_carrier_off(priv->netdev[0]);
298 /* Allocate driver context. */
299 priv->card = unifi_alloc_card(priv->sdio, priv);
300 if (priv->card == NULL) {
301 unifi_error(priv, "Failed to allocate UniFi driver card struct.\n");
305 if (Unifi_instances[bus_id]) {
306 unifi_error(priv, "Internal error: instance for slot %d is already taken\n",
309 Unifi_instances[bus_id] = priv;
310 In_use[bus_id] = UNIFI_DEV_IN_USE;
312 /* Save the netdev_priv for use by the netdev event callback mechanism */
313 Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES] = netdev_priv(priv->netdev[0]);
315 /* Initialise the mini-coredump capture buffers */
316 csrResult = unifi_coredump_init(priv->card, (u16)coredump_max);
317 if (csrResult != CSR_RESULT_SUCCESS) {
318 unifi_error(priv, "Couldn't allocate mini-coredump buffers\n");
321 /* Create the character device nodes */
322 r = uf_create_device_nodes(priv, bus_id);
328 * We use the slot number as unifi device index.
330 scnprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance);
332 * The following complex casting is in place in order to eliminate 64-bit compilation warning
333 * "cast to/from pointer from/to integer of different size"
335 if (!create_proc_read_entry(priv->proc_entry_name, 0, 0,
336 uf_read_proc, (void *)(long)priv->instance))
338 unifi_error(priv, "unifi: can't create /proc/driver/unifi\n");
341 /* Allocate the net_device for interfaces other than 0. */
344 priv->totalInterfaceCount =0;
346 for(i=1;i<CSR_WIFI_NUM_INTERFACES;i++)
348 if( !uf_alloc_netdevice_for_other_interfaces(priv,i) )
350 /* error occured while allocating the net_device for interface[i]. The net_device are
351 * allocated for the interfaces with id<i. Dont worry, all the allocated net_device will
352 * be releasing chen the control goes to the label failed0.
354 unifi_error(priv, "Failed to allocate driver private for interface[%d]\n",i);
359 SET_NETDEV_DEV(priv->netdev[i], dev);
361 /* We are not ready to send data yet. */
362 netif_carrier_off(priv->netdev[i]);
364 /* Save the netdev_priv for use by the netdev event callback mechanism */
365 Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES + i] = netdev_priv(priv->netdev[i]);
369 for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
371 netInterface_priv_t *interfacePriv = priv->interfacePriv[i];
372 interfacePriv->netdev_registered=0;
376 #ifdef CSR_WIFI_RX_PATH_SPLIT
377 if (signal_buffer_init(priv, CSR_WIFI_RX_SIGNAL_BUFFER_SIZE))
379 unifi_error(priv,"Failed to allocate shared memory for T-H signals\n");
382 priv->rx_workqueue = create_singlethread_workqueue("rx_workq");
383 if (priv->rx_workqueue == NULL) {
384 unifi_error(priv,"create_singlethread_workqueue failed \n");
387 INIT_WORK(&priv->rx_work_struct, rx_wq_handler);
390 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
393 uf_register_hip_offline_debug(priv);
397 /* Initialise the SME related threads and parameters */
398 r = uf_sme_init(priv);
400 unifi_error(priv, "SME initialisation failed.\n");
405 * Run the userspace helper program (unififw) to perform
406 * the device initialisation.
408 unifi_trace(priv, UDBG1, "run UniFi helper app...\n");
409 r = uf_run_unifihelper(priv);
411 unifi_notice(priv, "unable to run UniFi helper app\n");
412 /* Not a fatal error. */
415 up(&Unifi_instance_mutex);
421 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
424 uf_unregister_hip_offline_debug(priv);
427 #ifdef CSR_WIFI_RX_PATH_SPLIT
428 flush_workqueue(priv->rx_workqueue);
429 destroy_workqueue(priv->rx_workqueue);
431 signal_buffer_free(priv,CSR_WIFI_RX_SIGNAL_BUFFER_SIZE);
434 /* Remove the device nodes */
435 uf_destroy_device_nodes(priv);
437 /* Deregister priv->netdev_client */
438 ul_deregister_client(priv->netdev_client);
441 if (priv && priv->card) {
442 unifi_coredump_free(priv->card);
443 unifi_free_card(priv->card);
446 uf_free_netdevice(priv);
449 up(&Unifi_instance_mutex);
453 } /* register_unifi_sdio() */
457 * ---------------------------------------------------------------------------
458 * ask_unifi_sdio_cleanup
460 * We can not free our private context, until all the char device
461 * clients have closed the file handles. unregister_unifi_sdio() which
462 * is called when a card is removed, waits on Unifi_cleanup_wq until
463 * the reference count becomes zero. It is time to wake it up now.
466 * priv Pointer to driver context.
470 * ---------------------------------------------------------------------------
473 ask_unifi_sdio_cleanup(unifi_priv_t *priv)
478 * Now clear the flag that says the old instance is in use.
479 * This is used to prevent a new instance being started before old
480 * one has finshed closing down, for example if bounce makes the card
481 * appear to be ejected and re-inserted quickly.
483 In_use[priv->instance] = UNIFI_DEV_CLEANUP;
485 unifi_trace(NULL, UDBG5, "ask_unifi_sdio_cleanup: wake up cleanup workqueue.\n");
486 wake_up(&Unifi_cleanup_wq);
490 } /* ask_unifi_sdio_cleanup() */
494 * ---------------------------------------------------------------------------
497 * Release any resources owned by a unifi instance.
500 * priv Pointer to the instance to free.
504 * ---------------------------------------------------------------------------
507 cleanup_unifi_sdio(unifi_priv_t *priv)
511 static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
515 /* Remove the device nodes */
516 uf_destroy_device_nodes(priv);
518 /* Mark this device as gone away by NULLing the entry in Unifi_instances */
519 Unifi_instances[priv->instance] = NULL;
521 unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: remove_proc_entry\n");
523 * Free the children of priv before unifi_free_netdevice() frees
526 remove_proc_entry(priv->proc_entry_name, 0);
529 /* Unregister netdev as a client. */
530 if (priv->netdev_client) {
531 unifi_trace(priv, UDBG2, "Netdev client (id:%d s:0x%X) is unregistered\n",
532 priv->netdev_client->client_id, priv->netdev_client->sender_id);
533 ul_deregister_client(priv->netdev_client);
536 /* Destroy the SME related threads and parameters */
539 #ifdef CSR_SME_USERSPACE
540 priv->smepriv = NULL;
543 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
546 uf_unregister_hip_offline_debug(priv);
550 /* Free any packets left in the Rx queues */
551 for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
553 uf_free_pending_rx_packets(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address,i);
554 uf_free_pending_rx_packets(priv, UF_CONTROLLED_PORT_Q, broadcast_address,i);
557 * We need to free the resources held by the core, which include tx skbs,
558 * otherwise we can not call unregister_netdev().
561 unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: free card\n");
562 unifi_coredump_free(priv->card);
563 unifi_free_card(priv->card);
568 * Unregister the network device.
569 * We can not unregister the netdev before we release
570 * all pending packets in the core.
572 uf_unregister_netdev(priv);
573 priv->totalInterfaceCount = 0;
575 /* Clear the table of registered netdev_priv's */
576 for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
577 Unifi_netdev_instances[priv->instance * CSR_WIFI_NUM_INTERFACES + i] = NULL;
580 unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: uf_free_netdevice\n");
582 * When uf_free_netdevice() returns, the priv is invalid
583 * so we need to remember the instance to clear the global flag later.
585 priv_instance = priv->instance;
587 #ifdef CSR_WIFI_RX_PATH_SPLIT
588 flush_workqueue(priv->rx_workqueue);
589 destroy_workqueue(priv->rx_workqueue);
590 signal_buffer_free(priv,CSR_WIFI_RX_SIGNAL_BUFFER_SIZE);
593 /* Priv is freed as part of the net_device */
594 uf_free_netdevice(priv);
597 * Now clear the flag that says the old instance is in use.
598 * This is used to prevent a new instance being started before old
599 * one has finshed closing down, for example if bounce makes the card
600 * appear to be ejected and re-inserted quickly.
602 In_use[priv_instance] = UNIFI_DEV_NOT_IN_USE;
604 unifi_trace(NULL, UDBG5, "cleanup_unifi_sdio: DONE.\n");
608 } /* cleanup_unifi_sdio() */
612 * ---------------------------------------------------------------------------
613 * unregister_unifi_sdio
615 * Call from SDIO driver when it detects that UniFi has been removed.
618 * bus_id Number of the card that was ejected.
622 * ---------------------------------------------------------------------------
625 unregister_unifi_sdio(int bus_id)
629 u8 reason = CONFIG_IND_EXIT;
631 if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) {
632 unifi_error(NULL, "unregister_unifi_sdio: invalid device %d\n",
637 priv = Unifi_instances[bus_id];
639 unifi_error(priv, "unregister_unifi_sdio: device %d is not registered\n",
645 /* Stop the network traffic before freeing the core. */
646 for(interfaceTag=0;interfaceTag<priv->totalInterfaceCount;interfaceTag++)
648 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
649 if(interfacePriv->netdev_registered)
651 netif_carrier_off(priv->netdev[interfaceTag]);
652 netif_tx_stop_all_queues(priv->netdev[interfaceTag]);
656 #ifdef CSR_NATIVE_LINUX
658 * If the unifi thread was started, signal it to stop. This
659 * should cause any userspace processes with open unifi device to
662 uf_stop_thread(priv, &priv->bh_thread);
664 /* Unregister the interrupt handler */
665 if (csr_sdio_linux_remove_irq(priv->sdio)) {
667 "csr_sdio_linux_remove_irq failed to talk to card.\n");
670 /* Ensure no MLME functions are waiting on a the mlme_event semaphore. */
672 #endif /* CSR_NATIVE_LINUX */
674 ul_log_config_ind(priv, &reason, sizeof(u8));
676 /* Deregister the UDI hook from the core. */
677 unifi_remove_udi_hook(priv->card, logging_handler);
679 uf_put_instance(bus_id);
682 * Wait until the device is cleaned up. i.e., when all userspace
683 * processes have closed any open unifi devices.
685 wait_event(Unifi_cleanup_wq, In_use[bus_id] == UNIFI_DEV_CLEANUP);
686 unifi_trace(NULL, UDBG5, "Received clean up event\n");
688 /* Now we can free the private context and the char device nodes */
689 cleanup_unifi_sdio(priv);
691 } /* unregister_unifi_sdio() */
695 * ---------------------------------------------------------------------------
698 * Find the context structure for a given UniFi device instance.
701 * inst The instance number to look for.
705 * ---------------------------------------------------------------------------
708 uf_find_instance(int inst)
710 if ((inst < 0) || (inst >= MAX_UNIFI_DEVS)) {
713 return Unifi_instances[inst];
714 } /* uf_find_instance() */
718 * ---------------------------------------------------------------------------
721 * Find the device instance for a given context structure.
724 * priv The context structure pointer to look for.
727 * index of instance, -1 otherwise.
728 * ---------------------------------------------------------------------------
731 uf_find_priv(unifi_priv_t *priv)
739 for (inst = 0; inst < MAX_UNIFI_DEVS; inst++) {
740 if (Unifi_instances[inst] == priv) {
746 } /* uf_find_priv() */
749 * ---------------------------------------------------------------------------
750 * uf_find_netdev_priv
752 * Find the device instance for a given netdev context structure.
755 * priv The context structure pointer to look for.
758 * index of instance, -1 otherwise.
759 * ---------------------------------------------------------------------------
762 uf_find_netdev_priv(netInterface_priv_t *priv)
770 for (inst = 0; inst < MAX_UNIFI_DEVS * CSR_WIFI_NUM_INTERFACES; inst++) {
771 if (Unifi_netdev_instances[inst] == priv) {
777 } /* uf_find_netdev_priv() */
780 * ---------------------------------------------------------------------------
783 * Find the context structure for a given UniFi device instance
784 * and increment the reference count.
787 * inst The instance number to look for.
790 * Pointer to the instance or NULL if no instance exists.
791 * ---------------------------------------------------------------------------
794 uf_get_instance(int inst)
798 down(&Unifi_instance_mutex);
800 priv = uf_find_instance(inst);
805 up(&Unifi_instance_mutex);
811 * ---------------------------------------------------------------------------
814 * Decrement the context reference count, freeing resources and
815 * shutting down the driver when the count reaches zero.
818 * inst The instance number to look for.
821 * Pointer to the instance or NULL if no instance exists.
822 * ---------------------------------------------------------------------------
825 uf_put_instance(int inst)
829 down(&Unifi_instance_mutex);
831 priv = uf_find_instance(inst);
834 if (priv->ref_count == 0) {
835 ask_unifi_sdio_cleanup(priv);
839 up(&Unifi_instance_mutex);
844 * ---------------------------------------------------------------------------
847 * Read method for driver node in /proc/driver/unifi0
859 * ---------------------------------------------------------------------------
861 #ifdef CONFIG_PROC_FS
863 uf_read_proc(char *page, char **start, off_t offset, int count,
864 int *eof, void *data)
866 #define UNIFI_DEBUG_TXT_BUFFER 8*1024
868 int actual_amount_to_copy;
870 s32 remain = UNIFI_DEBUG_TXT_BUFFER;
875 * The following complex casting is in place in order to eliminate 64-bit compilation warning
876 * "cast to/from pointer from/to integer of different size"
878 priv = uf_find_instance((int)(long)data);
883 p = kmalloc( UNIFI_DEBUG_TXT_BUFFER, GFP_KERNEL );
887 written = scnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n",
888 CSR_WIFI_VERSION, __DATE__, __TIME__);
889 UNIFI_SNPRINTF_RET(p, remain, written);
890 #ifdef CSR_SME_USERSPACE
891 written = scnprintf(p, remain, "SME: CSR userspace ");
892 UNIFI_SNPRINTF_RET(p, remain, written);
893 #ifdef CSR_SUPPORT_WEXT
894 written = scnprintf(p, remain, "with WEXT support\n");
896 written = scnprintf(p, remain, "\n");
897 #endif /* CSR_SUPPORT_WEXT */
898 UNIFI_SNPRINTF_RET(p, remain, written);
899 #endif /* CSR_SME_USERSPACE */
900 #ifdef CSR_NATIVE_LINUX
901 written = scnprintf(p, remain, "SME: native\n");
902 UNIFI_SNPRINTF_RET(p, remain, written);
905 #ifdef CSR_SUPPORT_SME
906 written = scnprintf(p, remain,
907 "Firmware (ROM) build:%u, Patch:%u\n",
908 priv->card_info.fw_build,
909 priv->sme_versions.firmwarePatch);
910 UNIFI_SNPRINTF_RET(p, remain, written);
912 p += unifi_print_status(priv->card, p, &remain);
914 written = scnprintf(p, remain, "Last dbg str: %s\n",
915 priv->last_debug_string);
916 UNIFI_SNPRINTF_RET(p, remain, written);
918 written = scnprintf(p, remain, "Last dbg16:");
919 UNIFI_SNPRINTF_RET(p, remain, written);
920 for (i = 0; i < 8; i++) {
921 written = scnprintf(p, remain, " %04X",
922 priv->last_debug_word16[i]);
923 UNIFI_SNPRINTF_RET(p, remain, written);
925 written = scnprintf(p, remain, "\n");
926 UNIFI_SNPRINTF_RET(p, remain, written);
927 written = scnprintf(p, remain, " ");
928 UNIFI_SNPRINTF_RET(p, remain, written);
929 for (; i < 16; i++) {
930 written = scnprintf(p, remain, " %04X",
931 priv->last_debug_word16[i]);
932 UNIFI_SNPRINTF_RET(p, remain, written);
934 written = scnprintf(p, remain, "\n");
935 UNIFI_SNPRINTF_RET(p, remain, written);
938 written = UNIFI_DEBUG_TXT_BUFFER - remain;
940 if( offset >= written )
947 if( offset + count > written )
949 actual_amount_to_copy = written - offset;
954 actual_amount_to_copy = count;
957 memcpy( page, &(orig_p[offset]), actual_amount_to_copy );
961 return( actual_amount_to_copy );
962 } /* uf_read_proc() */
969 uf_lx_suspend(CsrSdioFunction *sdio_ctx)
971 unifi_priv_t *priv = sdio_ctx->driverData;
974 CsrSdioSuspendAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS);
978 uf_lx_resume(CsrSdioFunction *sdio_ctx)
980 unifi_priv_t *priv = sdio_ctx->driverData;
983 CsrSdioResumeAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS);
986 static int active_slot = MAX_UNIFI_DEVS;
987 static struct device *os_devices[MAX_UNIFI_DEVS];
990 uf_add_os_device(int bus_id, struct device *os_device)
992 if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) {
993 unifi_error(NULL, "uf_add_os_device: invalid device %d\n",
998 active_slot = bus_id;
999 os_devices[bus_id] = os_device;
1000 } /* uf_add_os_device() */
1003 uf_remove_os_device(int bus_id)
1005 if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) {
1006 unifi_error(NULL, "uf_remove_os_device: invalid device %d\n",
1011 active_slot = bus_id;
1012 os_devices[bus_id] = NULL;
1013 } /* uf_remove_os_device() */
1016 uf_sdio_inserted(CsrSdioFunction *sdio_ctx)
1020 unifi_trace(NULL, UDBG5, "uf_sdio_inserted(0x%p), slot_id=%d, dev=%p\n",
1021 sdio_ctx, active_slot, os_devices[active_slot]);
1023 priv = register_unifi_sdio(sdio_ctx, active_slot, os_devices[active_slot]);
1025 CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_FAILURE);
1029 sdio_ctx->driverData = priv;
1031 CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS);
1032 } /* uf_sdio_inserted() */
1036 uf_sdio_removed(CsrSdioFunction *sdio_ctx)
1038 unregister_unifi_sdio(active_slot);
1039 CsrSdioRemovedAcknowledge(sdio_ctx);
1040 } /* uf_sdio_removed() */
1044 uf_sdio_dsr_handler(CsrSdioFunction *sdio_ctx)
1046 unifi_priv_t *priv = sdio_ctx->driverData;
1048 unifi_sdio_interrupt_handler(priv->card);
1049 } /* uf_sdio_dsr_handler() */
1052 * ---------------------------------------------------------------------------
1053 * uf_sdio_int_handler
1055 * Interrupt callback function for SDIO interrupts.
1056 * This is called in kernel context (i.e. not interrupt context).
1057 * We retrieve the unifi context pointer and call the main UniFi
1058 * interrupt handler.
1061 * fdev SDIO context pointer
1065 * ---------------------------------------------------------------------------
1067 static CsrSdioInterruptDsrCallback
1068 uf_sdio_int_handler(CsrSdioFunction *sdio_ctx)
1070 return uf_sdio_dsr_handler;
1071 } /* uf_sdio_int_handler() */
1076 static CsrSdioFunctionId unifi_ids[] =
1079 .manfId = SDIO_MANF_ID_CSR,
1080 .cardId = SDIO_CARD_ID_UNIFI_3,
1081 .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_3,
1082 .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE,
1085 .manfId = SDIO_MANF_ID_CSR,
1086 .cardId = SDIO_CARD_ID_UNIFI_4,
1087 .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_4,
1088 .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE,
1094 * Structure to register with the glue layer.
1096 static CsrSdioFunctionDriver unifi_sdioFunction_drv =
1098 .inserted = uf_sdio_inserted,
1099 .removed = uf_sdio_removed,
1100 .intr = uf_sdio_int_handler,
1101 .suspend = uf_lx_suspend,
1102 .resume = uf_lx_resume,
1105 .idsCount = sizeof(unifi_ids) / sizeof(unifi_ids[0])
1110 * ---------------------------------------------------------------------------
1114 * These functions are called from the main module load and unload
1115 * functions. They perform the appropriate operations for the monolithic
1123 * ---------------------------------------------------------------------------
1128 CsrResult csrResult;
1130 csrResult = CsrSdioFunctionDriverRegister(&unifi_sdioFunction_drv);
1131 if (csrResult != CSR_RESULT_SUCCESS) {
1132 unifi_error(NULL, "Failed to register UniFi SDIO driver: csrResult=%d\n", csrResult);
1137 } /* uf_sdio_load() */
1142 uf_sdio_unload(void)
1144 CsrSdioFunctionDriverUnregister(&unifi_sdioFunction_drv);
1145 } /* uf_sdio_unload() */