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