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