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