Staging: csr: update to version 5.1.0 of the driver
[linux-2.6.git] / drivers / staging / csr / drv.c
blobfbe86301816cd198c3d2cb7f74f589bb6933811f
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_SIGNAL (1 << 0)
67 #define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA (1 << 1)
68 #define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP (1 << 2)
69 int log_hip_signals = 0;
70 #endif
72 MODULE_DESCRIPTION("CSR UniFi (SDIO)");
74 module_param(buswidth, int, S_IRUGO|S_IWUSR);
75 module_param(sdio_clock, int, S_IRUGO|S_IWUSR);
76 module_param(unifi_debug, int, S_IRUGO|S_IWUSR);
77 module_param_array(fw_init, int, NULL, S_IRUGO|S_IWUSR);
78 module_param(use_5g, int, S_IRUGO|S_IWUSR);
79 module_param(led_mask, int, S_IRUGO|S_IWUSR);
80 module_param(disable_hw_reset, int, S_IRUGO|S_IWUSR);
81 module_param(disable_power_control, int, S_IRUGO|S_IWUSR);
82 module_param(enable_wol, int, S_IRUGO|S_IWUSR);
83 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
84 module_param(tl_80211d, int, S_IRUGO|S_IWUSR);
85 #endif
86 module_param(sdio_block_size, int, S_IRUGO|S_IWUSR);
87 module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR);
88 module_param(coredump_max, int, S_IRUGO|S_IWUSR);
89 module_param(run_bh_once, int, S_IRUGO|S_IWUSR);
90 module_param(bh_priority, int, S_IRUGO|S_IWUSR);
91 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
92 module_param(log_hip_signals, int, S_IRUGO|S_IWUSR);
93 #endif
95 MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode");
96 MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)");
97 MODULE_PARM_DESC(unifi_debug, "Diagnostic reporting level");
98 MODULE_PARM_DESC(fw_init, "Set to 0 to prevent f/w initialization on error");
99 MODULE_PARM_DESC(use_5g, "Use the 5G (802.11a) radio band");
100 MODULE_PARM_DESC(led_mask, "LED mask flags");
101 MODULE_PARM_DESC(disable_hw_reset, "Set to 1 to disable hardware reset");
102 MODULE_PARM_DESC(disable_power_control, "Set to 1 to disable SDIO power control");
103 MODULE_PARM_DESC(enable_wol, "Enable wake-on-wlan function 0=off, 1=SDIO, 2=PIO");
104 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
105 MODULE_PARM_DESC(tl_80211d, "802.11d Trust Level (1-6, default = 5)");
106 #endif
107 MODULE_PARM_DESC(sdio_block_size, "Set to override SDIO block size");
108 MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO");
109 MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate");
110 MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts");
111 MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority");
112 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
113 MODULE_PARM_DESC(log_hip_signals, "Set to 1 to enable HIP signal offline logging");
114 #endif
117 /* Callback for event logging to UDI clients */
118 static void udi_log_event(ul_client_t *client,
119 const u8 *signal, int signal_len,
120 const bulk_data_param_t *bulkdata,
121 int dir);
123 static void udi_set_log_filter(ul_client_t *pcli,
124 unifiio_filter_t *udi_filter);
127 /* Mutex to protect access to priv->sme_cli */
128 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
129 DEFINE_SEMAPHORE(udi_mutex);
130 #else
131 DECLARE_MUTEX(udi_mutex);
132 #endif
134 CsrInt32 CsrHipResultToStatus(CsrResult csrResult)
136 CsrInt32 r = -EIO;
138 switch (csrResult)
140 case CSR_RESULT_SUCCESS:
141 r = 0;
142 break;
143 case CSR_WIFI_HIP_RESULT_RANGE:
144 r = -ERANGE;
145 break;
146 case CSR_WIFI_HIP_RESULT_NO_DEVICE:
147 r = -ENODEV;
148 break;
149 case CSR_WIFI_HIP_RESULT_INVALID_VALUE:
150 r = -EINVAL;
151 break;
152 case CSR_WIFI_HIP_RESULT_NOT_FOUND:
153 r = -ENOENT;
154 break;
155 case CSR_WIFI_HIP_RESULT_NO_SPACE:
156 r = -ENOSPC;
157 break;
158 case CSR_WIFI_HIP_RESULT_NO_MEMORY:
159 r = -ENOMEM;
160 break;
161 case CSR_RESULT_FAILURE:
162 r = -EIO;
163 break;
164 default:
165 /*unifi_warning(card->ospriv, "CsrHipResultToStatus: Unrecognised csrResult error code: %d\n", csrResult);*/
166 r = -EIO;
168 return r;
172 static const char*
173 trace_putest_cmdid(unifi_putest_command_t putest_cmd)
175 switch (putest_cmd)
177 case UNIFI_PUTEST_START:
178 return "START";
179 case UNIFI_PUTEST_STOP:
180 return "STOP";
181 case UNIFI_PUTEST_SET_SDIO_CLOCK:
182 return "SET CLOCK";
183 case UNIFI_PUTEST_CMD52_READ:
184 return "CMD52R";
185 case UNIFI_PUTEST_CMD52_BLOCK_READ:
186 return "CMD52BR";
187 case UNIFI_PUTEST_CMD52_WRITE:
188 return "CMD52W";
189 case UNIFI_PUTEST_DL_FW:
190 return "D/L FW";
191 case UNIFI_PUTEST_DL_FW_BUFF:
192 return "D/L FW BUFFER";
193 case UNIFI_PUTEST_COREDUMP_PREPARE:
194 return "PREPARE COREDUMP";
195 case UNIFI_PUTEST_GP_READ16:
196 return "GP16R";
197 case UNIFI_PUTEST_GP_WRITE16:
198 return "GP16W";
199 default:
200 return "ERROR: unrecognised command";
204 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
205 int uf_register_hip_offline_debug(unifi_priv_t *priv)
207 ul_client_t *udi_cli;
208 int i;
210 udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event);
211 if (udi_cli == NULL) {
212 /* Too many clients already using this device */
213 unifi_error(priv, "Too many UDI clients already open\n");
214 return -ENOSPC;
216 unifi_trace(priv, UDBG1, "Offline HIP client is registered\n");
218 down(&priv->udi_logging_mutex);
219 udi_cli->event_hook = udi_log_event;
220 unifi_set_udi_hook(priv->card, logging_handler);
221 /* Log all signals by default */
222 for (i = 0; i < SIG_FILTER_SIZE; i++) {
223 udi_cli->signal_filter[i] = 0xFFFF;
225 priv->logging_client = udi_cli;
226 up(&priv->udi_logging_mutex);
228 return 0;
231 int uf_unregister_hip_offline_debug(unifi_priv_t *priv)
233 ul_client_t *udi_cli = priv->logging_client;
234 if (udi_cli == NULL)
236 unifi_error(priv, "Unknown HIP client unregister request\n");
237 return -ERANGE;
240 unifi_trace(priv, UDBG1, "Offline HIP client is unregistered\n");
242 down(&priv->udi_logging_mutex);
243 priv->logging_client = NULL;
244 udi_cli->event_hook = NULL;
245 up(&priv->udi_logging_mutex);
247 ul_deregister_client(udi_cli);
249 return 0;
251 #endif
255 * ---------------------------------------------------------------------------
256 * unifi_open
257 * unifi_release
259 * Open and release entry points for the UniFi debug driver.
261 * Arguments:
262 * Normal linux driver args.
264 * Returns:
265 * Linux error code.
266 * ---------------------------------------------------------------------------
268 static int
269 unifi_open(struct inode *inode, struct file *file)
271 int devno;
272 unifi_priv_t *priv;
273 ul_client_t *udi_cli;
275 func_enter();
277 devno = MINOR(inode->i_rdev) >> 1;
280 * Increase the ref_count for the char device clients.
281 * Make sure you call uf_put_instance() to decreace it if
282 * unifi_open returns an error.
284 priv = uf_get_instance(devno);
285 if (priv == NULL) {
286 unifi_error(NULL, "unifi_open: No device present\n");
287 func_exit();
288 return -ENODEV;
291 /* Register this instance in the client's list. */
292 /* The minor number determines the nature of the client (Unicli or SME). */
293 if (MINOR(inode->i_rdev) & 0x1) {
294 udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event);
295 if (udi_cli == NULL) {
296 /* Too many clients already using this device */
297 unifi_error(priv, "Too many clients already open\n");
298 uf_put_instance(devno);
299 func_exit();
300 return -ENOSPC;
302 unifi_trace(priv, UDBG1, "Client is registered to /dev/unifiudi%d\n", devno);
303 } else {
305 * Even-numbered device nodes are the control application.
306 * This is the userspace helper containing SME or
307 * unifi_manager.
310 down(&udi_mutex);
312 #ifdef CSR_SME_USERSPACE
313 /* Check if a config client is already attached */
314 if (priv->sme_cli) {
315 up(&udi_mutex);
316 uf_put_instance(devno);
318 unifi_info(priv, "There is already a configuration client using the character device\n");
319 func_exit();
320 return -EBUSY;
322 #endif /* CSR_SME_USERSPACE */
324 #ifdef CSR_SUPPORT_SME
325 udi_cli = ul_register_client(priv,
326 CLI_USING_WIRE_FORMAT | CLI_SME_USERSPACE,
327 sme_log_event);
328 #else
329 /* Config client for native driver */
330 udi_cli = ul_register_client(priv,
332 sme_native_log_event);
333 #endif
334 if (udi_cli == NULL) {
335 /* Too many clients already using this device */
336 up(&udi_mutex);
337 uf_put_instance(devno);
339 unifi_error(priv, "Too many clients already open\n");
340 func_exit();
341 return -ENOSPC;
345 * Fill-in the pointer to the configuration client.
346 * This is the SME userspace helper or unifi_manager.
347 * Not used in the SME embedded version.
349 unifi_trace(priv, UDBG1, "SME client (id:%d s:0x%X) is registered\n",
350 udi_cli->client_id, udi_cli->sender_id);
351 /* Store the SME UniFi Linux Client */
352 if (priv->sme_cli == NULL) {
353 priv->sme_cli = udi_cli;
356 up(&udi_mutex);
361 * Store the pointer to the client.
362 * All char driver's entry points will pass this pointer.
364 file->private_data = udi_cli;
366 func_exit();
367 return 0;
368 } /* unifi_open() */
371 static int
372 unifi_release(struct inode *inode, struct file *filp)
374 ul_client_t *udi_cli = (void*)filp->private_data;
375 int devno;
376 unifi_priv_t *priv;
378 func_enter();
380 priv = uf_find_instance(udi_cli->instance);
381 if (!priv) {
382 unifi_error(priv, "unifi_close: instance for device not found\n");
383 return -ENODEV;
386 devno = MINOR(inode->i_rdev) >> 1;
388 /* Even device nodes are the config client (i.e. SME or unifi_manager) */
389 if ((MINOR(inode->i_rdev) & 0x1) == 0) {
391 if (priv->sme_cli != udi_cli) {
392 unifi_notice(priv, "Surprise closing config device: not the sme client\n");
394 unifi_notice(priv, "SME client close (unifi%d)\n", devno);
397 * Clear sme_cli before calling unifi_sys_... so it doesn't try to
398 * queue a reply to the (now gone) SME.
400 down(&udi_mutex);
401 priv->sme_cli = NULL;
402 up(&udi_mutex);
404 #ifdef CSR_SME_USERSPACE
405 /* Power-down when config client closes */
407 CsrWifiRouterCtrlWifiOffReq req = {{CSR_WIFI_ROUTER_CTRL_HIP_REQ, 0, 0, 0, NULL}};
408 CsrWifiRouterCtrlWifiOffReqHandler(priv, &req.common);
411 uf_sme_deinit(priv);
413 /* It is possible that a blocking SME request was made from another process
414 * which did not get read by the SME before the WifiOffReq.
415 * So check for a pending request which will go unanswered and cancel
416 * the wait for event. As only one blocking request can be in progress at
417 * a time, up to one event should be completed.
419 uf_sme_cancel_request(priv, 0);
421 #endif /* CSR_SME_USERSPACE */
422 } else {
424 unifi_trace(priv, UDBG2, "UDI client close (unifiudi%d)\n", devno);
426 /* If the pointer matches the logging client, stop logging. */
427 down(&priv->udi_logging_mutex);
428 if (udi_cli == priv->logging_client) {
429 priv->logging_client = NULL;
431 up(&priv->udi_logging_mutex);
433 if (udi_cli == priv->amp_client) {
434 priv->amp_client = NULL;
438 /* Deregister this instance from the client's list. */
439 ul_deregister_client(udi_cli);
441 uf_put_instance(devno);
443 return 0;
444 } /* unifi_release() */
449 * ---------------------------------------------------------------------------
450 * unifi_read
452 * The read() driver entry point.
454 * Arguments:
455 * filp The file descriptor returned by unifi_open()
456 * p The user space buffer to copy the read data
457 * len The size of the p buffer
458 * poff
460 * Returns:
461 * number of bytes read or an error code on failure
462 * ---------------------------------------------------------------------------
464 static ssize_t
465 unifi_read(struct file *filp, char *p, size_t len, loff_t *poff)
467 ul_client_t *pcli = (void*)filp->private_data;
468 unifi_priv_t *priv;
469 udi_log_t *logptr = NULL;
470 udi_msg_t *msgptr;
471 struct list_head *l;
472 int msglen;
474 func_enter();
476 priv = uf_find_instance(pcli->instance);
477 if (!priv) {
478 unifi_error(priv, "invalid priv\n");
479 return -ENODEV;
482 if (!pcli->udi_enabled) {
483 unifi_error(priv, "unifi_read: unknown client.");
484 return -EINVAL;
487 if (list_empty(&pcli->udi_log)) {
488 if (filp->f_flags & O_NONBLOCK) {
489 /* Non-blocking - just return if the udi_log is empty */
490 return 0;
491 } else {
492 /* Blocking - wait on the UDI wait queue */
493 if (wait_event_interruptible(pcli->udi_wq,
494 !list_empty(&pcli->udi_log)))
496 unifi_error(priv, "unifi_read: wait_event_interruptible failed.");
497 return -ERESTARTSYS;
502 /* Read entry from list head and remove it from the list */
503 if (down_interruptible(&pcli->udi_sem)) {
504 return -ERESTARTSYS;
506 l = pcli->udi_log.next;
507 list_del(l);
508 up(&pcli->udi_sem);
510 /* Get a pointer to whole struct */
511 logptr = list_entry(l, udi_log_t, q);
512 if (logptr == NULL) {
513 unifi_error(priv, "unifi_read: failed to get event.\n");
514 return -EINVAL;
517 /* Get the real message */
518 msgptr = &logptr->msg;
519 msglen = msgptr->length;
520 if (msglen > len) {
521 printk(KERN_WARNING "truncated read to %d actual msg len is %lu\n", msglen, (long unsigned int)len);
522 msglen = len;
525 /* and pass it to the client (SME or Unicli). */
526 if (copy_to_user(p, msgptr, msglen))
528 printk(KERN_ERR "Failed to copy UDI log to user\n");
529 kfree(logptr);
530 return -EFAULT;
533 /* It is our resposibility to free the message buffer. */
534 kfree(logptr);
536 func_exit_r(msglen);
537 return msglen;
539 } /* unifi_read() */
544 * ---------------------------------------------------------------------------
545 * udi_send_signal_unpacked
547 * Sends an unpacked signal to UniFi.
549 * Arguments:
550 * priv Pointer to private context struct
551 * data Pointer to request structure and data to send
552 * data_len Length of data in data pointer.
554 * Returns:
555 * Number of bytes written, error otherwise.
557 * Notes:
558 * All clients that use this function to send a signal to the unifi
559 * must use the host formatted structures.
560 * ---------------------------------------------------------------------------
562 static int
563 udi_send_signal_unpacked(unifi_priv_t *priv, unsigned char* data, uint data_len)
565 CSR_SIGNAL *sigptr = (CSR_SIGNAL*)data;
566 CSR_DATAREF *datarefptr;
567 bulk_data_param_t bulk_data;
568 uint signal_size, i;
569 uint bulk_data_offset = 0;
570 int bytecount, r;
571 CsrResult csrResult;
573 /* Number of bytes in the signal */
574 signal_size = SigGetSize(sigptr);
575 if (!signal_size || (signal_size > data_len)) {
576 unifi_error(priv, "unifi_sme_mlme_req - Invalid signal 0x%x size should be %d bytes\n",
577 sigptr->SignalPrimitiveHeader.SignalId,
578 signal_size);
579 return -EINVAL;
581 bytecount = signal_size;
583 /* Get a pointer to the information of the first data reference */
584 datarefptr = (CSR_DATAREF*)&sigptr->u;
586 /* Initialize the offset in the data buffer, bulk data is right after the signal. */
587 bulk_data_offset = signal_size;
589 /* store the references and the size of the bulk data to the bulkdata structure */
590 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
591 /* the length of the bulk data is in the signal */
592 if ((datarefptr+i)->DataLength) {
593 void *dest;
595 csrResult = unifi_net_data_malloc(priv, &bulk_data.d[i], (datarefptr+i)->DataLength);
596 if (csrResult != CSR_RESULT_SUCCESS) {
597 unifi_error(priv, "udi_send_signal_unpacked: failed to allocate request_data.\n");
598 return -EIO;
601 dest = (void*)bulk_data.d[i].os_data_ptr;
602 memcpy(dest, data + bulk_data_offset, bulk_data.d[i].data_length);
603 } else {
604 bulk_data.d[i].data_length = 0;
607 bytecount += bulk_data.d[i].data_length;
608 /* advance the offset, to point the next bulk data */
609 bulk_data_offset += bulk_data.d[i].data_length;
613 unifi_trace(priv, UDBG3, "SME Send: signal 0x%.4X\n", sigptr->SignalPrimitiveHeader.SignalId);
615 /* Send the signal. */
616 r = ul_send_signal_unpacked(priv, sigptr, &bulk_data);
617 if (r < 0) {
618 unifi_error(priv, "udi_send_signal_unpacked: send failed (%d)\n", r);
619 for(i=0;i<UNIFI_MAX_DATA_REFERENCES;i++) {
620 if(bulk_data.d[i].data_length != 0) {
621 unifi_net_data_free(priv, &bulk_data.d[i]);
624 func_exit();
625 return -EIO;
628 return bytecount;
629 } /* udi_send_signal_unpacked() */
634 * ---------------------------------------------------------------------------
635 * udi_send_signal_raw
637 * Sends a packed signal to UniFi.
639 * Arguments:
640 * priv Pointer to private context struct
641 * buf Pointer to request structure and data to send
642 * buflen Length of data in data pointer.
644 * Returns:
645 * Number of bytes written, error otherwise.
647 * Notes:
648 * All clients that use this function to send a signal to the unifi
649 * must use the wire formatted structures.
650 * ---------------------------------------------------------------------------
652 static int
653 udi_send_signal_raw(unifi_priv_t *priv, unsigned char *buf, int buflen)
655 int signal_size;
656 int sig_id;
657 bulk_data_param_t data_ptrs;
658 int i, r;
659 unsigned int num_data_refs;
660 int bytecount;
661 CsrResult csrResult;
663 func_enter();
666 * The signal is the first thing in buf, the signal id is the
667 * first 16 bits of the signal.
669 /* Number of bytes in the signal */
670 sig_id = GET_SIGNAL_ID(buf);
671 signal_size = buflen;
672 signal_size -= GET_PACKED_DATAREF_LEN(buf, 0);
673 signal_size -= GET_PACKED_DATAREF_LEN(buf, 1);
674 if ((signal_size <= 0) || (signal_size > buflen)) {
675 unifi_error(priv, "udi_send_signal_raw - Couldn't find length of signal 0x%x\n",
676 sig_id);
677 func_exit();
678 return -EINVAL;
680 unifi_trace(priv, UDBG2, "udi_send_signal_raw: signal 0x%.4X len:%d\n",
681 sig_id, signal_size);
682 /* Zero the data ref arrays */
683 memset(&data_ptrs, 0, sizeof(data_ptrs));
686 * Find the number of associated bulk data packets. Scan through
687 * the data refs to check that we have enough data and pick out
688 * pointers to appended bulk data.
690 num_data_refs = 0;
691 bytecount = signal_size;
693 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i)
695 unsigned int len = GET_PACKED_DATAREF_LEN(buf, i);
696 unifi_trace(priv, UDBG3, "udi_send_signal_raw: data_ref length = %d\n", len);
698 if (len != 0) {
699 void *dest;
701 csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[i], len);
702 if (csrResult != CSR_RESULT_SUCCESS) {
703 unifi_error(priv, "udi_send_signal_raw: failed to allocate request_data.\n");
704 return -EIO;
707 dest = (void*)data_ptrs.d[i].os_data_ptr;
708 memcpy(dest, buf + bytecount, len);
710 bytecount += len;
711 num_data_refs++;
713 data_ptrs.d[i].data_length = len;
716 unifi_trace(priv, UDBG3, "Queueing signal 0x%.4X from UDI with %u data refs\n",
717 sig_id,
718 num_data_refs);
720 if (bytecount > buflen) {
721 unifi_error(priv, "udi_send_signal_raw: Not enough data (%d instead of %d)\n", buflen, bytecount);
722 func_exit();
723 return -EINVAL;
726 /* Send the signal calling the function that uses the wire-formatted signals. */
727 r = ul_send_signal_raw(priv, buf, signal_size, &data_ptrs);
728 if (r < 0) {
729 unifi_error(priv, "udi_send_signal_raw: send failed (%d)\n", r);
730 func_exit();
731 return -EIO;
734 #ifdef CSR_NATIVE_LINUX
735 if (sig_id == CSR_MLME_POWERMGT_REQUEST_ID) {
736 int power_mode = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((buf +
737 SIZEOF_SIGNAL_HEADER + (UNIFI_MAX_DATA_REFERENCES*SIZEOF_DATAREF)));
738 #ifdef CSR_SUPPORT_WEXT
739 /* Overide the wext power mode to the new value */
740 priv->wext_conf.power_mode = power_mode;
741 #endif
742 /* Configure deep sleep signaling */
743 if (power_mode || (priv->interfacePriv[0]->connected == UnifiNotConnected)) {
744 csrResult = unifi_configure_low_power_mode(priv->card,
745 UNIFI_LOW_POWER_ENABLED,
746 UNIFI_PERIODIC_WAKE_HOST_DISABLED);
747 } else {
748 csrResult = unifi_configure_low_power_mode(priv->card,
749 UNIFI_LOW_POWER_DISABLED,
750 UNIFI_PERIODIC_WAKE_HOST_DISABLED);
753 #endif
755 func_exit_r(bytecount);
757 return bytecount;
758 } /* udi_send_signal_raw */
761 * ---------------------------------------------------------------------------
762 * unifi_write
764 * The write() driver entry point.
765 * A UniFi Debug Interface client such as unicli can write a signal
766 * plus bulk data to the driver for sending to the UniFi chip.
768 * Only one signal may be sent per write operation.
770 * Arguments:
771 * filp The file descriptor returned by unifi_open()
772 * p The user space buffer to get the data from
773 * len The size of the p buffer
774 * poff
776 * Returns:
777 * number of bytes written or an error code on failure
778 * ---------------------------------------------------------------------------
780 static ssize_t
781 unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff)
783 ul_client_t *pcli = (ul_client_t*)filp->private_data;
784 unifi_priv_t *priv;
785 unsigned char *buf;
786 unsigned char *bufptr;
787 int remaining;
788 int bytes_written;
789 int r;
790 bulk_data_param_t bulkdata;
791 CsrResult csrResult;
793 func_enter();
795 priv = uf_find_instance(pcli->instance);
796 if (!priv) {
797 unifi_error(priv, "invalid priv\n");
798 return -ENODEV;
801 unifi_trace(priv, UDBG5, "unifi_write: len = %d\n", len);
803 if (!pcli->udi_enabled) {
804 unifi_error(priv, "udi disabled\n");
805 return -EINVAL;
809 * AMP client sends only one signal at a time, so we can use
810 * unifi_net_data_malloc to save the extra copy.
812 if (pcli == priv->amp_client) {
813 int signal_size;
814 int sig_id;
815 unsigned char *signal_buf;
816 char *user_data_buf;
818 csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], len);
819 if (csrResult != CSR_RESULT_SUCCESS) {
820 unifi_error(priv, "unifi_write: failed to allocate request_data.\n");
821 func_exit();
822 return -ENOMEM;
825 user_data_buf = (char*)bulkdata.d[0].os_data_ptr;
827 /* Get the data from the AMP client. */
828 if (copy_from_user((void*)user_data_buf, p, len)) {
829 unifi_error(priv, "unifi_write: copy from user failed\n");
830 unifi_net_data_free(priv, &bulkdata.d[0]);
831 func_exit();
832 return -EFAULT;
835 bulkdata.d[1].os_data_ptr = NULL;
836 bulkdata.d[1].data_length = 0;
838 /* Number of bytes in the signal */
839 sig_id = GET_SIGNAL_ID(bulkdata.d[0].os_data_ptr);
840 signal_size = len;
841 signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 0);
842 signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 1);
843 if ((signal_size <= 0) || (signal_size > len)) {
844 unifi_error(priv, "unifi_write - Couldn't find length of signal 0x%x\n",
845 sig_id);
846 unifi_net_data_free(priv, &bulkdata.d[0]);
847 func_exit();
848 return -EINVAL;
851 unifi_trace(priv, UDBG2, "unifi_write: signal 0x%.4X len:%d\n",
852 sig_id, signal_size);
854 /* Allocate a buffer for the signal */
855 signal_buf = kmalloc(signal_size, GFP_KERNEL);
856 if (!signal_buf) {
857 unifi_net_data_free(priv, &bulkdata.d[0]);
858 func_exit();
859 return -ENOMEM;
862 /* Get the signal from the os_data_ptr */
863 memcpy(signal_buf, bulkdata.d[0].os_data_ptr, signal_size);
864 signal_buf[5] = (pcli->sender_id >> 8) & 0xff;
866 if (signal_size < len) {
867 /* Remove the signal from the os_data_ptr */
868 bulkdata.d[0].data_length -= signal_size;
869 bulkdata.d[0].os_data_ptr += signal_size;
870 } else {
871 bulkdata.d[0].data_length = 0;
872 bulkdata.d[0].os_data_ptr = NULL;
875 /* Send the signal calling the function that uses the wire-formatted signals. */
876 r = ul_send_signal_raw(priv, signal_buf, signal_size, &bulkdata);
877 if (r < 0) {
878 unifi_error(priv, "unifi_write: send failed (%d)\n", r);
879 if (bulkdata.d[0].os_data_ptr != NULL) {
880 unifi_net_data_free(priv, &bulkdata.d[0]);
884 /* Free the signal buffer and return */
885 kfree(signal_buf);
886 return len;
889 buf = kmalloc(len, GFP_KERNEL);
890 if (!buf) {
891 return -ENOMEM;
894 /* Get the data from the client (SME or Unicli). */
895 if (copy_from_user((void*)buf, p, len)) {
896 unifi_error(priv, "copy from user failed\n");
897 kfree(buf);
898 return -EFAULT;
902 * In SME userspace build read() contains a SYS or MGT message.
903 * Note that even though the SME sends one signal at a time, we can not
904 * use unifi_net_data_malloc because in the early stages, before having
905 * initialised the core, it will fail since the I/O block size is unknown.
907 #ifdef CSR_SME_USERSPACE
908 if (pcli->configuration & CLI_SME_USERSPACE) {
909 CsrWifiRouterTransportRecv(priv, buf, len);
910 kfree(buf);
911 return len;
913 #endif
915 /* ul_send_signal_raw will do a sanity check of len against signal content */
918 * udi_send_signal_raw() and udi_send_signal_unpacked() return the number of bytes consumed.
919 * A write call can pass multiple signal concatenated together.
921 bytes_written = 0;
922 remaining = len;
923 bufptr = buf;
924 while (remaining > 0)
926 int r;
929 * Set the SenderProcessId.
930 * The SignalPrimitiveHeader is the first 3 16-bit words of the signal,
931 * the SenderProcessId is bytes 4,5.
932 * The MSB of the sender ID needs to be set to the client ID.
933 * The LSB is controlled by the SME.
935 bufptr[5] = (pcli->sender_id >> 8) & 0xff;
937 /* use the appropriate interface, depending on the clients' configuration */
938 if (pcli->configuration & CLI_USING_WIRE_FORMAT) {
939 unifi_trace(priv, UDBG1, "unifi_write: call udi_send_signal().\n");
940 r = udi_send_signal_raw(priv, bufptr, remaining);
941 } else {
942 r = udi_send_signal_unpacked(priv, bufptr, remaining);
944 if (r < 0) {
945 /* Set the return value to the error code */
946 unifi_error(priv, "unifi_write: (udi or sme)_send_signal() returns %d\n", r);
947 bytes_written = r;
948 break;
950 bufptr += r;
951 remaining -= r;
952 bytes_written += r;
955 kfree(buf);
957 func_exit_r(bytes_written);
959 return bytes_written;
960 } /* unifi_write() */
963 static const char* build_type_to_string(unsigned char build_type)
965 switch (build_type)
967 case UNIFI_BUILD_NME: return "NME";
968 case UNIFI_BUILD_WEXT: return "WEXT";
969 case UNIFI_BUILD_AP: return "AP";
971 return "unknown";
976 * ----------------------------------------------------------------
977 * unifi_ioctl
979 * Ioctl handler for unifi driver.
981 * Arguments:
982 * inodep Pointer to inode structure.
983 * filp Pointer to file structure.
984 * cmd Ioctl cmd passed by user.
985 * arg Ioctl arg passed by user.
987 * Returns:
988 * 0 on success, -ve error code on error.
989 * ----------------------------------------------------------------
991 static long
992 unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
994 ul_client_t *pcli = (ul_client_t*)filp->private_data;
995 unifi_priv_t *priv;
996 struct net_device *dev;
997 int r = 0;
998 int int_param, i;
999 u8* buf;
1000 CsrResult csrResult;
1001 #if (defined CSR_SUPPORT_SME)
1002 unifi_cfg_command_t cfg_cmd;
1003 #if (defined CSR_SUPPORT_WEXT)
1004 CsrWifiSmeCoexConfig coex_config;
1005 unsigned char uchar_param;
1006 unsigned char varbind[MAX_VARBIND_LENGTH];
1007 int vblen;
1008 #endif
1009 #endif
1010 unifi_putest_command_t putest_cmd;
1012 priv = uf_find_instance(pcli->instance);
1013 if (!priv) {
1014 unifi_error(priv, "ioctl error: unknown instance=%d\n", pcli->instance);
1015 r = -ENODEV;
1016 goto out;
1018 unifi_trace(priv, UDBG5, "unifi_ioctl: cmd=0x%X, arg=0x%lX\n", cmd, arg);
1020 switch (cmd) {
1022 case UNIFI_GET_UDI_ENABLE:
1023 unifi_trace(priv, UDBG4, "UniFi Get UDI Enable\n");
1025 down(&priv->udi_logging_mutex);
1026 int_param = (priv->logging_client == NULL) ? 0 : 1;
1027 up(&priv->udi_logging_mutex);
1029 if (put_user(int_param, (int*)arg))
1031 unifi_error(priv, "UNIFI_GET_UDI_ENABLE: Failed to copy to user\n");
1032 r = -EFAULT;
1033 goto out;
1035 break;
1037 case UNIFI_SET_UDI_ENABLE:
1038 unifi_trace(priv, UDBG4, "UniFi Set UDI Enable\n");
1039 if (get_user(int_param, (int*)arg))
1041 unifi_error(priv, "UNIFI_SET_UDI_ENABLE: Failed to copy from user\n");
1042 r = -EFAULT;
1043 goto out;
1046 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
1047 if (log_hip_signals) {
1048 unifi_error(priv, "omnicli cannot be used when log_hip_signals is used\n");
1049 r = -EFAULT;
1050 goto out;
1052 #endif
1054 down(&priv->udi_logging_mutex);
1055 if (int_param) {
1056 pcli->event_hook = udi_log_event;
1057 unifi_set_udi_hook(priv->card, logging_handler);
1058 /* Log all signals by default */
1059 for (i = 0; i < SIG_FILTER_SIZE; i++) {
1060 pcli->signal_filter[i] = 0xFFFF;
1062 priv->logging_client = pcli;
1064 } else {
1065 priv->logging_client = NULL;
1066 pcli->event_hook = NULL;
1068 up(&priv->udi_logging_mutex);
1070 break;
1072 case UNIFI_SET_MIB:
1073 unifi_trace(priv, UDBG4, "UniFi Set MIB\n");
1074 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1075 /* Read first 2 bytes and check length */
1076 if (copy_from_user((void*)varbind, (void*)arg, 2)) {
1077 unifi_error(priv,
1078 "UNIFI_SET_MIB: Failed to copy in varbind header\n");
1079 r = -EFAULT;
1080 goto out;
1082 vblen = varbind[1];
1083 if ((vblen + 2) > MAX_VARBIND_LENGTH) {
1084 unifi_error(priv,
1085 "UNIFI_SET_MIB: Varbind too long (%d, limit %d)\n",
1086 (vblen+2), MAX_VARBIND_LENGTH);
1087 r = -EINVAL;
1088 goto out;
1090 /* Read rest of varbind */
1091 if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) {
1092 unifi_error(priv, "UNIFI_SET_MIB: Failed to copy in varbind\n");
1093 r = -EFAULT;
1094 goto out;
1097 /* send to SME */
1098 vblen += 2;
1099 r = sme_mgt_mib_set(priv, varbind, vblen);
1100 if (r) {
1101 goto out;
1103 #else
1104 unifi_notice(priv, "UNIFI_SET_MIB: Unsupported.\n");
1105 #endif /* CSR_SUPPORT_WEXT */
1106 break;
1108 case UNIFI_GET_MIB:
1109 unifi_trace(priv, UDBG4, "UniFi Get MIB\n");
1110 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1111 /* Read first 2 bytes and check length */
1112 if (copy_from_user((void*)varbind, (void*)arg, 2)) {
1113 unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind header\n");
1114 r = -EFAULT;
1115 goto out;
1117 vblen = varbind[1];
1118 if ((vblen+2) > MAX_VARBIND_LENGTH) {
1119 unifi_error(priv, "UNIFI_GET_MIB: Varbind too long (%d, limit %d)\n",
1120 (vblen+2), MAX_VARBIND_LENGTH);
1121 r = -EINVAL;
1122 goto out;
1124 /* Read rest of varbind */
1125 if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) {
1126 unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind\n");
1127 r = -EFAULT;
1128 goto out;
1131 vblen += 2;
1132 r = sme_mgt_mib_get(priv, varbind, &vblen);
1133 if (r) {
1134 goto out;
1136 /* copy out varbind */
1137 if (vblen > MAX_VARBIND_LENGTH) {
1138 unifi_error(priv,
1139 "UNIFI_GET_MIB: Varbind result too long (%d, limit %d)\n",
1140 vblen, MAX_VARBIND_LENGTH);
1141 r = -EINVAL;
1142 goto out;
1144 if (copy_to_user((void*)arg, varbind, vblen)) {
1145 r = -EFAULT;
1146 goto out;
1148 #else
1149 unifi_notice(priv, "UNIFI_GET_MIB: Unsupported.\n");
1150 #endif /* CSR_SUPPORT_WEXT */
1151 break;
1153 case UNIFI_CFG:
1154 #if (defined CSR_SUPPORT_SME)
1155 if (get_user(cfg_cmd, (unifi_cfg_command_t*)arg))
1157 unifi_error(priv, "UNIFI_CFG: Failed to get the command\n");
1158 r = -EFAULT;
1159 goto out;
1162 unifi_trace(priv, UDBG1, "UNIFI_CFG: Command is %d (t=%u) sz=%d\n",
1163 cfg_cmd, jiffies_to_msecs(jiffies), sizeof(unifi_cfg_command_t));
1164 switch (cfg_cmd) {
1165 case UNIFI_CFG_POWER:
1166 r = unifi_cfg_power(priv, (unsigned char*)arg);
1167 break;
1168 case UNIFI_CFG_POWERSAVE:
1169 r = unifi_cfg_power_save(priv, (unsigned char*)arg);
1170 break;
1171 case UNIFI_CFG_POWERSUPPLY:
1172 r = unifi_cfg_power_supply(priv, (unsigned char*)arg);
1173 break;
1174 case UNIFI_CFG_FILTER:
1175 r = unifi_cfg_packet_filters(priv, (unsigned char*)arg);
1176 break;
1177 case UNIFI_CFG_GET:
1178 r = unifi_cfg_get_info(priv, (unsigned char*)arg);
1179 break;
1180 case UNIFI_CFG_WMM_QOSINFO:
1181 r = unifi_cfg_wmm_qos_info(priv, (unsigned char*)arg);
1182 break;
1183 case UNIFI_CFG_WMM_ADDTS:
1184 r = unifi_cfg_wmm_addts(priv, (unsigned char*)arg);
1185 break;
1186 case UNIFI_CFG_WMM_DELTS:
1187 r = unifi_cfg_wmm_delts(priv, (unsigned char*)arg);
1188 break;
1189 case UNIFI_CFG_STRICT_DRAFT_N:
1190 r = unifi_cfg_strict_draft_n(priv, (unsigned char*)arg);
1191 break;
1192 case UNIFI_CFG_ENABLE_OKC:
1193 r = unifi_cfg_enable_okc(priv, (unsigned char*)arg);
1194 break;
1195 #ifdef CSR_SUPPORT_SME
1196 case UNIFI_CFG_CORE_DUMP:
1197 CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,CSR_WIFI_SME_CONTROL_INDICATION_ERROR);
1198 unifi_trace(priv, UDBG2, "UNIFI_CFG_CORE_DUMP: sent wifi off indication\n");
1199 break;
1200 #endif
1201 #ifdef CSR_SUPPORT_WEXT_AP
1202 case UNIFI_CFG_SET_AP_CONFIG:
1203 r= unifi_cfg_set_ap_config(priv,(unsigned char*)arg);
1204 break;
1205 #endif
1206 default:
1207 unifi_error(priv, "UNIFI_CFG: Unknown Command (%d)\n", cfg_cmd);
1208 r = -EINVAL;
1209 goto out;
1211 #endif
1213 break;
1215 case UNIFI_PUTEST:
1216 if (get_user(putest_cmd, (unifi_putest_command_t*)arg))
1218 unifi_error(priv, "UNIFI_PUTEST: Failed to get the command\n");
1219 r = -EFAULT;
1220 goto out;
1223 unifi_trace(priv, UDBG1, "UNIFI_PUTEST: Command is %s\n",
1224 trace_putest_cmdid(putest_cmd));
1225 switch (putest_cmd) {
1226 case UNIFI_PUTEST_START:
1227 r = unifi_putest_start(priv, (unsigned char*)arg);
1228 break;
1229 case UNIFI_PUTEST_STOP:
1230 r = unifi_putest_stop(priv, (unsigned char*)arg);
1231 break;
1232 case UNIFI_PUTEST_SET_SDIO_CLOCK:
1233 r = unifi_putest_set_sdio_clock(priv, (unsigned char*)arg);
1234 break;
1235 case UNIFI_PUTEST_CMD52_READ:
1236 r = unifi_putest_cmd52_read(priv, (unsigned char*)arg);
1237 break;
1238 case UNIFI_PUTEST_CMD52_BLOCK_READ:
1239 r = unifi_putest_cmd52_block_read(priv, (unsigned char*)arg);
1240 break;
1241 case UNIFI_PUTEST_CMD52_WRITE:
1242 r = unifi_putest_cmd52_write(priv, (unsigned char*)arg);
1243 break;
1244 case UNIFI_PUTEST_DL_FW:
1245 r = unifi_putest_dl_fw(priv, (unsigned char*)arg);
1246 break;
1247 case UNIFI_PUTEST_DL_FW_BUFF:
1248 r = unifi_putest_dl_fw_buff(priv, (unsigned char*)arg);
1249 break;
1250 case UNIFI_PUTEST_COREDUMP_PREPARE:
1251 r = unifi_putest_coredump_prepare(priv, (unsigned char*)arg);
1252 break;
1253 case UNIFI_PUTEST_GP_READ16:
1254 r = unifi_putest_gp_read16(priv, (unsigned char*)arg);
1255 break;
1256 case UNIFI_PUTEST_GP_WRITE16:
1257 r = unifi_putest_gp_write16(priv, (unsigned char*)arg);
1258 break;
1259 default:
1260 unifi_error(priv, "UNIFI_PUTEST: Unknown Command (%d)\n", putest_cmd);
1261 r = -EINVAL;
1262 goto out;
1265 break;
1266 case UNIFI_BUILD_TYPE:
1267 unifi_trace(priv, UDBG2, "UNIFI_BUILD_TYPE userspace=%s\n", build_type_to_string(*(unsigned char*)arg));
1268 #ifndef CSR_SUPPORT_WEXT_AP
1269 if (UNIFI_BUILD_AP == *(unsigned char*)arg)
1271 unifi_error(priv, "Userspace has AP support, which is incompatible\n");
1273 #endif
1275 #ifndef CSR_SUPPORT_WEXT
1276 if (UNIFI_BUILD_WEXT == *(unsigned char*)arg)
1278 unifi_error(priv, "Userspace has WEXT support, which is incompatible\n");
1280 #endif
1281 break;
1282 case UNIFI_INIT_HW:
1283 unifi_trace(priv, UDBG2, "UNIFI_INIT_HW.\n");
1284 priv->init_progress = UNIFI_INIT_NONE;
1286 #if defined(CSR_SUPPORT_WEXT) || defined (CSR_NATIVE_LINUX)
1287 /* At this point we are ready to start the SME. */
1288 r = sme_mgt_wifi_on(priv);
1289 if (r) {
1290 goto out;
1292 #endif
1294 break;
1296 case UNIFI_INIT_NETDEV:
1298 /* get the proper interfaceTagId */
1299 CsrUint16 interfaceTag=0;
1300 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
1302 dev = priv->netdev[interfaceTag];
1303 unifi_trace(priv, UDBG2, "UNIFI_INIT_NETDEV.\n");
1305 if (copy_from_user((void*)dev->dev_addr, (void*)arg, 6)) {
1306 r = -EFAULT;
1307 goto out;
1310 /* Attach the network device to the stack */
1311 if (!interfacePriv->netdev_registered)
1313 r = uf_register_netdev(priv,interfaceTag);
1314 if (r) {
1315 unifi_error(priv, "Failed to register the network device.\n");
1316 goto out;
1320 /* Apply scheduled interrupt mode, if requested by module param */
1321 if (run_bh_once != -1) {
1322 unifi_set_interrupt_mode(priv->card, (CsrUint32)run_bh_once);
1325 priv->init_progress = UNIFI_INIT_COMPLETED;
1327 /* Firmware initialisation is complete, so let the SDIO bus
1328 * clock be raised when convienent to the core.
1330 unifi_request_max_sdio_clock(priv->card);
1332 #ifdef CSR_SUPPORT_WEXT
1333 /* Notify the Android wpa_supplicant that we are ready */
1334 wext_send_started_event(priv);
1335 #endif
1337 unifi_info(priv, "UniFi ready\n");
1339 #ifdef ANDROID_BUILD
1340 /* Release the wakelock */
1341 unifi_trace(priv, UDBG1, "netdev_init: release wake lock\n");
1342 wake_unlock(&unifi_sdio_wake_lock);
1343 #endif
1344 #ifdef CSR_NATIVE_SOFTMAC /* For softmac dev, force-enable the network interface rather than wait for a connected-ind */
1346 struct net_device *dev = priv->netdev[interfaceTag];
1347 #ifdef CSR_SUPPORT_WEXT
1348 interfacePriv->wait_netdev_change = TRUE;
1349 #endif
1350 netif_carrier_on(dev);
1352 #endif
1354 break;
1355 case UNIFI_GET_INIT_STATUS:
1356 unifi_trace(priv, UDBG2, "UNIFI_GET_INIT_STATUS.\n");
1357 if (put_user(priv->init_progress, (int*)arg))
1359 printk(KERN_ERR "UNIFI_GET_INIT_STATUS: Failed to copy to user\n");
1360 r = -EFAULT;
1361 goto out;
1363 break;
1365 case UNIFI_KICK:
1366 unifi_trace(priv, UDBG4, "Kick UniFi\n");
1367 unifi_sdio_interrupt_handler(priv->card);
1368 break;
1370 case UNIFI_SET_DEBUG:
1371 unifi_debug = arg;
1372 unifi_trace(priv, UDBG4, "unifi_debug set to %d\n", unifi_debug);
1373 break;
1375 case UNIFI_SET_TRACE:
1376 /* no longer supported */
1377 r = -EINVAL;
1378 break;
1381 case UNIFI_SET_UDI_LOG_MASK:
1383 unifiio_filter_t udi_filter;
1384 uint16_t *sig_ids_addr;
1385 #define UF_MAX_SIG_IDS 128 /* Impose a sensible limit */
1387 if (copy_from_user((void*)(&udi_filter), (void*)arg, sizeof(udi_filter))) {
1388 r = -EFAULT;
1389 goto out;
1391 if ((udi_filter.action < UfSigFil_AllOn) ||
1392 (udi_filter.action > UfSigFil_SelectOff))
1394 printk(KERN_WARNING
1395 "UNIFI_SET_UDI_LOG_MASK: Bad action value: %d\n",
1396 udi_filter.action);
1397 r = -EINVAL;
1398 goto out;
1400 /* No signal list for "All" actions */
1401 if ((udi_filter.action == UfSigFil_AllOn) ||
1402 (udi_filter.action == UfSigFil_AllOff))
1404 udi_filter.num_sig_ids = 0;
1407 if (udi_filter.num_sig_ids > UF_MAX_SIG_IDS) {
1408 printk(KERN_WARNING
1409 "UNIFI_SET_UDI_LOG_MASK: too many signal ids (%d, max %d)\n",
1410 udi_filter.num_sig_ids, UF_MAX_SIG_IDS);
1411 r = -EINVAL;
1412 goto out;
1415 /* Copy in signal id list if given */
1416 if (udi_filter.num_sig_ids > 0) {
1417 /* Preserve userspace address of sig_ids array */
1418 sig_ids_addr = udi_filter.sig_ids;
1419 /* Allocate kernel memory for sig_ids and copy to it */
1420 udi_filter.sig_ids =
1421 kmalloc(udi_filter.num_sig_ids * sizeof(uint16_t), GFP_KERNEL);
1422 if (!udi_filter.sig_ids) {
1423 r = -ENOMEM;
1424 goto out;
1426 if (copy_from_user((void*)udi_filter.sig_ids,
1427 (void*)sig_ids_addr,
1428 udi_filter.num_sig_ids * sizeof(uint16_t)))
1430 kfree(udi_filter.sig_ids);
1431 r = -EFAULT;
1432 goto out;
1436 udi_set_log_filter(pcli, &udi_filter);
1438 if (udi_filter.num_sig_ids > 0) {
1439 kfree(udi_filter.sig_ids);
1442 break;
1444 case UNIFI_SET_AMP_ENABLE:
1445 unifi_trace(priv, UDBG4, "UniFi Set AMP Enable\n");
1446 if (get_user(int_param, (int*)arg))
1448 unifi_error(priv, "UNIFI_SET_AMP_ENABLE: Failed to copy from user\n");
1449 r = -EFAULT;
1450 goto out;
1453 if (int_param) {
1454 priv->amp_client = pcli;
1455 } else {
1456 priv->amp_client = NULL;
1459 int_param = 0;
1460 buf = (u8*)&int_param;
1461 buf[0] = UNIFI_SOFT_COMMAND_Q_LENGTH - 1;
1462 buf[1] = UNIFI_SOFT_TRAFFIC_Q_LENGTH - 1;
1463 if (copy_to_user((void*)arg, &int_param, sizeof(int))) {
1464 r = -EFAULT;
1465 goto out;
1467 break;
1469 case UNIFI_SET_UDI_SNAP_MASK:
1471 unifiio_snap_filter_t snap_filter;
1473 if (copy_from_user((void*)(&snap_filter), (void*)arg, sizeof(snap_filter))) {
1474 r = -EFAULT;
1475 goto out;
1478 if (pcli->snap_filter.count) {
1479 pcli->snap_filter.count = 0;
1480 CsrPmemFree(pcli->snap_filter.protocols);
1483 if (snap_filter.count == 0) {
1484 break;
1487 pcli->snap_filter.protocols = CsrPmemAlloc(snap_filter.count * sizeof(CsrUint16));
1488 if (!pcli->snap_filter.protocols) {
1489 r = -ENOMEM;
1490 goto out;
1492 if (copy_from_user((void*)pcli->snap_filter.protocols,
1493 (void*)snap_filter.protocols,
1494 snap_filter.count * sizeof(CsrUint16)))
1496 CsrPmemFree(pcli->snap_filter.protocols);
1497 r = -EFAULT;
1498 goto out;
1501 pcli->snap_filter.count = snap_filter.count;
1504 break;
1506 case UNIFI_SME_PRESENT:
1508 u8 ind;
1509 unifi_trace(priv, UDBG4, "UniFi SME Present IOCTL.\n");
1510 if (copy_from_user((void*)(&int_param), (void*)arg, sizeof(int)))
1512 printk(KERN_ERR "UNIFI_SME_PRESENT: Failed to copy from user\n");
1513 r = -EFAULT;
1514 goto out;
1517 priv->sme_is_present = int_param;
1518 if (priv->sme_is_present == 1) {
1519 ind = CONFIG_SME_PRESENT;
1520 } else {
1521 ind = CONFIG_SME_NOT_PRESENT;
1523 /* Send an indication to the helper app. */
1524 ul_log_config_ind(priv, &ind, sizeof(u8));
1526 break;
1528 case UNIFI_CFG_PERIOD_TRAFFIC:
1530 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1531 CsrWifiSmeCoexConfig coexConfig;
1532 #endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */
1533 unifi_trace(priv, UDBG4, "UniFi Configure Periodic Traffic.\n");
1534 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1535 if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) {
1536 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n");
1537 r = -EFAULT;
1538 goto out;
1541 if (uchar_param == 0) {
1542 r = sme_mgt_coex_config_get(priv, &coexConfig);
1543 if (r) {
1544 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Get unifi_CoexInfoValue failed.\n");
1545 goto out;
1547 if (copy_to_user((void*)(arg + 1),
1548 (void*)&coexConfig,
1549 sizeof(CsrWifiSmeCoexConfig))) {
1550 r = -EFAULT;
1551 goto out;
1553 goto out;
1556 if (copy_from_user((void*)(&coex_config), (void*)(arg + 1), sizeof(CsrWifiSmeCoexConfig)))
1558 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n");
1559 r = -EFAULT;
1560 goto out;
1563 coexConfig = coex_config;
1564 r = sme_mgt_coex_config_set(priv, &coexConfig);
1565 if (r) {
1566 unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Set unifi_CoexInfoValue failed.\n");
1567 goto out;
1570 #endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */
1571 break;
1573 case UNIFI_CFG_UAPSD_TRAFFIC:
1574 unifi_trace(priv, UDBG4, "UniFi Configure U-APSD Mask.\n");
1575 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
1576 if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) {
1577 unifi_error(priv, "UNIFI_CFG_UAPSD_TRAFFIC: Failed to copy from user\n");
1578 r = -EFAULT;
1579 goto out;
1581 unifi_trace(priv, UDBG4, "New U-APSD Mask: 0x%x\n", uchar_param);
1582 #endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */
1583 break;
1585 #ifndef UNIFI_DISABLE_COREDUMP
1586 case UNIFI_COREDUMP_GET_REG:
1587 unifi_trace(priv, UDBG4, "Mini-coredump data request\n");
1589 unifiio_coredump_req_t dump_req; /* Public OS layer structure */
1590 unifi_coredump_req_t priv_req; /* Private HIP structure */
1592 if (copy_from_user((void*)(&dump_req), (void*)arg, sizeof(dump_req))) {
1593 r = -EFAULT;
1594 goto out;
1596 memset(&priv_req, 0, sizeof(priv_req));
1597 priv_req.index = dump_req.index;
1598 priv_req.offset = dump_req.offset;
1600 /* Convert OS-layer's XAP memory space ID to HIP's ID in case they differ */
1601 switch (dump_req.space) {
1602 case UNIFIIO_COREDUMP_MAC_REG: priv_req.space = UNIFI_COREDUMP_MAC_REG; break;
1603 case UNIFIIO_COREDUMP_PHY_REG: priv_req.space = UNIFI_COREDUMP_PHY_REG; break;
1604 case UNIFIIO_COREDUMP_SH_DMEM: priv_req.space = UNIFI_COREDUMP_SH_DMEM; break;
1605 case UNIFIIO_COREDUMP_MAC_DMEM: priv_req.space = UNIFI_COREDUMP_MAC_DMEM; break;
1606 case UNIFIIO_COREDUMP_PHY_DMEM: priv_req.space = UNIFI_COREDUMP_PHY_DMEM; break;
1607 case UNIFIIO_COREDUMP_TRIGGER_MAGIC: priv_req.space = UNIFI_COREDUMP_TRIGGER_MAGIC; break;
1608 default:
1609 r = -EINVAL;
1610 goto out;
1613 if (priv_req.space == UNIFI_COREDUMP_TRIGGER_MAGIC) {
1614 /* Force a coredump grab now */
1615 unifi_trace(priv, UDBG2, "UNIFI_COREDUMP_GET_REG: Force capture\n");
1616 csrResult = unifi_coredump_capture(priv->card, &priv_req);
1617 r = CsrHipResultToStatus(csrResult);
1618 unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: status %d\n", r);
1619 } else {
1620 /* Retrieve the appropriate register entry */
1621 csrResult = unifi_coredump_get_value(priv->card, &priv_req);
1622 r = CsrHipResultToStatus(csrResult);
1623 if (r) {
1624 unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: Status %d\n", r);
1625 goto out;
1627 /* Update the OS-layer structure with values returned in the private */
1628 dump_req.value = priv_req.value;
1629 dump_req.timestamp = priv_req.timestamp;
1630 dump_req.requestor = priv_req.requestor;
1631 dump_req.serial = priv_req.serial;
1632 dump_req.chip_ver = priv_req.chip_ver;
1633 dump_req.fw_ver = priv_req.fw_ver;
1634 dump_req.drv_build = 0;
1636 unifi_trace(priv, UDBG6,
1637 "Dump: %d (seq %d): V:0x%04x (%d) @0x%02x:%04x = 0x%04x\n",
1638 dump_req.index, dump_req.serial,
1639 dump_req.chip_ver, dump_req.drv_build,
1640 dump_req.space, dump_req.offset, dump_req.value);
1642 if (copy_to_user((void*)arg, (void*)&dump_req, sizeof(dump_req))) {
1643 r = -EFAULT;
1644 goto out;
1647 break;
1648 #endif
1649 default:
1650 r = -EINVAL;
1653 out:
1654 return (long)r;
1655 } /* unifi_ioctl() */
1659 static unsigned int
1660 unifi_poll(struct file *filp, poll_table *wait)
1662 ul_client_t *pcli = (ul_client_t*)filp->private_data;
1663 unsigned int mask = 0;
1664 int ready;
1666 func_enter();
1668 ready = !list_empty(&pcli->udi_log);
1670 poll_wait(filp, &pcli->udi_wq, wait);
1672 if (ready) {
1673 mask |= POLLIN | POLLRDNORM; /* readable */
1676 func_exit();
1678 return mask;
1679 } /* unifi_poll() */
1684 * ---------------------------------------------------------------------------
1685 * udi_set_log_filter
1687 * Configure the bit mask that determines which signal primitives are
1688 * passed to the logging process.
1690 * Arguments:
1691 * pcli Pointer to the client to configure.
1692 * udi_filter Pointer to a unifiio_filter_t containing instructions.
1694 * Returns:
1695 * None.
1697 * Notes:
1698 * SigGetFilterPos() returns a 32-bit value that contains an index and a
1699 * mask for accessing a signal_filter array. The top 16 bits specify an
1700 * index into a signal_filter, the bottom 16 bits specify a mask to
1701 * apply.
1702 * ---------------------------------------------------------------------------
1704 static void
1705 udi_set_log_filter(ul_client_t *pcli, unifiio_filter_t *udi_filter)
1707 CsrUint32 filter_pos;
1708 int i;
1710 if (udi_filter->action == UfSigFil_AllOn)
1712 for (i = 0; i < SIG_FILTER_SIZE; i++) {
1713 pcli->signal_filter[i] = 0xFFFF;
1716 else if (udi_filter->action == UfSigFil_AllOff)
1718 for (i = 0; i < SIG_FILTER_SIZE; i++) {
1719 pcli->signal_filter[i] = 0;
1722 else if (udi_filter->action == UfSigFil_SelectOn)
1724 for (i = 0; i < udi_filter->num_sig_ids; i++) {
1725 filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]);
1726 if (filter_pos == 0xFFFFFFFF)
1728 printk(KERN_WARNING
1729 "Unrecognised signal id (0x%X) specifed in logging filter\n",
1730 udi_filter->sig_ids[i]);
1731 } else {
1732 pcli->signal_filter[filter_pos >> 16] |= (filter_pos & 0xFFFF);
1736 else if (udi_filter->action == UfSigFil_SelectOff)
1738 for (i = 0; i < udi_filter->num_sig_ids; i++) {
1739 filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]);
1740 if (filter_pos == 0xFFFFFFFF)
1742 printk(KERN_WARNING
1743 "Unrecognised signal id (0x%X) specifed in logging filter\n",
1744 udi_filter->sig_ids[i]);
1745 } else {
1746 pcli->signal_filter[filter_pos >> 16] &= ~(filter_pos & 0xFFFF);
1751 } /* udi_set_log_filter() */
1755 * ---------------------------------------------------------------------------
1756 * udi_log_event
1758 * Callback function to be registered as the UDI hook callback.
1759 * Copies the signal content into a new udi_log_t struct and adds
1760 * it to the read queue for this UDI client.
1762 * Arguments:
1763 * pcli A pointer to the client instance.
1764 * signal Pointer to the received signal.
1765 * signal_len Size of the signal structure in bytes.
1766 * bulkdata Pointers to any associated bulk data.
1767 * dir Direction of the signal. Zero means from host,
1768 * non-zero means to host.
1770 * Returns:
1771 * None.
1772 * ---------------------------------------------------------------------------
1774 void
1775 udi_log_event(ul_client_t *pcli,
1776 const u8 *signal, int signal_len,
1777 const bulk_data_param_t *bulkdata,
1778 int dir)
1780 udi_log_t *logptr;
1781 u8 *p;
1782 int i;
1783 int total_len;
1784 udi_msg_t *msgptr;
1785 CsrUint32 filter_pos;
1786 #ifdef OMNICLI_LINUX_EXTRA_LOG
1787 static volatile unsigned int printk_cpu = UINT_MAX;
1788 unsigned long long t;
1789 unsigned long nanosec_rem;
1790 unsigned long n_1000;
1791 #endif
1793 func_enter();
1795 /* Just a sanity check */
1796 if ((signal == NULL) || (signal_len <= 0)) {
1797 return;
1800 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
1801 /* When HIP offline signal logging is enabled, omnicli cannot run */
1802 if (log_hip_signals)
1804 /* Add timestamp */
1805 if (log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP)
1807 int timestamp = jiffies_to_msecs(jiffies);
1808 unifi_debug_log_to_buf("T:");
1809 unifi_debug_log_to_buf("%04X%04X ", *(((CsrUint16*)&timestamp) + 1),
1810 *(CsrUint16*)&timestamp);
1813 /* Add signal */
1814 unifi_debug_log_to_buf("S%s:%04X R:%04X D:%04X ",
1815 dir ? "T" : "F",
1816 *(CsrUint16*)signal,
1817 *(CsrUint16*)(signal + 2),
1818 *(CsrUint16*)(signal + 4));
1819 unifi_debug_hex_to_buf(signal + 6, signal_len - 6);
1821 /* Add bulk data (assume 1 bulk data per signal) */
1822 if ((log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA) &&
1823 (bulkdata->d[0].data_length > 0))
1825 unifi_debug_log_to_buf("\nD:");
1826 unifi_debug_hex_to_buf(bulkdata->d[0].os_data_ptr, bulkdata->d[0].data_length);
1828 unifi_debug_log_to_buf("\n");
1830 return;
1832 #endif
1834 #ifdef CSR_NATIVE_LINUX
1835 uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir);
1836 #endif
1839 * Apply the logging filter - only report signals that have their
1840 * bit set in the filter mask.
1842 filter_pos = SigGetFilterPos(GET_SIGNAL_ID(signal));
1844 if ((filter_pos != 0xFFFFFFFF) &&
1845 ((pcli->signal_filter[filter_pos >> 16] & (filter_pos & 0xFFFF)) == 0))
1847 /* Signal is not wanted by client */
1848 return;
1852 /* Calculate the buffer we need to store signal plus bulk data */
1853 total_len = signal_len;
1854 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
1855 total_len += bulkdata->d[i].data_length;
1858 /* Allocate log structure plus actual signal. */
1859 logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
1861 if (logptr == NULL) {
1862 printk(KERN_ERR
1863 "Failed to allocate %lu bytes for a UDI log record\n",
1864 (long unsigned int)(sizeof(udi_log_t) + total_len));
1865 return;
1868 /* Fill in udi_log struct */
1869 INIT_LIST_HEAD(&logptr->q);
1870 msgptr = &logptr->msg;
1871 msgptr->length = sizeof(udi_msg_t) + total_len;
1872 #ifdef OMNICLI_LINUX_EXTRA_LOG
1873 t = cpu_clock(printk_cpu);
1874 nanosec_rem = do_div(t, 1000000000);
1875 n_1000 = nanosec_rem/1000;
1876 msgptr->timestamp = (t <<10 ) | ((unsigned long)(n_1000 >> 10) & 0x3ff);
1877 #else
1878 msgptr->timestamp = jiffies_to_msecs(jiffies);
1879 #endif
1880 msgptr->direction = dir;
1881 msgptr->signal_length = signal_len;
1883 /* Copy signal and bulk data to the log */
1884 p = (u8 *)(msgptr + 1);
1885 memcpy(p, signal, signal_len);
1886 p += signal_len;
1888 /* Append any bulk data */
1889 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
1890 int len = bulkdata->d[i].data_length;
1893 * Len here might not be the same as the length in the bulk data slot.
1894 * The slot length will always be even, but len could be odd.
1896 if (len > 0) {
1897 if (bulkdata->d[i].os_data_ptr) {
1898 memcpy(p, bulkdata->d[i].os_data_ptr, len);
1899 } else {
1900 memset(p, 0, len);
1902 p += len;
1906 /* Add to tail of log queue */
1907 if (down_interruptible(&pcli->udi_sem)) {
1908 printk(KERN_WARNING "udi_log_event_q: Failed to get udi sem\n");
1909 kfree(logptr);
1910 func_exit();
1911 return;
1913 list_add_tail(&logptr->q, &pcli->udi_log);
1914 up(&pcli->udi_sem);
1916 /* Wake any waiting user process */
1917 wake_up_interruptible(&pcli->udi_wq);
1919 func_exit();
1920 } /* udi_log_event() */
1922 #ifdef CSR_SME_USERSPACE
1924 uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length)
1926 udi_log_t *logptr;
1927 udi_msg_t *msgptr;
1928 u8 *p;
1930 func_enter();
1932 /* Just a sanity check */
1933 if ((buffer == NULL) || (length <= 0)) {
1934 return -EINVAL;
1937 /* Allocate log structure plus actual signal. */
1938 logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC);
1939 if (logptr == NULL) {
1940 unifi_error(priv, "Failed to allocate %d bytes for an SME message\n",
1941 sizeof(udi_log_t) + length);
1942 CsrPmemFree(buffer);
1943 return -ENOMEM;
1946 /* Fill in udi_log struct */
1947 INIT_LIST_HEAD(&logptr->q);
1948 msgptr = &logptr->msg;
1949 msgptr->length = sizeof(udi_msg_t) + length;
1950 msgptr->signal_length = length;
1952 /* Copy signal and bulk data to the log */
1953 p = (u8 *)(msgptr + 1);
1954 memcpy(p, buffer, length);
1956 /* Add to tail of log queue */
1957 down(&udi_mutex);
1958 if (priv->sme_cli == NULL) {
1959 kfree(logptr);
1960 CsrPmemFree(buffer);
1961 up(&udi_mutex);
1962 unifi_info(priv, "Message for the SME dropped, SME has gone away\n");
1963 return 0;
1966 down(&priv->sme_cli->udi_sem);
1967 list_add_tail(&logptr->q, &priv->sme_cli->udi_log);
1968 up(&priv->sme_cli->udi_sem);
1970 /* Wake any waiting user process */
1971 wake_up_interruptible(&priv->sme_cli->udi_wq);
1972 up(&udi_mutex);
1974 /* It is our responsibility to free the buffer allocated in build_packed_*() */
1975 CsrPmemFree(buffer);
1977 func_exit();
1979 return 0;
1981 } /* uf_sme_queue_message() */
1982 #endif
1985 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
1986 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
1987 device_create(_class, _parent, _devno, _priv, _fmt, _args)
1988 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
1989 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
1990 device_create_drvdata(_class, _parent, _devno, _priv, _fmt, _args)
1991 #else
1992 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
1993 device_create(_class, _parent, _devno, _fmt, _args)
1994 #endif
1997 ****************************************************************************
1999 * Driver instantiation
2001 ****************************************************************************
2003 static struct file_operations unifi_fops = {
2004 .owner = THIS_MODULE,
2005 .open = unifi_open,
2006 .release = unifi_release,
2007 .read = unifi_read,
2008 .write = unifi_write,
2009 .unlocked_ioctl = unifi_ioctl,
2010 .poll = unifi_poll,
2013 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
2014 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
2015 device_create(_class, _parent, _devno, _priv, _fmt, _args)
2016 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
2017 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
2018 device_create_drvdata(_class, _parent, _devno, _priv, _fmt, _args)
2019 #else
2020 #define UF_DEVICE_CREATE(_class, _parent, _devno, _priv, _fmt, _args) \
2021 device_create(_class, _parent, _devno, _fmt, _args)
2022 #endif
2024 static dev_t unifi_first_devno;
2025 static struct class *unifi_class;
2028 int uf_create_device_nodes(unifi_priv_t *priv, int bus_id)
2030 dev_t devno;
2031 int r;
2033 cdev_init(&priv->unifi_cdev, &unifi_fops);
2035 /* cdev_init() should set the cdev owner, but it does not */
2036 priv->unifi_cdev.owner = THIS_MODULE;
2038 devno = MKDEV(MAJOR(unifi_first_devno),
2039 MINOR(unifi_first_devno) + (bus_id * 2));
2040 r = cdev_add(&priv->unifi_cdev, devno, 1);
2041 if (r) {
2042 return r;
2045 #ifdef SDIO_EXPORTS_STRUCT_DEVICE
2046 if (!UF_DEVICE_CREATE(unifi_class, priv->unifi_device,
2047 devno, priv, "unifi%d", bus_id)) {
2048 #else
2049 priv->unifi_device = UF_DEVICE_CREATE(unifi_class, NULL,
2050 devno, priv, "unifi%d", bus_id);
2051 if (priv->unifi_device == NULL) {
2052 #endif /* SDIO_EXPORTS_STRUCT_DEVICE */
2054 cdev_del(&priv->unifi_cdev);
2055 return -EINVAL;
2058 cdev_init(&priv->unifiudi_cdev, &unifi_fops);
2060 /* cdev_init() should set the cdev owner, but it does not */
2061 priv->unifiudi_cdev.owner = THIS_MODULE;
2063 devno = MKDEV(MAJOR(unifi_first_devno),
2064 MINOR(unifi_first_devno) + (bus_id * 2) + 1);
2065 r = cdev_add(&priv->unifiudi_cdev, devno, 1);
2066 if (r) {
2067 device_destroy(unifi_class, priv->unifi_cdev.dev);
2068 cdev_del(&priv->unifi_cdev);
2069 return r;
2072 if (!UF_DEVICE_CREATE(unifi_class,
2073 #ifdef SDIO_EXPORTS_STRUCT_DEVICE
2074 priv->unifi_device,
2075 #else
2076 NULL,
2077 #endif /* SDIO_EXPORTS_STRUCT_DEVICE */
2078 devno, priv, "unifiudi%d", bus_id)) {
2079 device_destroy(unifi_class, priv->unifi_cdev.dev);
2080 cdev_del(&priv->unifiudi_cdev);
2081 cdev_del(&priv->unifi_cdev);
2082 return -EINVAL;
2085 return 0;
2089 void uf_destroy_device_nodes(unifi_priv_t *priv)
2091 device_destroy(unifi_class, priv->unifiudi_cdev.dev);
2092 device_destroy(unifi_class, priv->unifi_cdev.dev);
2093 cdev_del(&priv->unifiudi_cdev);
2094 cdev_del(&priv->unifi_cdev);
2100 * ----------------------------------------------------------------
2101 * uf_create_debug_device
2103 * Allocates device numbers for unifi character device nodes
2104 * and creates a unifi class in sysfs
2106 * Arguments:
2107 * fops Pointer to the char device operations structure.
2109 * Returns:
2110 * 0 on success, -ve error code on error.
2111 * ----------------------------------------------------------------
2113 static int
2114 uf_create_debug_device(struct file_operations *fops)
2116 int ret;
2118 /* Allocate two device numbers for each device. */
2119 ret = alloc_chrdev_region(&unifi_first_devno, 0, MAX_UNIFI_DEVS*2, UNIFI_NAME);
2120 if (ret) {
2121 unifi_error(NULL, "Failed to add alloc dev numbers: %d\n", ret);
2122 return ret;
2125 /* Create a UniFi class */
2126 unifi_class = class_create(THIS_MODULE, UNIFI_NAME);
2127 if (IS_ERR(unifi_class)) {
2128 unifi_error(NULL, "Failed to create UniFi class\n");
2130 /* Release device numbers */
2131 unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2);
2132 unifi_first_devno = 0;
2133 return -EINVAL;
2136 return 0;
2137 } /* uf_create_debug_device() */
2141 * ----------------------------------------------------------------
2142 * uf_remove_debug_device
2144 * Destroys the unifi class and releases the allocated
2145 * device numbers for unifi character device nodes.
2147 * Arguments:
2149 * Returns:
2150 * ----------------------------------------------------------------
2152 static void
2153 uf_remove_debug_device(void)
2155 /* Destroy the UniFi class */
2156 class_destroy(unifi_class);
2158 /* Release device numbers */
2159 unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2);
2160 unifi_first_devno = 0;
2162 } /* uf_remove_debug_device() */
2166 * ---------------------------------------------------------------------------
2168 * Module loading.
2170 * ---------------------------------------------------------------------------
2172 int __init
2173 unifi_load(void)
2175 int r;
2177 printk("UniFi SDIO Driver: %s %s %s\n",
2178 CSR_WIFI_VERSION,
2179 __DATE__, __TIME__);
2181 #ifdef CSR_SME_USERSPACE
2182 #ifdef CSR_SUPPORT_WEXT
2183 printk("CSR SME with WEXT support\n");
2184 #else
2185 printk("CSR SME no WEXT support\n");
2186 #endif /* CSR_SUPPORT_WEXT */
2187 #endif /* CSR_SME_USERSPACE */
2189 #ifdef CSR_NATIVE_LINUX
2190 #ifdef CSR_SUPPORT_WEXT
2191 #error WEXT unsupported in the native driver
2192 #endif
2193 printk("CSR native no WEXT support\n");
2194 #endif
2195 #ifdef CSR_WIFI_SPLIT_PATCH
2196 printk("Split patch support\n");
2197 #endif
2198 printk("Kernel %d.%d.%d\n",
2199 ((LINUX_VERSION_CODE) >> 16) & 0xff,
2200 ((LINUX_VERSION_CODE) >> 8) & 0xff,
2201 (LINUX_VERSION_CODE) & 0xff);
2203 * Instantiate the /dev/unifi* device nodes.
2204 * We must do this before registering with the SDIO driver because it
2205 * will immediately call the "insert" callback if the card is
2206 * already present.
2208 r = uf_create_debug_device(&unifi_fops);
2209 if (r) {
2210 return r;
2213 /* Now register with the SDIO driver */
2214 r = uf_sdio_load();
2215 if (r) {
2216 uf_remove_debug_device();
2217 return r;
2220 if (sdio_block_size > -1) {
2221 unifi_info(NULL, "sdio_block_size %d\n", sdio_block_size);
2224 if (sdio_byte_mode) {
2225 unifi_info(NULL, "sdio_byte_mode\n");
2228 if (disable_power_control) {
2229 unifi_info(NULL, "disable_power_control\n");
2232 if (disable_hw_reset) {
2233 unifi_info(NULL, "disable_hw_reset\n");
2236 if (enable_wol) {
2237 unifi_info(NULL, "enable_wol %d\n", enable_wol);
2240 if (run_bh_once != -1) {
2241 unifi_info(NULL, "run_bh_once %d\n", run_bh_once);
2244 return 0;
2245 } /* unifi_load() */
2248 void __exit
2249 unifi_unload(void)
2251 /* The SDIO remove hook will call unifi_disconnect(). */
2252 uf_sdio_unload();
2254 uf_remove_debug_device();
2256 } /* unifi_unload() */
2258 module_init(unifi_load);
2259 module_exit(unifi_unload);
2261 MODULE_DESCRIPTION("UniFi Device driver");
2262 MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
2263 MODULE_LICENSE("GPL and additional rights");