• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ---------------------------------------------------------------------------
3  *  FILE:     drv.c
4  *
5  *  PURPOSE:
6  *      Conventional device interface for debugging/monitoring of the
7  *      driver and h/w using unicli. This interface is also being used
8  *      by the SME linux implementation and the helper apps.
9  *
10  * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
11  *
12  * Refer to LICENSE.txt included with this source code for details on
13  * the license terms.
14  *
15  * ---------------------------------------------------------------------------
16  */
17 
18 /*
19  * Porting Notes:
20  * Part of this file contains an example for how to glue the OS layer
21  * with the HIP core lib, the SDIO glue layer, and the SME.
22  *
23  * When the unifi_sdio.ko modules loads, the linux kernel calls unifi_load().
24  * unifi_load() calls uf_sdio_load() which is exported by the SDIO glue
25  * layer. uf_sdio_load() registers this driver with the underlying SDIO driver.
26  * When a card is detected, the SDIO glue layer calls register_unifi_sdio()
27  * to pass the SDIO function context and ask the OS layer to initialise
28  * the card. register_unifi_sdio() allocates all the private data of the OS
29  * layer and calls uf_run_unifihelper() to start the SME. The SME calls
30  * unifi_sys_wifi_on_req() which uses the HIP core lib to initialise the card.
31  */
32 
33 #include <linux/init.h>
34 #include <linux/slab.h>
35 #include <linux/poll.h>
36 #include <asm/uaccess.h>
37 #include <linux/jiffies.h>
38 #include <linux/version.h>
39 
40 #include "csr_wifi_hip_unifiversion.h"
41 #include "unifi_priv.h"
42 #include "csr_wifi_hip_conversions.h"
43 #include "unifi_native.h"
44 
45 /* Module parameter variables */
46 int buswidth = 0;               /* 0 means use default, values 1,4 */
47 int sdio_clock = 50000;         /* kHz */
48 int unifi_debug = 0;
49 /* fw_init prevents f/w initialisation on error. */
50 int fw_init[MAX_UNIFI_DEVS] = {-1, -1};
51 int use_5g = 0;
52 int led_mask = 0;               /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */
53 int disable_hw_reset = 0;
54 int disable_power_control = 0;
55 int enable_wol = UNIFI_WOL_OFF; /* 0 for none, 1 for SDIO IRQ, 2 for PIO */
56 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
57 int tl_80211d = (int)CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB;
58 #endif
59 int sdio_block_size = -1;      /* Override SDIO block size */
60 int sdio_byte_mode = 0;        /* 0 for block mode + padding, 1 for byte mode */
61 int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS;
62 int run_bh_once = -1;          /* Set for scheduled interrupt mode, -1 = default */
63 int bh_priority = -1;
64 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
65 #define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA   (1 << 1)
66 #define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP  (1 << 2)
67 int log_hip_signals = 0;
68 #endif
69 
70 MODULE_DESCRIPTION("CSR UniFi (SDIO)");
71 
72 module_param(buswidth,    int, S_IRUGO|S_IWUSR);
73 module_param(sdio_clock,  int, S_IRUGO|S_IWUSR);
74 module_param(unifi_debug, int, S_IRUGO|S_IWUSR);
75 module_param_array(fw_init, int, NULL, S_IRUGO|S_IWUSR);
76 module_param(use_5g,      int, S_IRUGO|S_IWUSR);
77 module_param(led_mask,    int, S_IRUGO|S_IWUSR);
78 module_param(disable_hw_reset,  int, S_IRUGO|S_IWUSR);
79 module_param(disable_power_control,  int, S_IRUGO|S_IWUSR);
80 module_param(enable_wol,  int, S_IRUGO|S_IWUSR);
81 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
82 module_param(tl_80211d,   int, S_IRUGO|S_IWUSR);
83 #endif
84 module_param(sdio_block_size, int, S_IRUGO|S_IWUSR);
85 module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR);
86 module_param(coredump_max, int, S_IRUGO|S_IWUSR);
87 module_param(run_bh_once, int, S_IRUGO|S_IWUSR);
88 module_param(bh_priority, int, S_IRUGO|S_IWUSR);
89 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
90 module_param(log_hip_signals, int, S_IRUGO|S_IWUSR);
91 #endif
92 
93 MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode");
94 MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)");
95 MODULE_PARM_DESC(unifi_debug, "Diagnostic reporting level");
96 MODULE_PARM_DESC(fw_init, "Set to 0 to prevent f/w initialization on error");
97 MODULE_PARM_DESC(use_5g, "Use the 5G (802.11a) radio band");
98 MODULE_PARM_DESC(led_mask, "LED mask flags");
99 MODULE_PARM_DESC(disable_hw_reset, "Set to 1 to disable hardware reset");
100 MODULE_PARM_DESC(disable_power_control, "Set to 1 to disable SDIO power control");
101 MODULE_PARM_DESC(enable_wol, "Enable wake-on-wlan function 0=off, 1=SDIO, 2=PIO");
102 #if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT)
103 MODULE_PARM_DESC(tl_80211d, "802.11d Trust Level (1-6, default = 5)");
104 #endif
105 MODULE_PARM_DESC(sdio_block_size, "Set to override SDIO block size");
106 MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO");
107 MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate");
108 MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts");
109 MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority");
110 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
111 MODULE_PARM_DESC(log_hip_signals, "Set to 1 to enable HIP signal offline logging");
112 #endif
113 
114 
115 /* Callback for event logging to UDI clients */
116 static void udi_log_event(ul_client_t *client,
117                           const u8 *signal, int signal_len,
118                           const bulk_data_param_t *bulkdata,
119                           int dir);
120 
121 static void udi_set_log_filter(ul_client_t *pcli,
122                                unifiio_filter_t *udi_filter);
123 
124 
125 /* Mutex to protect access to  priv->sme_cli */
126 DEFINE_SEMAPHORE(udi_mutex);
127 
CsrHipResultToStatus(CsrResult csrResult)128 s32 CsrHipResultToStatus(CsrResult csrResult)
129 {
130     s32 r = -EIO;
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 
166 static const char*
trace_putest_cmdid(unifi_putest_command_t putest_cmd)167 trace_putest_cmdid(unifi_putest_command_t putest_cmd)
168 {
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 	}
195  }
196 
197 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
uf_register_hip_offline_debug(unifi_priv_t * priv)198 int 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 
uf_unregister_hip_offline_debug(unifi_priv_t * priv)224 int 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
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  */
261 static int
unifi_open(struct inode * inode,struct file * file)262 unifi_open(struct inode *inode, struct file *file)
263 {
264     int devno;
265     unifi_priv_t *priv;
266     ul_client_t *udi_cli;
267 
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");
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);
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");
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");
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 
353     return 0;
354 } /* unifi_open() */
355 
356 
357 static int
unifi_release(struct inode * inode,struct file * filp)358 unifi_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 
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);
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 
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  */
448 static ssize_t
unifi_read(struct file * filp,char * p,size_t len,loff_t * poff)449 unifi_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 
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 
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  */
543 static int
udi_send_signal_unpacked(unifi_priv_t * priv,unsigned char * data,uint data_len)544 udi_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         }
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  */
632 static int
udi_send_signal_raw(unifi_priv_t * priv,unsigned char * buf,int buflen)633 udi_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 
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);
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);
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);
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 
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  */
753 static ssize_t
unifi_write(struct file * filp,const char * p,size_t len,loff_t * poff)754 unifi_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 
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");
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]);
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]);
816             return -EINVAL;
817         }
818 
819         unifi_trace(priv, UDBG2, "unifi_write: signal 0x%.4X len:%d\n",
820                     sig_id, signal_size);
821 
822 	/* Allocate a buffer for the signal */
823 	signal_buf = kmemdup(bulkdata.d[0].os_data_ptr, signal_size,
824 				GFP_KERNEL);
825         if (!signal_buf) {
826             unifi_net_data_free(priv, &bulkdata.d[0]);
827             return -ENOMEM;
828         }
829 
830         /* Get the signal from the os_data_ptr */
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 
924     return bytes_written;
925 } /* unifi_write() */
926 
927 
build_type_to_string(unsigned char build_type)928 static 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  */
956 static long
unifi_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)957 unifi_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 
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 
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 */
1264             u16 interfaceTag=0;
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) {
1287                 unifi_set_interrupt_mode(priv->card, (u32)run_bh_once);
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 
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
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;
1445                 kfree(pcli->snap_filter.protocols);
1446             }
1447 
1448             if (snap_filter.count == 0) {
1449                 break;
1450             }
1451 
1452             pcli->snap_filter.protocols = kmalloc(snap_filter.count * sizeof(u16), GFP_KERNEL);
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,
1459                                snap_filter.count * sizeof(u16)))
1460             {
1461                 kfree(pcli->snap_filter.protocols);
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 
1618 out:
1619     return (long)r;
1620 } /* unifi_ioctl() */
1621 
1622 
1623 
1624 static unsigned int
unifi_poll(struct file * filp,poll_table * wait)1625 unifi_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 
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 
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  */
1665 static void
udi_set_log_filter(ul_client_t * pcli,unifiio_filter_t * udi_filter)1666 udi_set_log_filter(ul_client_t *pcli, unifiio_filter_t *udi_filter)
1667 {
1668     u32 filter_pos;
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  */
1735 void
udi_log_event(ul_client_t * pcli,const u8 * signal,int signal_len,const bulk_data_param_t * bulkdata,int dir)1736 udi_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;
1746     u32 filter_pos;
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 
1754     /* Just a sanity check */
1755     if ((signal == NULL) || (signal_len <= 0)) {
1756         return;
1757     }
1758 
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:");
1768             unifi_debug_log_to_buf("%04X%04X ", *(((u16*)&timestamp) + 1),
1769                                    *(u16*)&timestamp);
1770         }
1771 
1772         /* Add signal */
1773         unifi_debug_log_to_buf("S%s:%04X R:%04X D:%04X ",
1774                                dir ? "T" : "F",
1775                                *(u16*)signal,
1776                                *(u16*)(signal + 2),
1777                                *(u16*)(signal + 4));
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 
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 = 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);
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 
1877 } /* udi_log_event() */
1878 
1879 #ifdef CSR_SME_USERSPACE
1880 int
uf_sme_queue_message(unifi_priv_t * priv,u8 * buffer,int length)1881 uf_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 
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 = 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);
1897                     kfree(buffer);
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);
1915         kfree(buffer);
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_*() */
1930     kfree(buffer);
1931 
1932     return 0;
1933 
1934 } /* uf_sme_queue_message() */
1935 #endif
1936 
1937 /*
1938  ****************************************************************************
1939  *
1940  *      Driver instantiation
1941  *
1942  ****************************************************************************
1943  */
1944 static const 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 
1954 static dev_t unifi_first_devno;
1955 static struct class *unifi_class;
1956 
1957 
uf_create_device_nodes(unifi_priv_t * priv,int bus_id)1958 int 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
1976     if (!device_create(unifi_class, priv->unifi_device,
1977                        devno, priv, "unifi%d", bus_id)) {
1978 #else
1979     priv->unifi_device = device_create(unifi_class, NULL,
1980                                        devno, priv, "unifi%d", bus_id);
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),
1994                   MINOR(unifi_first_devno) + (bus_id * 2) + 1);
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 
2002     if (!device_create(unifi_class,
2003 #ifdef SDIO_EXPORTS_STRUCT_DEVICE
2004                        priv->unifi_device,
2005 #else
2006                        NULL,
2007 #endif /* SDIO_EXPORTS_STRUCT_DEVICE */
2008                        devno, priv, "unifiudi%d", bus_id)) {
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 
2019 void uf_destroy_device_nodes(unifi_priv_t *priv)
2020 {
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);
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  */
2043 static int
2044 uf_create_debug_device(const 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  */
2082 static void
2083 uf_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  */
2102 int __init
2103 unifi_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
2125 #ifdef CSR_WIFI_SPLIT_PATCH
2126     printk("Split patch support\n");
2127 #endif
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 
2178 void __exit
2179 unifi_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 
2188 module_init(unifi_load);
2189 module_exit(unifi_unload);
2190 
2191 MODULE_DESCRIPTION("UniFi Device driver");
2192 MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
2193 MODULE_LICENSE("GPL and additional rights");
2194