tzh
2024-08-15 d4a1bd480003f3e1a0590bc46fbcb24f05652ca7
longan/kernel/linux-4.9/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_fw_trace.c
old mode 100644new mode 100755
....@@ -16,806 +16,32 @@
1616 #include <linux/delay.h>
1717 #include "rwnx_fw_trace.h"
1818
19
-#define RWNX_FW_TRACE_HEADER_LEN 4
20
-#define RWNX_FW_TRACE_HEADER_FMT "ts=%12u ID=%8d"
21
-#define RWNX_FW_TRACE_HEADER_ASCII_LEN (3 + 12 + 4 + 8)
22
-#define RWNX_FW_TRACE_PARAM_FMT ", %5d"
23
-#define RWNX_FW_TRACE_PARAM_ASCII_LEN (7)
24
-
25
-#define RWNX_FW_TRACE_NB_PARAM(a) ((*a >> 8) & 0xff)
26
-#define RWNX_FW_TRACE_ID(a) (uint32_t)(((a[0] & 0xff) << 16) + a[1])
27
-#define RWNX_FW_TRACE_ENTRY_SIZE(a) (RWNX_FW_TRACE_NB_PARAM(a) + \
28
- RWNX_FW_TRACE_HEADER_LEN)
29
-
30
-#define RWNX_FW_TRACE_READY 0x1234
31
-#define RWNX_FW_TRACE_LOCKED 0xdead
32
-#define RWNX_FW_TRACE_LOCKED_HOST 0x0230
33
-#define RWNX_FW_TRACE_LAST_ENTRY 0xffff
34
-
35
-#define RWNX_FW_TRACE_RESET "*** RESET ***\n"
36
-#define RWNX_FW_TRACE_RESET_SIZE (sizeof(RWNX_FW_TRACE_RESET) - 1) // don't count '\0'
37
-
38
-static int trace_last_reset;
39
-
40
-static const int startup_max_to = 500;
41
-
42
-#define RWNX_FW_TRACE_CHECK_INT_MS 1000
43
-
44
-
45
-/**
46
- * rwnx_fw_trace_work() - Work function to check for new traces
47
- * process function for &struct rwnx_fw_trace.work
48
- *
49
- * @ws: work structure
50
- *
51
- * Check if new traces are available in the shared buffer, by comparing current
52
- * end index with end index in the last check. If so wake up pending threads,
53
- * otherwise re-schedule the work is there are still some pending readers.
54
- *
55
- * Note: If between two check firmware exactly write one buffer of trace then
56
- * those traces will be lost. Fortunately this is very unlikely to happen.
57
- *
58
- * Note: Even if wake_up doesn't actually wake up threads (because condition
59
- * failed), calling waitqueue_active just after will still return false.
60
- * Fortunately this should never happen (new trace should always trigger the
61
- * waiting condition) otherwise it may be needed to re-schedule the work after
62
- * wake_up.
63
- */
64
-static void rwnx_fw_trace_work(struct work_struct *ws)
19
+int rwnx_fw_log_init(struct rwnx_fw_log *fw_log)
6520 {
66
- struct delayed_work *dw = container_of(ws, struct delayed_work, work);
67
- struct rwnx_fw_trace *trace = container_of(dw, struct rwnx_fw_trace, work);
68
-
69
- if (trace->closing ||
70
- (!rwnx_fw_trace_empty(&trace->buf) &&
71
- trace->last_read_index != *trace->buf.end)) {
72
- trace->last_read_index = *trace->buf.end;
73
- wake_up_interruptible(&trace->queue);
74
- return;
75
- }
76
-
77
- if (waitqueue_active(&trace->queue) && !delayed_work_pending(dw)) {
78
- schedule_delayed_work(dw, msecs_to_jiffies(RWNX_FW_TRACE_CHECK_INT_MS));
79
- }
80
-}
81
-
82
-/**
83
- * rwnx_fw_trace_buf_lock() - Lock trace buffer for firmware
84
- *
85
- * @shared_buf: Pointer to shared buffer
86
- *
87
- * Very basic synchro mechanism so that fw do not update trace buffer while host
88
- * is reading it. Not safe to race condition if host and fw read lock value at
89
- * the "same" time.
90
- */
91
-static void rwnx_fw_trace_buf_lock(struct rwnx_fw_trace_buf *shared_buf)
92
-{
93
-wait:
94
- while (*shared_buf->lock == RWNX_FW_TRACE_LOCKED) {
95
- }
96
- *shared_buf->lock &= RWNX_FW_TRACE_LOCKED_HOST;
97
-
98
- /* re-read to reduce race condition window */
99
- if (*shared_buf->lock == RWNX_FW_TRACE_LOCKED)
100
- goto wait;
101
-}
102
-
103
-/**
104
- * rwnx_fw_trace_buf_unlock() - Unlock trace buffer for firmware
105
- *
106
- * @shared_buf: Pointer to shared buffer
107
- *
108
- */
109
-static void rwnx_fw_trace_buf_unlock(struct rwnx_fw_trace_buf *shared_buf)
110
-{
111
- *shared_buf->lock = RWNX_FW_TRACE_READY;
112
-}
113
-
114
-/**
115
- * rwnx_fw_trace_buf_init() - Initialize rwnx_fw_trace_buf structure
116
- *
117
- * @shared_buf: Structure to initialize
118
- * @ipc: Pointer to IPC shard structure that contains trace buffer info
119
- *
120
- *
121
- * Return: 0 if initialization succeed, <0 otherwise. It can only fail if
122
- * trace feature is not enabled in the firmware (or buffer is corrupted).
123
- */
124
-int rwnx_fw_trace_buf_init(struct rwnx_fw_trace_buf *shared_buf,
125
- struct rwnx_fw_trace_ipc_desc *ipc)
126
-{
127
- uint16_t lock_status = ipc->pattern;
128
-
129
- if ((lock_status != RWNX_FW_TRACE_READY &&
130
- lock_status != RWNX_FW_TRACE_LOCKED)) {
131
- shared_buf->data = NULL;
132
- return -ENOENT;
133
- }
134
-
135
- /* Buffer starts <offset> bytes from the location of ipc->offset */
136
- shared_buf->data = (uint16_t *)((uint8_t *)(&ipc->offset) + ipc->offset);
137
- shared_buf->lock = &ipc->pattern;
138
- shared_buf->size = ipc->size;
139
- shared_buf->start = &ipc->start;
140
- shared_buf->end = &ipc->end;
141
- shared_buf->reset_idx = ++trace_last_reset;
142
-
143
- /* backward compatibilty with firmware without trace activation */
144
- if ((ipc->nb_compo >> 16) == RWNX_FW_TRACE_READY) {
145
- shared_buf->nb_compo = ipc->nb_compo & 0xffff;
146
- shared_buf->compo_table = (uint32_t *)((uint8_t *)(&ipc->offset_compo)
147
- + ipc->offset_compo);
148
- } else {
149
- shared_buf->nb_compo = 0;
150
- shared_buf->compo_table = NULL;
151
- }
152
-
153
- return 0;
154
-}
155
-
156
-/**
157
- * rwnx_fw_trace_init() - Initialize rwnx_fw_trace structure
158
- *
159
- * @trace: Structure to initialize
160
- * @ipc: Pointer to IPC shard structure that contains trace buffer info
161
- *
162
- * Return: 0 if initialization succeed, <0 otherwise. It can only fail if
163
- * trace feature is not enabled in the firmware (or buffer is corrupted).
164
- */
165
-int rwnx_fw_trace_init(struct rwnx_fw_trace *trace,
166
- struct rwnx_fw_trace_ipc_desc *ipc)
167
-{
168
- if (rwnx_fw_trace_buf_init(&trace->buf, ipc))
169
- return -ENOENT;
170
-
171
- INIT_DELAYED_WORK(&trace->work, rwnx_fw_trace_work);
172
- init_waitqueue_head(&trace->queue);
173
- mutex_init(&trace->mutex);
174
- trace->closing = false;
175
- return 0;
176
-}
177
-
178
-/**
179
- * rwnx_fw_trace_deinit() - De-initialization before releasing rwnx_fw_trace
180
- *
181
- * @trace: fw trace control structure
182
- */
183
-void rwnx_fw_trace_deinit(struct rwnx_fw_trace *trace)
184
-{
185
- trace->closing = true;
186
- flush_delayed_work(&trace->work);
187
- trace->buf.data = NULL;
188
-}
189
-
190
-/**
191
- * rwnx_fw_trace_reset_local() - Reset local buffer pointer/status
192
- *
193
- * @local_buf: structure to reset
194
- */
195
-static void rwnx_fw_trace_reset_local(struct rwnx_fw_trace_local_buf *local_buf)
196
-{
197
- local_buf->read = local_buf->data;
198
- local_buf->write = local_buf->data;
199
- local_buf->nb_entries = 0;
200
- local_buf->free_space = local_buf->size;
201
- local_buf->last_read = NULL;
202
- local_buf->reset_idx = 0;
203
- local_buf->show_reset = NULL;
204
-}
205
-
206
-/**
207
- * rwnx_fw_trace_alloc_local() - Allocate a local buffer and initialize
208
- * rwnx_fw_trace_local_buf structure
209
- *
210
- * @local_buf: structure to initialize
211
- * @size: Size of the buffer to allocate
212
- *
213
- * @local structure is initialized to use the allocated buffer.
214
- *
215
- * Return: 0 if allocation succeed and <0 otherwise.
216
- */
217
-int rwnx_fw_trace_alloc_local(struct rwnx_fw_trace_local_buf *local_buf,
218
- int size)
219
-{
220
- local_buf->data = kmalloc(size * sizeof(uint16_t), GFP_KERNEL);
221
- if (!local_buf->data) {
222
- return -ENOMEM;
223
- }
224
-
225
- local_buf->data_end = local_buf->data + size;
226
- local_buf->size = size;
227
- rwnx_fw_trace_reset_local(local_buf);
228
- return 0;
229
-}
230
-
231
-/**
232
- * rwnx_fw_trace_free_local() - Free local buffer
233
- *
234
- * @local_buf: structure containing buffer pointer to free.
235
- */
236
-void rwnx_fw_trace_free_local(struct rwnx_fw_trace_local_buf *local_buf)
237
-{
238
- if (local_buf->data)
239
- kfree(local_buf->data);
240
- local_buf->data = NULL;
241
-}
242
-
243
-/**
244
- * rwnx_fw_trace_strlen() - Return buffer size needed convert a trace entry into
245
- * string
246
- *
247
- * @entry: Pointer on trace entry
248
- *
249
- */
250
-static inline int rwnx_fw_trace_strlen(uint16_t *entry)
251
-{
252
- return (RWNX_FW_TRACE_HEADER_ASCII_LEN +
253
- (RWNX_FW_TRACE_NB_PARAM(entry) * RWNX_FW_TRACE_PARAM_ASCII_LEN) +
254
- 1); /* for \n */
255
-}
256
-
257
-/**
258
- * rwnx_fw_trace_to_str() - Convert one trace entry to a string
259
- *
260
- * @trace: Poitner to the trace entry
261
- * @buf: Buffer for the string
262
- * @size: Size of the string buffer, updated with the actual string size
263
- *
264
- * Return: pointer to the next tag entry.
265
- */
266
-static uint16_t *rwnx_fw_trace_to_str(uint16_t *trace, char *buf, size_t *size)
267
-{
268
- uint32_t ts, id;
269
- int nb_param;
270
- int res, buf_idx = 0, left = *size;
271
-
272
- id = RWNX_FW_TRACE_ID(trace);
273
- nb_param = RWNX_FW_TRACE_NB_PARAM(trace);
274
-
275
- trace += 2;
276
- ts = *trace++;
277
- ts <<= 16;
278
- ts += *trace++;
279
-
280
- res = scnprintf(&buf[buf_idx], left, RWNX_FW_TRACE_HEADER_FMT, ts, id);
281
- buf_idx += res;
282
- left -= res;
283
-
284
- while (nb_param > 0) {
285
- res = scnprintf(&buf[buf_idx], left, RWNX_FW_TRACE_PARAM_FMT, *trace++);
286
- buf_idx += res;
287
- left -= res;
288
- nb_param--;
289
- }
290
-
291
- res = scnprintf(&buf[buf_idx], left, "\n");
292
- left -= res;
293
- *size = (*size - left);
294
-
295
- return trace;
296
-}
297
-
298
-/**
299
- * rwnx_fw_trace_copy_entry() - Copy one trace entry in a local buffer
300
- *
301
- * @local_buf: Local buffer to copy trace into
302
- * @trace_entry: Pointer to the trace entry (in shared memory) to copy
303
- * @size: Size, in 16bits words, of the trace entry
304
- *
305
- * It is assumed that local has enough contiguous free-space available in
306
- * local buffer (i.e. from local_buf->write) to copy this trace.
307
- */
308
-static void rwnx_fw_trace_copy_entry(struct rwnx_fw_trace_local_buf *local_buf,
309
- uint16_t *trace_entry, int size)
310
-{
311
- uint16_t *write = local_buf->write;
312
- uint16_t *read = trace_entry;
313
- int i;
314
-
315
- for (i = 0; i < size; i++) {
316
- *write++ = *read++;
317
- }
318
-
319
- if (write >= local_buf->data_end)
320
- local_buf->write = local_buf->data;
321
- else
322
- local_buf->write = write;
323
-
324
- local_buf->free_space -= size;
325
- local_buf->last_read = trace_entry;
326
- local_buf->last_read_value = *trace_entry;
327
- local_buf->nb_entries++;
328
-}
329
-
330
-/**
331
- * rwnx_fw_trace_copy() - Copy trace entries from shared to local buffer
332
- *
333
- * @trace_buf: Pointer to shard buffer
334
- * @local_buf: Pointer to local buffer
335
- *
336
- * Copy has many trace entry as possible from shared buffer to local buffer
337
- * without overwriting traces in local buffer.
338
- *
339
- * Return: number of trace entries copied to local buffer
340
- */
341
-static int rwnx_fw_trace_copy(struct rwnx_fw_trace *trace,
342
- struct rwnx_fw_trace_local_buf *local_buf)
343
-{
344
- struct rwnx_fw_trace_buf *trace_buf = &trace->buf;
345
- uint16_t *ptr, *ptr_end, *ptr_limit;
346
- int entry_size, ret = 0;
347
-
348
- if (mutex_lock_interruptible(&trace->mutex))
349
- return 0;
350
-
351
- /* reset last_read ptr if shared buffer has been reset */
352
- if (local_buf->reset_idx != trace_buf->reset_idx) {
353
- local_buf->show_reset = local_buf->write;
354
- local_buf->reset_idx = trace_buf->reset_idx;
355
- local_buf->last_read = NULL;
356
- }
357
-
358
- rwnx_fw_trace_buf_lock(trace_buf);
359
-
360
- ptr_end = trace_buf->data + *trace_buf->end;
361
- if (rwnx_fw_trace_empty(trace_buf) || (ptr_end == local_buf->last_read))
362
- goto end;
363
- ptr_limit = trace_buf->data + trace_buf->size;
364
-
365
- if (local_buf->last_read &&
366
- (local_buf->last_read_value == *local_buf->last_read)) {
367
- ptr = local_buf->last_read;
368
- ptr += RWNX_FW_TRACE_ENTRY_SIZE(ptr);
369
- } else {
370
- ptr = trace_buf->data + *trace_buf->start;
371
- }
372
-
373
- while (1) {
374
-
375
- if ((ptr == ptr_limit) || (*ptr == RWNX_FW_TRACE_LAST_ENTRY))
376
- ptr = trace_buf->data;
377
-
378
- entry_size = RWNX_FW_TRACE_ENTRY_SIZE(ptr);
379
-
380
- if ((ptr + entry_size) > ptr_limit) {
381
- pr_err("Corrupted trace buffer\n");
382
- _rwnx_fw_trace_reset(trace, false);
383
- break;
384
- } else if (entry_size > local_buf->size) {
385
- pr_err("FW_TRACE local buffer too small, trace skipped");
386
- goto next_entry;
387
- }
388
-
389
- if (local_buf->free_space >= entry_size) {
390
- int contiguous = local_buf->data_end - local_buf->write;
391
-
392
- if ((local_buf->write < local_buf->read) || contiguous >= entry_size) {
393
- /* enough contiguous memory from local_buf->write */
394
- rwnx_fw_trace_copy_entry(local_buf, ptr, entry_size);
395
- ret++;
396
- } else if ((local_buf->free_space - contiguous) >= entry_size) {
397
- /* not enough contiguous from local_buf->write but enough
398
- from local_buf->data */
399
- *local_buf->write = RWNX_FW_TRACE_LAST_ENTRY;
400
- if (local_buf->show_reset == local_buf->write)
401
- local_buf->show_reset = local_buf->data;
402
- local_buf->write = local_buf->data;
403
- local_buf->free_space -= contiguous;
404
- rwnx_fw_trace_copy_entry(local_buf, ptr, entry_size);
405
- ret++;
406
- } else {
407
- /* not enough contiguous memory */
408
- goto end;
409
- }
410
- } else {
411
- goto end;
412
- }
413
-
414
- if (ptr == ptr_end)
415
- break;
416
-
417
- next_entry:
418
- ptr += entry_size;
419
- }
420
-
421
-end:
422
- rwnx_fw_trace_buf_unlock(trace_buf);
423
- mutex_unlock(&trace->mutex);
424
- return ret;
425
-}
426
-
427
-/**
428
- * rwnx_fw_trace_read_local() - Read trace from local buffer and convert it to
429
- * string in a user buffer
430
- *
431
- * @local_buf: Pointer to local buffer
432
- * @user_buf: Pointer to user buffer
433
- * @size: Size of the user buffer
434
- *
435
- * Read traces from shared buffer to write them in the user buffer after string
436
- * conversion. Stop when no more space in user buffer or no more trace to read.
437
- *
438
- * Return: The size written in the user buffer.
439
- */
440
-static size_t rwnx_fw_trace_read_local(struct rwnx_fw_trace_local_buf *local_buf,
441
- char __user *user_buf, size_t size)
442
-{
443
- uint16_t *ptr;
444
- char str[1824]; // worst case 255 params
445
- size_t str_size;
446
- int entry_size;
447
- size_t res = 0, remain = size, not_cpy = 0;
448
-
449
- if (!local_buf->nb_entries)
450
- return res;
451
-
452
- ptr = local_buf->read;
453
- while (local_buf->nb_entries && !not_cpy) {
454
-
455
- if (local_buf->show_reset == ptr) {
456
- if (remain < RWNX_FW_TRACE_RESET_SIZE)
457
- break;
458
-
459
- local_buf->show_reset = NULL;
460
- not_cpy = copy_to_user(user_buf + res, RWNX_FW_TRACE_RESET,
461
- RWNX_FW_TRACE_RESET_SIZE);
462
- res += (RWNX_FW_TRACE_RESET_SIZE - not_cpy);
463
- remain -= (RWNX_FW_TRACE_RESET_SIZE - not_cpy);
464
- }
465
-
466
- if (remain < rwnx_fw_trace_strlen(ptr))
467
- break;
468
-
469
- entry_size = RWNX_FW_TRACE_ENTRY_SIZE(ptr);
470
- str_size = sizeof(str);
471
- ptr = rwnx_fw_trace_to_str(ptr, str, &str_size);
472
- not_cpy = copy_to_user(user_buf + res, str, str_size);
473
- str_size -= not_cpy;
474
- res += str_size;
475
- remain -= str_size;
476
-
477
- local_buf->nb_entries--;
478
- local_buf->free_space += entry_size;
479
- if (ptr >= local_buf->data_end) {
480
- ptr = local_buf->data;
481
- } else if (*ptr == RWNX_FW_TRACE_LAST_ENTRY) {
482
- local_buf->free_space += local_buf->data_end - ptr;
483
- ptr = local_buf->data;
484
- }
485
- local_buf->read = ptr;
486
- }
487
-
488
- /* read all entries reset pointer */
489
- if (!local_buf->nb_entries) {
490
-
491
- local_buf->write = local_buf->read = local_buf->data;
492
- local_buf->free_space = local_buf->size;
493
- }
494
-
495
- return res;
496
-}
497
-
498
-/**
499
- * rwnx_fw_trace_read() - Update local buffer from shared buffer and convert
500
- * local buffer to string in user buffer
501
- *
502
- * @trace: Fw trace control structure
503
- * @local_buf: Local buffer to update and read from
504
- * @dont_wait: Indicate whether function should wait or not for traces before
505
- * returning
506
- * @user_buf: Pointer to user buffer
507
- * @size: Size of the user buffer
508
- *
509
- * Read traces from shared buffer to write them in the user buffer after string
510
- * conversion. Stop when no more space in user buffer or no more trace to read.
511
- *
512
- * Return: The size written in the user buffer if > 0, -EAGAIN if there is no
513
- * new traces and dont_wait is set and -ERESTARTSYS if signal has been
514
- * received while waiting for new traces.
515
- */
516
-size_t rwnx_fw_trace_read(struct rwnx_fw_trace *trace,
517
- struct rwnx_fw_trace_local_buf *local_buf,
518
- bool dont_wait, char __user *user_buf, size_t size)
519
-{
520
- size_t res = 0;
521
-
522
- rwnx_fw_trace_copy(trace, local_buf);
523
-
524
- while (!local_buf->nb_entries) {
525
- int last_index;
526
-
527
- if (dont_wait)
528
- return -EAGAIN;
529
-
530
- /* no trace, schedule work to periodically check trace buffer */
531
- if (!delayed_work_pending(&trace->work)) {
532
- trace->last_read_index = *trace->buf.end;
533
- schedule_delayed_work(&trace->work,
534
- msecs_to_jiffies(RWNX_FW_TRACE_CHECK_INT_MS));
535
- }
536
-
537
- /* and wait for traces */
538
- last_index = *trace->buf.end;
539
- if (wait_event_interruptible(trace->queue,
540
- (trace->closing ||
541
- (last_index != *trace->buf.end)))) {
542
- return -ERESTARTSYS;
543
- }
544
-
545
- if (trace->closing)
546
- return 0;
547
-
548
- rwnx_fw_trace_copy(trace, local_buf);
549
- }
550
-
551
- /* copy as many traces as possible in user buffer */
552
- while (1) {
553
- size_t read;
554
- read = rwnx_fw_trace_read_local(local_buf, user_buf + res, size - res);
555
- res += read;
556
- rwnx_fw_trace_copy(trace, local_buf);
557
- if (!read)
558
- break;
559
- }
560
-
561
- return res;
562
-}
563
-
564
-
565
-/**
566
- * _rwnx_fw_trace_dump() - Dump shared trace buffer in kernel buffer
567
- *
568
- * @trace_buf: Pointer to shared trace buffer;
569
- *
570
- * Called when error is detected, output trace on dmesg directly read from
571
- * shared memory
572
- */
573
-void _rwnx_fw_trace_dump(struct rwnx_fw_trace_buf *trace_buf)
574
-{
575
- uint16_t *ptr, *ptr_end, *ptr_limit, *next_ptr;
576
- char buf[1824]; // worst case 255 params
577
- size_t size;
578
-
579
- if (!trace_buf->data || rwnx_fw_trace_empty(trace_buf))
580
- return;
581
-
582
- rwnx_fw_trace_buf_lock(trace_buf);
583
-
584
- ptr = trace_buf->data + *trace_buf->start;
585
- ptr_end = trace_buf->data + *trace_buf->end;
586
- ptr_limit = trace_buf->data + trace_buf->size;
587
-
588
- while (1) {
589
- size = sizeof(buf);
590
- next_ptr = rwnx_fw_trace_to_str(ptr, buf, &size);
591
- pr_info("%s", buf);
592
-
593
- if (ptr == ptr_end) {
594
- break;
595
- } else if ((next_ptr == ptr_limit) ||
596
- (*next_ptr == RWNX_FW_TRACE_LAST_ENTRY)) {
597
- ptr = trace_buf->data;
598
- } else if (next_ptr > ptr_limit) {
599
- pr_err("Corrupted trace buffer\n");
600
- break;
601
- } else {
602
- ptr = next_ptr;
603
- }
604
- }
605
-
606
- rwnx_fw_trace_buf_unlock(trace_buf);
607
-}
608
-
609
-/**
610
- * _rwnx_fw_trace_reset() - Reset trace buffer at firmware level
611
- *
612
- * @trace: Pointer to shared trace buffer;
613
- * @bool: Indicate if mutex must be aquired before
614
- */
615
-int _rwnx_fw_trace_reset(struct rwnx_fw_trace *trace, bool lock)
616
-{
617
- struct rwnx_fw_trace_buf *trace_buf = &trace->buf;
618
-
619
- if (lock && mutex_lock_interruptible(&trace->mutex))
620
- return -ERESTARTSYS;
621
-
622
- if (trace->buf.data) {
623
- rwnx_fw_trace_buf_lock(trace_buf);
624
- *trace_buf->start = 0;
625
- *trace_buf->end = trace_buf->size + 1;
626
- trace_buf->reset_idx = ++trace_last_reset;
627
- rwnx_fw_trace_buf_unlock(trace_buf);
628
- }
629
-
630
- if (lock)
631
- mutex_unlock(&trace->mutex);
632
- return 0;
633
-}
634
-
635
-/**
636
- * rwnx_fw_trace_get_trace_level() - Get trace level for a given component
637
- *
638
- * @trace: Pointer to shared trace buffer;
639
- * @compo_id: Index of the componetn in the table
640
- *
641
- * Return: The trace level set for the given component, 0 if component index
642
- * is invalid.
643
- */
644
-static uint32_t rwnx_fw_trace_get_trace_level(struct rwnx_fw_trace_buf *trace_buf,
645
- unsigned int compo_id)
646
-{
647
- if (compo_id >= trace_buf->nb_compo)
648
- return 0;
649
- return trace_buf->compo_table[compo_id];
650
-}
651
-
652
-/**
653
- * rwnx_fw_trace_set_trace_level() - Set trace level for a given component
654
- *
655
- * @trace_buf: Pointer to shared trace buffer;
656
- * @compo_id: Index of the componetn in the table
657
- * @level: Trace level to set
658
- *
659
- * Set all components if compo_id is equals to the number of component and
660
- * does nothing if it is greater.
661
- */
662
-static void rwnx_fw_trace_set_trace_level(struct rwnx_fw_trace_buf *trace_buf,
663
- unsigned int compo_id, uint32_t level)
664
-{
665
- if (compo_id > trace_buf->nb_compo)
666
- return;
667
-
668
- if (compo_id == trace_buf->nb_compo) {
669
- int i;
670
- for (i = 0; i < trace_buf->nb_compo; i++) {
671
- trace_buf->compo_table[i] = level;
672
- }
673
- } else {
674
- trace_buf->compo_table[compo_id] = level;
675
- }
676
-}
677
-
678
-/**
679
- * rwnx_fw_trace_level_read() - Write current trace level in a user buffer
680
- * as a string
681
- *
682
- * @trace: Fw trace control structure
683
- * @user_buf: Pointer to user buffer
684
- * @len: Size of the user buffer
685
- * @ppos: position offset
686
- *
687
- * Return: Number of bytes written in user buffer if > 0, error otherwise
688
- */
689
-size_t rwnx_fw_trace_level_read(struct rwnx_fw_trace *trace,
690
- char __user *user_buf, size_t len, loff_t *ppos)
691
-{
692
- struct rwnx_fw_trace_buf *trace_buf = &trace->buf;
693
- size_t res = 0;
694
- int i, size;
695
- char *buf;
696
-
697
- size = trace_buf->nb_compo * 16;
698
- buf = kmalloc(size, GFP_KERNEL);
699
- if (buf == NULL)
700
- return 0;
701
-
702
- if (mutex_lock_interruptible(&trace->mutex)) {
703
- kfree(buf);
704
- return -ERESTARTSYS;
705
- }
706
-
707
- for (i = 0; i < trace_buf->nb_compo; i++) {
708
- res += scnprintf(&buf[res], size - res, "%3d:0x%08x\n", i,
709
- rwnx_fw_trace_get_trace_level(trace_buf, i));
710
- }
711
- mutex_unlock(&trace->mutex);
712
-
713
- res = simple_read_from_buffer(user_buf, len, ppos, buf, res);
714
-
715
- kfree(buf);
716
- return res;
717
-}
718
-
719
-/**
720
- * rwnx_fw_trace_level_write() - Read trace level from a user buffer provided
721
- * as a string and applyt them.
722
- *
723
- * @trace: Fw trace control structure
724
- * @user_buf: Pointer to user buffer
725
- * @len: Size of the user buffer
726
- *
727
- * trace level must be provided in the following form:
728
- * <compo_id>:<trace_level> where <compo_id> is in decimal notation and
729
- * <trace_level> in decical or hexadecimal notation.
730
- * Several trace level can be provided, separated by space,tab or new line.
731
- *
732
- * Return: Number of bytes read form user buffer if > 0, error otherwise
733
- */
734
-size_t rwnx_fw_trace_level_write(struct rwnx_fw_trace *trace,
735
- const char __user *user_buf, size_t len)
736
-{
737
- struct rwnx_fw_trace_buf *trace_buf = &trace->buf;
738
- char *buf, *token, *next;
739
-
740
- buf = kmalloc(len + 1, GFP_KERNEL);
741
- if (buf == NULL)
21
+ u8 *buf = kmalloc(FW_LOG_SIZE, GFP_KERNEL);
22
+ if (!buf)
74223 return -ENOMEM;
74324
744
- if (copy_from_user(buf, user_buf, len)) {
745
- kfree(buf);
746
- return -EFAULT;
747
- }
748
- buf[len] = '\0';
25
+ fw_log->buf.data = buf;
26
+ fw_log->buf.start = fw_log->buf.data;
27
+ fw_log->buf.size = 0;
28
+ fw_log->buf.end = fw_log->buf.data;
29
+ fw_log->buf.dataend = fw_log->buf.data + FW_LOG_SIZE;
30
+ spin_lock_init(&fw_log->lock);
74931
750
- if (mutex_lock_interruptible(&trace->mutex)) {
751
- kfree(buf);
752
- return -ERESTARTSYS;
753
- }
754
-
755
- next = buf;
756
- token = strsep(&next, " \t\n");
757
- while (token) {
758
- unsigned int compo, level;
759
- if ((sscanf(token, "%d:0x%x", &compo, &level) == 2) ||
760
- (sscanf(token, "%d:%d", &compo, &level) == 2)) {
761
- rwnx_fw_trace_set_trace_level(trace_buf, compo, level);
762
- }
763
-
764
- token = strsep(&next, " \t");
765
- }
766
- mutex_unlock(&trace->mutex);
767
-
768
- kfree(buf);
769
- return len;
32
+ printk("fw_log_init: %lx, %lx\n", (unsigned long)fw_log->buf.start, (unsigned long)(fw_log->buf.dataend));
33
+ return 0;
77034 }
77135
772
-/**
773
- * rwnx_fw_trace_config_filters() - Update FW trace filters
774
- *
775
- * @trace_buf: Pointer to shared buffer
776
- * @ipc: Pointer to IPC shared structure that contains trace buffer info
777
- * @ftl: Firmware trace level
778
- *
779
- * Return: 0 if the trace filters are successfully updated, <0 otherwise.
780
- */
781
-int rwnx_fw_trace_config_filters(struct rwnx_fw_trace_buf *trace_buf,
782
- struct rwnx_fw_trace_ipc_desc *ipc, char *ftl)
36
+void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log)
78337 {
784
- int to;
785
- char *next, *token;
38
+ if (!fw_log)
39
+ return;
78640
787
- to = 0;
788
- while ((ipc->pattern != RWNX_FW_TRACE_READY) && (to < startup_max_to)) {
789
- msleep(50);
790
- to += 50;
791
- }
792
-
793
- if (rwnx_fw_trace_buf_init(trace_buf, ipc))
794
- return -ENOENT;
795
-
796
- next = ftl;
797
- token = strsep(&next, " ");
798
- while (token) {
799
- unsigned int compo, ret, id, level = 0;
800
- char action;
801
-
802
- if ((sscanf(token, "%d%c0x%x", &compo, &action, &id) == 3) ||
803
- (sscanf(token, "%d%c%d", &compo, &action, &id) == 3)) {
804
- if (action == '=') {
805
- level = id;
806
- } else {
807
- ret = rwnx_fw_trace_get_trace_level(trace_buf, compo);
808
- if (action == '+')
809
- level = (ret | id);
810
- else if (action == '-')
811
- level = (ret & ~id);
812
- }
813
- rwnx_fw_trace_set_trace_level(trace_buf, compo, level);
814
- }
815
-
816
- token = strsep(&next, " ");
817
- }
818
-
819
- return 0;
41
+ if (fw_log->buf.data)
42
+ kfree(fw_log->buf.data);
43
+ fw_log->buf.start = NULL;
44
+ fw_log->buf.end = NULL;
45
+ fw_log->buf.size = 0;
82046 }
82147