greybus: loopback: add gb_loopback_nsec_to_usec_latency
[linux-2.6-block.git] / drivers / staging / greybus / loopback.c
CommitLineData
355a7058
AB
1/*
2 * Loopback bridge driver for the Greybus loopback module.
3 *
4 * Copyright 2014 Google Inc.
5 * Copyright 2014 Linaro Ltd.
6 *
7 * Released under the GPLv2 only.
8 */
9#include <linux/kernel.h>
10#include <linux/module.h>
85d678c0 11#include <linux/mutex.h>
355a7058
AB
12#include <linux/slab.h>
13#include <linux/kthread.h>
14#include <linux/delay.h>
15#include <linux/random.h>
5679f783 16#include <linux/sizes.h>
cbd204b4
BD
17#include <linux/cdev.h>
18#include <linux/fs.h>
19#include <linux/kfifo.h>
aa27bf82 20#include <linux/debugfs.h>
cbd204b4 21
1ffc12be
JH
22#include <asm/div64.h>
23
355a7058
AB
24#include "greybus.h"
25
fd489e1a
BD
26#define NSEC_PER_DAY 86400000000000ULL
27
355a7058 28struct gb_loopback_stats {
e051c82b
AE
29 u32 min;
30 u32 max;
00af6583 31 u64 sum;
e13fc28f 32 u32 count;
355a7058
AB
33};
34
aa27bf82
BD
35struct gb_loopback_device {
36 struct dentry *root;
37 u32 count;
67d1eece
BD
38
39 struct mutex mutex;
40 struct list_head list;
41 wait_queue_head_t wq;
42
43 int type;
44 u32 size;
45 u32 iteration_max;
46 u32 iteration_count;
47 size_t size_max;
48 int ms_wait;
49 u32 error;
50
51 struct timeval start;
52 struct timeval end;
53
54 /* Overall stats */
55 struct gb_loopback_stats latency;
56 struct gb_loopback_stats latency_gb;
57 struct gb_loopback_stats throughput;
58 struct gb_loopback_stats requests_per_second;
aa27bf82
BD
59};
60
61static struct gb_loopback_device gb_dev;
62
355a7058
AB
63struct gb_loopback {
64 struct gb_connection *connection;
355a7058 65
aa27bf82 66 struct dentry *file;
cbd204b4 67 struct kfifo kfifo;
85d678c0 68 struct mutex mutex;
355a7058 69 struct task_struct *task;
67d1eece 70 struct list_head entry;
355a7058 71
67d1eece 72 /* Per connection stats */
355a7058 73 struct gb_loopback_stats latency;
2f842304 74 struct gb_loopback_stats latency_gb;
355a7058 75 struct gb_loopback_stats throughput;
583cbf50 76 struct gb_loopback_stats requests_per_second;
67d1eece
BD
77
78 u32 iteration_count;
355a7058 79 u64 elapsed_nsecs;
2f842304 80 u64 elapsed_nsecs_gb;
355a7058
AB
81 u32 error;
82};
83
cbd204b4
BD
84#define GB_LOOPBACK_FIFO_DEFAULT 8192
85
cbd204b4
BD
86static unsigned kfifo_depth = GB_LOOPBACK_FIFO_DEFAULT;
87module_param(kfifo_depth, uint, 0444);
88
cbd204b4
BD
89/* Maximum size of any one send data buffer we support */
90#define MAX_PACKET_SIZE (PAGE_SIZE * 2)
91
91262c3a 92#define GB_LOOPBACK_MS_WAIT_MAX 1000
355a7058 93
355a7058 94/* interface sysfs attributes */
19c2a443 95#define gb_loopback_ro_attr(field) \
355a7058
AB
96static ssize_t field##_show(struct device *dev, \
97 struct device_attribute *attr, \
98 char *buf) \
99{ \
100 struct gb_connection *connection = to_gb_connection(dev); \
3f12c3ed 101 struct gb_loopback *gb = connection->private; \
19c2a443 102 return sprintf(buf, "%u\n", gb->field); \
355a7058
AB
103} \
104static DEVICE_ATTR_RO(field)
105
106#define gb_loopback_ro_stats_attr(name, field, type) \
107static ssize_t name##_##field##_show(struct device *dev, \
108 struct device_attribute *attr, \
109 char *buf) \
110{ \
111 struct gb_connection *connection = to_gb_connection(dev); \
3f12c3ed 112 struct gb_loopback *gb = connection->private; \
355a7058
AB
113 return sprintf(buf, "%"#type"\n", gb->name.field); \
114} \
115static DEVICE_ATTR_RO(name##_##field)
116
7a135a96
AE
117#define gb_loopback_ro_avg_attr(name) \
118static ssize_t name##_avg_show(struct device *dev, \
119 struct device_attribute *attr, \
120 char *buf) \
121{ \
122 struct gb_connection *connection = to_gb_connection(dev); \
123 struct gb_loopback *gb = connection->private; \
ff71d395
AE
124 struct gb_loopback_stats *stats = &gb->name; \
125 u32 count = stats->count ? stats->count : 1; \
126 u64 avg = stats->sum + count / 2; /* round closest */ \
127 u32 rem = do_div(avg, count); \
128 return sprintf(buf, "%llu.%06u\n", avg, 1000000 * rem / count); \
7a135a96
AE
129} \
130static DEVICE_ATTR_RO(name##_avg)
131
355a7058 132#define gb_loopback_stats_attrs(field) \
e051c82b
AE
133 gb_loopback_ro_stats_attr(field, min, u); \
134 gb_loopback_ro_stats_attr(field, max, u); \
7a135a96 135 gb_loopback_ro_avg_attr(field);
355a7058
AB
136
137#define gb_loopback_attr(field, type) \
138static ssize_t field##_show(struct device *dev, \
139 struct device_attribute *attr, \
140 char *buf) \
141{ \
142 struct gb_connection *connection = to_gb_connection(dev); \
3f12c3ed 143 struct gb_loopback *gb = connection->private; \
355a7058
AB
144 return sprintf(buf, "%"#type"\n", gb->field); \
145} \
146static ssize_t field##_store(struct device *dev, \
147 struct device_attribute *attr, \
148 const char *buf, \
149 size_t len) \
150{ \
151 int ret; \
152 struct gb_connection *connection = to_gb_connection(dev); \
67d1eece 153 mutex_lock(&gb_dev.mutex); \
355a7058 154 ret = sscanf(buf, "%"#type, &gb->field); \
355a7058 155 if (ret != 1) \
85d678c0
BD
156 len = -EINVAL; \
157 else \
67d1eece
BD
158 gb_loopback_check_attr(connection); \
159 mutex_unlock(&gb_dev.mutex); \
355a7058
AB
160 return len; \
161} \
162static DEVICE_ATTR_RW(field)
163
67d1eece
BD
164#define gb_dev_loopback_ro_attr(field) \
165static ssize_t field##_show(struct device *dev, \
166 struct device_attribute *attr, \
167 char *buf) \
168{ \
169 return sprintf(buf, "%u\n", gb_dev.field); \
170} \
171static DEVICE_ATTR_RO(field)
172
173#define gb_dev_loopback_rw_attr(field, type) \
174static ssize_t field##_show(struct device *dev, \
175 struct device_attribute *attr, \
176 char *buf) \
177{ \
178 return sprintf(buf, "%"#type"\n", gb_dev.field); \
179} \
180static ssize_t field##_store(struct device *dev, \
181 struct device_attribute *attr, \
182 const char *buf, \
183 size_t len) \
184{ \
185 int ret; \
186 struct gb_connection *connection = to_gb_connection(dev); \
187 mutex_lock(&gb_dev.mutex); \
188 ret = sscanf(buf, "%"#type, &gb_dev.field); \
189 if (ret != 1) \
190 len = -EINVAL; \
191 else \
192 gb_loopback_check_attr(&gb_dev, connection); \
193 mutex_unlock(&gb_dev.mutex); \
194 return len; \
195} \
196static DEVICE_ATTR_RW(field)
197
198static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev);
199static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev,
200 struct gb_connection *connection)
355a7058 201{
67d1eece
BD
202 struct gb_loopback *gb;
203
204 if (gb_dev->ms_wait > GB_LOOPBACK_MS_WAIT_MAX)
205 gb_dev->ms_wait = GB_LOOPBACK_MS_WAIT_MAX;
206 if (gb_dev->size > gb_dev->size_max)
207 gb_dev->size = gb_dev->size_max;
208 gb_dev->iteration_count = 0;
209 gb_dev->error = 0;
210
211 list_for_each_entry(gb, &gb_dev->list, entry) {
212 mutex_lock(&gb->mutex);
213 gb->iteration_count = 0;
214 gb->error = 0;
215 if (kfifo_depth < gb_dev->iteration_max) {
216 dev_warn(&connection->dev,
217 "cannot log bytes %u kfifo_depth %u\n",
218 gb_dev->iteration_max, kfifo_depth);
219 }
220 kfifo_reset_out(&gb->kfifo);
221 mutex_unlock(&gb->mutex);
cb60f496
BD
222 }
223
67d1eece 224 switch (gb_dev->type) {
a598f438
BD
225 case GB_LOOPBACK_TYPE_PING:
226 case GB_LOOPBACK_TYPE_TRANSFER:
384a7a3c 227 case GB_LOOPBACK_TYPE_SINK:
67d1eece
BD
228 gb_loopback_reset_stats(gb_dev);
229 wake_up(&gb_dev->wq);
a598f438
BD
230 break;
231 default:
67d1eece 232 gb_dev->type = 0;
a598f438
BD
233 break;
234 }
355a7058
AB
235}
236
237/* Time to send and receive one message */
238gb_loopback_stats_attrs(latency);
2f842304
BD
239/* Time to send and receive one message not including greybus */
240gb_loopback_stats_attrs(latency_gb);
583cbf50
BD
241/* Number of requests sent per second on this cport */
242gb_loopback_stats_attrs(requests_per_second);
355a7058
AB
243/* Quantity of data sent and received on this cport */
244gb_loopback_stats_attrs(throughput);
e140c75e 245/* Number of errors encountered during loop */
19c2a443 246gb_loopback_ro_attr(error);
355a7058
AB
247
248/*
799a3f03 249 * Type of loopback message to send based on protocol type definitions
355a7058 250 * 0 => Don't send message
799a3f03 251 * 2 => Send ping message continuously (message without payload)
006335a0 252 * 3 => Send transfer message continuously (message with payload,
799a3f03
BD
253 * payload returned in response)
254 * 4 => Send a sink message (message with payload, no payload in response)
355a7058 255 */
67d1eece 256gb_dev_loopback_rw_attr(type, d);
355a7058 257/* Size of transfer message payload: 0-4096 bytes */
67d1eece 258gb_dev_loopback_rw_attr(size, u);
48f19ee8 259/* Time to wait between two messages: 0-1000 ms */
67d1eece 260gb_dev_loopback_rw_attr(ms_wait, d);
00af6583 261/* Maximum iterations for a given operation: 1-(2^32-1), 0 implies infinite */
67d1eece
BD
262gb_dev_loopback_rw_attr(iteration_max, u);
263/* The current index of the for (i = 0; i < iteration_max; i++) loop */
264gb_dev_loopback_ro_attr(iteration_count);
355a7058
AB
265
266#define dev_stats_attrs(name) \
267 &dev_attr_##name##_min.attr, \
268 &dev_attr_##name##_max.attr, \
269 &dev_attr_##name##_avg.attr
270
271static struct attribute *loopback_attrs[] = {
272 dev_stats_attrs(latency),
2f842304 273 dev_stats_attrs(latency_gb),
583cbf50 274 dev_stats_attrs(requests_per_second),
355a7058
AB
275 dev_stats_attrs(throughput),
276 &dev_attr_type.attr,
277 &dev_attr_size.attr,
278 &dev_attr_ms_wait.attr,
00af6583
BD
279 &dev_attr_iteration_count.attr,
280 &dev_attr_iteration_max.attr,
355a7058
AB
281 &dev_attr_error.attr,
282 NULL,
283};
284ATTRIBUTE_GROUPS(loopback);
285
bd416103
BD
286static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs)
287{
288 u32 lat;
289
290 do_div(elapsed_nsecs, NSEC_PER_USEC);
291 lat = elapsed_nsecs;
292 return lat;
293}
294
2f842304 295static u64 gb_loopback_calc_latency(struct timeval *ts, struct timeval *te)
4c192665
BD
296{
297 u64 t1, t2;
298
299 t1 = timeval_to_ns(ts);
300 t2 = timeval_to_ns(te);
fd489e1a 301 if (t2 > t1)
2f842304 302 return t2 - t1;
fd489e1a 303 else
2f842304 304 return NSEC_PER_DAY - t2 + t1;
4c192665
BD
305}
306
a7e60062 307static int gb_loopback_sink(struct gb_loopback *gb, u32 len)
384a7a3c
BD
308{
309 struct timeval ts, te;
384a7a3c
BD
310 struct gb_loopback_transfer_request *request;
311 int retval;
312
313 request = kmalloc(len + sizeof(*request), GFP_KERNEL);
314 if (!request)
315 return -ENOMEM;
316
317 request->len = cpu_to_le32(len);
318
319 do_gettimeofday(&ts);
320 retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_SINK,
321 request, len + sizeof(*request), NULL, 0);
c3bba87a 322
384a7a3c 323 do_gettimeofday(&te);
2f842304
BD
324
325 /* Calculate the total time the message took */
326 gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te);
327
328 /* Calculate non-greybus related component of the latency */
329 gb_connection_pop_timestamp(gb->connection, &ts);
330 gb_connection_pop_timestamp(gb->connection, &te);
331 gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te);
332
384a7a3c
BD
333
334 kfree(request);
335 return retval;
336}
337
a7e60062 338static int gb_loopback_transfer(struct gb_loopback *gb, u32 len)
355a7058
AB
339{
340 struct timeval ts, te;
355a7058
AB
341 struct gb_loopback_transfer_request *request;
342 struct gb_loopback_transfer_response *response;
343 int retval;
344
345 request = kmalloc(len + sizeof(*request), GFP_KERNEL);
346 if (!request)
347 return -ENOMEM;
348 response = kmalloc(len + sizeof(*response), GFP_KERNEL);
349 if (!response) {
350 kfree(request);
351 return -ENOMEM;
352 }
353
dc4a1069
VK
354 memset(request->data, 0x5A, len);
355
355a7058
AB
356 request->len = cpu_to_le32(len);
357
358 do_gettimeofday(&ts);
359 retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_TRANSFER,
360 request, len + sizeof(*request),
361 response, len + sizeof(*response));
362 do_gettimeofday(&te);
2f842304
BD
363
364 /* Calculate the total time the message took */
365 gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te);
366
367 /* Calculate non-greybus related component of the latency */
368 gb_connection_pop_timestamp(gb->connection, &ts);
369 gb_connection_pop_timestamp(gb->connection, &te);
370 gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te);
355a7058
AB
371
372 if (retval)
373 goto gb_error;
374
dc366f8e
VK
375 if (memcmp(request->data, response->data, len)) {
376 pr_info("%s: Loopback Data doesn't match\n", __func__);
355a7058 377 retval = -EREMOTEIO;
dc366f8e 378 }
355a7058
AB
379
380gb_error:
381 kfree(request);
382 kfree(response);
383
384 return retval;
385}
386
a7e60062 387static int gb_loopback_ping(struct gb_loopback *gb)
355a7058
AB
388{
389 struct timeval ts, te;
355a7058
AB
390 int retval;
391
392 do_gettimeofday(&ts);
393 retval = gb_operation_sync(gb->connection, GB_LOOPBACK_TYPE_PING,
394 NULL, 0, NULL, 0);
395 do_gettimeofday(&te);
2f842304
BD
396
397 /* Calculate the total time the message took */
398 gb->elapsed_nsecs = gb_loopback_calc_latency(&ts, &te);
399
400 /* Calculate non-greybus related component of the latency */
401 gb_connection_pop_timestamp(gb->connection, &ts);
402 gb_connection_pop_timestamp(gb->connection, &te);
403 gb->elapsed_nsecs_gb = gb_loopback_calc_latency(&ts, &te);
355a7058
AB
404
405 return retval;
406}
407
ac1c2840
AE
408static int gb_loopback_request_recv(u8 type, struct gb_operation *operation)
409{
410 struct gb_connection *connection = operation->connection;
411 struct gb_loopback_transfer_request *request;
412 struct gb_loopback_transfer_response *response;
e51eafeb 413 size_t len;
ac1c2840
AE
414
415 /* By convention, the AP initiates the version operation */
416 switch (type) {
0e2462d1 417 case GB_REQUEST_TYPE_PROTOCOL_VERSION:
ac1c2840
AE
418 dev_err(&connection->dev,
419 "module-initiated version operation\n");
420 return -EINVAL;
421 case GB_LOOPBACK_TYPE_PING:
384a7a3c 422 case GB_LOOPBACK_TYPE_SINK:
ac1c2840
AE
423 return 0;
424 case GB_LOOPBACK_TYPE_TRANSFER:
425 if (operation->request->payload_size < sizeof(*request)) {
426 dev_err(&connection->dev,
427 "transfer request too small (%zu < %zu)\n",
428 operation->request->payload_size,
429 sizeof(*request));
430 return -EINVAL; /* -EMSGSIZE */
431 }
432 request = operation->request->payload;
433 len = le32_to_cpu(request->len);
67d1eece 434 if (len > gb_dev.size_max) {
c3bba87a
BD
435 dev_err(&connection->dev,
436 "transfer request too large (%zu > %zu)\n",
67d1eece 437 len, gb_dev.size_max);
c3bba87a
BD
438 return -EINVAL;
439 }
440
ac1c2840 441 if (len) {
1c7658cf
JH
442 if (!gb_operation_response_alloc(operation, len,
443 GFP_KERNEL)) {
ac1c2840
AE
444 dev_err(&connection->dev,
445 "error allocating response\n");
446 return -ENOMEM;
447 }
448 response = operation->response->payload;
449 memcpy(response->data, request->data, len);
450 }
451 return 0;
452 default:
453 dev_err(&connection->dev,
454 "unsupported request: %hhu\n", type);
455 return -EINVAL;
456 }
457}
458
67d1eece 459static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev)
355a7058
AB
460{
461 struct gb_loopback_stats reset = {
e051c82b 462 .min = U32_MAX,
355a7058 463 };
67d1eece
BD
464 struct gb_loopback *gb;
465
466 /* Reset per-connection stats */
467 list_for_each_entry(gb, &gb_dev->list, entry) {
468 mutex_lock(&gb->mutex);
469 memcpy(&gb->latency, &reset,
470 sizeof(struct gb_loopback_stats));
471 memcpy(&gb->latency_gb, &reset,
472 sizeof(struct gb_loopback_stats));
473 memcpy(&gb->throughput, &reset,
474 sizeof(struct gb_loopback_stats));
475 memcpy(&gb->requests_per_second, &reset,
476 sizeof(struct gb_loopback_stats));
477 mutex_unlock(&gb->mutex);
478 }
479
480 /* Reset aggregate stats */
481 memset(&gb_dev->start, 0, sizeof(struct timeval));
482 memset(&gb_dev->end, 0, sizeof(struct timeval));
483 memcpy(&gb_dev->latency, &reset, sizeof(struct gb_loopback_stats));
484 memcpy(&gb_dev->latency_gb, &reset, sizeof(struct gb_loopback_stats));
485 memcpy(&gb_dev->throughput, &reset, sizeof(struct gb_loopback_stats));
486 memcpy(&gb_dev->requests_per_second, &reset,
583cbf50 487 sizeof(struct gb_loopback_stats));
355a7058
AB
488}
489
a6e7e535 490static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val)
355a7058 491{
00af6583
BD
492 if (stats->min > val)
493 stats->min = val;
494 if (stats->max < val)
495 stats->max = val;
496 stats->sum += val;
497 stats->count++;
355a7058
AB
498}
499
583cbf50 500static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency)
355a7058 501{
583cbf50 502 u32 req = USEC_PER_SEC;
00af6583 503
583cbf50 504 do_div(req, latency);
67d1eece 505 gb_loopback_update_stats(&gb_dev.requests_per_second, req);
583cbf50 506 gb_loopback_update_stats(&gb->requests_per_second, req);
355a7058
AB
507}
508
00af6583 509static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency)
355a7058 510{
00af6583 511 u32 throughput;
f7908e4d
BD
512 u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2;
513
67d1eece 514 switch (gb_dev.type) {
f7908e4d
BD
515 case GB_LOOPBACK_TYPE_PING:
516 break;
517 case GB_LOOPBACK_TYPE_SINK:
518 aggregate_size += sizeof(struct gb_loopback_transfer_request) +
67d1eece 519 gb_dev.size;
f7908e4d
BD
520 break;
521 case GB_LOOPBACK_TYPE_TRANSFER:
522 aggregate_size += sizeof(struct gb_loopback_transfer_request) +
523 sizeof(struct gb_loopback_transfer_response) +
67d1eece 524 gb_dev.size * 2;
f7908e4d
BD
525 break;
526 default:
527 return;
528 }
00af6583
BD
529
530 /* Calculate bytes per second */
531 throughput = USEC_PER_SEC;
532 do_div(throughput, latency);
533 throughput *= aggregate_size;
67d1eece 534 gb_loopback_update_stats(&gb_dev.throughput, throughput);
00af6583 535 gb_loopback_update_stats(&gb->throughput, throughput);
355a7058
AB
536}
537
a7e60062 538static void gb_loopback_calculate_stats(struct gb_loopback *gb)
355a7058
AB
539{
540 u32 lat;
1ffc12be 541 u64 tmp;
355a7058 542
00af6583 543 /* Express latency in terms of microseconds */
bd416103 544 lat = gb_loopback_nsec_to_usec_latency(gb->elapsed_nsecs);
355a7058 545
006335a0 546 /* Log latency statistic */
67d1eece 547 gb_loopback_update_stats(&gb_dev.latency, lat);
00af6583 548 gb_loopback_update_stats(&gb->latency, lat);
67d1eece
BD
549
550 /* Raw latency log on a per thread basis */
cbd204b4 551 kfifo_in(&gb->kfifo, (unsigned char *)&lat, sizeof(lat));
00af6583 552
583cbf50 553 /* Log throughput and requests using latency as benchmark */
00af6583 554 gb_loopback_throughput_update(gb, lat);
583cbf50 555 gb_loopback_requests_update(gb, lat);
2f842304
BD
556
557 /* Calculate the greybus related latency number in nanoseconds */
558 tmp = gb->elapsed_nsecs - gb->elapsed_nsecs_gb;
559 lat = tmp;
67d1eece 560 gb_loopback_update_stats(&gb_dev.latency_gb, lat);
2f842304 561 gb_loopback_update_stats(&gb->latency_gb, lat);
355a7058
AB
562}
563
564static int gb_loopback_fn(void *data)
565{
566 int error = 0;
85d678c0 567 int ms_wait;
67d1eece
BD
568 int type;
569 u32 size;
570 u32 low_count;
3f12c3ed 571 struct gb_loopback *gb = data;
67d1eece 572 struct gb_loopback *gb_list;
355a7058 573
3dfe8aaa 574 while (1) {
67d1eece
BD
575 if (!gb_dev.type)
576 wait_event_interruptible(gb_dev.wq, gb_dev.type ||
3dfe8aaa
BD
577 kthread_should_stop());
578 if (kthread_should_stop())
579 break;
85d678c0 580
67d1eece
BD
581 mutex_lock(&gb_dev.mutex);
582 if (gb_dev.iteration_max) {
583 /* Determine overall lowest count */
584 low_count = gb->iteration_count;
585 list_for_each_entry(gb_list, &gb_dev.list, entry) {
586 if (gb_list->iteration_count < low_count)
587 low_count = gb_list->iteration_count;
588 }
589 /* All threads achieved at least low_count iterations */
590 if (gb_dev.iteration_count < low_count) {
591 gb_dev.iteration_count = low_count;
c2939f41
GKH
592 sysfs_notify(&gb->connection->dev.kobj, NULL,
593 "iteration_count");
67d1eece
BD
594 }
595 /* Optionally terminate */
596 if (gb_dev.iteration_count == gb_dev.iteration_max) {
597 gb_dev.type = 0;
598 mutex_unlock(&gb_dev.mutex);
00af6583
BD
599 continue;
600 }
601 }
67d1eece
BD
602 size = gb_dev.size;
603 ms_wait = gb_dev.ms_wait;
604 type = gb_dev.type;
605 mutex_unlock(&gb_dev.mutex);
606
607 mutex_lock(&gb->mutex);
608 if (gb->iteration_count >= gb_dev.iteration_max) {
609 /* If this thread finished before siblings then sleep */
610 ms_wait = 1;
611 mutex_unlock(&gb->mutex);
612 goto sleep;
613 }
614 /* Else operations to perform */
615 if (type == GB_LOOPBACK_TYPE_PING)
a7e60062 616 error = gb_loopback_ping(gb);
67d1eece
BD
617 else if (type == GB_LOOPBACK_TYPE_TRANSFER)
618 error = gb_loopback_transfer(gb, size);
619 else if (type == GB_LOOPBACK_TYPE_SINK)
620 error = gb_loopback_sink(gb, size);
621 mutex_unlock(&gb->mutex);
622
623 mutex_lock(&gb_dev.mutex);
624 mutex_lock(&gb->mutex);
625
626 if (error) {
627 gb_dev.error++;
355a7058 628 gb->error++;
67d1eece 629 }
a7e60062 630 gb_loopback_calculate_stats(gb);
67d1eece
BD
631 gb->iteration_count++;
632
85d678c0 633 mutex_unlock(&gb->mutex);
67d1eece
BD
634 mutex_unlock(&gb_dev.mutex);
635sleep:
85d678c0
BD
636 if (ms_wait)
637 msleep(ms_wait);
355a7058
AB
638 }
639 return 0;
640}
641
aa27bf82
BD
642static int gb_loopback_dbgfs_latency_show(struct seq_file *s, void *unused)
643{
644 struct gb_loopback *gb = s->private;
645 u32 latency;
646 int retval;
647
648 if (kfifo_len(&gb->kfifo) == 0) {
649 retval = -EAGAIN;
650 goto done;
651 }
652
653 mutex_lock(&gb->mutex);
654 retval = kfifo_out(&gb->kfifo, &latency, sizeof(latency));
655 if (retval > 0) {
656 seq_printf(s, "%u", latency);
657 retval = 0;
658 }
659 mutex_unlock(&gb->mutex);
660done:
661 return retval;
662}
663
664static int gb_loopback_latency_open(struct inode *inode, struct file *file)
665{
666 return single_open(file, gb_loopback_dbgfs_latency_show,
667 inode->i_private);
668}
669
670static const struct file_operations gb_loopback_debugfs_latency_ops = {
671 .open = gb_loopback_latency_open,
672 .read = seq_read,
673 .llseek = seq_lseek,
674 .release = single_release,
675};
676
67d1eece 677#define DEBUGFS_NAMELEN 32
aa27bf82 678
355a7058
AB
679static int gb_loopback_connection_init(struct gb_connection *connection)
680{
681 struct gb_loopback *gb;
682 int retval;
aa27bf82 683 char name[DEBUGFS_NAMELEN];
355a7058
AB
684
685 gb = kzalloc(sizeof(*gb), GFP_KERNEL);
686 if (!gb)
687 return -ENOMEM;
67d1eece 688 gb_loopback_reset_stats(&gb_dev);
355a7058 689
aa27bf82
BD
690 snprintf(name, sizeof(name), "raw_latency_endo0:%d:%d:%d:%d",
691 connection->bundle->intf->module->module_id,
692 connection->bundle->intf->interface_id,
693 connection->bundle->id,
694 connection->intf_cport_id);
695 gb->file = debugfs_create_file(name, S_IFREG | S_IRUGO, gb_dev.root, gb,
696 &gb_loopback_debugfs_latency_ops);
355a7058
AB
697 gb->connection = connection;
698 connection->private = gb;
7a51b936 699 retval = sysfs_create_groups(&connection->dev.kobj, loopback_groups);
355a7058 700 if (retval)
aa27bf82 701 goto out_debugfs;
cbd204b4 702
c3bba87a 703 /* Calculate maximum payload */
67d1eece
BD
704 mutex_lock(&gb_dev.mutex);
705 gb_dev.size_max = gb_operation_get_payload_size_max(connection);
706 if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) {
c3bba87a 707 retval = -EINVAL;
aa27bf82 708 goto out_sysfs;
c3bba87a 709 }
67d1eece
BD
710 gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request);
711 mutex_unlock(&gb_dev.mutex);
c3bba87a 712
cbd204b4
BD
713 /* Allocate kfifo */
714 if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32),
715 GFP_KERNEL)) {
716 retval = -ENOMEM;
aa27bf82 717 goto out_sysfs;
cbd204b4
BD
718 }
719
720 /* Fork worker thread */
85d678c0 721 mutex_init(&gb->mutex);
355a7058
AB
722 gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback");
723 if (IS_ERR(gb->task)) {
69f60347 724 retval = PTR_ERR(gb->task);
aa27bf82 725 goto out_kfifo;
355a7058
AB
726 }
727
67d1eece
BD
728 mutex_lock(&gb_dev.mutex);
729 list_add_tail(&gb->entry, &gb_dev.list);
730 mutex_unlock(&gb_dev.mutex);
aa27bf82 731 gb_dev.count++;
355a7058
AB
732 return 0;
733
cbd204b4
BD
734out_kfifo:
735 kfifo_free(&gb->kfifo);
1fb807cf 736out_sysfs:
6f8528e0 737 sysfs_remove_groups(&connection->dev.kobj, loopback_groups);
aa27bf82
BD
738out_debugfs:
739 debugfs_remove(gb->file);
1fb807cf 740 connection->private = NULL;
355a7058 741 kfree(gb);
1fb807cf 742
355a7058
AB
743 return retval;
744}
745
746static void gb_loopback_connection_exit(struct gb_connection *connection)
747{
748 struct gb_loopback *gb = connection->private;
749
aa27bf82 750 gb_dev.count--;
1fb807cf 751 connection->private = NULL;
355a7058
AB
752 if (!IS_ERR_OR_NULL(gb->task))
753 kthread_stop(gb->task);
cbd204b4 754
cbd204b4 755 kfifo_free(&gb->kfifo);
7a51b936 756 sysfs_remove_groups(&connection->dev.kobj, loopback_groups);
aa27bf82 757 debugfs_remove(gb->file);
355a7058
AB
758 kfree(gb);
759}
760
761static struct gb_protocol loopback_protocol = {
762 .name = "loopback",
763 .id = GREYBUS_PROTOCOL_LOOPBACK,
764 .major = GB_LOOPBACK_VERSION_MAJOR,
765 .minor = GB_LOOPBACK_VERSION_MINOR,
766 .connection_init = gb_loopback_connection_init,
767 .connection_exit = gb_loopback_connection_exit,
ac1c2840 768 .request_recv = gb_loopback_request_recv,
355a7058
AB
769};
770
cbd204b4
BD
771static int loopback_init(void)
772{
67d1eece
BD
773 init_waitqueue_head(&gb_dev.wq);
774 INIT_LIST_HEAD(&gb_dev.list);
775 mutex_init(&gb_dev.mutex);
aa27bf82 776 gb_dev.root = debugfs_create_dir("gb_loopback", NULL);
67d1eece 777
aa27bf82 778 return gb_protocol_register(&loopback_protocol);
cbd204b4
BD
779}
780module_init(loopback_init);
781
782static void __exit loopback_exit(void)
783{
aa27bf82 784 debugfs_remove_recursive(gb_dev.root);
cbd204b4 785 gb_protocol_deregister(&loopback_protocol);
cbd204b4
BD
786}
787module_exit(loopback_exit);
355a7058
AB
788
789MODULE_LICENSE("GPL v2");