ASoC: wm2000: Correct register size
[linux-2.6/btrfs-unstable.git] / drivers / staging / csr / drv.c
blobb2c27f4f03d4dba1e03d4ce8d38797a160c99b6b
1 /*
2 * ---------------------------------------------------------------------------
3 * FILE: drv.c
5 * PURPOSE:
6 * Conventional device interface for debugging/monitoring of the
7 * driver and h/w using unicli. This interface is also being used
8 * by the SME linux implementation and the helper apps.
10 * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
12 * Refer to LICENSE.txt included with this source code for details on
13 * the license terms.
15 * ---------------------------------------------------------------------------
21 * Porting Notes:
22 * Part of this file contains an example for how to glue the OS layer
23 * with the HIP core lib, the SDIO glue layer, and the SME.
25 * When the unifi_sdio.ko modules loads, the linux kernel calls unifi_load().
26 * unifi_load() calls uf_sdio_load() which is exported by the SDIO glue
27 * layer. uf_sdio_load() registers this driver with the underlying SDIO driver.
28 * When a card is detected, the SDIO glue layer calls register_unifi_sdio()
29 * to pass the SDIO function context and ask the OS layer to initialise
30 * the card. register_unifi_sdio() allocates all the private data of the OS
31 * layer and calls uf_run_unifihelper() to start the SME. The SME calls
32 * unifi_sys_wifi_on_req() which uses the HIP core lib to initialise the card.
35 #include <linux/init.h>
36 #include <linux/slab.h>
37 #include <linux/poll.h>
38 #include <asm/uaccess.h>
39 #include <linux/jiffies.h>
41 #include "csr_wifi_hip_unifiversion.h"
42 #include "unifi_priv.h"
43 #include "csr_wifi_hip_conversions.h"
44 #include "unifi_native.h"
46 /* Module parameter variables */
47 int buswidth = 0; /* 0 means use default, values 1,4 */
48 int sdio_clock = 50000; /* kHz */
49 int unifi_debug = 0;
50 /* fw_init prevents f/w initialisation on error. */
51 int fw_init[MAX_UNIFI_DEVS] = {-1, -1};
52 int use_5g = 0;
53 int led_mask = 0; /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */
54 int disable_hw_reset = 0;
55 int disable_power_control = 0;
56 int enable_wol = UNIFI_WOL_OFF; /* 0 for none, 1 for SDIO IRQ, 2 for PIO */
57 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
58 int tl_80211d = (int)CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB;
59 #endif
60 int sdio_block_size = -1; /* Override SDIO block size */
61 int sdio_byte_mode = 0; /* 0 for block mode + padding, 1 for byte mode */
62 int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS;
63 int run_bh_once = -1; /* Set for scheduled interrupt mode, -1 = default */
64 int bh_priority = -1;
65 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
66 #define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA (1 << 1)
67 #define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP (1 << 2)
68 int log_hip_signals = 0;
69 #endif
71 MODULE_DESCRIPTION("CSR UniFi (SDIO)");
73 module_param(buswidth, int, S_IRUGO|S_IWUSR);
74 module_param(sdio_clock, int, S_IRUGO|S_IWUSR);
75 module_param(unifi_debug, int, S_IRUGO|S_IWUSR);
76 module_param_array(fw_init, int, NULL, S_IRUGO|S_IWUSR);
77 module_param(use_5g, int, S_IRUGO|S_IWUSR);
78 module_param(led_mask, int, S_IRUGO|S_IWUSR);
79 module_param(disable_hw_reset, int, S_IRUGO|S_IWUSR);
80 module_param(disable_power_control, int, S_IRUGO|S_IWUSR);
81 module_param(enable_wol, int, S_IRUGO|S_IWUSR);
82 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
83 module_param(tl_80211d, int, S_IRUGO|S_IWUSR);
84 #endif
85 module_param(sdio_block_size, int, S_IRUGO|S_IWUSR);
86 module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR);
87 module_param(coredump_max, int, S_IRUGO|S_IWUSR);
88 module_param(run_bh_once, int, S_IRUGO|S_IWUSR);
89 module_param(bh_priority, int, S_IRUGO|S_IWUSR);
90 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
91 module_param(log_hip_signals, int, S_IRUGO|S_IWUSR);
92 #endif
94 MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode");
95 MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)");
96 MODULE_PARM_DESC(unifi_debug, "Diagnostic reporting level");
97 MODULE_PARM_DESC(fw_init, "Set to 0 to prevent f/w initialization on error");
98 MODULE_PARM_DESC(use_5g, "Use the 5G (802.11a) radio band");
99 MODULE_PARM_DESC(led_mask, "LED mask flags");
100 MODULE_PARM_DESC(disable_hw_reset, "Set to 1 to disable hardware reset");
101 MODULE_PARM_DESC(disable_power_control, "Set to 1 to disable SDIO power control");
102 MODULE_PARM_DESC(enable_wol, "Enable wake-on-wlan function 0=off, 1=SDIO, 2=PIO");
103 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
104 MODULE_PARM_DESC(tl_80211d, "802.11d Trust Level (1-6, default = 5)");
105 #endif
106 MODULE_PARM_DESC(sdio_block_size, "Set to override SDIO block size");
107 MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO");
108 MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate");
109 MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts");
110 MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority");
111 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
112 MODULE_PARM_DESC(log_hip_signals, "Set to 1 to enable HIP signal offline logging");
113 #endif
116 /* Callback for event logging to UDI clients */
117 static void udi_log_event(ul_client_t *client,
118 const u8 *signal, int signal_len,
119 const bulk_data_param_t *bulkdata,
120 int dir);
122 static void udi_set_log_filter(ul_client_t *pcli,
123 unifiio_filter_t *udi_filter);
126 /* Mutex to protect access to priv->sme_cli */
127 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
128 DEFINE_SEMAPHORE(udi_mutex);
129 #else
130 DECLARE_MUTEX(udi_mutex);
131 #endif
133 s32 CsrHipResultToStatus(CsrResult csrResult)
135 s32 r = -EIO;
137 switch (csrResult)
139 case CSR_RESULT_SUCCESS:
140 r = 0;
141 break;
142 case CSR_WIFI_HIP_RESULT_RANGE:
143 r = -ERANGE;
144 break;
145 case CSR_WIFI_HIP_RESULT_NO_DEVICE:
146 r = -ENODEV;
147 break;
148 case CSR_WIFI_HIP_RESULT_INVALID_VALUE:
149 r = -EINVAL;
150 break;
151 case CSR_WIFI_HIP_RESULT_NOT_FOUND:
152 r = -ENOENT;
153 break;
154 case CSR_WIFI_HIP_RESULT_NO_SPACE:
155 r = -ENOSPC;
156 break;
157 case CSR_WIFI_HIP_RESULT_NO_MEMORY:
158 r = -ENOMEM;
159 break;
160 case CSR_RESULT_FAILURE:
161 r = -EIO;
162 break;
163 default:
164 /*unifi_warning(card->ospriv, "CsrHipResultToStatus: Unrecognised csrResult error code: %d\n", csrResult);*/
165 r = -EIO;
167 return r;
171 static const char*
172 trace_putest_cmdid(unifi_putest_command_t putest_cmd)
174 switch (putest_cmd)
176 case UNIFI_PUTEST_START:
177 return "START";
178 case UNIFI_PUTEST_STOP:
179 return "STOP";
180 case UNIFI_PUTEST_SET_SDIO_CLOCK:
181 return "SET CLOCK";
182 case UNIFI_PUTEST_CMD52_READ:
183 return "CMD52R";
184 case UNIFI_PUTEST_CMD52_BLOCK_READ:
185 return "CMD52BR";
186 case UNIFI_PUTEST_CMD52_WRITE:
187 return "CMD52W";
188 case UNIFI_PUTEST_DL_FW:
189 return "D/L FW";
190 case UNIFI_PUTEST_DL_FW_BUFF:
191 return "D/L FW BUFFER";
192 case UNIFI_PUTEST_COREDUMP_PREPARE:
193 return "PREPARE COREDUMP";
194 case UNIFI_PUTEST_GP_READ16:
195 return "GP16R";
196 case UNIFI_PUTEST_GP_WRITE16:
197 return "GP16W";
198 default:
199 return "ERROR: unrecognised command";
203 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
204 int uf_register_hip_offline_debug(unifi_priv_t *priv)
206 ul_client_t *udi_cli;
207 int i;
209 udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event);
210 if (udi_cli == NULL) {
211 /* Too many clients already using this device */
212 unifi_error(priv, "Too many UDI clients already open\n");
213 return -ENOSPC;
215 unifi_trace(priv, UDBG1, "Offline HIP client is registered\n");
217 down(&priv->udi_logging_mutex);
218 udi_cli->event_hook = udi_log_event;
219 unifi_set_udi_hook(priv->card, logging_handler);
220 /* Log all signals by default */
221 for (i = 0; i < SIG_FILTER_SIZE; i++) {
222 udi_cli->signal_filter[i] = 0xFFFF;
224 priv->logging_client = udi_cli;
225 up(&priv->udi_logging_mutex);
227 return 0;
230 int uf_unregister_hip_offline_debug(unifi_priv_t *priv)
232 ul_client_t *udi_cli = priv->logging_client;
233 if (udi_cli == NULL)
235 unifi_error(priv, "Unknown HIP client unregister request\n");
236 return -ERANGE;
239 unifi_trace(priv, UDBG1, "Offline HIP client is unregistered\n");
241 down(&priv->udi_logging_mutex);
242 priv->logging_client = NULL;
243 udi_cli->event_hook = NULL;
244 up(&priv->udi_logging_mutex);
246 ul_deregister_client(udi_cli);
248 return 0;
250 #endif
254 * ---------------------------------------------------------------------------
255 * unifi_open
256 * unifi_release
258 * Open and release entry points for the UniFi debug driver.
260 * Arguments:
261 * Normal linux driver args.
263 * Returns:
264 * Linux error code.
265 * ---------------------------------------------------------------------------
267 static int
268 unifi_open(struct inode *inode, struct file *file)
270 int devno;
271 unifi_priv_t *priv;
272 ul_client_t *udi_cli;
274 func_enter();
276 devno = MINOR(inode->i_rdev) >> 1;
279 * Increase the ref_count for the char device clients.
280 * Make sure you call uf_put_instance() to decreace it if
281 * unifi_open returns an error.
283 priv = uf_get_instance(devno);
284 if (priv == NULL) {
285 unifi_error(NULL, "unifi_open: No device present\n");
286 func_exit();
287 return -ENODEV;
290 /* Register this instance in the client's list. */
291 /* The minor number determines the nature of the client (Unicli or SME). */
292 if (MINOR(inode->i_rdev) & 0x1) {
293 udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event);
294 if (udi_cli == NULL) {
295 /* Too many clients already using this device */
296 unifi_error(priv, "Too many clients already open\n");
297 uf_put_instance(devno);
298 func_exit();
299 return -ENOSPC;
301 unifi_trace(priv, UDBG1, "Client is registered to /dev/unifiudi%d\n", devno);
302 } else {
304 * Even-numbered device nodes are the control application.
305 * This is the userspace helper containing SME or
306 * unifi_manager.
309 down(&udi_mutex);
311 #ifdef CSR_SME_USERSPACE
312 /* Check if a config client is already attached */
313 if (priv->sme_cli) {
314 up(&udi_mutex);
315 uf_put_instance(devno);
317 unifi_info(priv, "There is already a configuration client using the character device\n");
318 func_exit();
319 return -EBUSY;
321 #endif /* CSR_SME_USERSPACE */
323 #ifdef CSR_SUPPORT_SME
324 udi_cli = ul_register_client(priv,
325 CLI_USING_WIRE_FORMAT | CLI_SME_USERSPACE,
326 sme_log_event);
327 #else
328 /* Config client for native driver */
329 udi_cli = ul_register_client(priv,
331 sme_native_log_event);
332 #endif
333 if (udi_cli == NULL) {
334 /* Too many clients already using this device */
335 up(&udi_mutex);
336 uf_put_instance(devno);
338 unifi_error(priv, "Too many clients already open\n");
339 func_exit();
340 return -ENOSPC;
344 * Fill-in the pointer to the configuration client.
345 * This is the SME userspace helper or unifi_manager.
346 * Not used in the SME embedded version.
348 unifi_trace(priv, UDBG1, "SME client (id:%d s:0x%X) is registered\n",
349 udi_cli->client_id, udi_cli->sender_id);
350 /* Store the SME UniFi Linux Client */
351 if (priv->sme_cli == NULL) {
352 priv->sme_cli = udi_cli;
355 up(&udi_mutex);
360 * Store the pointer to the client.
361 * All char driver's entry points will pass this pointer.
363 file->private_data = udi_cli;
365 func_exit();
366 return 0;
367 } /* unifi_open() */
370 static int
371 unifi_release(struct inode *inode, struct file *filp)
373 ul_client_t *udi_cli = (void*)filp->private_data;
374 int devno;
375 unifi_priv_t *priv;
377 func_enter();
379 priv = uf_find_instance(udi_cli->instance);
380 if (!priv) {
381 unifi_error(priv, "unifi_close: instance for device not found\n");
382 return -ENODEV;
385 devno = MINOR(inode->i_rdev) >> 1;
387 /* Even device nodes are the config client (i.e. SME or unifi_manager) */
388 if ((MINOR(inode->i_rdev) & 0x1) == 0) {
390 if (priv->sme_cli != udi_cli) {
391 unifi_notice(priv, "Surprise closing config device: not the sme client\n");
393 unifi_notice(priv, "SME client close (unifi%d)\n", devno);
396 * Clear sme_cli before calling unifi_sys_... so it doesn't try to
397 * queue a reply to the (now gone) SME.
399 down(&udi_mutex);
400 priv->sme_cli = NULL;
401 up(&udi_mutex);
403 #ifdef CSR_SME_USERSPACE
404 /* Power-down when config client closes */
406 CsrWifiRouterCtrlWifiOffReq req = {{CSR_WIFI_ROUTER_CTRL_HIP_REQ, 0, 0, 0, NULL}};
407 CsrWifiRouterCtrlWifiOffReqHandler(priv, &req.common);
410 uf_sme_deinit(priv);
412 /* It is possible that a blocking SME request was made from another process
413 * which did not get read by the SME before the WifiOffReq.
414 * So check for a pending request which will go unanswered and cancel
415 * the wait for event. As only one blocking request can be in progress at
416 * a time, up to one event should be completed.
418 uf_sme_cancel_request(priv, 0);
420 #endif /* CSR_SME_USERSPACE */
421 } else {
423 unifi_trace(priv, UDBG2, "UDI client close (unifiudi%d)\n", devno);
425 /* If the pointer matches the logging client, stop logging. */
426 down(&priv->udi_logging_mutex);
427 if (udi_cli == priv->logging_client) {
428 priv->logging_client = NULL;
430 up(&priv->udi_logging_mutex);
432 if (udi_cli == priv->amp_client) {
433 priv->amp_client = NULL;
437 /* Deregister this instance from the client's list. */
438 ul_deregister_client(udi_cli);
440 uf_put_instance(devno);
442 return 0;
443 } /* unifi_release() */
448 * ---------------------------------------------------------------------------
449 * unifi_read
451 * The read() driver entry point.
453 * Arguments:
454 * filp The file descriptor returned by unifi_open()
455 * p The user space buffer to copy the read data
456 * len The size of the p buffer
457 * poff
459 * Returns:
460 * number of bytes read or an error code on failure
461 * ---------------------------------------------------------------------------
463 static ssize_t
464 unifi_read(struct file *filp, char *p, size_t len, loff_t *poff)
466 ul_client_t *pcli = (void*)filp->private_data;
467 unifi_priv_t *priv;
468 udi_log_t *logptr = NULL;
469 udi_msg_t *msgptr;
470 struct list_head *l;
471 int msglen;
473 func_enter();
475 priv = uf_find_instance(pcli->instance);
476 if (!priv) {
477 unifi_error(priv, "invalid priv\n");
478 return -ENODEV;
481 if (!pcli->udi_enabled) {
482 unifi_error(priv, "unifi_read: unknown client.");
483 return -EINVAL;
486 if (list_empty(&pcli->udi_log)) {
487 if (filp->f_flags & O_NONBLOCK) {
488 /* Non-blocking - just return if the udi_log is empty */
489 return 0;
490 } else {
491 /* Blocking - wait on the UDI wait queue */
492 if (wait_event_interruptible(pcli->udi_wq,
493 !list_empty(&pcli->udi_log)))
495 unifi_error(priv, "unifi_read: wait_event_interruptible failed.");
496 return -ERESTARTSYS;
501 /* Read entry from list head and remove it from the list */
502 if (down_interruptible(&pcli->udi_sem)) {
503 return -ERESTARTSYS;
505 l = pcli->udi_log.next;
506 list_del(l);
507 up(&pcli->udi_sem);
509 /* Get a pointer to whole struct */
510 logptr = list_entry(l, udi_log_t, q);
511 if (logptr == NULL) {
512 unifi_error(priv, "unifi_read: failed to get event.\n");
513 return -EINVAL;
516 /* Get the real message */
517 msgptr = &logptr->msg;
518 msglen = msgptr->length;
519 if (msglen > len) {
520 printk(KERN_WARNING "truncated read to %d actual msg len is %lu\n", msglen, (long unsigned int)len);
521 msglen = len;
524 /* and pass it to the client (SME or Unicli). */
525 if (copy_to_user(p, msgptr, msglen))
527 printk(KERN_ERR "Failed to copy UDI log to user\n");
528 kfree(logptr);
529 return -EFAULT;
532 /* It is our resposibility to free the message buffer. */
533 kfree(logptr);
535 func_exit_r(msglen);
536 return msglen;
538 } /* unifi_read() */
543 * ---------------------------------------------------------------------------
544 * udi_send_signal_unpacked
546 * Sends an unpacked signal to UniFi.
548 * Arguments:
549 * priv Pointer to private context struct
550 * data Pointer to request structure and data to send
551 * data_len Length of data in data pointer.
553 * Returns:
554 * Number of bytes written, error otherwise.
556 * Notes:
557 * All clients that use this function to send a signal to the unifi
558 * must use the host formatted structures.
559 * ---------------------------------------------------------------------------
561 static int
562 udi_send_signal_unpacked(unifi_priv_t *priv, unsigned char* data, uint data_len)
564 CSR_SIGNAL *sigptr = (CSR_SIGNAL*)data;
565 CSR_DATAREF *datarefptr;
566 bulk_data_param_t bulk_data;
567 uint signal_size, i;
568 uint bulk_data_offset = 0;
569 int bytecount, r;
570 CsrResult csrResult;
572 /* Number of bytes in the signal */
573 signal_size = SigGetSize(sigptr);
574 if (!signal_size || (signal_size > data_len)) {
575 unifi_error(priv, "unifi_sme_mlme_req - Invalid signal 0x%x size should be %d bytes\n",
576 sigptr->SignalPrimitiveHeader.SignalId,
577 signal_size);
578 return -EINVAL;
580 bytecount = signal_size;
582 /* Get a pointer to the information of the first data reference */
583 datarefptr = (CSR_DATAREF*)&sigptr->u;
585 /* Initialize the offset in the data buffer, bulk data is right after the signal. */
586 bulk_data_offset = signal_size;
588 /* store the references and the size of the bulk data to the bulkdata structure */
589 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
590 /* the length of the bulk data is in the signal */
591 if ((datarefptr+i)->DataLength) {
592 void *dest;
594 csrResult = unifi_net_data_malloc(priv, &bulk_data.d[i], (datarefptr+i)->DataLength);
595 if (csrResult != CSR_RESULT_SUCCESS) {
596 unifi_error(priv, "udi_send_signal_unpacked: failed to allocate request_data.\n");
597 return -EIO;
600 dest = (void*)bulk_data.d[i].os_data_ptr;
601 memcpy(dest, data + bulk_data_offset, bulk_data.d[i].data_length);
602 } else {
603 bulk_data.d[i].data_length = 0;
606 bytecount += bulk_data.d[i].data_length;
607 /* advance the offset, to point the next bulk data */
608 bulk_data_offset += bulk_data.d[i].data_length;
612 unifi_trace(priv, UDBG3, "SME Send: signal 0x%.4X\n", sigptr->SignalPrimitiveHeader.SignalId);
614 /* Send the signal. */
615 r = ul_send_signal_unpacked(priv, sigptr, &bulk_data);
616 if (r < 0) {
617 unifi_error(priv, "udi_send_signal_unpacked: send failed (%d)\n", r);
618 for(i=0;i<UNIFI_MAX_DATA_REFERENCES;i++) {
619 if(bulk_data.d[i].data_length != 0) {
620 unifi_net_data_free(priv, &bulk_data.d[i]);
623 func_exit();
624 return -EIO;
627 return bytecount;
628 } /* udi_send_signal_unpacked() */
633 * ---------------------------------------------------------------------------
634 * udi_send_signal_raw
636 * Sends a packed signal to UniFi.
638 * Arguments:
639 * priv Pointer to private context struct
640 * buf Pointer to request structure and data to send
641 * buflen Length of data in data pointer.
643 * Returns:
644 * Number of bytes written, error otherwise.
646 * Notes:
647 * All clients that use this function to send a signal to the unifi
648 * must use the wire formatted structures.
649 * ---------------------------------------------------------------------------
651 static int
652 udi_send_signal_raw(unifi_priv_t *priv, unsigned char *buf, int buflen)
654 int signal_size;
655 int sig_id;
656 bulk_data_param_t data_ptrs;
657 int i, r;
658 unsigned int num_data_refs;
659 int bytecount;
660 CsrResult csrResult;
662 func_enter();
665 * The signal is the first thing in buf, the signal id is the
666 * first 16 bits of the signal.
668 /* Number of bytes in the signal */
669 sig_id = GET_SIGNAL_ID(buf);
670 signal_size = buflen;
671 signal_size -= GET_PACKED_DATAREF_LEN(buf, 0);
672 signal_size -= GET_PACKED_DATAREF_LEN(buf, 1);
673 if ((signal_size <= 0) || (signal_size > buflen)) {
674 unifi_error(priv, "udi_send_signal_raw - Couldn't find length of signal 0x%x\n",
675 sig_id);
676 func_exit();
677 return -EINVAL;
679 unifi_trace(priv, UDBG2, "udi_send_signal_raw: signal 0x%.4X len:%d\n",
680 sig_id, signal_size);
681 /* Zero the data ref arrays */
682 memset(&data_ptrs, 0, sizeof(data_ptrs));
685 * Find the number of associated bulk data packets. Scan through
686 * the data refs to check that we have enough data and pick out
687 * pointers to appended bulk data.
689 num_data_refs = 0;
690 bytecount = signal_size;
692 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i)
694 unsigned int len = GET_PACKED_DATAREF_LEN(buf, i);
695 unifi_trace(priv, UDBG3, "udi_send_signal_raw: data_ref length = %d\n", len);
697 if (len != 0) {
698 void *dest;
700 csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[i], len);
701 if (csrResult != CSR_RESULT_SUCCESS) {
702 unifi_error(priv, "udi_send_signal_raw: failed to allocate request_data.\n");
703 return -EIO;
706 dest = (void*)data_ptrs.d[i].os_data_ptr;
707 memcpy(dest, buf + bytecount, len);
709 bytecount += len;
710 num_data_refs++;
712 data_ptrs.d[i].data_length = len;
715 unifi_trace(priv, UDBG3, "Queueing signal 0x%.4X from UDI with %u data refs\n",
716 sig_id,
717 num_data_refs);
719 if (bytecount > buflen) {
720 unifi_error(priv, "udi_send_signal_raw: Not enough data (%d instead of %d)\n", buflen, bytecount);
721 func_exit();
722 return -EINVAL;
725 /* Send the signal calling the function that uses the wire-formatted signals. */
726 r = ul_send_signal_raw(priv, buf, signal_size, &data_ptrs);
727 if (r < 0) {
728 unifi_error(priv, "udi_send_signal_raw: send failed (%d)\n", r);
729 func_exit();
730 return -EIO;
733 #ifdef CSR_NATIVE_LINUX
734 if (sig_id == CSR_MLME_POWERMGT_REQUEST_ID) {
735 int power_mode = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((buf +
736 SIZEOF_SIGNAL_HEADER + (UNIFI_MAX_DATA_REFERENCES*SIZEOF_DATAREF)));
737 #ifdef CSR_SUPPORT_WEXT
738 /* Overide the wext power mode to the new value */
739 priv->wext_conf.power_mode = power_mode;
740 #endif
741 /* Configure deep sleep signaling */
742 if (power_mode || (priv->interfacePriv[0]->connected == UnifiNotConnected)) {
743 csrResult = unifi_configure_low_power_mode(priv->card,
744 UNIFI_LOW_POWER_ENABLED,
745 UNIFI_PERIODIC_WAKE_HOST_DISABLED);
746 } else {
747 csrResult = unifi_configure_low_power_mode(priv->card,
748 UNIFI_LOW_POWER_DISABLED,
749 UNIFI_PERIODIC_WAKE_HOST_DISABLED);
752 #endif
754 func_exit_r(bytecount);
756 return bytecount;
757 } /* udi_send_signal_raw */
760 * ---------------------------------------------------------------------------
761 * unifi_write
763 * The write() driver entry point.
764 * A UniFi Debug Interface client such as unicli can write a signal
765 * plus bulk data to the driver for sending to the UniFi chip.
767 * Only one signal may be sent per write operation.
769 * Arguments:
770 * filp The file descriptor returned by unifi_open()
771 * p The user space buffer to get the data from
772 * len The size of the p buffer
773 * poff
775 * Returns:
776 * number of bytes written or an error code on failure
777 * ---------------------------------------------------------------------------
779 static ssize_t
780 unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff)
782 ul_client_t *pcli = (ul_client_t*)filp->private_data;
783 unifi_priv_t *priv;
784 unsigned char *buf;
785 unsigned char *bufptr;
786 int remaining;
787 int bytes_written;
788 int r;
789 bulk_data_param_t bulkdata;
790 CsrResult csrResult;
792 func_enter();
794 priv = uf_find_instance(pcli->instance);
795 if (!priv) {
796 unifi_error(priv, "invalid priv\n");
797 return -ENODEV;
800 unifi_trace(priv, UDBG5, "unifi_write: len = %d\n", len);
802 if (!pcli->udi_enabled) {
803 unifi_error(priv, "udi disabled\n");
804 return -EINVAL;
808 * AMP client sends only one signal at a time, so we can use
809 * unifi_net_data_malloc to save the extra copy.
811 if (pcli == priv->amp_client) {
812 int signal_size;
813 int sig_id;
814 unsigned char *signal_buf;
815 char *user_data_buf;
817 csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], len);
818 if (csrResult != CSR_RESULT_SUCCESS) {
819 unifi_error(priv, "unifi_write: failed to allocate request_data.\n");
820 func_exit();
821 return -ENOMEM;
824 user_data_buf = (char*)bulkdata.d[0].os_data_ptr;
826 /* Get the data from the AMP client. */
827 if (copy_from_user((void*)user_data_buf, p, len)) {
828 unifi_error(priv, "unifi_write: copy from user failed\n");
829 unifi_net_data_free(priv, &bulkdata.d[0]);
830 func_exit();
831 return -EFAULT;
834 bulkdata.d[1].os_data_ptr = NULL;
835 bulkdata.d[1].data_length = 0;
837 /* Number of bytes in the signal */
838 sig_id = GET_SIGNAL_ID(bulkdata.d[0].os_data_ptr);
839 signal_size = len;
840 signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 0);
841 signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 1);
842 if ((signal_size <= 0) || (signal_size > len)) {
843 unifi_error(priv, "unifi_write - Couldn't find length of signal 0x%x\n",
844 sig_id);
845 unifi_net_data_free(priv, &bulkdata.d[0]);
846 func_exit();
847 return -EINVAL;
850 unifi_trace(priv, UDBG2, "unifi_write: signal 0x%.4X len:%d\n",
851 sig_id, signal_size);
853 /* Allocate a buffer for the signal */
854 signal_buf = kmalloc(signal_size, GFP_KERNEL);
855 if (!signal_buf) {
856 unifi_net_data_free(priv, &bulkdata.d[0]);
857 func_exit();
858 return -ENOMEM;
861 /* Get the signal from the os_data_ptr */
862 memcpy(signal_buf, bulkdata.d[0].os_data_ptr, signal_size);
863 signal_buf[5] = (pcli->sender_id >> 8) & 0xff;
865 if (signal_size < len) {
866 /* Remove the signal from the os_data_ptr */
867 bulkdata.d[0].data_length -= signal_size;
868 bulkdata.d[0].os_data_ptr += signal_size;
869 } else {
870 bulkdata.d[0].data_length = 0;
871 bulkdata.d[0].os_data_ptr = NULL;
874 /* Send the signal calling the function that uses the wire-formatted signals. */
875 r = ul_send_signal_raw(priv, signal_buf, signal_size, &bulkdata);
876 if (r < 0) {
877 unifi_error(priv, "unifi_write: send failed (%d)\n", r);
878 if (bulkdata.d[0].os_data_ptr != NULL) {
879 unifi_net_data_free(priv, &bulkdata.d[0]);
883 /* Free the signal buffer and return */
884 kfree(signal_buf);
885 return len;
888 buf = kmalloc(len, GFP_KERNEL);
889 if (!buf) {
890 return -ENOMEM;
893 /* Get the data from the client (SME or Unicli). */
894 if (copy_from_user((void*)buf, p, len)) {
895 unifi_error(priv, "copy from user failed\n");
896 kfree(buf);
897 return -EFAULT;
901 * In SME userspace build read() contains a SYS or MGT message.
902 * Note that even though the SME sends one signal at a time, we can not
903 * use unifi_net_data_malloc because in the early stages, before having
904 * initialised the core, it will fail since the I/O block size is unknown.
906 #ifdef CSR_SME_USERSPACE
907 if (pcli->configuration & CLI_SME_USERSPACE) {
908 CsrWifiRouterTransportRecv(priv, buf, len);
909 kfree(buf);
910 return len;
912 #endif
914 /* ul_send_signal_raw will do a sanity check of len against signal content */
917 * udi_send_signal_raw() and udi_send_signal_unpacked() return the number of bytes consumed.
918 * A write call can pass multiple signal concatenated together.
920 bytes_written = 0;
921 remaining = len;
922 bufptr = buf;
923 while (remaining > 0)
925 int r;
928 * Set the SenderProcessId.
929 * The SignalPrimitiveHeader is the first 3 16-bit words of the signal,
930 * the SenderProcessId is bytes 4,5.
931 * The MSB of the sender ID needs to be set to the client ID.
932 * The LSB is controlled by the SME.
934 bufptr[5] = (pcli->sender_id >> 8) & 0xff;
936 /* use the appropriate interface, depending on the clients' configuration */
937 if (pcli->configuration & CLI_USING_WIRE_FORMAT) {
938 unifi_trace(priv, UDBG1, "unifi_write: call udi_send_signal().\n");
939 r = udi_send_signal_raw(priv, bufptr, remaining);
940 } else {
941 r = udi_send_signal_unpacked(priv, bufptr, remaining);
943 if (r < 0) {
944 /* Set the return value to the error code */
945 unifi_error(priv, "unifi_write: (udi or sme)_send_signal() returns %d\n", r);
946 bytes_written = r;
947 break;
949 bufptr += r;
950 remaining -= r;
951 bytes_written += r;
954 kfree(buf);
956 func_exit_r(bytes_written);
958 return bytes_written;
959 } /* unifi_write() */
962 static const char* build_type_to_string(unsigned char build_type)
964 switch (build_type)
966 case UNIFI_BUILD_NME: return "NME";
967 case UNIFI_BUILD_WEXT: return "WEXT";
968 case UNIFI_BUILD_AP: return "AP";
970 return "unknown";
975 * ----------------------------------------------------------------
976 * unifi_ioctl
978 * Ioctl handler for unifi driver.
980 * Arguments:
981 * inodep Pointer to inode structure.
982 * filp Pointer to file structure.
983 * cmd Ioctl cmd passed by user.
984 * arg Ioctl arg passed by user.
986 * Returns:
987 * 0 on success, -ve error code on error.
988 * ----------------------------------------------------------------
990 static long
991 unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
993 ul_client_t *pcli = (ul_client_t*)filp->private_data;
994 unifi_priv_t *priv;
995 struct net_device *dev;
996 int r = 0;
997 int int_param, i;
998 u8* buf;
999 CsrResult csrResult;
1000 #if (defined CSR_SUPPORT_SME)
1001 unifi_cfg_command_t cfg_cmd;
1002 #if (defined CSR_SUPPORT_WEXT)
1003 CsrWifiSmeCoexConfig coex_config;
1004 unsigned char uchar_param;
1005 unsigned char varbind[MAX_VARBIND_LENGTH];
1006 int vblen;
1007 #endif
1008 #endif
1009 unifi_putest_command_t putest_cmd;
1011 priv = uf_find_instance(pcli->instance);
1012 if (!priv) {
1013 unifi_error(priv, "ioctl error: unknown instance=%d\n", pcli->instance);
1014 r = -ENODEV;
1015 goto out;
1017 unifi_trace(priv, UDBG5, "unifi_ioctl: cmd=0x%X, arg=0x%lX\n", cmd, arg);
1019 switch (cmd) {
1021 case UNIFI_GET_UDI_ENABLE:
1022 unifi_trace(priv, UDBG4, "UniFi Get UDI Enable\n");
1024 down(&priv->udi_logging_mutex);
1025 int_param = (priv->logging_client == NULL) ? 0 : 1;
1026 up(&priv->udi_logging_mutex);
1028 if (put_user(int_param, (int*)arg))
1030 unifi_error(priv, "UNIFI_GET_UDI_ENABLE: Failed to copy to user\n");
1031 r = -EFAULT;
1032 goto out;
1034 break;
1036 case UNIFI_SET_UDI_ENABLE:
1037 unifi_trace(priv, UDBG4, "UniFi Set UDI Enable\n");
1038 if (get_user(int_param, (int*)arg))
1040 unifi_error(priv, "UNIFI_SET_UDI_ENABLE: Failed to copy from user\n");
1041 r = -EFAULT;
1042 goto out;
1045 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
1046 if (log_hip_signals) {
1047 unifi_error(priv, "omnicli cannot be used when log_hip_signals is used\n");
1048 r = -EFAULT;
1049 goto out;
1051 #endif
1053 down(&priv->udi_logging_mutex);
1054 if (int_param) {
1055 pcli->event_hook = udi_log_event;
1056 unifi_set_udi_hook(priv->card, logging_handler);
1057 /* Log all signals by default */
1058 for (i = 0; i < SIG_FILTER_SIZE; i++) {
1059 pcli->signal_filter[i] = 0xFFFF;
1061 priv->logging_client = pcli;
1063 } else {
1064 priv->logging_client = NULL;
1065 pcli->event_hook = NULL;
1067 up(&priv->udi_logging_mutex);
1069 break;
1071 case UNIFI_SET_MIB:
1072 unifi_trace(priv, UDBG4, "UniFi Set MIB\n");
1073 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1074 /* Read first 2 bytes and check length */
1075 if (copy_from_user((void*)varbind, (void*)arg, 2)) {
1076 unifi_error(priv,
1077 "UNIFI_SET_MIB: Failed to copy in varbind header\n");
1078 r = -EFAULT;
1079 goto out;
1081 vblen = varbind[1];
1082 if ((vblen + 2) > MAX_VARBIND_LENGTH) {
1083 unifi_error(priv,
1084 "UNIFI_SET_MIB: Varbind too long (%d, limit %d)\n",
1085 (vblen+2), MAX_VARBIND_LENGTH);
1086 r = -EINVAL;
1087 goto out;
1089 /* Read rest of varbind */
1090 if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) {
1091 unifi_error(priv, "UNIFI_SET_MIB: Failed to copy in varbind\n");
1092 r = -EFAULT;
1093 goto out;
1096 /* send to SME */
1097 vblen += 2;
1098 r = sme_mgt_mib_set(priv, varbind, vblen);
1099 if (r) {
1100 goto out;
1102 #else
1103 unifi_notice(priv, "UNIFI_SET_MIB: Unsupported.\n");
1104 #endif /* CSR_SUPPORT_WEXT */
1105 break;
1107 case UNIFI_GET_MIB:
1108 unifi_trace(priv, UDBG4, "UniFi Get MIB\n");
1109 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1110 /* Read first 2 bytes and check length */
1111 if (copy_from_user((void*)varbind, (void*)arg, 2)) {
1112 unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind header\n");
1113 r = -EFAULT;
1114 goto out;
1116 vblen = varbind[1];
1117 if ((vblen+2) > MAX_VARBIND_LENGTH) {
1118 unifi_error(priv, "UNIFI_GET_MIB: Varbind too long (%d, limit %d)\n",
1119 (vblen+2), MAX_VARBIND_LENGTH);
1120 r = -EINVAL;
1121 goto out;
1123 /* Read rest of varbind */
1124 if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) {
1125 unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind\n");
1126 r = -EFAULT;
1127 goto out;
1130 vblen += 2;
1131 r = sme_mgt_mib_get(priv, varbind, &vblen);
1132 if (r) {
1133 goto out;
1135 /* copy out varbind */
1136 if (vblen > MAX_VARBIND_LENGTH) {
1137 unifi_error(priv,
1138 "UNIFI_GET_MIB: Varbind result too long (%d, limit %d)\n",
1139 vblen, MAX_VARBIND_LENGTH);
1140 r = -EINVAL;
1141 goto out;
1143 if (copy_to_user((void*)arg, varbind, vblen)) {
1144 r = -EFAULT;
1145 goto out;
1147 #else
1148 unifi_notice(priv, "UNIFI_GET_MIB: Unsupported.\n");
1149 #endif /* CSR_SUPPORT_WEXT */
1150 break;
1152 case UNIFI_CFG:
1153 #if (defined CSR_SUPPORT_SME)
1154 if (get_user(cfg_cmd, (unifi_cfg_command_t*)arg))
1156 unifi_error(priv, "UNIFI_CFG: Failed to get the command\n");
1157 r = -EFAULT;
1158 goto out;
1161 unifi_trace(priv, UDBG1, "UNIFI_CFG: Command is %d (t=%u) sz=%d\n",
1162 cfg_cmd, jiffies_to_msecs(jiffies), sizeof(unifi_cfg_command_t));
1163 switch (cfg_cmd) {
1164 case UNIFI_CFG_POWER:
1165 r = unifi_cfg_power(priv, (unsigned char*)arg);
1166 break;
1167 case UNIFI_CFG_POWERSAVE:
1168 r = unifi_cfg_power_save(priv, (unsigned char*)arg);
1169 break;
1170 case UNIFI_CFG_POWERSUPPLY:
1171 r = unifi_cfg_power_supply(priv, (unsigned char*)arg);
1172 break;
1173 case UNIFI_CFG_FILTER:
1174 r = unifi_cfg_packet_filters(priv, (unsigned char*)arg);
1175 break;
1176 case UNIFI_CFG_GET:
1177 r = unifi_cfg_get_info(priv, (unsigned char*)arg);
1178 break;
1179 case UNIFI_CFG_WMM_QOSINFO:
1180 r = unifi_cfg_wmm_qos_info(priv, (unsigned char*)arg);
1181 break;
1182 case UNIFI_CFG_WMM_ADDTS:
1183 r = unifi_cfg_wmm_addts(priv, (unsigned char*)arg);
1184 break;
1185 case UNIFI_CFG_WMM_DELTS:
1186 r = unifi_cfg_wmm_delts(priv, (unsigned char*)arg);
1187 break;
1188 case UNIFI_CFG_STRICT_DRAFT_N:
1189 r = unifi_cfg_strict_draft_n(priv, (unsigned char*)arg);
1190 break;
1191 case UNIFI_CFG_ENABLE_OKC:
1192 r = unifi_cfg_enable_okc(priv, (unsigned char*)arg);
1193 break;
1194 #ifdef CSR_SUPPORT_SME
1195 case UNIFI_CFG_CORE_DUMP:
1196 CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,CSR_WIFI_SME_CONTROL_INDICATION_ERROR);
1197 unifi_trace(priv, UDBG2, "UNIFI_CFG_CORE_DUMP: sent wifi off indication\n");
1198 break;
1199 #endif
1200 #ifdef CSR_SUPPORT_WEXT_AP
1201 case UNIFI_CFG_SET_AP_CONFIG:
1202 r= unifi_cfg_set_ap_config(priv,(unsigned char*)arg);
1203 break;
1204 #endif
1205 default:
1206 unifi_error(priv, "UNIFI_CFG: Unknown Command (%d)\n", cfg_cmd);
1207 r = -EINVAL;
1208 goto out;
1210 #endif
1212 break;
1214 case UNIFI_PUTEST:
1215 if (get_user(putest_cmd, (unifi_putest_command_t*)arg))
1217 unifi_error(priv, "UNIFI_PUTEST: Failed to get the command\n");
1218 r = -EFAULT;
1219 goto out;
1222 unifi_trace(priv, UDBG1, "UNIFI_PUTEST: Command is %s\n",
1223 trace_putest_cmdid(putest_cmd));
1224 switch (putest_cmd) {
1225 case UNIFI_PUTEST_START:
1226 r = unifi_putest_start(priv, (unsigned char*)arg);
1227 break;
1228 case UNIFI_PUTEST_STOP:
1229 r = unifi_putest_stop(priv, (unsigned char*)arg);
1230 break;
1231 case UNIFI_PUTEST_SET_SDIO_CLOCK:
1232 r = unifi_putest_set_sdio_clock(priv, (unsigned char*)arg);
1233 break;
1234 case UNIFI_PUTEST_CMD52_READ:
1235 r = unifi_putest_cmd52_read(priv, (unsigned char*)arg);
1236 break;
1237 case UNIFI_PUTEST_CMD52_BLOCK_READ:
1238 r = unifi_putest_cmd52_block_read(priv, (unsigned char*)arg);
1239 break;
1240 case UNIFI_PUTEST_CMD52_WRITE:
1241 r = unifi_putest_cmd52_write(priv, (unsigned char*)arg);
1242 break;
1243 case UNIFI_PUTEST_DL_FW:
1244 r = unifi_putest_dl_fw(priv, (unsigned char*)arg);
1245 break;
1246 case UNIFI_PUTEST_DL_FW_BUFF:
1247 r = unifi_putest_dl_fw_buff(priv, (unsigned char*)arg);
1248 break;
1249 case UNIFI_PUTEST_COREDUMP_PREPARE:
1250 r = unifi_putest_coredump_prepare(priv, (unsigned char*)arg);
1251 break;
1252 case UNIFI_PUTEST_GP_READ16:
1253 r = unifi_putest_gp_read16(priv, (unsigned char*)arg);
1254 break;
1255 case UNIFI_PUTEST_GP_WRITE16:
1256 r = unifi_putest_gp_write16(priv, (unsigned char*)arg);
1257 break;
1258 default:
1259 unifi_error(priv, "UNIFI_PUTEST: Unknown Command (%d)\n", putest_cmd);
1260 r = -EINVAL;
1261 goto out;
1264 break;
1265 case UNIFI_BUILD_TYPE:
1266 unifi_trace(priv, UDBG2, "UNIFI_BUILD_TYPE userspace=%s\n", build_type_to_string(*(unsigned char*)arg));
1267 #ifndef CSR_SUPPORT_WEXT_AP
1268 if (UNIFI_BUILD_AP == *(unsigned char*)arg)
1270 unifi_error(priv, "Userspace has AP support, which is incompatible\n");
1272 #endif
1274 #ifndef CSR_SUPPORT_WEXT
1275 if (UNIFI_BUILD_WEXT == *(unsigned char*)arg)
1277 unifi_error(priv, "Userspace has WEXT support, which is incompatible\n");
1279 #endif
1280 break;
1281 case UNIFI_INIT_HW:
1282 unifi_trace(priv, UDBG2, "UNIFI_INIT_HW.\n");
1283 priv->init_progress = UNIFI_INIT_NONE;
1285 #if defined(CSR_SUPPORT_WEXT) || defined (CSR_NATIVE_LINUX)
1286 /* At this point we are ready to start the SME. */
1287 r = sme_mgt_wifi_on(priv);
1288 if (r) {
1289 goto out;
1291 #endif
1293 break;
1295 case UNIFI_INIT_NETDEV:
1297 /* get the proper interfaceTagId */
1298 u16 interfaceTag=0;
1299 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
1301 dev = priv->netdev[interfaceTag];
1302 unifi_trace(priv, UDBG2, "UNIFI_INIT_NETDEV.\n");
1304 if (copy_from_user((void*)dev->dev_addr, (void*)arg, 6)) {
1305 r = -EFAULT;
1306 goto out;
1309 /* Attach the network device to the stack */
1310 if (!interfacePriv->netdev_registered)
1312 r = uf_register_netdev(priv,interfaceTag);
1313 if (r) {
1314 unifi_error(priv, "Failed to register the network device.\n");
1315 goto out;
1319 /* Apply scheduled interrupt mode, if requested by module param */
1320 if (run_bh_once != -1) {
1321 unifi_set_interrupt_mode(priv->card, (u32)run_bh_once);
1324 priv->init_progress = UNIFI_INIT_COMPLETED;
1326 /* Firmware initialisation is complete, so let the SDIO bus
1327 * clock be raised when convienent to the core.
1329 unifi_request_max_sdio_clock(priv->card);
1331 #ifdef CSR_SUPPORT_WEXT
1332 /* Notify the Android wpa_supplicant that we are ready */
1333 wext_send_started_event(priv);
1334 #endif
1336 unifi_info(priv, "UniFi ready\n");
1338 #ifdef ANDROID_BUILD
1339 /* Release the wakelock */
1340 unifi_trace(priv, UDBG1, "netdev_init: release wake lock\n");
1341 wake_unlock(&unifi_sdio_wake_lock);
1342 #endif
1343 #ifdef CSR_NATIVE_SOFTMAC /* For softmac dev, force-enable the network interface rather than wait for a connected-ind */
1345 struct net_device *dev = priv->netdev[interfaceTag];
1346 #ifdef CSR_SUPPORT_WEXT
1347 interfacePriv->wait_netdev_change = TRUE;
1348 #endif
1349 netif_carrier_on(dev);
1351 #endif
1353 break;
1354 case UNIFI_GET_INIT_STATUS:
1355 unifi_trace(priv, UDBG2, "UNIFI_GET_INIT_STATUS.\n");
1356 if (put_user(priv->init_progress, (int*)arg))
1358 printk(KERN_ERR "UNIFI_GET_INIT_STATUS: Failed to copy to user\n");
1359 r = -EFAULT;
1360 goto out;
1362 break;
1364 case UNIFI_KICK:
1365 unifi_trace(priv, UDBG4, "Kick UniFi\n");
1366 unifi_sdio_interrupt_handler(priv->card);
1367 break;
1369 case UNIFI_SET_DEBUG:
1370 unifi_debug = arg;
1371 unifi_trace(priv, UDBG4, "unifi_debug set to %d\n", unifi_debug);
1372 break;
1374 case UNIFI_SET_TRACE:
1375 /* no longer supported */
1376 r = -EINVAL;
1377 break;
1380 case UNIFI_SET_UDI_LOG_MASK:
1382 unifiio_filter_t udi_filter;
1383 uint16_t *sig_ids_addr;
1384 #define UF_MAX_SIG_IDS 128 /* Impose a sensible limit */
1386 if (copy_from_user((void*)(&udi_filter), (void*)arg, sizeof(udi_filter))) {
1387 r = -EFAULT;
1388 goto out;
1390 if ((udi_filter.action < UfSigFil_AllOn) ||
1391 (udi_filter.action > UfSigFil_SelectOff))
1393 printk(KERN_WARNING
1394 "UNIFI_SET_UDI_LOG_MASK: Bad action value: %d\n",
1395 udi_filter.action);
1396 r = -EINVAL;
1397 goto out;
1399 /* No signal list for "All" actions */
1400 if ((udi_filter.action == UfSigFil_AllOn) ||
1401 (udi_filter.action == UfSigFil_AllOff))
1403 udi_filter.num_sig_ids = 0;
1406 if (udi_filter.num_sig_ids > UF_MAX_SIG_IDS) {
1407 printk(KERN_WARNING
1408 "UNIFI_SET_UDI_LOG_MASK: too many signal ids (%d, max %d)\n",
1409 udi_filter.num_sig_ids, UF_MAX_SIG_IDS);
1410 r = -EINVAL;
1411 goto out;
1414 /* Copy in signal id list if given */
1415 if (udi_filter.num_sig_ids > 0) {
1416 /* Preserve userspace address of sig_ids array */
1417 sig_ids_addr = udi_filter.sig_ids;
1418 /* Allocate kernel memory for sig_ids and copy to it */
1419 udi_filter.sig_ids =
1420 kmalloc(udi_filter.num_sig_ids * sizeof(uint16_t), GFP_KERNEL);
1421 if (!udi_filter.sig_ids) {
1422 r = -ENOMEM;
1423 goto out;
1425 if (copy_from_user((void*)udi_filter.sig_ids,
1426 (void*)sig_ids_addr,
1427 udi_filter.num_sig_ids * sizeof(uint16_t)))
1429 kfree(udi_filter.sig_ids);
1430 r = -EFAULT;
1431 goto out;
1435 udi_set_log_filter(pcli, &udi_filter);
1437 if (udi_filter.num_sig_ids > 0) {
1438 kfree(udi_filter.sig_ids);
1441 break;
1443 case UNIFI_SET_AMP_ENABLE:
1444 unifi_trace(priv, UDBG4, "UniFi Set AMP Enable\n");
1445 if (get_user(int_param, (int*)arg))
1447 unifi_error(priv, "UNIFI_SET_AMP_ENABLE: Failed to copy from user\n");
1448 r = -EFAULT;
1449 goto out;
1452 if (int_param) {
1453 priv->amp_client = pcli;
1454 } else {
1455 priv->amp_client = NULL;
1458 int_param = 0;
1459 buf = (u8*)&int_param;
1460 buf[0] = UNIFI_SOFT_COMMAND_Q_LENGTH - 1;
1461 buf[1] = UNIFI_SOFT_TRAFFIC_Q_LENGTH - 1;
1462 if (copy_to_user((void*)arg, &int_param, sizeof(int))) {
1463 r = -EFAULT;
1464 goto out;
1466 break;
1468 case UNIFI_SET_UDI_SNAP_MASK:
1470 unifiio_snap_filter_t snap_filter;
1472 if (copy_from_user((void*)(&snap_filter), (void*)arg, sizeof(snap_filter))) {
1473 r = -EFAULT;
1474 goto out;
1477 if (pcli->snap_filter.count) {
1478 pcli->snap_filter.count = 0;
1479 kfree(pcli->snap_filter.protocols);
1482 if (snap_filter.count == 0) {
1483 break;
1486 pcli->snap_filter.protocols = kmalloc(snap_filter.count * sizeof(u16), GFP_KERNEL);
1487 if (!pcli->snap_filter.protocols) {
1488 r = -ENOMEM;
1489 goto out;
1491 if (copy_from_user((void*)pcli->snap_filter.protocols,
1492 (void*)snap_filter.protocols,
1493 snap_filter.count * sizeof(u16)))
1495 kfree(pcli->snap_filter.protocols);
1496 r = -EFAULT;
1497 goto out;
1500 pcli->snap_filter.count = snap_filter.count;
1503 break;
1505 case UNIFI_SME_PRESENT:
1507 u8 ind;
1508 unifi_trace(priv, UDBG4, "UniFi SME Present IOCTL.\n");
1509 if (copy_from_user((void*)(&int_param), (void*)arg, sizeof(int)))
1511 printk(KERN_ERR "UNIFI_SME_PRESENT: Failed to copy from user\n");
1512 r = -EFAULT;
1513 goto out;
1516 priv->sme_is_present = int_param;
1517 if (priv->sme_is_present == 1) {
1518 ind = CONFIG_SME_PRESENT;
1519 } else {
1520 ind = CONFIG_SME_NOT_PRESENT;
1522 /* Send an indication to the helper app. */
1523 ul_log_config_ind(priv, &ind, sizeof(u8));
1525 break;
1527 case UNIFI_CFG_PERIOD_TRAFFIC:
1529 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1530 CsrWifiSmeCoexConfig coexConfig;
1531 #endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */
1532 unifi_trace(priv, UDBG4, "UniFi Configure Periodic Traffic.\n");
1533 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1534 if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) {
1535 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n");
1536 r = -EFAULT;
1537 goto out;
1540 if (uchar_param == 0) {
1541 r = sme_mgt_coex_config_get(priv, &coexConfig);
1542 if (r) {
1543 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Get unifi_CoexInfoValue failed.\n");
1544 goto out;
1546 if (copy_to_user((void*)(arg + 1),
1547 (void*)&coexConfig,
1548 sizeof(CsrWifiSmeCoexConfig))) {
1549 r = -EFAULT;
1550 goto out;
1552 goto out;
1555 if (copy_from_user((void*)(&coex_config), (void*)(arg + 1), sizeof(CsrWifiSmeCoexConfig)))
1557 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n");
1558 r = -EFAULT;
1559 goto out;
1562 coexConfig = coex_config;
1563 r = sme_mgt_coex_config_set(priv, &coexConfig);
1564 if (r) {
1565 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Set unifi_CoexInfoValue failed.\n");
1566 goto out;
1569 #endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */
1570 break;
1572 case UNIFI_CFG_UAPSD_TRAFFIC:
1573 unifi_trace(priv, UDBG4, "UniFi Configure U-APSD Mask.\n");
1574 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1575 if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) {
1576 unifi_error(priv, "UNIFI_CFG_UAPSD_TRAFFIC: Failed to copy from user\n");
1577 r = -EFAULT;
1578 goto out;
1580 unifi_trace(priv, UDBG4, "New U-APSD Mask: 0x%x\n", uchar_param);
1581 #endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */
1582 break;
1584 #ifndef UNIFI_DISABLE_COREDUMP
1585 case UNIFI_COREDUMP_GET_REG:
1586 unifi_trace(priv, UDBG4, "Mini-coredump data request\n");
1588 unifiio_coredump_req_t dump_req; /* Public OS layer structure */
1589 unifi_coredump_req_t priv_req; /* Private HIP structure */
1591 if (copy_from_user((void*)(&dump_req), (void*)arg, sizeof(dump_req))) {
1592 r = -EFAULT;
1593 goto out;
1595 memset(&priv_req, 0, sizeof(priv_req));
1596 priv_req.index = dump_req.index;
1597 priv_req.offset = dump_req.offset;
1599 /* Convert OS-layer's XAP memory space ID to HIP's ID in case they differ */
1600 switch (dump_req.space) {
1601 case UNIFIIO_COREDUMP_MAC_REG: priv_req.space = UNIFI_COREDUMP_MAC_REG; break;
1602 case UNIFIIO_COREDUMP_PHY_REG: priv_req.space = UNIFI_COREDUMP_PHY_REG; break;
1603 case UNIFIIO_COREDUMP_SH_DMEM: priv_req.space = UNIFI_COREDUMP_SH_DMEM; break;
1604 case UNIFIIO_COREDUMP_MAC_DMEM: priv_req.space = UNIFI_COREDUMP_MAC_DMEM; break;
1605 case UNIFIIO_COREDUMP_PHY_DMEM: priv_req.space = UNIFI_COREDUMP_PHY_DMEM; break;
1606 case UNIFIIO_COREDUMP_TRIGGER_MAGIC: priv_req.space = UNIFI_COREDUMP_TRIGGER_MAGIC; break;
1607 default:
1608 r = -EINVAL;
1609 goto out;
1612 if (priv_req.space == UNIFI_COREDUMP_TRIGGER_MAGIC) {
1613 /* Force a coredump grab now */
1614 unifi_trace(priv, UDBG2, "UNIFI_COREDUMP_GET_REG: Force capture\n");
1615 csrResult = unifi_coredump_capture(priv->card, &priv_req);
1616 r = CsrHipResultToStatus(csrResult);
1617 unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: status %d\n", r);
1618 } else {
1619 /* Retrieve the appropriate register entry */
1620 csrResult = unifi_coredump_get_value(priv->card, &priv_req);
1621 r = CsrHipResultToStatus(csrResult);
1622 if (r) {
1623 unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: Status %d\n", r);
1624 goto out;
1626 /* Update the OS-layer structure with values returned in the private */
1627 dump_req.value = priv_req.value;
1628 dump_req.timestamp = priv_req.timestamp;
1629 dump_req.requestor = priv_req.requestor;
1630 dump_req.serial = priv_req.serial;
1631 dump_req.chip_ver = priv_req.chip_ver;
1632 dump_req.fw_ver = priv_req.fw_ver;
1633 dump_req.drv_build = 0;
1635 unifi_trace(priv, UDBG6,
1636 "Dump: %d (seq %d): V:0x%04x (%d) @0x%02x:%04x = 0x%04x\n",
1637 dump_req.index, dump_req.serial,
1638 dump_req.chip_ver, dump_req.drv_build,
1639 dump_req.space, dump_req.offset, dump_req.value);
1641 if (copy_to_user((void*)arg, (void*)&dump_req, sizeof(dump_req))) {
1642 r = -EFAULT;
1643 goto out;
1646 break;
1647 #endif
1648 default:
1649 r = -EINVAL;
1652 out:
1653 return (long)r;
1654 } /* unifi_ioctl() */
1658 static unsigned int
1659 unifi_poll(struct file *filp, poll_table *wait)
1661 ul_client_t *pcli = (ul_client_t*)filp->private_data;
1662 unsigned int mask = 0;
1663 int ready;
1665 func_enter();
1667 ready = !list_empty(&pcli->udi_log);
1669 poll_wait(filp, &pcli->udi_wq, wait);
1671 if (ready) {
1672 mask |= POLLIN | POLLRDNORM; /* readable */
1675 func_exit();
1677 return mask;
1678 } /* unifi_poll() */
1683 * ---------------------------------------------------------------------------
1684 * udi_set_log_filter
1686 * Configure the bit mask that determines which signal primitives are
1687 * passed to the logging process.
1689 * Arguments:
1690 * pcli Pointer to the client to configure.
1691 * udi_filter Pointer to a unifiio_filter_t containing instructions.
1693 * Returns:
1694 * None.
1696 * Notes:
1697 * SigGetFilterPos() returns a 32-bit value that contains an index and a
1698 * mask for accessing a signal_filter array. The top 16 bits specify an
1699 * index into a signal_filter, the bottom 16 bits specify a mask to
1700 * apply.
1701 * ---------------------------------------------------------------------------
1703 static void
1704 udi_set_log_filter(ul_client_t *pcli, unifiio_filter_t *udi_filter)
1706 u32 filter_pos;
1707 int i;
1709 if (udi_filter->action == UfSigFil_AllOn)
1711 for (i = 0; i < SIG_FILTER_SIZE; i++) {
1712 pcli->signal_filter[i] = 0xFFFF;
1715 else if (udi_filter->action == UfSigFil_AllOff)
1717 for (i = 0; i < SIG_FILTER_SIZE; i++) {
1718 pcli->signal_filter[i] = 0;
1721 else if (udi_filter->action == UfSigFil_SelectOn)
1723 for (i = 0; i < udi_filter->num_sig_ids; i++) {
1724 filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]);
1725 if (filter_pos == 0xFFFFFFFF)
1727 printk(KERN_WARNING
1728 "Unrecognised signal id (0x%X) specifed in logging filter\n",
1729 udi_filter->sig_ids[i]);
1730 } else {
1731 pcli->signal_filter[filter_pos >> 16] |= (filter_pos & 0xFFFF);
1735 else if (udi_filter->action == UfSigFil_SelectOff)
1737 for (i = 0; i < udi_filter->num_sig_ids; i++) {
1738 filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]);
1739 if (filter_pos == 0xFFFFFFFF)
1741 printk(KERN_WARNING
1742 "Unrecognised signal id (0x%X) specifed in logging filter\n",
1743 udi_filter->sig_ids[i]);
1744 } else {
1745 pcli->signal_filter[filter_pos >> 16] &= ~(filter_pos & 0xFFFF);
1750 } /* udi_set_log_filter() */
1754 * ---------------------------------------------------------------------------
1755 * udi_log_event
1757 * Callback function to be registered as the UDI hook callback.
1758 * Copies the signal content into a new udi_log_t struct and adds
1759 * it to the read queue for this UDI client.
1761 * Arguments:
1762 * pcli A pointer to the client instance.
1763 * signal Pointer to the received signal.
1764 * signal_len Size of the signal structure in bytes.
1765 * bulkdata Pointers to any associated bulk data.
1766 * dir Direction of the signal. Zero means from host,
1767 * non-zero means to host.
1769 * Returns:
1770 * None.
1771 * ---------------------------------------------------------------------------
1773 void
1774 udi_log_event(ul_client_t *pcli,
1775 const u8 *signal, int signal_len,
1776 const bulk_data_param_t *bulkdata,
1777 int dir)
1779 udi_log_t *logptr;
1780 u8 *p;
1781 int i;
1782 int total_len;
1783 udi_msg_t *msgptr;
1784 u32 filter_pos;
1785 #ifdef OMNICLI_LINUX_EXTRA_LOG
1786 static volatile unsigned int printk_cpu = UINT_MAX;
1787 unsigned long long t;
1788 unsigned long nanosec_rem;
1789 unsigned long n_1000;
1790 #endif
1792 func_enter();
1794 /* Just a sanity check */
1795 if ((signal == NULL) || (signal_len <= 0)) {
1796 return;
1799 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
1800 /* When HIP offline signal logging is enabled, omnicli cannot run */
1801 if (log_hip_signals)
1803 /* Add timestamp */
1804 if (log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP)
1806 int timestamp = jiffies_to_msecs(jiffies);
1807 unifi_debug_log_to_buf("T:");
1808 unifi_debug_log_to_buf("%04X%04X ", *(((u16*)&timestamp) + 1),
1809 *(u16*)&timestamp);
1812 /* Add signal */
1813 unifi_debug_log_to_buf("S%s:%04X R:%04X D:%04X ",
1814 dir ? "T" : "F",
1815 *(u16*)signal,
1816 *(u16*)(signal + 2),
1817 *(u16*)(signal + 4));
1818 unifi_debug_hex_to_buf(signal + 6, signal_len - 6);
1820 /* Add bulk data (assume 1 bulk data per signal) */
1821 if ((log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA) &&
1822 (bulkdata->d[0].data_length > 0))
1824 unifi_debug_log_to_buf("\nD:");
1825 unifi_debug_hex_to_buf(bulkdata->d[0].os_data_ptr, bulkdata->d[0].data_length);
1827 unifi_debug_log_to_buf("\n");
1829 return;
1831 #endif
1833 #ifdef CSR_NATIVE_LINUX
1834 uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir);
1835 #endif
1838 * Apply the logging filter - only report signals that have their
1839 * bit set in the filter mask.
1841 filter_pos = SigGetFilterPos(GET_SIGNAL_ID(signal));
1843 if ((filter_pos != 0xFFFFFFFF) &&
1844 ((pcli->signal_filter[filter_pos >> 16] & (filter_pos & 0xFFFF)) == 0))
1846 /* Signal is not wanted by client */
1847 return;
1851 /* Calculate the buffer we need to store signal plus bulk data */
1852 total_len = signal_len;
1853 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
1854 total_len += bulkdata->d[i].data_length;
1857 /* Allocate log structure plus actual signal. */
1858 logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
1860 if (logptr == NULL) {
1861 printk(KERN_ERR
1862 "Failed to allocate %lu bytes for a UDI log record\n",
1863 (long unsigned int)(sizeof(udi_log_t) + total_len));
1864 return;
1867 /* Fill in udi_log struct */
1868 INIT_LIST_HEAD(&logptr->q);
1869 msgptr = &logptr->msg;
1870 msgptr->length = sizeof(udi_msg_t) + total_len;
1871 #ifdef OMNICLI_LINUX_EXTRA_LOG
1872 t = cpu_clock(printk_cpu);
1873 nanosec_rem = do_div(t, 1000000000);
1874 n_1000 = nanosec_rem/1000;
1875 msgptr->timestamp = (t <<10 ) | ((unsigned long)(n_1000 >> 10) & 0x3ff);
1876 #else
1877 msgptr->timestamp = jiffies_to_msecs(jiffies);
1878 #endif
1879 msgptr->direction = dir;
1880 msgptr->signal_length = signal_len;
1882 /* Copy signal and bulk data to the log */
1883 p = (u8 *)(msgptr + 1);
1884 memcpy(p, signal, signal_len);
1885 p += signal_len;
1887 /* Append any bulk data */
1888 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
1889 int len = bulkdata->d[i].data_length;
1892 * Len here might not be the same as the length in the bulk data slot.
1893 * The slot length will always be even, but len could be odd.
1895 if (len > 0) {
1896 if (bulkdata->d[i].os_data_ptr) {
1897 memcpy(p, bulkdata->d[i].os_data_ptr, len);
1898 } else {
1899 memset(p, 0, len);
1901 p += len;
1905 /* Add to tail of log queue */
1906 if (down_interruptible(&pcli->udi_sem)) {
1907 printk(KERN_WARNING "udi_log_event_q: Failed to get udi sem\n");
1908 kfree(logptr);
1909 func_exit();
1910 return;
1912 list_add_tail(&logptr->q, &pcli->udi_log);
1913 up(&pcli->udi_sem);
1915 /* Wake any waiting user process */
1916 wake_up_interruptible(&pcli->udi_wq);
1918 func_exit();
1919 } /* udi_log_event() */
1921 #ifdef CSR_SME_USERSPACE
1923 uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length)
1925 udi_log_t *logptr;
1926 udi_msg_t *msgptr;
1927 u8 *p;
1929 func_enter();
1931 /* Just a sanity check */
1932 if ((buffer == NULL) || (length <= 0)) {
1933 return -EINVAL;
1936 /* Allocate log structure plus actual signal. */
1937 logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC);
1938 if (logptr == NULL) {
1939 unifi_error(priv, "Failed to allocate %d bytes for an SME message\n",
1940 sizeof(udi_log_t) + length);
1941 kfree(buffer);
1942 return -ENOMEM;
1945 /* Fill in udi_log struct */
1946 INIT_LIST_HEAD(&logptr->q);
1947 msgptr = &logptr->msg;
1948 msgptr->length = sizeof(udi_msg_t) + length;
1949 msgptr->signal_length = length;
1951 /* Copy signal and bulk data to the log */
1952 p = (u8 *)(msgptr + 1);
1953 memcpy(p, buffer, length);
1955 /* Add to tail of log queue */
1956 down(&udi_mutex);
1957 if (priv->sme_cli == NULL) {
1958 kfree(logptr);
1959 kfree(buffer);
1960 up(&udi_mutex);
1961 unifi_info(priv, "Message for the SME dropped, SME has gone away\n");
1962 return 0;
1965 down(&priv->sme_cli->udi_sem);
1966 list_add_tail(&logptr->q, &priv->sme_cli->udi_log);
1967 up(&priv->sme_cli->udi_sem);
1969 /* Wake any waiting user process */
1970 wake_up_interruptible(&priv->sme_cli->udi_wq);
1971 up(&udi_mutex);
1973 /* It is our responsibility to free the buffer allocated in build_packed_*() */
1974 kfree(buffer);
1976 func_exit();
1978 return 0;
1980 } /* uf_sme_queue_message() */
1981 #endif
1984 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
1985 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
1986 device_create(_class, _parent, _devno, _priv, _fmt, _args)
1987 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
1988 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
1989 device_create_drvdata(_class, _parent, _devno, _priv, _fmt, _args)
1990 #else
1991 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
1992 device_create(_class, _parent, _devno, _fmt, _args)
1993 #endif
1996 ****************************************************************************
1998 * Driver instantiation
2000 ****************************************************************************
2002 static struct file_operations unifi_fops = {
2003 .owner = THIS_MODULE,
2004 .open = unifi_open,
2005 .release = unifi_release,
2006 .read = unifi_read,
2007 .write = unifi_write,
2008 .unlocked_ioctl = unifi_ioctl,
2009 .poll = unifi_poll,
2012 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
2013 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
2014 device_create(_class, _parent, _devno, _priv, _fmt, _args)
2015 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
2016 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
2017 device_create_drvdata(_class, _parent, _devno, _priv, _fmt, _args)
2018 #else
2019 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
2020 device_create(_class, _parent, _devno, _fmt, _args)
2021 #endif
2023 static dev_t unifi_first_devno;
2024 static struct class *unifi_class;
2027 int uf_create_device_nodes(unifi_priv_t *priv, int bus_id)
2029 dev_t devno;
2030 int r;
2032 cdev_init(&priv->unifi_cdev, &unifi_fops);
2034 /* cdev_init() should set the cdev owner, but it does not */
2035 priv->unifi_cdev.owner = THIS_MODULE;
2037 devno = MKDEV(MAJOR(unifi_first_devno),
2038 MINOR(unifi_first_devno) + (bus_id * 2));
2039 r = cdev_add(&priv->unifi_cdev, devno, 1);
2040 if (r) {
2041 return r;
2044 #ifdef SDIO_EXPORTS_STRUCT_DEVICE
2045 if (!UF_DEVICE_CREATE(unifi_class, priv->unifi_device,
2046 devno, priv, "unifi%d", bus_id)) {
2047 #else
2048 priv->unifi_device = UF_DEVICE_CREATE(unifi_class, NULL,
2049 devno, priv, "unifi%d", bus_id);
2050 if (priv->unifi_device == NULL) {
2051 #endif /* SDIO_EXPORTS_STRUCT_DEVICE */
2053 cdev_del(&priv->unifi_cdev);
2054 return -EINVAL;
2057 cdev_init(&priv->unifiudi_cdev, &unifi_fops);
2059 /* cdev_init() should set the cdev owner, but it does not */
2060 priv->unifiudi_cdev.owner = THIS_MODULE;
2062 devno = MKDEV(MAJOR(unifi_first_devno),
2063 MINOR(unifi_first_devno) + (bus_id * 2) + 1);
2064 r = cdev_add(&priv->unifiudi_cdev, devno, 1);
2065 if (r) {
2066 device_destroy(unifi_class, priv->unifi_cdev.dev);
2067 cdev_del(&priv->unifi_cdev);
2068 return r;
2071 if (!UF_DEVICE_CREATE(unifi_class,
2072 #ifdef SDIO_EXPORTS_STRUCT_DEVICE
2073 priv->unifi_device,
2074 #else
2075 NULL,
2076 #endif /* SDIO_EXPORTS_STRUCT_DEVICE */
2077 devno, priv, "unifiudi%d", bus_id)) {
2078 device_destroy(unifi_class, priv->unifi_cdev.dev);
2079 cdev_del(&priv->unifiudi_cdev);
2080 cdev_del(&priv->unifi_cdev);
2081 return -EINVAL;
2084 return 0;
2088 void uf_destroy_device_nodes(unifi_priv_t *priv)
2090 device_destroy(unifi_class, priv->unifiudi_cdev.dev);
2091 device_destroy(unifi_class, priv->unifi_cdev.dev);
2092 cdev_del(&priv->unifiudi_cdev);
2093 cdev_del(&priv->unifi_cdev);
2099 * ----------------------------------------------------------------
2100 * uf_create_debug_device
2102 * Allocates device numbers for unifi character device nodes
2103 * and creates a unifi class in sysfs
2105 * Arguments:
2106 * fops Pointer to the char device operations structure.
2108 * Returns:
2109 * 0 on success, -ve error code on error.
2110 * ----------------------------------------------------------------
2112 static int
2113 uf_create_debug_device(struct file_operations *fops)
2115 int ret;
2117 /* Allocate two device numbers for each device. */
2118 ret = alloc_chrdev_region(&unifi_first_devno, 0, MAX_UNIFI_DEVS*2, UNIFI_NAME);
2119 if (ret) {
2120 unifi_error(NULL, "Failed to add alloc dev numbers: %d\n", ret);
2121 return ret;
2124 /* Create a UniFi class */
2125 unifi_class = class_create(THIS_MODULE, UNIFI_NAME);
2126 if (IS_ERR(unifi_class)) {
2127 unifi_error(NULL, "Failed to create UniFi class\n");
2129 /* Release device numbers */
2130 unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2);
2131 unifi_first_devno = 0;
2132 return -EINVAL;
2135 return 0;
2136 } /* uf_create_debug_device() */
2140 * ----------------------------------------------------------------
2141 * uf_remove_debug_device
2143 * Destroys the unifi class and releases the allocated
2144 * device numbers for unifi character device nodes.
2146 * Arguments:
2148 * Returns:
2149 * ----------------------------------------------------------------
2151 static void
2152 uf_remove_debug_device(void)
2154 /* Destroy the UniFi class */
2155 class_destroy(unifi_class);
2157 /* Release device numbers */
2158 unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2);
2159 unifi_first_devno = 0;
2161 } /* uf_remove_debug_device() */
2165 * ---------------------------------------------------------------------------
2167 * Module loading.
2169 * ---------------------------------------------------------------------------
2171 int __init
2172 unifi_load(void)
2174 int r;
2176 printk("UniFi SDIO Driver: %s %s %s\n",
2177 CSR_WIFI_VERSION,
2178 __DATE__, __TIME__);
2180 #ifdef CSR_SME_USERSPACE
2181 #ifdef CSR_SUPPORT_WEXT
2182 printk("CSR SME with WEXT support\n");
2183 #else
2184 printk("CSR SME no WEXT support\n");
2185 #endif /* CSR_SUPPORT_WEXT */
2186 #endif /* CSR_SME_USERSPACE */
2188 #ifdef CSR_NATIVE_LINUX
2189 #ifdef CSR_SUPPORT_WEXT
2190 #error WEXT unsupported in the native driver
2191 #endif
2192 printk("CSR native no WEXT support\n");
2193 #endif
2194 #ifdef CSR_WIFI_SPLIT_PATCH
2195 printk("Split patch support\n");
2196 #endif
2197 printk("Kernel %d.%d.%d\n",
2198 ((LINUX_VERSION_CODE) >> 16) & 0xff,
2199 ((LINUX_VERSION_CODE) >> 8) & 0xff,
2200 (LINUX_VERSION_CODE) & 0xff);
2202 * Instantiate the /dev/unifi* device nodes.
2203 * We must do this before registering with the SDIO driver because it
2204 * will immediately call the "insert" callback if the card is
2205 * already present.
2207 r = uf_create_debug_device(&unifi_fops);
2208 if (r) {
2209 return r;
2212 /* Now register with the SDIO driver */
2213 r = uf_sdio_load();
2214 if (r) {
2215 uf_remove_debug_device();
2216 return r;
2219 if (sdio_block_size > -1) {
2220 unifi_info(NULL, "sdio_block_size %d\n", sdio_block_size);
2223 if (sdio_byte_mode) {
2224 unifi_info(NULL, "sdio_byte_mode\n");
2227 if (disable_power_control) {
2228 unifi_info(NULL, "disable_power_control\n");
2231 if (disable_hw_reset) {
2232 unifi_info(NULL, "disable_hw_reset\n");
2235 if (enable_wol) {
2236 unifi_info(NULL, "enable_wol %d\n", enable_wol);
2239 if (run_bh_once != -1) {
2240 unifi_info(NULL, "run_bh_once %d\n", run_bh_once);
2243 return 0;
2244 } /* unifi_load() */
2247 void __exit
2248 unifi_unload(void)
2250 /* The SDIO remove hook will call unifi_disconnect(). */
2251 uf_sdio_unload();
2253 uf_remove_debug_device();
2255 } /* unifi_unload() */
2257 module_init(unifi_load);
2258 module_exit(unifi_unload);
2260 MODULE_DESCRIPTION("UniFi Device driver");
2261 MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
2262 MODULE_LICENSE("GPL and additional rights");