~ubuntu-branches/ubuntu/trusty/linux-backports-modules-3.2.0/trusty

« back to all changes in this revision

Viewing changes to updates/cw-3.3/drivers/net/wireless/libertas/debugfs.c

  • Committer: Package Import Robot
  • Author(s): Leann Ogasawara
  • Date: 2012-02-15 08:42:08 UTC
  • Revision ID: package-import@ubuntu.com-20120215084208-2gcs2zosufz014pi
Tags: 3.2.0-18.1
* Open Precise LBM
* Add compat-wireless v3.3
* Consolidated amd64 server flavour into generic
* Remove lpia control file
* Update Vcs-Git to ubuntu-preicse-lbm

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <linux/dcache.h>
 
2
#include <linux/debugfs.h>
 
3
#include <linux/delay.h>
 
4
#include <linux/hardirq.h>
 
5
#include <linux/mm.h>
 
6
#include <linux/string.h>
 
7
#include <linux/slab.h>
 
8
#include <linux/export.h>
 
9
 
 
10
#include "decl.h"
 
11
#include "cmd.h"
 
12
#include "debugfs.h"
 
13
 
 
14
static struct dentry *lbs_dir;
 
15
static char *szStates[] = {
 
16
        "Connected",
 
17
        "Disconnected"
 
18
};
 
19
 
 
20
#ifdef PROC_DEBUG
 
21
static void lbs_debug_init(struct lbs_private *priv);
 
22
#endif
 
23
 
 
24
static int open_file_generic(struct inode *inode, struct file *file)
 
25
{
 
26
        file->private_data = inode->i_private;
 
27
        return 0;
 
28
}
 
29
 
 
30
static ssize_t write_file_dummy(struct file *file, const char __user *buf,
 
31
                                size_t count, loff_t *ppos)
 
32
{
 
33
        return -EINVAL;
 
34
}
 
35
 
 
36
static const size_t len = PAGE_SIZE;
 
37
 
 
38
static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
 
39
                                  size_t count, loff_t *ppos)
 
40
{
 
41
        struct lbs_private *priv = file->private_data;
 
42
        size_t pos = 0;
 
43
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
44
        char *buf = (char *)addr;
 
45
        ssize_t res;
 
46
        if (!buf)
 
47
                return -ENOMEM;
 
48
 
 
49
        pos += snprintf(buf+pos, len-pos, "state = %s\n",
 
50
                                szStates[priv->connect_status]);
 
51
        pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
 
52
                                (u32) priv->regioncode);
 
53
 
 
54
        res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 
55
 
 
56
        free_page(addr);
 
57
        return res;
 
58
}
 
59
 
 
60
static ssize_t lbs_sleepparams_write(struct file *file,
 
61
                                const char __user *user_buf, size_t count,
 
62
                                loff_t *ppos)
 
63
{
 
64
        struct lbs_private *priv = file->private_data;
 
65
        ssize_t buf_size, ret;
 
66
        struct sleep_params sp;
 
67
        int p1, p2, p3, p4, p5, p6;
 
68
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
69
        char *buf = (char *)addr;
 
70
        if (!buf)
 
71
                return -ENOMEM;
 
72
 
 
73
        buf_size = min(count, len - 1);
 
74
        if (copy_from_user(buf, user_buf, buf_size)) {
 
75
                ret = -EFAULT;
 
76
                goto out_unlock;
 
77
        }
 
78
        ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
 
79
        if (ret != 6) {
 
80
                ret = -EINVAL;
 
81
                goto out_unlock;
 
82
        }
 
83
        sp.sp_error = p1;
 
84
        sp.sp_offset = p2;
 
85
        sp.sp_stabletime = p3;
 
86
        sp.sp_calcontrol = p4;
 
87
        sp.sp_extsleepclk = p5;
 
88
        sp.sp_reserved = p6;
 
89
 
 
90
        ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
 
91
        if (!ret)
 
92
                ret = count;
 
93
        else if (ret > 0)
 
94
                ret = -EINVAL;
 
95
 
 
96
out_unlock:
 
97
        free_page(addr);
 
98
        return ret;
 
99
}
 
100
 
 
101
static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
 
102
                                  size_t count, loff_t *ppos)
 
103
{
 
104
        struct lbs_private *priv = file->private_data;
 
105
        ssize_t ret;
 
106
        size_t pos = 0;
 
107
        struct sleep_params sp;
 
108
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
109
        char *buf = (char *)addr;
 
110
        if (!buf)
 
111
                return -ENOMEM;
 
112
 
 
113
        ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
 
114
        if (ret)
 
115
                goto out_unlock;
 
116
 
 
117
        pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error,
 
118
                        sp.sp_offset, sp.sp_stabletime,
 
119
                        sp.sp_calcontrol, sp.sp_extsleepclk,
 
120
                        sp.sp_reserved);
 
121
 
 
122
        ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 
123
 
 
124
out_unlock:
 
125
        free_page(addr);
 
126
        return ret;
 
127
}
 
128
 
 
129
static ssize_t lbs_host_sleep_write(struct file *file,
 
130
                                const char __user *user_buf, size_t count,
 
131
                                loff_t *ppos)
 
132
{
 
133
        struct lbs_private *priv = file->private_data;
 
134
        ssize_t buf_size, ret;
 
135
        int host_sleep;
 
136
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
137
        char *buf = (char *)addr;
 
138
        if (!buf)
 
139
                return -ENOMEM;
 
140
 
 
141
        buf_size = min(count, len - 1);
 
142
        if (copy_from_user(buf, user_buf, buf_size)) {
 
143
                ret = -EFAULT;
 
144
                goto out_unlock;
 
145
        }
 
146
        ret = sscanf(buf, "%d", &host_sleep);
 
147
        if (ret != 1) {
 
148
                ret = -EINVAL;
 
149
                goto out_unlock;
 
150
        }
 
151
 
 
152
        if (host_sleep == 0)
 
153
                ret = lbs_set_host_sleep(priv, 0);
 
154
        else if (host_sleep == 1) {
 
155
                if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
 
156
                        netdev_info(priv->dev,
 
157
                                    "wake parameters not configured\n");
 
158
                        ret = -EINVAL;
 
159
                        goto out_unlock;
 
160
                }
 
161
                ret = lbs_set_host_sleep(priv, 1);
 
162
        } else {
 
163
                netdev_err(priv->dev, "invalid option\n");
 
164
                ret = -EINVAL;
 
165
        }
 
166
 
 
167
        if (!ret)
 
168
                ret = count;
 
169
 
 
170
out_unlock:
 
171
        free_page(addr);
 
172
        return ret;
 
173
}
 
174
 
 
175
static ssize_t lbs_host_sleep_read(struct file *file, char __user *userbuf,
 
176
                                  size_t count, loff_t *ppos)
 
177
{
 
178
        struct lbs_private *priv = file->private_data;
 
179
        ssize_t ret;
 
180
        size_t pos = 0;
 
181
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
182
        char *buf = (char *)addr;
 
183
        if (!buf)
 
184
                return -ENOMEM;
 
185
 
 
186
        pos += snprintf(buf, len, "%d\n", priv->is_host_sleep_activated);
 
187
 
 
188
        ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 
189
 
 
190
        free_page(addr);
 
191
        return ret;
 
192
}
 
193
 
 
194
/*
 
195
 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
 
196
 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
 
197
 * firmware. Here's an example:
 
198
 *      04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
 
199
 *      00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
 
200
 *      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 
201
 *
 
202
 * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
 
203
 * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
 
204
 * defined in mrvlietypes_thresholds
 
205
 *
 
206
 * This function searches in this TLV data chunk for a given TLV type
 
207
 * and returns a pointer to the first data byte of the TLV, or to NULL
 
208
 * if the TLV hasn't been found.
 
209
 */
 
210
static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
 
211
{
 
212
        struct mrvl_ie_header *tlv_h;
 
213
        uint16_t length;
 
214
        ssize_t pos = 0;
 
215
 
 
216
        while (pos < size) {
 
217
                tlv_h = (struct mrvl_ie_header *) tlv;
 
218
                if (!tlv_h->len)
 
219
                        return NULL;
 
220
                if (tlv_h->type == cpu_to_le16(tlv_type))
 
221
                        return tlv_h;
 
222
                length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
 
223
                pos += length;
 
224
                tlv += length;
 
225
        }
 
226
        return NULL;
 
227
}
 
228
 
 
229
 
 
230
static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
 
231
                                  struct file *file, char __user *userbuf,
 
232
                                  size_t count, loff_t *ppos)
 
233
{
 
234
        struct cmd_ds_802_11_subscribe_event *subscribed;
 
235
        struct mrvl_ie_thresholds *got;
 
236
        struct lbs_private *priv = file->private_data;
 
237
        ssize_t ret = 0;
 
238
        size_t pos = 0;
 
239
        char *buf;
 
240
        u8 value;
 
241
        u8 freq;
 
242
        int events = 0;
 
243
 
 
244
        buf = (char *)get_zeroed_page(GFP_KERNEL);
 
245
        if (!buf)
 
246
                return -ENOMEM;
 
247
 
 
248
        subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL);
 
249
        if (!subscribed) {
 
250
                ret = -ENOMEM;
 
251
                goto out_page;
 
252
        }
 
253
 
 
254
        subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed));
 
255
        subscribed->action = cpu_to_le16(CMD_ACT_GET);
 
256
 
 
257
        ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
 
258
        if (ret)
 
259
                goto out_cmd;
 
260
 
 
261
        got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
 
262
        if (got) {
 
263
                value = got->value;
 
264
                freq  = got->freq;
 
265
                events = le16_to_cpu(subscribed->events);
 
266
 
 
267
                pos += snprintf(buf, len, "%d %d %d\n", value, freq,
 
268
                                !!(events & event_mask));
 
269
        }
 
270
 
 
271
        ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 
272
 
 
273
 out_cmd:
 
274
        kfree(subscribed);
 
275
 
 
276
 out_page:
 
277
        free_page((unsigned long)buf);
 
278
        return ret;
 
279
}
 
280
 
 
281
 
 
282
static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
 
283
                                   struct file *file,
 
284
                                   const char __user *userbuf, size_t count,
 
285
                                   loff_t *ppos)
 
286
{
 
287
        struct cmd_ds_802_11_subscribe_event *events;
 
288
        struct mrvl_ie_thresholds *tlv;
 
289
        struct lbs_private *priv = file->private_data;
 
290
        ssize_t buf_size;
 
291
        int value, freq, new_mask;
 
292
        uint16_t curr_mask;
 
293
        char *buf;
 
294
        int ret;
 
295
 
 
296
        buf = (char *)get_zeroed_page(GFP_KERNEL);
 
297
        if (!buf)
 
298
                return -ENOMEM;
 
299
 
 
300
        buf_size = min(count, len - 1);
 
301
        if (copy_from_user(buf, userbuf, buf_size)) {
 
302
                ret = -EFAULT;
 
303
                goto out_page;
 
304
        }
 
305
        ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
 
306
        if (ret != 3) {
 
307
                ret = -EINVAL;
 
308
                goto out_page;
 
309
        }
 
310
        events = kzalloc(sizeof(*events), GFP_KERNEL);
 
311
        if (!events) {
 
312
                ret = -ENOMEM;
 
313
                goto out_page;
 
314
        }
 
315
 
 
316
        events->hdr.size = cpu_to_le16(sizeof(*events));
 
317
        events->action = cpu_to_le16(CMD_ACT_GET);
 
318
 
 
319
        ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
 
320
        if (ret)
 
321
                goto out_events;
 
322
 
 
323
        curr_mask = le16_to_cpu(events->events);
 
324
 
 
325
        if (new_mask)
 
326
                new_mask = curr_mask | event_mask;
 
327
        else
 
328
                new_mask = curr_mask & ~event_mask;
 
329
 
 
330
        /* Now everything is set and we can send stuff down to the firmware */
 
331
 
 
332
        tlv = (void *)events->tlv;
 
333
 
 
334
        events->action = cpu_to_le16(CMD_ACT_SET);
 
335
        events->events = cpu_to_le16(new_mask);
 
336
        tlv->header.type = cpu_to_le16(tlv_type);
 
337
        tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
 
338
        tlv->value = value;
 
339
        if (tlv_type != TLV_TYPE_BCNMISS)
 
340
                tlv->freq = freq;
 
341
 
 
342
        /* The command header, the action, the event mask, and one TLV */
 
343
        events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));
 
344
 
 
345
        ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
 
346
 
 
347
        if (!ret)
 
348
                ret = count;
 
349
 out_events:
 
350
        kfree(events);
 
351
 out_page:
 
352
        free_page((unsigned long)buf);
 
353
        return ret;
 
354
}
 
355
 
 
356
 
 
357
static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
 
358
                                size_t count, loff_t *ppos)
 
359
{
 
360
        return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
 
361
                                  file, userbuf, count, ppos);
 
362
}
 
363
 
 
364
 
 
365
static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf,
 
366
                                 size_t count, loff_t *ppos)
 
367
{
 
368
        return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
 
369
                                   file, userbuf, count, ppos);
 
370
}
 
371
 
 
372
 
 
373
static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
 
374
                               size_t count, loff_t *ppos)
 
375
{
 
376
        return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
 
377
                                  file, userbuf, count, ppos);
 
378
}
 
379
 
 
380
 
 
381
static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf,
 
382
                                size_t count, loff_t *ppos)
 
383
{
 
384
        return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
 
385
                                   file, userbuf, count, ppos);
 
386
}
 
387
 
 
388
 
 
389
static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
 
390
                                  size_t count, loff_t *ppos)
 
391
{
 
392
        return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
 
393
                                  file, userbuf, count, ppos);
 
394
}
 
395
 
 
396
 
 
397
static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf,
 
398
                                   size_t count, loff_t *ppos)
 
399
{
 
400
        return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
 
401
                                   file, userbuf, count, ppos);
 
402
}
 
403
 
 
404
 
 
405
static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
 
406
                                 size_t count, loff_t *ppos)
 
407
{
 
408
        return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
 
409
                                  file, userbuf, count, ppos);
 
410
}
 
411
 
 
412
 
 
413
static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf,
 
414
                                  size_t count, loff_t *ppos)
 
415
{
 
416
        return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
 
417
                                   file, userbuf, count, ppos);
 
418
}
 
419
 
 
420
 
 
421
static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf,
 
422
                                size_t count, loff_t *ppos)
 
423
{
 
424
        return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
 
425
                                  file, userbuf, count, ppos);
 
426
}
 
427
 
 
428
 
 
429
static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf,
 
430
                                 size_t count, loff_t *ppos)
 
431
{
 
432
        return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
 
433
                                   file, userbuf, count, ppos);
 
434
}
 
435
 
 
436
static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
 
437
                                size_t count, loff_t *ppos)
 
438
{
 
439
        return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
 
440
                                  file, userbuf, count, ppos);
 
441
}
 
442
 
 
443
 
 
444
static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
 
445
                                 size_t count, loff_t *ppos)
 
446
{
 
447
        return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
 
448
                                   file, userbuf, count, ppos);
 
449
}
 
450
 
 
451
 
 
452
static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
 
453
                                  size_t count, loff_t *ppos)
 
454
{
 
455
        struct lbs_private *priv = file->private_data;
 
456
        ssize_t pos = 0;
 
457
        int ret;
 
458
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
459
        char *buf = (char *)addr;
 
460
        u32 val = 0;
 
461
 
 
462
        if (!buf)
 
463
                return -ENOMEM;
 
464
 
 
465
        ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val);
 
466
        mdelay(10);
 
467
        if (!ret) {
 
468
                pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n",
 
469
                                priv->mac_offset, val);
 
470
                ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 
471
        }
 
472
        free_page(addr);
 
473
        return ret;
 
474
}
 
475
 
 
476
static ssize_t lbs_rdmac_write(struct file *file,
 
477
                                    const char __user *userbuf,
 
478
                                    size_t count, loff_t *ppos)
 
479
{
 
480
        struct lbs_private *priv = file->private_data;
 
481
        ssize_t res, buf_size;
 
482
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
483
        char *buf = (char *)addr;
 
484
        if (!buf)
 
485
                return -ENOMEM;
 
486
 
 
487
        buf_size = min(count, len - 1);
 
488
        if (copy_from_user(buf, userbuf, buf_size)) {
 
489
                res = -EFAULT;
 
490
                goto out_unlock;
 
491
        }
 
492
        priv->mac_offset = simple_strtoul((char *)buf, NULL, 16);
 
493
        res = count;
 
494
out_unlock:
 
495
        free_page(addr);
 
496
        return res;
 
497
}
 
498
 
 
499
static ssize_t lbs_wrmac_write(struct file *file,
 
500
                                    const char __user *userbuf,
 
501
                                    size_t count, loff_t *ppos)
 
502
{
 
503
 
 
504
        struct lbs_private *priv = file->private_data;
 
505
        ssize_t res, buf_size;
 
506
        u32 offset, value;
 
507
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
508
        char *buf = (char *)addr;
 
509
        if (!buf)
 
510
                return -ENOMEM;
 
511
 
 
512
        buf_size = min(count, len - 1);
 
513
        if (copy_from_user(buf, userbuf, buf_size)) {
 
514
                res = -EFAULT;
 
515
                goto out_unlock;
 
516
        }
 
517
        res = sscanf(buf, "%x %x", &offset, &value);
 
518
        if (res != 2) {
 
519
                res = -EFAULT;
 
520
                goto out_unlock;
 
521
        }
 
522
 
 
523
        res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value);
 
524
        mdelay(10);
 
525
 
 
526
        if (!res)
 
527
                res = count;
 
528
out_unlock:
 
529
        free_page(addr);
 
530
        return res;
 
531
}
 
532
 
 
533
static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
 
534
                                  size_t count, loff_t *ppos)
 
535
{
 
536
        struct lbs_private *priv = file->private_data;
 
537
        ssize_t pos = 0;
 
538
        int ret;
 
539
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
540
        char *buf = (char *)addr;
 
541
        u32 val;
 
542
 
 
543
        if (!buf)
 
544
                return -ENOMEM;
 
545
 
 
546
        ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val);
 
547
        mdelay(10);
 
548
        if (!ret) {
 
549
                pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n",
 
550
                                priv->bbp_offset, val);
 
551
                ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 
552
        }
 
553
        free_page(addr);
 
554
 
 
555
        return ret;
 
556
}
 
557
 
 
558
static ssize_t lbs_rdbbp_write(struct file *file,
 
559
                                    const char __user *userbuf,
 
560
                                    size_t count, loff_t *ppos)
 
561
{
 
562
        struct lbs_private *priv = file->private_data;
 
563
        ssize_t res, buf_size;
 
564
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
565
        char *buf = (char *)addr;
 
566
        if (!buf)
 
567
                return -ENOMEM;
 
568
 
 
569
        buf_size = min(count, len - 1);
 
570
        if (copy_from_user(buf, userbuf, buf_size)) {
 
571
                res = -EFAULT;
 
572
                goto out_unlock;
 
573
        }
 
574
        priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16);
 
575
        res = count;
 
576
out_unlock:
 
577
        free_page(addr);
 
578
        return res;
 
579
}
 
580
 
 
581
static ssize_t lbs_wrbbp_write(struct file *file,
 
582
                                    const char __user *userbuf,
 
583
                                    size_t count, loff_t *ppos)
 
584
{
 
585
 
 
586
        struct lbs_private *priv = file->private_data;
 
587
        ssize_t res, buf_size;
 
588
        u32 offset, value;
 
589
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
590
        char *buf = (char *)addr;
 
591
        if (!buf)
 
592
                return -ENOMEM;
 
593
 
 
594
        buf_size = min(count, len - 1);
 
595
        if (copy_from_user(buf, userbuf, buf_size)) {
 
596
                res = -EFAULT;
 
597
                goto out_unlock;
 
598
        }
 
599
        res = sscanf(buf, "%x %x", &offset, &value);
 
600
        if (res != 2) {
 
601
                res = -EFAULT;
 
602
                goto out_unlock;
 
603
        }
 
604
 
 
605
        res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value);
 
606
        mdelay(10);
 
607
 
 
608
        if (!res)
 
609
                res = count;
 
610
out_unlock:
 
611
        free_page(addr);
 
612
        return res;
 
613
}
 
614
 
 
615
static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
 
616
                                  size_t count, loff_t *ppos)
 
617
{
 
618
        struct lbs_private *priv = file->private_data;
 
619
        ssize_t pos = 0;
 
620
        int ret;
 
621
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
622
        char *buf = (char *)addr;
 
623
        u32 val;
 
624
 
 
625
        if (!buf)
 
626
                return -ENOMEM;
 
627
 
 
628
        ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val);
 
629
        mdelay(10);
 
630
        if (!ret) {
 
631
                pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n",
 
632
                                priv->rf_offset, val);
 
633
                ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 
634
        }
 
635
        free_page(addr);
 
636
 
 
637
        return ret;
 
638
}
 
639
 
 
640
static ssize_t lbs_rdrf_write(struct file *file,
 
641
                                    const char __user *userbuf,
 
642
                                    size_t count, loff_t *ppos)
 
643
{
 
644
        struct lbs_private *priv = file->private_data;
 
645
        ssize_t res, buf_size;
 
646
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
647
        char *buf = (char *)addr;
 
648
        if (!buf)
 
649
                return -ENOMEM;
 
650
 
 
651
        buf_size = min(count, len - 1);
 
652
        if (copy_from_user(buf, userbuf, buf_size)) {
 
653
                res = -EFAULT;
 
654
                goto out_unlock;
 
655
        }
 
656
        priv->rf_offset = simple_strtoul(buf, NULL, 16);
 
657
        res = count;
 
658
out_unlock:
 
659
        free_page(addr);
 
660
        return res;
 
661
}
 
662
 
 
663
static ssize_t lbs_wrrf_write(struct file *file,
 
664
                                    const char __user *userbuf,
 
665
                                    size_t count, loff_t *ppos)
 
666
{
 
667
 
 
668
        struct lbs_private *priv = file->private_data;
 
669
        ssize_t res, buf_size;
 
670
        u32 offset, value;
 
671
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
672
        char *buf = (char *)addr;
 
673
        if (!buf)
 
674
                return -ENOMEM;
 
675
 
 
676
        buf_size = min(count, len - 1);
 
677
        if (copy_from_user(buf, userbuf, buf_size)) {
 
678
                res = -EFAULT;
 
679
                goto out_unlock;
 
680
        }
 
681
        res = sscanf(buf, "%x %x", &offset, &value);
 
682
        if (res != 2) {
 
683
                res = -EFAULT;
 
684
                goto out_unlock;
 
685
        }
 
686
 
 
687
        res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value);
 
688
        mdelay(10);
 
689
 
 
690
        if (!res)
 
691
                res = count;
 
692
out_unlock:
 
693
        free_page(addr);
 
694
        return res;
 
695
}
 
696
 
 
697
#define FOPS(fread, fwrite) { \
 
698
        .owner = THIS_MODULE, \
 
699
        .open = open_file_generic, \
 
700
        .read = (fread), \
 
701
        .write = (fwrite), \
 
702
        .llseek = generic_file_llseek, \
 
703
}
 
704
 
 
705
struct lbs_debugfs_files {
 
706
        const char *name;
 
707
        umode_t perm;
 
708
        struct file_operations fops;
 
709
};
 
710
 
 
711
static const struct lbs_debugfs_files debugfs_files[] = {
 
712
        { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
 
713
        { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
 
714
                                lbs_sleepparams_write), },
 
715
        { "hostsleep", 0644, FOPS(lbs_host_sleep_read,
 
716
                                lbs_host_sleep_write), },
 
717
};
 
718
 
 
719
static const struct lbs_debugfs_files debugfs_events_files[] = {
 
720
        {"low_rssi", 0644, FOPS(lbs_lowrssi_read,
 
721
                                lbs_lowrssi_write), },
 
722
        {"low_snr", 0644, FOPS(lbs_lowsnr_read,
 
723
                                lbs_lowsnr_write), },
 
724
        {"failure_count", 0644, FOPS(lbs_failcount_read,
 
725
                                lbs_failcount_write), },
 
726
        {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read,
 
727
                                lbs_bcnmiss_write), },
 
728
        {"high_rssi", 0644, FOPS(lbs_highrssi_read,
 
729
                                lbs_highrssi_write), },
 
730
        {"high_snr", 0644, FOPS(lbs_highsnr_read,
 
731
                                lbs_highsnr_write), },
 
732
};
 
733
 
 
734
static const struct lbs_debugfs_files debugfs_regs_files[] = {
 
735
        {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), },
 
736
        {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), },
 
737
        {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), },
 
738
        {"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), },
 
739
        {"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), },
 
740
        {"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), },
 
741
};
 
742
 
 
743
void lbs_debugfs_init(void)
 
744
{
 
745
        if (!lbs_dir)
 
746
                lbs_dir = debugfs_create_dir("lbs_wireless", NULL);
 
747
}
 
748
 
 
749
void lbs_debugfs_remove(void)
 
750
{
 
751
        if (lbs_dir)
 
752
                 debugfs_remove(lbs_dir);
 
753
}
 
754
 
 
755
void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
 
756
{
 
757
        int i;
 
758
        const struct lbs_debugfs_files *files;
 
759
        if (!lbs_dir)
 
760
                goto exit;
 
761
 
 
762
        priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir);
 
763
        if (!priv->debugfs_dir)
 
764
                goto exit;
 
765
 
 
766
        for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
 
767
                files = &debugfs_files[i];
 
768
                priv->debugfs_files[i] = debugfs_create_file(files->name,
 
769
                                                             files->perm,
 
770
                                                             priv->debugfs_dir,
 
771
                                                             priv,
 
772
                                                             &files->fops);
 
773
        }
 
774
 
 
775
        priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
 
776
        if (!priv->events_dir)
 
777
                goto exit;
 
778
 
 
779
        for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
 
780
                files = &debugfs_events_files[i];
 
781
                priv->debugfs_events_files[i] = debugfs_create_file(files->name,
 
782
                                                             files->perm,
 
783
                                                             priv->events_dir,
 
784
                                                             priv,
 
785
                                                             &files->fops);
 
786
        }
 
787
 
 
788
        priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
 
789
        if (!priv->regs_dir)
 
790
                goto exit;
 
791
 
 
792
        for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
 
793
                files = &debugfs_regs_files[i];
 
794
                priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
 
795
                                                             files->perm,
 
796
                                                             priv->regs_dir,
 
797
                                                             priv,
 
798
                                                             &files->fops);
 
799
        }
 
800
 
 
801
#ifdef PROC_DEBUG
 
802
        lbs_debug_init(priv);
 
803
#endif
 
804
exit:
 
805
        return;
 
806
}
 
807
 
 
808
void lbs_debugfs_remove_one(struct lbs_private *priv)
 
809
{
 
810
        int i;
 
811
 
 
812
        for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
 
813
                debugfs_remove(priv->debugfs_regs_files[i]);
 
814
 
 
815
        debugfs_remove(priv->regs_dir);
 
816
 
 
817
        for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
 
818
                debugfs_remove(priv->debugfs_events_files[i]);
 
819
 
 
820
        debugfs_remove(priv->events_dir);
 
821
#ifdef PROC_DEBUG
 
822
        debugfs_remove(priv->debugfs_debug);
 
823
#endif
 
824
        for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
 
825
                debugfs_remove(priv->debugfs_files[i]);
 
826
        debugfs_remove(priv->debugfs_dir);
 
827
}
 
828
 
 
829
 
 
830
 
 
831
/* debug entry */
 
832
 
 
833
#ifdef PROC_DEBUG
 
834
 
 
835
#define item_size(n)    (FIELD_SIZEOF(struct lbs_private, n))
 
836
#define item_addr(n)    (offsetof(struct lbs_private, n))
 
837
 
 
838
 
 
839
struct debug_data {
 
840
        char name[32];
 
841
        u32 size;
 
842
        size_t addr;
 
843
};
 
844
 
 
845
/* To debug any member of struct lbs_private, simply add one line here.
 
846
 */
 
847
static struct debug_data items[] = {
 
848
        {"psmode", item_size(psmode), item_addr(psmode)},
 
849
        {"psstate", item_size(psstate), item_addr(psstate)},
 
850
};
 
851
 
 
852
static int num_of_items = ARRAY_SIZE(items);
 
853
 
 
854
/**
 
855
 * lbs_debugfs_read - proc read function
 
856
 *
 
857
 * @file:       file to read
 
858
 * @userbuf:    pointer to buffer
 
859
 * @count:      number of bytes to read
 
860
 * @ppos:       read data starting position
 
861
 *
 
862
 * returns:     amount of data read or negative error code
 
863
 */
 
864
static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
 
865
                        size_t count, loff_t *ppos)
 
866
{
 
867
        int val = 0;
 
868
        size_t pos = 0;
 
869
        ssize_t res;
 
870
        char *p;
 
871
        int i;
 
872
        struct debug_data *d;
 
873
        unsigned long addr = get_zeroed_page(GFP_KERNEL);
 
874
        char *buf = (char *)addr;
 
875
        if (!buf)
 
876
                return -ENOMEM;
 
877
 
 
878
        p = buf;
 
879
 
 
880
        d = file->private_data;
 
881
 
 
882
        for (i = 0; i < num_of_items; i++) {
 
883
                if (d[i].size == 1)
 
884
                        val = *((u8 *) d[i].addr);
 
885
                else if (d[i].size == 2)
 
886
                        val = *((u16 *) d[i].addr);
 
887
                else if (d[i].size == 4)
 
888
                        val = *((u32 *) d[i].addr);
 
889
                else if (d[i].size == 8)
 
890
                        val = *((u64 *) d[i].addr);
 
891
 
 
892
                pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
 
893
        }
 
894
 
 
895
        res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
 
896
 
 
897
        free_page(addr);
 
898
        return res;
 
899
}
 
900
 
 
901
/**
 
902
 * lbs_debugfs_write - proc write function
 
903
 *
 
904
 * @f:          file pointer
 
905
 * @buf:        pointer to data buffer
 
906
 * @cnt:        data number to write
 
907
 * @ppos:       file position
 
908
 *
 
909
 * returns:     amount of data written
 
910
 */
 
911
static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
 
912
                            size_t cnt, loff_t *ppos)
 
913
{
 
914
        int r, i;
 
915
        char *pdata;
 
916
        char *p;
 
917
        char *p0;
 
918
        char *p1;
 
919
        char *p2;
 
920
        struct debug_data *d = f->private_data;
 
921
 
 
922
        pdata = kmalloc(cnt, GFP_KERNEL);
 
923
        if (pdata == NULL)
 
924
                return 0;
 
925
 
 
926
        if (copy_from_user(pdata, buf, cnt)) {
 
927
                lbs_deb_debugfs("Copy from user failed\n");
 
928
                kfree(pdata);
 
929
                return 0;
 
930
        }
 
931
 
 
932
        p0 = pdata;
 
933
        for (i = 0; i < num_of_items; i++) {
 
934
                do {
 
935
                        p = strstr(p0, d[i].name);
 
936
                        if (p == NULL)
 
937
                                break;
 
938
                        p1 = strchr(p, '\n');
 
939
                        if (p1 == NULL)
 
940
                                break;
 
941
                        p0 = p1++;
 
942
                        p2 = strchr(p, '=');
 
943
                        if (!p2)
 
944
                                break;
 
945
                        p2++;
 
946
                        r = simple_strtoul(p2, NULL, 0);
 
947
                        if (d[i].size == 1)
 
948
                                *((u8 *) d[i].addr) = (u8) r;
 
949
                        else if (d[i].size == 2)
 
950
                                *((u16 *) d[i].addr) = (u16) r;
 
951
                        else if (d[i].size == 4)
 
952
                                *((u32 *) d[i].addr) = (u32) r;
 
953
                        else if (d[i].size == 8)
 
954
                                *((u64 *) d[i].addr) = (u64) r;
 
955
                        break;
 
956
                } while (1);
 
957
        }
 
958
        kfree(pdata);
 
959
 
 
960
        return (ssize_t)cnt;
 
961
}
 
962
 
 
963
static const struct file_operations lbs_debug_fops = {
 
964
        .owner = THIS_MODULE,
 
965
        .open = open_file_generic,
 
966
        .write = lbs_debugfs_write,
 
967
        .read = lbs_debugfs_read,
 
968
        .llseek = default_llseek,
 
969
};
 
970
 
 
971
/**
 
972
 * lbs_debug_init - create debug proc file
 
973
 *
 
974
 * @priv:       pointer to &struct lbs_private
 
975
 *
 
976
 * returns:     N/A
 
977
 */
 
978
static void lbs_debug_init(struct lbs_private *priv)
 
979
{
 
980
        int i;
 
981
 
 
982
        if (!priv->debugfs_dir)
 
983
                return;
 
984
 
 
985
        for (i = 0; i < num_of_items; i++)
 
986
                items[i].addr += (size_t) priv;
 
987
 
 
988
        priv->debugfs_debug = debugfs_create_file("debug", 0644,
 
989
                                                  priv->debugfs_dir, &items[0],
 
990
                                                  &lbs_debug_fops);
 
991
}
 
992
#endif