~ubuntu-branches/ubuntu/natty/linux-backports-modules-2.6.38/natty-security

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Herton Ronaldo Krzesinski, Herton Ronaldo Krzesinski, Tim Gardner
  • Date: 2011-09-27 18:53:53 UTC
  • Revision ID: package-import@ubuntu.com-20110927185353-kv2b0it2l42t74bh
Tags: 2.6.38-12.8
[ Herton Ronaldo Krzesinski ]

* Bump ABI - Natty ABI 12

[ Tim Gardner ]

* Added compat wireless 3.0.0
  - LP: #819484

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