Root/drivers/staging/csr/drv.c

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

Archive Download this file



interactive