xref: /linux/kernel/trace/trace_remote.c (revision 01f492e1817e858d1712f2489d0afbaa552f417b)
196e43537SVincent Donnefort // SPDX-License-Identifier: GPL-2.0
296e43537SVincent Donnefort /*
396e43537SVincent Donnefort  * Copyright (C) 2025 - Google LLC
496e43537SVincent Donnefort  * Author: Vincent Donnefort <vdonnefort@google.com>
596e43537SVincent Donnefort  */
696e43537SVincent Donnefort 
796e43537SVincent Donnefort #include <linux/kstrtox.h>
896e43537SVincent Donnefort #include <linux/lockdep.h>
996e43537SVincent Donnefort #include <linux/mutex.h>
1096e43537SVincent Donnefort #include <linux/tracefs.h>
1196e43537SVincent Donnefort #include <linux/trace_remote.h>
1296e43537SVincent Donnefort #include <linux/trace_seq.h>
1396e43537SVincent Donnefort #include <linux/types.h>
1496e43537SVincent Donnefort 
1596e43537SVincent Donnefort #include "trace.h"
1696e43537SVincent Donnefort 
1796e43537SVincent Donnefort #define TRACEFS_DIR		"remotes"
1896e43537SVincent Donnefort #define TRACEFS_MODE_WRITE	0640
1996e43537SVincent Donnefort #define TRACEFS_MODE_READ	0440
2096e43537SVincent Donnefort 
21330b0cceSVincent Donnefort enum tri_type {
22330b0cceSVincent Donnefort 	TRI_CONSUMING,
23330b0cceSVincent Donnefort 	TRI_NONCONSUMING,
24330b0cceSVincent Donnefort };
25330b0cceSVincent Donnefort 
2696e43537SVincent Donnefort struct trace_remote_iterator {
2796e43537SVincent Donnefort 	struct trace_remote		*remote;
2896e43537SVincent Donnefort 	struct trace_seq		seq;
2996e43537SVincent Donnefort 	struct delayed_work		poll_work;
3096e43537SVincent Donnefort 	unsigned long			lost_events;
3196e43537SVincent Donnefort 	u64				ts;
32330b0cceSVincent Donnefort 	struct ring_buffer_iter		*rb_iter;
33330b0cceSVincent Donnefort 	struct ring_buffer_iter		**rb_iters;
3407252915SVincent Donnefort 	struct remote_event_hdr		*evt;
3596e43537SVincent Donnefort 	int				cpu;
3696e43537SVincent Donnefort 	int				evt_cpu;
37330b0cceSVincent Donnefort 	loff_t				pos;
38330b0cceSVincent Donnefort 	enum tri_type			type;
3996e43537SVincent Donnefort };
4096e43537SVincent Donnefort 
4196e43537SVincent Donnefort struct trace_remote {
4296e43537SVincent Donnefort 	struct trace_remote_callbacks	*cbs;
4396e43537SVincent Donnefort 	void				*priv;
4496e43537SVincent Donnefort 	struct trace_buffer		*trace_buffer;
4596e43537SVincent Donnefort 	struct trace_buffer_desc	*trace_buffer_desc;
4607252915SVincent Donnefort 	struct dentry			*dentry;
4707252915SVincent Donnefort 	struct eventfs_inode		*eventfs;
4807252915SVincent Donnefort 	struct remote_event		*events;
4907252915SVincent Donnefort 	unsigned long			nr_events;
5096e43537SVincent Donnefort 	unsigned long			trace_buffer_size;
5196e43537SVincent Donnefort 	struct ring_buffer_remote	rb_remote;
5296e43537SVincent Donnefort 	struct mutex			lock;
53330b0cceSVincent Donnefort 	struct rw_semaphore		reader_lock;
54330b0cceSVincent Donnefort 	struct rw_semaphore		*pcpu_reader_locks;
5596e43537SVincent Donnefort 	unsigned int			nr_readers;
5696e43537SVincent Donnefort 	unsigned int			poll_ms;
5796e43537SVincent Donnefort 	bool				tracing_on;
5896e43537SVincent Donnefort };
5996e43537SVincent Donnefort 
6096e43537SVincent Donnefort static bool trace_remote_loaded(struct trace_remote *remote)
6196e43537SVincent Donnefort {
6296e43537SVincent Donnefort 	return !!remote->trace_buffer;
6396e43537SVincent Donnefort }
6496e43537SVincent Donnefort 
6596e43537SVincent Donnefort static int trace_remote_load(struct trace_remote *remote)
6696e43537SVincent Donnefort {
6796e43537SVincent Donnefort 	struct ring_buffer_remote *rb_remote = &remote->rb_remote;
6896e43537SVincent Donnefort 	struct trace_buffer_desc *desc;
6996e43537SVincent Donnefort 
7096e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
7196e43537SVincent Donnefort 
7296e43537SVincent Donnefort 	if (trace_remote_loaded(remote))
7396e43537SVincent Donnefort 		return 0;
7496e43537SVincent Donnefort 
7596e43537SVincent Donnefort 	desc = remote->cbs->load_trace_buffer(remote->trace_buffer_size, remote->priv);
7696e43537SVincent Donnefort 	if (IS_ERR(desc))
7796e43537SVincent Donnefort 		return PTR_ERR(desc);
7896e43537SVincent Donnefort 
7996e43537SVincent Donnefort 	rb_remote->desc = desc;
8096e43537SVincent Donnefort 	rb_remote->swap_reader_page = remote->cbs->swap_reader_page;
8196e43537SVincent Donnefort 	rb_remote->priv = remote->priv;
829af4ab0eSVincent Donnefort 	rb_remote->reset = remote->cbs->reset;
8396e43537SVincent Donnefort 	remote->trace_buffer = ring_buffer_alloc_remote(rb_remote);
8496e43537SVincent Donnefort 	if (!remote->trace_buffer) {
8596e43537SVincent Donnefort 		remote->cbs->unload_trace_buffer(desc, remote->priv);
8696e43537SVincent Donnefort 		return -ENOMEM;
8796e43537SVincent Donnefort 	}
8896e43537SVincent Donnefort 
8996e43537SVincent Donnefort 	remote->trace_buffer_desc = desc;
9096e43537SVincent Donnefort 
9196e43537SVincent Donnefort 	return 0;
9296e43537SVincent Donnefort }
9396e43537SVincent Donnefort 
9496e43537SVincent Donnefort static void trace_remote_try_unload(struct trace_remote *remote)
9596e43537SVincent Donnefort {
9696e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
9796e43537SVincent Donnefort 
9896e43537SVincent Donnefort 	if (!trace_remote_loaded(remote))
9996e43537SVincent Donnefort 		return;
10096e43537SVincent Donnefort 
10196e43537SVincent Donnefort 	/* The buffer is being read or writable */
10296e43537SVincent Donnefort 	if (remote->nr_readers || remote->tracing_on)
10396e43537SVincent Donnefort 		return;
10496e43537SVincent Donnefort 
10596e43537SVincent Donnefort 	/* The buffer has readable data */
10696e43537SVincent Donnefort 	if (!ring_buffer_empty(remote->trace_buffer))
10796e43537SVincent Donnefort 		return;
10896e43537SVincent Donnefort 
10996e43537SVincent Donnefort 	ring_buffer_free(remote->trace_buffer);
11096e43537SVincent Donnefort 	remote->trace_buffer = NULL;
11196e43537SVincent Donnefort 	remote->cbs->unload_trace_buffer(remote->trace_buffer_desc, remote->priv);
11296e43537SVincent Donnefort }
11396e43537SVincent Donnefort 
11496e43537SVincent Donnefort static int trace_remote_enable_tracing(struct trace_remote *remote)
11596e43537SVincent Donnefort {
11696e43537SVincent Donnefort 	int ret;
11796e43537SVincent Donnefort 
11896e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
11996e43537SVincent Donnefort 
12096e43537SVincent Donnefort 	if (remote->tracing_on)
12196e43537SVincent Donnefort 		return 0;
12296e43537SVincent Donnefort 
12396e43537SVincent Donnefort 	ret = trace_remote_load(remote);
12496e43537SVincent Donnefort 	if (ret)
12596e43537SVincent Donnefort 		return ret;
12696e43537SVincent Donnefort 
12796e43537SVincent Donnefort 	ret = remote->cbs->enable_tracing(true, remote->priv);
12896e43537SVincent Donnefort 	if (ret) {
12996e43537SVincent Donnefort 		trace_remote_try_unload(remote);
13096e43537SVincent Donnefort 		return ret;
13196e43537SVincent Donnefort 	}
13296e43537SVincent Donnefort 
13396e43537SVincent Donnefort 	remote->tracing_on = true;
13496e43537SVincent Donnefort 
13596e43537SVincent Donnefort 	return 0;
13696e43537SVincent Donnefort }
13796e43537SVincent Donnefort 
13896e43537SVincent Donnefort static int trace_remote_disable_tracing(struct trace_remote *remote)
13996e43537SVincent Donnefort {
14096e43537SVincent Donnefort 	int ret;
14196e43537SVincent Donnefort 
14296e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
14396e43537SVincent Donnefort 
14496e43537SVincent Donnefort 	if (!remote->tracing_on)
14596e43537SVincent Donnefort 		return 0;
14696e43537SVincent Donnefort 
14796e43537SVincent Donnefort 	ret = remote->cbs->enable_tracing(false, remote->priv);
14896e43537SVincent Donnefort 	if (ret)
14996e43537SVincent Donnefort 		return ret;
15096e43537SVincent Donnefort 
15196e43537SVincent Donnefort 	ring_buffer_poll_remote(remote->trace_buffer, RING_BUFFER_ALL_CPUS);
15296e43537SVincent Donnefort 	remote->tracing_on = false;
15396e43537SVincent Donnefort 	trace_remote_try_unload(remote);
15496e43537SVincent Donnefort 
15596e43537SVincent Donnefort 	return 0;
15696e43537SVincent Donnefort }
15796e43537SVincent Donnefort 
1589af4ab0eSVincent Donnefort static void trace_remote_reset(struct trace_remote *remote, int cpu)
1599af4ab0eSVincent Donnefort {
1609af4ab0eSVincent Donnefort 	lockdep_assert_held(&remote->lock);
1619af4ab0eSVincent Donnefort 
1629af4ab0eSVincent Donnefort 	if (!trace_remote_loaded(remote))
1639af4ab0eSVincent Donnefort 		return;
1649af4ab0eSVincent Donnefort 
1659af4ab0eSVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS)
1669af4ab0eSVincent Donnefort 		ring_buffer_reset(remote->trace_buffer);
1679af4ab0eSVincent Donnefort 	else
1689af4ab0eSVincent Donnefort 		ring_buffer_reset_cpu(remote->trace_buffer, cpu);
1699af4ab0eSVincent Donnefort 
1709af4ab0eSVincent Donnefort 	trace_remote_try_unload(remote);
1719af4ab0eSVincent Donnefort }
1729af4ab0eSVincent Donnefort 
17396e43537SVincent Donnefort static ssize_t
17496e43537SVincent Donnefort tracing_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
17596e43537SVincent Donnefort {
17607252915SVincent Donnefort 	struct seq_file *seq = filp->private_data;
17707252915SVincent Donnefort 	struct trace_remote *remote = seq->private;
17896e43537SVincent Donnefort 	unsigned long val;
17996e43537SVincent Donnefort 	int ret;
18096e43537SVincent Donnefort 
18196e43537SVincent Donnefort 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
18296e43537SVincent Donnefort 	if (ret)
18396e43537SVincent Donnefort 		return ret;
18496e43537SVincent Donnefort 
18596e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
18696e43537SVincent Donnefort 
18796e43537SVincent Donnefort 	ret = val ? trace_remote_enable_tracing(remote) : trace_remote_disable_tracing(remote);
18896e43537SVincent Donnefort 	if (ret)
18996e43537SVincent Donnefort 		return ret;
19096e43537SVincent Donnefort 
19196e43537SVincent Donnefort 	return cnt;
19296e43537SVincent Donnefort }
19396e43537SVincent Donnefort static int tracing_on_show(struct seq_file *s, void *unused)
19496e43537SVincent Donnefort {
19596e43537SVincent Donnefort 	struct trace_remote *remote = s->private;
19696e43537SVincent Donnefort 
19796e43537SVincent Donnefort 	seq_printf(s, "%d\n", remote->tracing_on);
19896e43537SVincent Donnefort 
19996e43537SVincent Donnefort 	return 0;
20096e43537SVincent Donnefort }
20196e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(tracing_on);
20296e43537SVincent Donnefort 
20396e43537SVincent Donnefort static ssize_t buffer_size_kb_write(struct file *filp, const char __user *ubuf, size_t cnt,
20496e43537SVincent Donnefort 				    loff_t *ppos)
20596e43537SVincent Donnefort {
20607252915SVincent Donnefort 	struct seq_file *seq = filp->private_data;
20707252915SVincent Donnefort 	struct trace_remote *remote = seq->private;
20896e43537SVincent Donnefort 	unsigned long val;
20996e43537SVincent Donnefort 	int ret;
21096e43537SVincent Donnefort 
21196e43537SVincent Donnefort 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
21296e43537SVincent Donnefort 	if (ret)
21396e43537SVincent Donnefort 		return ret;
21496e43537SVincent Donnefort 
21596e43537SVincent Donnefort 	/* KiB to Bytes */
21696e43537SVincent Donnefort 	if (!val || check_shl_overflow(val, 10, &val))
21796e43537SVincent Donnefort 		return -EINVAL;
21896e43537SVincent Donnefort 
21996e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
22096e43537SVincent Donnefort 
22196e43537SVincent Donnefort 	if (trace_remote_loaded(remote))
22296e43537SVincent Donnefort 		return -EBUSY;
22396e43537SVincent Donnefort 
22496e43537SVincent Donnefort 	remote->trace_buffer_size = val;
22596e43537SVincent Donnefort 
22696e43537SVincent Donnefort 	return cnt;
22796e43537SVincent Donnefort }
22896e43537SVincent Donnefort 
22996e43537SVincent Donnefort static int buffer_size_kb_show(struct seq_file *s, void *unused)
23096e43537SVincent Donnefort {
23196e43537SVincent Donnefort 	struct trace_remote *remote = s->private;
23296e43537SVincent Donnefort 
23396e43537SVincent Donnefort 	seq_printf(s, "%lu (%s)\n", remote->trace_buffer_size >> 10,
23496e43537SVincent Donnefort 		   trace_remote_loaded(remote) ? "loaded" : "unloaded");
23596e43537SVincent Donnefort 
23696e43537SVincent Donnefort 	return 0;
23796e43537SVincent Donnefort }
23896e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(buffer_size_kb);
23996e43537SVincent Donnefort 
24096e43537SVincent Donnefort static int trace_remote_get(struct trace_remote *remote, int cpu)
24196e43537SVincent Donnefort {
24296e43537SVincent Donnefort 	int ret;
24396e43537SVincent Donnefort 
24496e43537SVincent Donnefort 	if (remote->nr_readers == UINT_MAX)
24596e43537SVincent Donnefort 		return -EBUSY;
24696e43537SVincent Donnefort 
24796e43537SVincent Donnefort 	ret = trace_remote_load(remote);
24896e43537SVincent Donnefort 	if (ret)
24996e43537SVincent Donnefort 		return ret;
25096e43537SVincent Donnefort 
251330b0cceSVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS && !remote->pcpu_reader_locks) {
252330b0cceSVincent Donnefort 		int lock_cpu;
253330b0cceSVincent Donnefort 
254330b0cceSVincent Donnefort 		remote->pcpu_reader_locks = kcalloc(nr_cpu_ids, sizeof(*remote->pcpu_reader_locks),
255330b0cceSVincent Donnefort 						    GFP_KERNEL);
256330b0cceSVincent Donnefort 		if (!remote->pcpu_reader_locks) {
257330b0cceSVincent Donnefort 			trace_remote_try_unload(remote);
258330b0cceSVincent Donnefort 			return -ENOMEM;
259330b0cceSVincent Donnefort 		}
260330b0cceSVincent Donnefort 
261330b0cceSVincent Donnefort 		for_each_possible_cpu(lock_cpu)
262330b0cceSVincent Donnefort 			init_rwsem(&remote->pcpu_reader_locks[lock_cpu]);
263330b0cceSVincent Donnefort 	}
264330b0cceSVincent Donnefort 
26596e43537SVincent Donnefort 	remote->nr_readers++;
26696e43537SVincent Donnefort 
26796e43537SVincent Donnefort 	return 0;
26896e43537SVincent Donnefort }
26996e43537SVincent Donnefort 
27096e43537SVincent Donnefort static void trace_remote_put(struct trace_remote *remote)
27196e43537SVincent Donnefort {
27296e43537SVincent Donnefort 	if (WARN_ON(!remote->nr_readers))
27396e43537SVincent Donnefort 		return;
27496e43537SVincent Donnefort 
27596e43537SVincent Donnefort 	remote->nr_readers--;
27696e43537SVincent Donnefort 	if (remote->nr_readers)
27796e43537SVincent Donnefort 		return;
27896e43537SVincent Donnefort 
279330b0cceSVincent Donnefort 	kfree(remote->pcpu_reader_locks);
280330b0cceSVincent Donnefort 	remote->pcpu_reader_locks = NULL;
281330b0cceSVincent Donnefort 
28296e43537SVincent Donnefort 	trace_remote_try_unload(remote);
28396e43537SVincent Donnefort }
28496e43537SVincent Donnefort 
285*ce47b798SVincent Donnefort static bool trace_remote_has_cpu(struct trace_remote *remote, int cpu)
286*ce47b798SVincent Donnefort {
287*ce47b798SVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS)
288*ce47b798SVincent Donnefort 		return true;
289*ce47b798SVincent Donnefort 
290*ce47b798SVincent Donnefort 	return ring_buffer_poll_remote(remote->trace_buffer, cpu) == 0;
291*ce47b798SVincent Donnefort }
292*ce47b798SVincent Donnefort 
29396e43537SVincent Donnefort static void __poll_remote(struct work_struct *work)
29496e43537SVincent Donnefort {
29596e43537SVincent Donnefort 	struct delayed_work *dwork = to_delayed_work(work);
29696e43537SVincent Donnefort 	struct trace_remote_iterator *iter;
29796e43537SVincent Donnefort 
29896e43537SVincent Donnefort 	iter = container_of(dwork, struct trace_remote_iterator, poll_work);
29996e43537SVincent Donnefort 	ring_buffer_poll_remote(iter->remote->trace_buffer, iter->cpu);
30096e43537SVincent Donnefort 	schedule_delayed_work((struct delayed_work *)work,
30196e43537SVincent Donnefort 			      msecs_to_jiffies(iter->remote->poll_ms));
30296e43537SVincent Donnefort }
30396e43537SVincent Donnefort 
304330b0cceSVincent Donnefort static void __free_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu)
305330b0cceSVincent Donnefort {
306330b0cceSVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
307330b0cceSVincent Donnefort 		ring_buffer_read_finish(iter->rb_iter);
308330b0cceSVincent Donnefort 		return;
309330b0cceSVincent Donnefort 	}
310330b0cceSVincent Donnefort 
311330b0cceSVincent Donnefort 	for_each_possible_cpu(cpu) {
312330b0cceSVincent Donnefort 		if (iter->rb_iters[cpu])
313330b0cceSVincent Donnefort 			ring_buffer_read_finish(iter->rb_iters[cpu]);
314330b0cceSVincent Donnefort 	}
315330b0cceSVincent Donnefort 
316330b0cceSVincent Donnefort 	kfree(iter->rb_iters);
317330b0cceSVincent Donnefort }
318330b0cceSVincent Donnefort 
319330b0cceSVincent Donnefort static int __alloc_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu)
320330b0cceSVincent Donnefort {
321330b0cceSVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
322330b0cceSVincent Donnefort 		iter->rb_iter = ring_buffer_read_start(iter->remote->trace_buffer, cpu, GFP_KERNEL);
323330b0cceSVincent Donnefort 
324330b0cceSVincent Donnefort 		return iter->rb_iter ? 0 : -ENOMEM;
325330b0cceSVincent Donnefort 	}
326330b0cceSVincent Donnefort 
327330b0cceSVincent Donnefort 	iter->rb_iters = kcalloc(nr_cpu_ids, sizeof(*iter->rb_iters), GFP_KERNEL);
328330b0cceSVincent Donnefort 	if (!iter->rb_iters)
329330b0cceSVincent Donnefort 		return -ENOMEM;
330330b0cceSVincent Donnefort 
331330b0cceSVincent Donnefort 	for_each_possible_cpu(cpu) {
332330b0cceSVincent Donnefort 		iter->rb_iters[cpu] = ring_buffer_read_start(iter->remote->trace_buffer, cpu,
333330b0cceSVincent Donnefort 							     GFP_KERNEL);
334330b0cceSVincent Donnefort 		if (!iter->rb_iters[cpu]) {
335*ce47b798SVincent Donnefort 			/* This CPU isn't part of trace_buffer. Skip it */
336*ce47b798SVincent Donnefort 			if (!trace_remote_has_cpu(iter->remote, cpu))
337*ce47b798SVincent Donnefort 				continue;
338*ce47b798SVincent Donnefort 
339330b0cceSVincent Donnefort 			__free_ring_buffer_iter(iter, RING_BUFFER_ALL_CPUS);
340330b0cceSVincent Donnefort 			return -ENOMEM;
341330b0cceSVincent Donnefort 		}
342330b0cceSVincent Donnefort 	}
343330b0cceSVincent Donnefort 
344330b0cceSVincent Donnefort 	return 0;
345330b0cceSVincent Donnefort }
346330b0cceSVincent Donnefort 
347330b0cceSVincent Donnefort static struct trace_remote_iterator
348330b0cceSVincent Donnefort *trace_remote_iter(struct trace_remote *remote, int cpu, enum tri_type type)
34996e43537SVincent Donnefort {
35096e43537SVincent Donnefort 	struct trace_remote_iterator *iter = NULL;
35196e43537SVincent Donnefort 	int ret;
35296e43537SVincent Donnefort 
35396e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
35496e43537SVincent Donnefort 
355330b0cceSVincent Donnefort 	if (type == TRI_NONCONSUMING && !trace_remote_loaded(remote))
356330b0cceSVincent Donnefort 		return NULL;
35796e43537SVincent Donnefort 
35896e43537SVincent Donnefort 	ret = trace_remote_get(remote, cpu);
35996e43537SVincent Donnefort 	if (ret)
36096e43537SVincent Donnefort 		return ERR_PTR(ret);
36196e43537SVincent Donnefort 
362*ce47b798SVincent Donnefort 	if (!trace_remote_has_cpu(remote, cpu)) {
363*ce47b798SVincent Donnefort 		ret = -ENODEV;
36496e43537SVincent Donnefort 		goto err;
365*ce47b798SVincent Donnefort 	}
36696e43537SVincent Donnefort 
36796e43537SVincent Donnefort 	iter = kzalloc_obj(*iter);
36896e43537SVincent Donnefort 	if (iter) {
36996e43537SVincent Donnefort 		iter->remote = remote;
37096e43537SVincent Donnefort 		iter->cpu = cpu;
371330b0cceSVincent Donnefort 		iter->type = type;
37296e43537SVincent Donnefort 		trace_seq_init(&iter->seq);
373330b0cceSVincent Donnefort 
374330b0cceSVincent Donnefort 		switch (type) {
375330b0cceSVincent Donnefort 		case TRI_CONSUMING:
376*ce47b798SVincent Donnefort 			ring_buffer_poll_remote(remote->trace_buffer, cpu);
37796e43537SVincent Donnefort 			INIT_DELAYED_WORK(&iter->poll_work, __poll_remote);
37896e43537SVincent Donnefort 			schedule_delayed_work(&iter->poll_work, msecs_to_jiffies(remote->poll_ms));
379330b0cceSVincent Donnefort 			break;
380330b0cceSVincent Donnefort 		case TRI_NONCONSUMING:
381330b0cceSVincent Donnefort 			ret = __alloc_ring_buffer_iter(iter, cpu);
382330b0cceSVincent Donnefort 			break;
383330b0cceSVincent Donnefort 		}
384330b0cceSVincent Donnefort 
385330b0cceSVincent Donnefort 		if (ret)
386330b0cceSVincent Donnefort 			goto err;
38796e43537SVincent Donnefort 
38896e43537SVincent Donnefort 		return iter;
38996e43537SVincent Donnefort 	}
39096e43537SVincent Donnefort 	ret = -ENOMEM;
39196e43537SVincent Donnefort 
39296e43537SVincent Donnefort err:
39396e43537SVincent Donnefort 	kfree(iter);
39496e43537SVincent Donnefort 	trace_remote_put(remote);
39596e43537SVincent Donnefort 
39696e43537SVincent Donnefort 	return ERR_PTR(ret);
39796e43537SVincent Donnefort }
39896e43537SVincent Donnefort 
39996e43537SVincent Donnefort static void trace_remote_iter_free(struct trace_remote_iterator *iter)
40096e43537SVincent Donnefort {
40196e43537SVincent Donnefort 	struct trace_remote *remote;
40296e43537SVincent Donnefort 
40396e43537SVincent Donnefort 	if (!iter)
40496e43537SVincent Donnefort 		return;
40596e43537SVincent Donnefort 
40696e43537SVincent Donnefort 	remote = iter->remote;
40796e43537SVincent Donnefort 
40896e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
40996e43537SVincent Donnefort 
410330b0cceSVincent Donnefort 	switch (iter->type) {
411330b0cceSVincent Donnefort 	case TRI_CONSUMING:
412330b0cceSVincent Donnefort 		cancel_delayed_work_sync(&iter->poll_work);
413330b0cceSVincent Donnefort 		break;
414330b0cceSVincent Donnefort 	case TRI_NONCONSUMING:
415330b0cceSVincent Donnefort 		__free_ring_buffer_iter(iter, iter->cpu);
416330b0cceSVincent Donnefort 		break;
417330b0cceSVincent Donnefort 	}
418330b0cceSVincent Donnefort 
41996e43537SVincent Donnefort 	kfree(iter);
42096e43537SVincent Donnefort 	trace_remote_put(remote);
42196e43537SVincent Donnefort }
42296e43537SVincent Donnefort 
423330b0cceSVincent Donnefort static void trace_remote_iter_read_start(struct trace_remote_iterator *iter)
424330b0cceSVincent Donnefort {
425330b0cceSVincent Donnefort 	struct trace_remote *remote = iter->remote;
426330b0cceSVincent Donnefort 	int cpu = iter->cpu;
427330b0cceSVincent Donnefort 
428330b0cceSVincent Donnefort 	/* Acquire global reader lock */
429330b0cceSVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING)
430330b0cceSVincent Donnefort 		down_write(&remote->reader_lock);
431330b0cceSVincent Donnefort 	else
432330b0cceSVincent Donnefort 		down_read(&remote->reader_lock);
433330b0cceSVincent Donnefort 
434330b0cceSVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS)
435330b0cceSVincent Donnefort 		return;
436330b0cceSVincent Donnefort 
437330b0cceSVincent Donnefort 	/*
438330b0cceSVincent Donnefort 	 * No need for the remote lock here, iter holds a reference on
439330b0cceSVincent Donnefort 	 * remote->nr_readers
440330b0cceSVincent Donnefort 	 */
441330b0cceSVincent Donnefort 
442330b0cceSVincent Donnefort 	/* Get the per-CPU one */
443330b0cceSVincent Donnefort 	if (WARN_ON_ONCE(!remote->pcpu_reader_locks))
444330b0cceSVincent Donnefort 		return;
445330b0cceSVincent Donnefort 
446330b0cceSVincent Donnefort 	if (iter->type == TRI_CONSUMING)
447330b0cceSVincent Donnefort 		down_write(&remote->pcpu_reader_locks[cpu]);
448330b0cceSVincent Donnefort 	else
449330b0cceSVincent Donnefort 		down_read(&remote->pcpu_reader_locks[cpu]);
450330b0cceSVincent Donnefort }
451330b0cceSVincent Donnefort 
452330b0cceSVincent Donnefort static void trace_remote_iter_read_finished(struct trace_remote_iterator *iter)
453330b0cceSVincent Donnefort {
454330b0cceSVincent Donnefort 	struct trace_remote *remote = iter->remote;
455330b0cceSVincent Donnefort 	int cpu = iter->cpu;
456330b0cceSVincent Donnefort 
457330b0cceSVincent Donnefort 	/* Release per-CPU reader lock */
458330b0cceSVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
459330b0cceSVincent Donnefort 		/*
460330b0cceSVincent Donnefort 		 * No need for the remote lock here, iter holds a reference on
461330b0cceSVincent Donnefort 		 * remote->nr_readers
462330b0cceSVincent Donnefort 		 */
463330b0cceSVincent Donnefort 		if (iter->type == TRI_CONSUMING)
464330b0cceSVincent Donnefort 			up_write(&remote->pcpu_reader_locks[cpu]);
465330b0cceSVincent Donnefort 		else
466330b0cceSVincent Donnefort 			up_read(&remote->pcpu_reader_locks[cpu]);
467330b0cceSVincent Donnefort 	}
468330b0cceSVincent Donnefort 
469330b0cceSVincent Donnefort 	/* Release global reader lock */
470330b0cceSVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING)
471330b0cceSVincent Donnefort 		up_write(&remote->reader_lock);
472330b0cceSVincent Donnefort 	else
473330b0cceSVincent Donnefort 		up_read(&remote->reader_lock);
474330b0cceSVincent Donnefort }
475330b0cceSVincent Donnefort 
476330b0cceSVincent Donnefort static struct ring_buffer_iter *__get_rb_iter(struct trace_remote_iterator *iter, int cpu)
477330b0cceSVincent Donnefort {
478330b0cceSVincent Donnefort 	return iter->cpu != RING_BUFFER_ALL_CPUS ? iter->rb_iter : iter->rb_iters[cpu];
479330b0cceSVincent Donnefort }
480330b0cceSVincent Donnefort 
481330b0cceSVincent Donnefort static struct ring_buffer_event *
482330b0cceSVincent Donnefort __peek_event(struct trace_remote_iterator *iter, int cpu, u64 *ts, unsigned long *lost_events)
483330b0cceSVincent Donnefort {
484330b0cceSVincent Donnefort 	struct ring_buffer_event *rb_evt;
485330b0cceSVincent Donnefort 	struct ring_buffer_iter *rb_iter;
486330b0cceSVincent Donnefort 
487330b0cceSVincent Donnefort 	switch (iter->type) {
488330b0cceSVincent Donnefort 	case TRI_CONSUMING:
489330b0cceSVincent Donnefort 		return ring_buffer_peek(iter->remote->trace_buffer, cpu, ts, lost_events);
490330b0cceSVincent Donnefort 	case TRI_NONCONSUMING:
491330b0cceSVincent Donnefort 		rb_iter = __get_rb_iter(iter, cpu);
492*ce47b798SVincent Donnefort 		if (!rb_iter)
493*ce47b798SVincent Donnefort 			return NULL;
494*ce47b798SVincent Donnefort 
495330b0cceSVincent Donnefort 		rb_evt = ring_buffer_iter_peek(rb_iter, ts);
496330b0cceSVincent Donnefort 		if (!rb_evt)
497330b0cceSVincent Donnefort 			return NULL;
498330b0cceSVincent Donnefort 
499330b0cceSVincent Donnefort 		*lost_events = ring_buffer_iter_dropped(rb_iter);
500330b0cceSVincent Donnefort 
501330b0cceSVincent Donnefort 		return rb_evt;
502330b0cceSVincent Donnefort 	}
503330b0cceSVincent Donnefort 
504330b0cceSVincent Donnefort 	return NULL;
505330b0cceSVincent Donnefort }
506330b0cceSVincent Donnefort 
50796e43537SVincent Donnefort static bool trace_remote_iter_read_event(struct trace_remote_iterator *iter)
50896e43537SVincent Donnefort {
50996e43537SVincent Donnefort 	struct trace_buffer *trace_buffer = iter->remote->trace_buffer;
51007252915SVincent Donnefort 	struct ring_buffer_event *rb_evt;
51196e43537SVincent Donnefort 	int cpu = iter->cpu;
51296e43537SVincent Donnefort 
51396e43537SVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
51496e43537SVincent Donnefort 		if (ring_buffer_empty_cpu(trace_buffer, cpu))
51596e43537SVincent Donnefort 			return false;
51696e43537SVincent Donnefort 
51707252915SVincent Donnefort 		rb_evt = __peek_event(iter, cpu, &iter->ts, &iter->lost_events);
51807252915SVincent Donnefort 		if (!rb_evt)
51996e43537SVincent Donnefort 			return false;
52096e43537SVincent Donnefort 
52196e43537SVincent Donnefort 		iter->evt_cpu = cpu;
52207252915SVincent Donnefort 		iter->evt = ring_buffer_event_data(rb_evt);
52396e43537SVincent Donnefort 		return true;
52496e43537SVincent Donnefort 	}
52596e43537SVincent Donnefort 
52696e43537SVincent Donnefort 	iter->ts = U64_MAX;
52796e43537SVincent Donnefort 	for_each_possible_cpu(cpu) {
52896e43537SVincent Donnefort 		unsigned long lost_events;
52996e43537SVincent Donnefort 		u64 ts;
53096e43537SVincent Donnefort 
53196e43537SVincent Donnefort 		if (ring_buffer_empty_cpu(trace_buffer, cpu))
53296e43537SVincent Donnefort 			continue;
53396e43537SVincent Donnefort 
53407252915SVincent Donnefort 		rb_evt = __peek_event(iter, cpu, &ts, &lost_events);
53507252915SVincent Donnefort 		if (!rb_evt)
53696e43537SVincent Donnefort 			continue;
53796e43537SVincent Donnefort 
53896e43537SVincent Donnefort 		if (ts >= iter->ts)
53996e43537SVincent Donnefort 			continue;
54096e43537SVincent Donnefort 
54196e43537SVincent Donnefort 		iter->ts = ts;
54296e43537SVincent Donnefort 		iter->evt_cpu = cpu;
54307252915SVincent Donnefort 		iter->evt = ring_buffer_event_data(rb_evt);
54496e43537SVincent Donnefort 		iter->lost_events = lost_events;
54596e43537SVincent Donnefort 	}
54696e43537SVincent Donnefort 
54796e43537SVincent Donnefort 	return iter->ts != U64_MAX;
54896e43537SVincent Donnefort }
54996e43537SVincent Donnefort 
550330b0cceSVincent Donnefort static void trace_remote_iter_move(struct trace_remote_iterator *iter)
551330b0cceSVincent Donnefort {
552330b0cceSVincent Donnefort 	struct trace_buffer *trace_buffer = iter->remote->trace_buffer;
553330b0cceSVincent Donnefort 
554330b0cceSVincent Donnefort 	switch (iter->type) {
555330b0cceSVincent Donnefort 	case TRI_CONSUMING:
556330b0cceSVincent Donnefort 		ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL);
557330b0cceSVincent Donnefort 		break;
558330b0cceSVincent Donnefort 	case TRI_NONCONSUMING:
559330b0cceSVincent Donnefort 		ring_buffer_iter_advance(__get_rb_iter(iter, iter->evt_cpu));
560330b0cceSVincent Donnefort 		break;
561330b0cceSVincent Donnefort 	}
562330b0cceSVincent Donnefort }
563330b0cceSVincent Donnefort 
56407252915SVincent Donnefort static struct remote_event *trace_remote_find_event(struct trace_remote *remote, unsigned short id);
56507252915SVincent Donnefort 
56696e43537SVincent Donnefort static int trace_remote_iter_print_event(struct trace_remote_iterator *iter)
56796e43537SVincent Donnefort {
56807252915SVincent Donnefort 	struct remote_event *evt;
56996e43537SVincent Donnefort 	unsigned long usecs_rem;
57096e43537SVincent Donnefort 	u64 ts = iter->ts;
57196e43537SVincent Donnefort 
57296e43537SVincent Donnefort 	if (iter->lost_events)
57396e43537SVincent Donnefort 		trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
57496e43537SVincent Donnefort 				 iter->evt_cpu, iter->lost_events);
57596e43537SVincent Donnefort 
57696e43537SVincent Donnefort 	do_div(ts, 1000);
57796e43537SVincent Donnefort 	usecs_rem = do_div(ts, USEC_PER_SEC);
57896e43537SVincent Donnefort 
57996e43537SVincent Donnefort 	trace_seq_printf(&iter->seq, "[%03d]\t%5llu.%06lu: ", iter->evt_cpu,
58096e43537SVincent Donnefort 			 ts, usecs_rem);
58196e43537SVincent Donnefort 
58207252915SVincent Donnefort 	evt = trace_remote_find_event(iter->remote, iter->evt->id);
58307252915SVincent Donnefort 	if (!evt)
58407252915SVincent Donnefort 		trace_seq_printf(&iter->seq, "UNKNOWN id=%d\n", iter->evt->id);
58507252915SVincent Donnefort 	else
58607252915SVincent Donnefort 		evt->print(iter->evt, &iter->seq);
58707252915SVincent Donnefort 
58896e43537SVincent Donnefort 	return trace_seq_has_overflowed(&iter->seq) ? -EOVERFLOW : 0;
58996e43537SVincent Donnefort }
59096e43537SVincent Donnefort 
59196e43537SVincent Donnefort static int trace_pipe_open(struct inode *inode, struct file *filp)
59296e43537SVincent Donnefort {
59396e43537SVincent Donnefort 	struct trace_remote *remote = inode->i_private;
59496e43537SVincent Donnefort 	struct trace_remote_iterator *iter;
595330b0cceSVincent Donnefort 	int cpu = tracing_get_cpu(inode);
59696e43537SVincent Donnefort 
59796e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
598330b0cceSVincent Donnefort 
599330b0cceSVincent Donnefort 	iter = trace_remote_iter(remote, cpu, TRI_CONSUMING);
600330b0cceSVincent Donnefort 	if (IS_ERR(iter))
601330b0cceSVincent Donnefort 		return PTR_ERR(iter);
602330b0cceSVincent Donnefort 
60396e43537SVincent Donnefort 	filp->private_data = iter;
60496e43537SVincent Donnefort 
60596e43537SVincent Donnefort 	return IS_ERR(iter) ? PTR_ERR(iter) : 0;
60696e43537SVincent Donnefort }
60796e43537SVincent Donnefort 
60896e43537SVincent Donnefort static int trace_pipe_release(struct inode *inode, struct file *filp)
60996e43537SVincent Donnefort {
61096e43537SVincent Donnefort 	struct trace_remote_iterator *iter = filp->private_data;
61196e43537SVincent Donnefort 	struct trace_remote *remote = iter->remote;
61296e43537SVincent Donnefort 
61396e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
61496e43537SVincent Donnefort 
61596e43537SVincent Donnefort 	trace_remote_iter_free(iter);
61696e43537SVincent Donnefort 
61796e43537SVincent Donnefort 	return 0;
61896e43537SVincent Donnefort }
61996e43537SVincent Donnefort 
62096e43537SVincent Donnefort static ssize_t trace_pipe_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
62196e43537SVincent Donnefort {
62296e43537SVincent Donnefort 	struct trace_remote_iterator *iter = filp->private_data;
62396e43537SVincent Donnefort 	struct trace_buffer *trace_buffer = iter->remote->trace_buffer;
62496e43537SVincent Donnefort 	int ret;
62596e43537SVincent Donnefort 
62696e43537SVincent Donnefort copy_to_user:
62796e43537SVincent Donnefort 	ret = trace_seq_to_user(&iter->seq, ubuf, cnt);
62896e43537SVincent Donnefort 	if (ret != -EBUSY)
62996e43537SVincent Donnefort 		return ret;
63096e43537SVincent Donnefort 
63196e43537SVincent Donnefort 	trace_seq_init(&iter->seq);
63296e43537SVincent Donnefort 
63396e43537SVincent Donnefort 	ret = ring_buffer_wait(trace_buffer, iter->cpu, 0, NULL, NULL);
63496e43537SVincent Donnefort 	if (ret < 0)
63596e43537SVincent Donnefort 		return ret;
63696e43537SVincent Donnefort 
637330b0cceSVincent Donnefort 	trace_remote_iter_read_start(iter);
638330b0cceSVincent Donnefort 
63996e43537SVincent Donnefort 	while (trace_remote_iter_read_event(iter)) {
64096e43537SVincent Donnefort 		int prev_len = iter->seq.seq.len;
64196e43537SVincent Donnefort 
64296e43537SVincent Donnefort 		if (trace_remote_iter_print_event(iter)) {
64396e43537SVincent Donnefort 			iter->seq.seq.len = prev_len;
64496e43537SVincent Donnefort 			break;
64596e43537SVincent Donnefort 		}
64696e43537SVincent Donnefort 
647330b0cceSVincent Donnefort 		trace_remote_iter_move(iter);
64896e43537SVincent Donnefort 	}
64996e43537SVincent Donnefort 
650330b0cceSVincent Donnefort 	trace_remote_iter_read_finished(iter);
651330b0cceSVincent Donnefort 
65296e43537SVincent Donnefort 	goto copy_to_user;
65396e43537SVincent Donnefort }
65496e43537SVincent Donnefort 
65596e43537SVincent Donnefort static const struct file_operations trace_pipe_fops = {
65696e43537SVincent Donnefort 	.open		= trace_pipe_open,
65796e43537SVincent Donnefort 	.read		= trace_pipe_read,
65896e43537SVincent Donnefort 	.release	= trace_pipe_release,
65996e43537SVincent Donnefort };
66096e43537SVincent Donnefort 
661330b0cceSVincent Donnefort static void *trace_next(struct seq_file *m, void *v, loff_t *pos)
662330b0cceSVincent Donnefort {
663330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = m->private;
664330b0cceSVincent Donnefort 
665330b0cceSVincent Donnefort 	++*pos;
666330b0cceSVincent Donnefort 
667330b0cceSVincent Donnefort 	if (!iter || !trace_remote_iter_read_event(iter))
668330b0cceSVincent Donnefort 		return NULL;
669330b0cceSVincent Donnefort 
670330b0cceSVincent Donnefort 	trace_remote_iter_move(iter);
671330b0cceSVincent Donnefort 	iter->pos++;
672330b0cceSVincent Donnefort 
673330b0cceSVincent Donnefort 	return iter;
674330b0cceSVincent Donnefort }
675330b0cceSVincent Donnefort 
676330b0cceSVincent Donnefort static void *trace_start(struct seq_file *m, loff_t *pos)
677330b0cceSVincent Donnefort {
678330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = m->private;
679330b0cceSVincent Donnefort 	loff_t i;
680330b0cceSVincent Donnefort 
681330b0cceSVincent Donnefort 	if (!iter)
682330b0cceSVincent Donnefort 		return NULL;
683330b0cceSVincent Donnefort 
684330b0cceSVincent Donnefort 	trace_remote_iter_read_start(iter);
685330b0cceSVincent Donnefort 
686330b0cceSVincent Donnefort 	if (!*pos) {
687330b0cceSVincent Donnefort 		iter->pos = -1;
688330b0cceSVincent Donnefort 		return trace_next(m, NULL, &i);
689330b0cceSVincent Donnefort 	}
690330b0cceSVincent Donnefort 
691330b0cceSVincent Donnefort 	i = iter->pos;
692330b0cceSVincent Donnefort 	while (i < *pos) {
693330b0cceSVincent Donnefort 		iter = trace_next(m, NULL, &i);
694330b0cceSVincent Donnefort 		if (!iter)
695330b0cceSVincent Donnefort 			return NULL;
696330b0cceSVincent Donnefort 	}
697330b0cceSVincent Donnefort 
698330b0cceSVincent Donnefort 	return iter;
699330b0cceSVincent Donnefort }
700330b0cceSVincent Donnefort 
701330b0cceSVincent Donnefort static int trace_show(struct seq_file *m, void *v)
702330b0cceSVincent Donnefort {
703330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = v;
704330b0cceSVincent Donnefort 
705330b0cceSVincent Donnefort 	trace_seq_init(&iter->seq);
706330b0cceSVincent Donnefort 
707330b0cceSVincent Donnefort 	if (trace_remote_iter_print_event(iter)) {
708330b0cceSVincent Donnefort 		seq_printf(m, "[EVENT %d PRINT TOO BIG]\n", iter->evt->id);
709330b0cceSVincent Donnefort 		return 0;
710330b0cceSVincent Donnefort 	}
711330b0cceSVincent Donnefort 
712330b0cceSVincent Donnefort 	return trace_print_seq(m, &iter->seq);
713330b0cceSVincent Donnefort }
714330b0cceSVincent Donnefort 
715330b0cceSVincent Donnefort static void trace_stop(struct seq_file *m, void *v)
716330b0cceSVincent Donnefort {
717330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = m->private;
718330b0cceSVincent Donnefort 
719330b0cceSVincent Donnefort 	if (iter)
720330b0cceSVincent Donnefort 		trace_remote_iter_read_finished(iter);
721330b0cceSVincent Donnefort }
722330b0cceSVincent Donnefort 
723330b0cceSVincent Donnefort static const struct seq_operations trace_sops = {
724330b0cceSVincent Donnefort 	.start		= trace_start,
725330b0cceSVincent Donnefort 	.next		= trace_next,
726330b0cceSVincent Donnefort 	.show		= trace_show,
727330b0cceSVincent Donnefort 	.stop		= trace_stop,
728330b0cceSVincent Donnefort };
729330b0cceSVincent Donnefort 
730330b0cceSVincent Donnefort static int trace_open(struct inode *inode, struct file *filp)
731330b0cceSVincent Donnefort {
732330b0cceSVincent Donnefort 	struct trace_remote *remote = inode->i_private;
733330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = NULL;
734330b0cceSVincent Donnefort 	int cpu = tracing_get_cpu(inode);
735330b0cceSVincent Donnefort 	int ret;
736330b0cceSVincent Donnefort 
737330b0cceSVincent Donnefort 	if (!(filp->f_mode & FMODE_READ))
738330b0cceSVincent Donnefort 		return 0;
739330b0cceSVincent Donnefort 
740330b0cceSVincent Donnefort 	guard(mutex)(&remote->lock);
741330b0cceSVincent Donnefort 
742330b0cceSVincent Donnefort 	iter = trace_remote_iter(remote, cpu, TRI_NONCONSUMING);
743330b0cceSVincent Donnefort 	if (IS_ERR(iter))
744330b0cceSVincent Donnefort 		return PTR_ERR(iter);
745330b0cceSVincent Donnefort 
746330b0cceSVincent Donnefort 	ret = seq_open(filp, &trace_sops);
747330b0cceSVincent Donnefort 	if (ret) {
748330b0cceSVincent Donnefort 		trace_remote_iter_free(iter);
749330b0cceSVincent Donnefort 		return ret;
750330b0cceSVincent Donnefort 	}
751330b0cceSVincent Donnefort 
752330b0cceSVincent Donnefort 	((struct seq_file *)filp->private_data)->private = (void *)iter;
753330b0cceSVincent Donnefort 
754330b0cceSVincent Donnefort 	return 0;
755330b0cceSVincent Donnefort }
756330b0cceSVincent Donnefort 
757330b0cceSVincent Donnefort static int trace_release(struct inode *inode, struct file *filp)
758330b0cceSVincent Donnefort {
759330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter;
760330b0cceSVincent Donnefort 
761330b0cceSVincent Donnefort 	if (!(filp->f_mode & FMODE_READ))
762330b0cceSVincent Donnefort 		return 0;
763330b0cceSVincent Donnefort 
764330b0cceSVincent Donnefort 	iter = ((struct seq_file *)filp->private_data)->private;
765330b0cceSVincent Donnefort 	seq_release(inode, filp);
766330b0cceSVincent Donnefort 
767330b0cceSVincent Donnefort 	if (!iter)
768330b0cceSVincent Donnefort 		return 0;
769330b0cceSVincent Donnefort 
770330b0cceSVincent Donnefort 	guard(mutex)(&iter->remote->lock);
771330b0cceSVincent Donnefort 
772330b0cceSVincent Donnefort 	trace_remote_iter_free(iter);
773330b0cceSVincent Donnefort 
774330b0cceSVincent Donnefort 	return 0;
775330b0cceSVincent Donnefort }
776330b0cceSVincent Donnefort 
7779af4ab0eSVincent Donnefort static ssize_t trace_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
7789af4ab0eSVincent Donnefort {
7799af4ab0eSVincent Donnefort 	struct inode *inode = file_inode(filp);
7809af4ab0eSVincent Donnefort 	struct trace_remote *remote = inode->i_private;
781330b0cceSVincent Donnefort 	int cpu = tracing_get_cpu(inode);
7829af4ab0eSVincent Donnefort 
7839af4ab0eSVincent Donnefort 	guard(mutex)(&remote->lock);
7849af4ab0eSVincent Donnefort 
7859af4ab0eSVincent Donnefort 	trace_remote_reset(remote, cpu);
7869af4ab0eSVincent Donnefort 
7879af4ab0eSVincent Donnefort 	return cnt;
7889af4ab0eSVincent Donnefort }
7899af4ab0eSVincent Donnefort 
7909af4ab0eSVincent Donnefort static const struct file_operations trace_fops = {
791330b0cceSVincent Donnefort 	.open		= trace_open,
7929af4ab0eSVincent Donnefort 	.write		= trace_write,
793330b0cceSVincent Donnefort 	.read		= seq_read,
794330b0cceSVincent Donnefort 	.read_iter	= seq_read_iter,
795330b0cceSVincent Donnefort 	.release	= trace_release,
7969af4ab0eSVincent Donnefort };
7979af4ab0eSVincent Donnefort 
79896e43537SVincent Donnefort static int trace_remote_init_tracefs(const char *name, struct trace_remote *remote)
79996e43537SVincent Donnefort {
80096e43537SVincent Donnefort 	struct dentry *remote_d, *percpu_d, *d;
80196e43537SVincent Donnefort 	static struct dentry *root;
80296e43537SVincent Donnefort 	static DEFINE_MUTEX(lock);
80396e43537SVincent Donnefort 	bool root_inited = false;
80496e43537SVincent Donnefort 	int cpu;
80596e43537SVincent Donnefort 
80696e43537SVincent Donnefort 	guard(mutex)(&lock);
80796e43537SVincent Donnefort 
80896e43537SVincent Donnefort 	if (!root) {
80996e43537SVincent Donnefort 		root = tracefs_create_dir(TRACEFS_DIR, NULL);
81096e43537SVincent Donnefort 		if (!root) {
81196e43537SVincent Donnefort 			pr_err("Failed to create tracefs dir "TRACEFS_DIR"\n");
81296e43537SVincent Donnefort 			return -ENOMEM;
81396e43537SVincent Donnefort 		}
81496e43537SVincent Donnefort 		root_inited = true;
81596e43537SVincent Donnefort 	}
81696e43537SVincent Donnefort 
81796e43537SVincent Donnefort 	remote_d = tracefs_create_dir(name, root);
81896e43537SVincent Donnefort 	if (!remote_d) {
81996e43537SVincent Donnefort 		pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/\n", name);
82096e43537SVincent Donnefort 		goto err;
82196e43537SVincent Donnefort 	}
82296e43537SVincent Donnefort 
82396e43537SVincent Donnefort 	d = trace_create_file("tracing_on", TRACEFS_MODE_WRITE, remote_d, remote, &tracing_on_fops);
82496e43537SVincent Donnefort 	if (!d)
82596e43537SVincent Donnefort 		goto err;
82696e43537SVincent Donnefort 
82796e43537SVincent Donnefort 	d = trace_create_file("buffer_size_kb", TRACEFS_MODE_WRITE, remote_d, remote,
82896e43537SVincent Donnefort 			      &buffer_size_kb_fops);
82996e43537SVincent Donnefort 	if (!d)
83096e43537SVincent Donnefort 		goto err;
83196e43537SVincent Donnefort 
83296e43537SVincent Donnefort 	d = trace_create_file("trace_pipe", TRACEFS_MODE_READ, remote_d, remote, &trace_pipe_fops);
83396e43537SVincent Donnefort 	if (!d)
83496e43537SVincent Donnefort 		goto err;
83596e43537SVincent Donnefort 
8369af4ab0eSVincent Donnefort 	d = trace_create_file("trace", TRACEFS_MODE_WRITE, remote_d, remote, &trace_fops);
8379af4ab0eSVincent Donnefort 	if (!d)
8389af4ab0eSVincent Donnefort 		goto err;
8399af4ab0eSVincent Donnefort 
84096e43537SVincent Donnefort 	percpu_d = tracefs_create_dir("per_cpu", remote_d);
84196e43537SVincent Donnefort 	if (!percpu_d) {
84296e43537SVincent Donnefort 		pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/per_cpu/\n", name);
84396e43537SVincent Donnefort 		goto err;
84496e43537SVincent Donnefort 	}
84596e43537SVincent Donnefort 
84696e43537SVincent Donnefort 	for_each_possible_cpu(cpu) {
84796e43537SVincent Donnefort 		struct dentry *cpu_d;
84896e43537SVincent Donnefort 		char cpu_name[16];
84996e43537SVincent Donnefort 
85096e43537SVincent Donnefort 		snprintf(cpu_name, sizeof(cpu_name), "cpu%d", cpu);
85196e43537SVincent Donnefort 		cpu_d = tracefs_create_dir(cpu_name, percpu_d);
85296e43537SVincent Donnefort 		if (!cpu_d) {
85396e43537SVincent Donnefort 			pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/percpu/cpu%d\n",
85496e43537SVincent Donnefort 			       name, cpu);
85596e43537SVincent Donnefort 			goto err;
85696e43537SVincent Donnefort 		}
85796e43537SVincent Donnefort 
85896e43537SVincent Donnefort 		d = trace_create_cpu_file("trace_pipe", TRACEFS_MODE_READ, cpu_d, remote, cpu,
85996e43537SVincent Donnefort 					  &trace_pipe_fops);
86096e43537SVincent Donnefort 		if (!d)
86196e43537SVincent Donnefort 			goto err;
8629af4ab0eSVincent Donnefort 
8639af4ab0eSVincent Donnefort 		d = trace_create_cpu_file("trace", TRACEFS_MODE_WRITE, cpu_d, remote, cpu,
8649af4ab0eSVincent Donnefort 					  &trace_fops);
8659af4ab0eSVincent Donnefort 		if (!d)
8669af4ab0eSVincent Donnefort 			goto err;
86796e43537SVincent Donnefort 	}
86896e43537SVincent Donnefort 
86907252915SVincent Donnefort 	remote->dentry = remote_d;
87007252915SVincent Donnefort 
87196e43537SVincent Donnefort 	return 0;
87296e43537SVincent Donnefort 
87396e43537SVincent Donnefort err:
87496e43537SVincent Donnefort 	if (root_inited) {
87596e43537SVincent Donnefort 		tracefs_remove(root);
87696e43537SVincent Donnefort 		root = NULL;
87796e43537SVincent Donnefort 	} else {
87896e43537SVincent Donnefort 		tracefs_remove(remote_d);
87996e43537SVincent Donnefort 	}
88096e43537SVincent Donnefort 
88196e43537SVincent Donnefort 	return -ENOMEM;
88296e43537SVincent Donnefort }
88396e43537SVincent Donnefort 
88407252915SVincent Donnefort static int trace_remote_register_events(const char *remote_name, struct trace_remote *remote,
88507252915SVincent Donnefort 					struct remote_event *events, size_t nr_events);
88607252915SVincent Donnefort 
88796e43537SVincent Donnefort /**
88896e43537SVincent Donnefort  * trace_remote_register() - Register a Tracefs remote
88996e43537SVincent Donnefort  * @name:	Name of the remote, used for the Tracefs remotes/ directory.
89096e43537SVincent Donnefort  * @cbs:	Set of callbacks used to control the remote.
89196e43537SVincent Donnefort  * @priv:	Private data, passed to each callback from @cbs.
89296e43537SVincent Donnefort  * @events:	Array of events. &remote_event.name and &remote_event.id must be
89396e43537SVincent Donnefort  *		filled by the caller.
89496e43537SVincent Donnefort  * @nr_events:	Number of events in the @events array.
89596e43537SVincent Donnefort  *
89696e43537SVincent Donnefort  * A trace remote is an entity, outside of the kernel (most likely firmware or
89796e43537SVincent Donnefort  * hypervisor) capable of writing events into a Tracefs compatible ring-buffer.
89896e43537SVincent Donnefort  * The kernel would then act as a reader.
89996e43537SVincent Donnefort  *
90096e43537SVincent Donnefort  * The registered remote will be found under the Tracefs directory
90196e43537SVincent Donnefort  * remotes/<name>.
90296e43537SVincent Donnefort  *
90396e43537SVincent Donnefort  * Return: 0 on success, negative error code on failure.
90496e43537SVincent Donnefort  */
90507252915SVincent Donnefort int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, void *priv,
90607252915SVincent Donnefort 			  struct remote_event *events, size_t nr_events)
90796e43537SVincent Donnefort {
90896e43537SVincent Donnefort 	struct trace_remote *remote;
909bf2ba0f8SVincent Donnefort 	int ret;
91096e43537SVincent Donnefort 
91196e43537SVincent Donnefort 	remote = kzalloc_obj(*remote);
91296e43537SVincent Donnefort 	if (!remote)
91396e43537SVincent Donnefort 		return -ENOMEM;
91496e43537SVincent Donnefort 
91596e43537SVincent Donnefort 	remote->cbs = cbs;
91696e43537SVincent Donnefort 	remote->priv = priv;
91796e43537SVincent Donnefort 	remote->trace_buffer_size = 7 << 10;
91896e43537SVincent Donnefort 	remote->poll_ms = 100;
91996e43537SVincent Donnefort 	mutex_init(&remote->lock);
920330b0cceSVincent Donnefort 	init_rwsem(&remote->reader_lock);
92196e43537SVincent Donnefort 
92296e43537SVincent Donnefort 	if (trace_remote_init_tracefs(name, remote)) {
92396e43537SVincent Donnefort 		kfree(remote);
92496e43537SVincent Donnefort 		return -ENOMEM;
92596e43537SVincent Donnefort 	}
92696e43537SVincent Donnefort 
92707252915SVincent Donnefort 	ret = trace_remote_register_events(name, remote, events, nr_events);
92807252915SVincent Donnefort 	if (ret) {
92907252915SVincent Donnefort 		pr_err("Failed to register events for trace remote '%s' (%d)\n",
93007252915SVincent Donnefort 		       name, ret);
93107252915SVincent Donnefort 		return ret;
93207252915SVincent Donnefort 	}
93307252915SVincent Donnefort 
934bf2ba0f8SVincent Donnefort 	ret = cbs->init ? cbs->init(remote->dentry, priv) : 0;
935bf2ba0f8SVincent Donnefort 	if (ret)
936bf2ba0f8SVincent Donnefort 		pr_err("Init failed for trace remote '%s' (%d)\n", name, ret);
937bf2ba0f8SVincent Donnefort 
938bf2ba0f8SVincent Donnefort 	return ret;
93996e43537SVincent Donnefort }
94096e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register);
94196e43537SVincent Donnefort 
94296e43537SVincent Donnefort /**
94396e43537SVincent Donnefort  * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer()
94496e43537SVincent Donnefort  * @desc:	Descriptor of the per-CPU ring-buffers, originally filled by
94596e43537SVincent Donnefort  *		trace_remote_alloc_buffer()
94696e43537SVincent Donnefort  *
94796e43537SVincent Donnefort  * Most likely called from &trace_remote_callbacks.unload_trace_buffer.
94896e43537SVincent Donnefort  */
94996e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc)
95096e43537SVincent Donnefort {
95196e43537SVincent Donnefort 	struct ring_buffer_desc *rb_desc;
95296e43537SVincent Donnefort 	int cpu;
95396e43537SVincent Donnefort 
95496e43537SVincent Donnefort 	for_each_ring_buffer_desc(rb_desc, cpu, desc) {
95596e43537SVincent Donnefort 		unsigned int id;
95696e43537SVincent Donnefort 
95796e43537SVincent Donnefort 		free_page(rb_desc->meta_va);
95896e43537SVincent Donnefort 
95996e43537SVincent Donnefort 		for (id = 0; id < rb_desc->nr_page_va; id++)
96096e43537SVincent Donnefort 			free_page(rb_desc->page_va[id]);
96196e43537SVincent Donnefort 	}
96296e43537SVincent Donnefort }
96396e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer);
96496e43537SVincent Donnefort 
96596e43537SVincent Donnefort /**
96696e43537SVincent Donnefort  * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer
96796e43537SVincent Donnefort  * @desc:		Uninitialized trace_buffer_desc
96896e43537SVincent Donnefort  * @desc_size:		Size of the trace_buffer_desc. Must be at least equal to
96996e43537SVincent Donnefort  *			trace_buffer_desc_size()
97096e43537SVincent Donnefort  * @buffer_size:	Size in bytes of each per-CPU ring-buffer
97196e43537SVincent Donnefort  * @cpumask:		CPUs to allocate a ring-buffer for
97296e43537SVincent Donnefort  *
97396e43537SVincent Donnefort  * Helper to dynamically allocate a set of pages (enough to cover @buffer_size)
97496e43537SVincent Donnefort  * for each CPU from @cpumask and fill @desc. Most likely called from
97596e43537SVincent Donnefort  * &trace_remote_callbacks.load_trace_buffer.
97696e43537SVincent Donnefort  *
97796e43537SVincent Donnefort  * Return: 0 on success, negative error code on failure.
97896e43537SVincent Donnefort  */
97996e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size,
98096e43537SVincent Donnefort 			      const struct cpumask *cpumask)
98196e43537SVincent Donnefort {
98296e43537SVincent Donnefort 	unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1;
98396e43537SVincent Donnefort 	void *desc_end = desc + desc_size;
98496e43537SVincent Donnefort 	struct ring_buffer_desc *rb_desc;
98596e43537SVincent Donnefort 	int cpu, ret = -ENOMEM;
98696e43537SVincent Donnefort 
98796e43537SVincent Donnefort 	if (desc_size < struct_size(desc, __data, 0))
98896e43537SVincent Donnefort 		return -EINVAL;
98996e43537SVincent Donnefort 
99096e43537SVincent Donnefort 	desc->nr_cpus = 0;
99196e43537SVincent Donnefort 	desc->struct_len = struct_size(desc, __data, 0);
99296e43537SVincent Donnefort 
99396e43537SVincent Donnefort 	rb_desc = (struct ring_buffer_desc *)&desc->__data[0];
99496e43537SVincent Donnefort 
99596e43537SVincent Donnefort 	for_each_cpu(cpu, cpumask) {
99696e43537SVincent Donnefort 		unsigned int id;
99796e43537SVincent Donnefort 
99896e43537SVincent Donnefort 		if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) {
99996e43537SVincent Donnefort 			ret = -EINVAL;
100096e43537SVincent Donnefort 			goto err;
100196e43537SVincent Donnefort 		}
100296e43537SVincent Donnefort 
100396e43537SVincent Donnefort 		rb_desc->cpu = cpu;
100496e43537SVincent Donnefort 		rb_desc->nr_page_va = 0;
100596e43537SVincent Donnefort 		rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL);
100696e43537SVincent Donnefort 		if (!rb_desc->meta_va)
100796e43537SVincent Donnefort 			goto err;
100896e43537SVincent Donnefort 
100996e43537SVincent Donnefort 		for (id = 0; id < nr_pages; id++) {
101096e43537SVincent Donnefort 			rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL);
101196e43537SVincent Donnefort 			if (!rb_desc->page_va[id])
101296e43537SVincent Donnefort 				goto err;
101396e43537SVincent Donnefort 
101496e43537SVincent Donnefort 			rb_desc->nr_page_va++;
101596e43537SVincent Donnefort 		}
101696e43537SVincent Donnefort 		desc->nr_cpus++;
101796e43537SVincent Donnefort 		desc->struct_len += offsetof(struct ring_buffer_desc, page_va);
101896e43537SVincent Donnefort 		desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va);
101996e43537SVincent Donnefort 		rb_desc = __next_ring_buffer_desc(rb_desc);
102096e43537SVincent Donnefort 	}
102196e43537SVincent Donnefort 
102296e43537SVincent Donnefort 	return 0;
102396e43537SVincent Donnefort 
102496e43537SVincent Donnefort err:
102596e43537SVincent Donnefort 	trace_remote_free_buffer(desc);
102696e43537SVincent Donnefort 	return ret;
102796e43537SVincent Donnefort }
102896e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer);
102907252915SVincent Donnefort 
103007252915SVincent Donnefort static int
103107252915SVincent Donnefort trace_remote_enable_event(struct trace_remote *remote, struct remote_event *evt, bool enable)
103207252915SVincent Donnefort {
103307252915SVincent Donnefort 	int ret;
103407252915SVincent Donnefort 
103507252915SVincent Donnefort 	lockdep_assert_held(&remote->lock);
103607252915SVincent Donnefort 
103707252915SVincent Donnefort 	if (evt->enabled == enable)
103807252915SVincent Donnefort 		return 0;
103907252915SVincent Donnefort 
104007252915SVincent Donnefort 	ret = remote->cbs->enable_event(evt->id, enable, remote->priv);
104107252915SVincent Donnefort 	if (ret)
104207252915SVincent Donnefort 		return ret;
104307252915SVincent Donnefort 
104407252915SVincent Donnefort 	evt->enabled = enable;
104507252915SVincent Donnefort 
104607252915SVincent Donnefort 	return 0;
104707252915SVincent Donnefort }
104807252915SVincent Donnefort 
104907252915SVincent Donnefort static int remote_event_enable_show(struct seq_file *s, void *unused)
105007252915SVincent Donnefort {
105107252915SVincent Donnefort 	struct remote_event *evt = s->private;
105207252915SVincent Donnefort 
105307252915SVincent Donnefort 	seq_printf(s, "%d\n", evt->enabled);
105407252915SVincent Donnefort 
105507252915SVincent Donnefort 	return 0;
105607252915SVincent Donnefort }
105707252915SVincent Donnefort 
105807252915SVincent Donnefort static ssize_t remote_event_enable_write(struct file *filp, const char __user *ubuf,
105907252915SVincent Donnefort 					 size_t count, loff_t *ppos)
106007252915SVincent Donnefort {
106107252915SVincent Donnefort 	struct seq_file *seq = filp->private_data;
106207252915SVincent Donnefort 	struct remote_event *evt = seq->private;
106307252915SVincent Donnefort 	struct trace_remote *remote = evt->remote;
106407252915SVincent Donnefort 	u8 enable;
106507252915SVincent Donnefort 	int ret;
106607252915SVincent Donnefort 
106707252915SVincent Donnefort 	ret = kstrtou8_from_user(ubuf, count, 10, &enable);
106807252915SVincent Donnefort 	if (ret)
106907252915SVincent Donnefort 		return ret;
107007252915SVincent Donnefort 
107107252915SVincent Donnefort 	guard(mutex)(&remote->lock);
107207252915SVincent Donnefort 
107307252915SVincent Donnefort 	ret = trace_remote_enable_event(remote, evt, enable);
107407252915SVincent Donnefort 	if (ret)
107507252915SVincent Donnefort 		return ret;
107607252915SVincent Donnefort 
107707252915SVincent Donnefort 	return count;
107807252915SVincent Donnefort }
107907252915SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(remote_event_enable);
108007252915SVincent Donnefort 
108107252915SVincent Donnefort static int remote_event_id_show(struct seq_file *s, void *unused)
108207252915SVincent Donnefort {
108307252915SVincent Donnefort 	struct remote_event *evt = s->private;
108407252915SVincent Donnefort 
108507252915SVincent Donnefort 	seq_printf(s, "%d\n", evt->id);
108607252915SVincent Donnefort 
108707252915SVincent Donnefort 	return 0;
108807252915SVincent Donnefort }
108907252915SVincent Donnefort DEFINE_SHOW_ATTRIBUTE(remote_event_id);
109007252915SVincent Donnefort 
109107252915SVincent Donnefort static int remote_event_format_show(struct seq_file *s, void *unused)
109207252915SVincent Donnefort {
109307252915SVincent Donnefort 	size_t offset = sizeof(struct remote_event_hdr);
109407252915SVincent Donnefort 	struct remote_event *evt = s->private;
109507252915SVincent Donnefort 	struct trace_event_fields *field;
109607252915SVincent Donnefort 
109707252915SVincent Donnefort 	seq_printf(s, "name: %s\n", evt->name);
109807252915SVincent Donnefort 	seq_printf(s, "ID: %d\n", evt->id);
109907252915SVincent Donnefort 	seq_puts(s,
110007252915SVincent Donnefort 		 "format:\n\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n\n");
110107252915SVincent Donnefort 
110207252915SVincent Donnefort 	field = &evt->fields[0];
110307252915SVincent Donnefort 	while (field->name) {
110407252915SVincent Donnefort 		seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%u;\tsigned:%d;\n",
110507252915SVincent Donnefort 			   field->type, field->name, offset, field->size,
110607252915SVincent Donnefort 			   field->is_signed);
110707252915SVincent Donnefort 		offset += field->size;
110807252915SVincent Donnefort 		field++;
110907252915SVincent Donnefort 	}
111007252915SVincent Donnefort 
111107252915SVincent Donnefort 	if (field != &evt->fields[0])
111207252915SVincent Donnefort 		seq_puts(s, "\n");
111307252915SVincent Donnefort 
111407252915SVincent Donnefort 	seq_printf(s, "print fmt: %s\n", evt->print_fmt);
111507252915SVincent Donnefort 
111607252915SVincent Donnefort 	return 0;
111707252915SVincent Donnefort }
111807252915SVincent Donnefort DEFINE_SHOW_ATTRIBUTE(remote_event_format);
111907252915SVincent Donnefort 
112007252915SVincent Donnefort static int remote_event_callback(const char *name, umode_t *mode, void **data,
112107252915SVincent Donnefort 				 const struct file_operations **fops)
112207252915SVincent Donnefort {
112307252915SVincent Donnefort 	if (!strcmp(name, "enable")) {
112407252915SVincent Donnefort 		*mode = TRACEFS_MODE_WRITE;
112507252915SVincent Donnefort 		*fops = &remote_event_enable_fops;
112607252915SVincent Donnefort 		return 1;
112707252915SVincent Donnefort 	}
112807252915SVincent Donnefort 
112907252915SVincent Donnefort 	if (!strcmp(name, "id")) {
113007252915SVincent Donnefort 		*mode = TRACEFS_MODE_READ;
113107252915SVincent Donnefort 		*fops = &remote_event_id_fops;
113207252915SVincent Donnefort 		return 1;
113307252915SVincent Donnefort 	}
113407252915SVincent Donnefort 
113507252915SVincent Donnefort 	if (!strcmp(name, "format")) {
113607252915SVincent Donnefort 		*mode = TRACEFS_MODE_READ;
113707252915SVincent Donnefort 		*fops = &remote_event_format_fops;
113807252915SVincent Donnefort 		return 1;
113907252915SVincent Donnefort 	}
114007252915SVincent Donnefort 
114107252915SVincent Donnefort 	return 0;
114207252915SVincent Donnefort }
114307252915SVincent Donnefort 
1144775cb093SVincent Donnefort static ssize_t remote_events_dir_enable_write(struct file *filp, const char __user *ubuf,
1145775cb093SVincent Donnefort 					      size_t count, loff_t *ppos)
1146775cb093SVincent Donnefort {
1147775cb093SVincent Donnefort 	struct trace_remote *remote = file_inode(filp)->i_private;
1148775cb093SVincent Donnefort 	int i, ret;
1149775cb093SVincent Donnefort 	u8 enable;
1150775cb093SVincent Donnefort 
1151775cb093SVincent Donnefort 	ret = kstrtou8_from_user(ubuf, count, 10, &enable);
1152775cb093SVincent Donnefort 	if (ret)
1153775cb093SVincent Donnefort 		return ret;
1154775cb093SVincent Donnefort 
1155775cb093SVincent Donnefort 	guard(mutex)(&remote->lock);
1156775cb093SVincent Donnefort 
1157775cb093SVincent Donnefort 	for (i = 0; i < remote->nr_events; i++) {
1158775cb093SVincent Donnefort 		struct remote_event *evt = &remote->events[i];
1159775cb093SVincent Donnefort 
1160775cb093SVincent Donnefort 		trace_remote_enable_event(remote, evt, enable);
1161775cb093SVincent Donnefort 	}
1162775cb093SVincent Donnefort 
1163775cb093SVincent Donnefort 	return count;
1164775cb093SVincent Donnefort }
1165775cb093SVincent Donnefort 
1166775cb093SVincent Donnefort static ssize_t remote_events_dir_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
1167775cb093SVincent Donnefort 					     loff_t *ppos)
1168775cb093SVincent Donnefort {
1169775cb093SVincent Donnefort 	struct trace_remote *remote = file_inode(filp)->i_private;
1170775cb093SVincent Donnefort 	const char enabled_char[] = {'0', '1', 'X'};
1171775cb093SVincent Donnefort 	char enabled_str[] = " \n";
1172775cb093SVincent Donnefort 	int i, enabled = -1;
1173775cb093SVincent Donnefort 
1174775cb093SVincent Donnefort 	guard(mutex)(&remote->lock);
1175775cb093SVincent Donnefort 
1176775cb093SVincent Donnefort 	for (i = 0; i < remote->nr_events; i++) {
1177775cb093SVincent Donnefort 		struct remote_event *evt = &remote->events[i];
1178775cb093SVincent Donnefort 
1179775cb093SVincent Donnefort 		if (enabled == -1) {
1180775cb093SVincent Donnefort 			enabled = evt->enabled;
1181775cb093SVincent Donnefort 		} else if (enabled != evt->enabled) {
1182775cb093SVincent Donnefort 			enabled = 2;
1183775cb093SVincent Donnefort 			break;
1184775cb093SVincent Donnefort 		}
1185775cb093SVincent Donnefort 	}
1186775cb093SVincent Donnefort 
1187775cb093SVincent Donnefort 	enabled_str[0] = enabled_char[enabled == -1 ? 0 : enabled];
1188775cb093SVincent Donnefort 
1189775cb093SVincent Donnefort 	return simple_read_from_buffer(ubuf, cnt, ppos, enabled_str, 2);
1190775cb093SVincent Donnefort }
1191775cb093SVincent Donnefort 
1192775cb093SVincent Donnefort static const struct file_operations remote_events_dir_enable_fops = {
1193775cb093SVincent Donnefort 	.write = remote_events_dir_enable_write,
1194775cb093SVincent Donnefort 	.read = remote_events_dir_enable_read,
1195775cb093SVincent Donnefort };
1196775cb093SVincent Donnefort 
1197775cb093SVincent Donnefort static ssize_t
1198775cb093SVincent Donnefort remote_events_dir_header_page_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1199775cb093SVincent Donnefort {
1200775cb093SVincent Donnefort 	struct trace_seq *s;
1201775cb093SVincent Donnefort 	int ret;
1202775cb093SVincent Donnefort 
1203775cb093SVincent Donnefort 	s = kmalloc(sizeof(*s), GFP_KERNEL);
1204775cb093SVincent Donnefort 	if (!s)
1205775cb093SVincent Donnefort 		return -ENOMEM;
1206775cb093SVincent Donnefort 
1207775cb093SVincent Donnefort 	trace_seq_init(s);
1208775cb093SVincent Donnefort 
1209775cb093SVincent Donnefort 	ring_buffer_print_page_header(NULL, s);
1210775cb093SVincent Donnefort 	ret = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, trace_seq_used(s));
1211775cb093SVincent Donnefort 	kfree(s);
1212775cb093SVincent Donnefort 
1213775cb093SVincent Donnefort 	return ret;
1214775cb093SVincent Donnefort }
1215775cb093SVincent Donnefort 
1216775cb093SVincent Donnefort static const struct file_operations remote_events_dir_header_page_fops = {
1217775cb093SVincent Donnefort 	.read = remote_events_dir_header_page_read,
1218775cb093SVincent Donnefort };
1219775cb093SVincent Donnefort 
1220775cb093SVincent Donnefort static ssize_t
1221775cb093SVincent Donnefort remote_events_dir_header_event_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1222775cb093SVincent Donnefort {
1223775cb093SVincent Donnefort 	struct trace_seq *s;
1224775cb093SVincent Donnefort 	int ret;
1225775cb093SVincent Donnefort 
1226775cb093SVincent Donnefort 	s = kmalloc(sizeof(*s), GFP_KERNEL);
1227775cb093SVincent Donnefort 	if (!s)
1228775cb093SVincent Donnefort 		return -ENOMEM;
1229775cb093SVincent Donnefort 
1230775cb093SVincent Donnefort 	trace_seq_init(s);
1231775cb093SVincent Donnefort 
1232775cb093SVincent Donnefort 	ring_buffer_print_entry_header(s);
1233775cb093SVincent Donnefort 	ret = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, trace_seq_used(s));
1234775cb093SVincent Donnefort 	kfree(s);
1235775cb093SVincent Donnefort 
1236775cb093SVincent Donnefort 	return ret;
1237775cb093SVincent Donnefort }
1238775cb093SVincent Donnefort 
1239775cb093SVincent Donnefort static const struct file_operations remote_events_dir_header_event_fops = {
1240775cb093SVincent Donnefort 	.read = remote_events_dir_header_event_read,
1241775cb093SVincent Donnefort };
1242775cb093SVincent Donnefort 
1243775cb093SVincent Donnefort static int remote_events_dir_callback(const char *name, umode_t *mode, void **data,
1244775cb093SVincent Donnefort 				      const struct file_operations **fops)
1245775cb093SVincent Donnefort {
1246775cb093SVincent Donnefort 	if (!strcmp(name, "enable")) {
1247775cb093SVincent Donnefort 		*mode = TRACEFS_MODE_WRITE;
1248775cb093SVincent Donnefort 		*fops = &remote_events_dir_enable_fops;
1249775cb093SVincent Donnefort 		return 1;
1250775cb093SVincent Donnefort 	}
1251775cb093SVincent Donnefort 
1252775cb093SVincent Donnefort 	if (!strcmp(name, "header_page")) {
1253775cb093SVincent Donnefort 		*mode = TRACEFS_MODE_READ;
1254775cb093SVincent Donnefort 		*fops = &remote_events_dir_header_page_fops;
1255775cb093SVincent Donnefort 		return 1;
1256775cb093SVincent Donnefort 	}
1257775cb093SVincent Donnefort 
1258775cb093SVincent Donnefort 	if (!strcmp(name, "header_event")) {
1259775cb093SVincent Donnefort 		*mode = TRACEFS_MODE_READ;
1260775cb093SVincent Donnefort 		*fops = &remote_events_dir_header_event_fops;
1261775cb093SVincent Donnefort 		return 1;
1262775cb093SVincent Donnefort 	}
1263775cb093SVincent Donnefort 
1264775cb093SVincent Donnefort 	return 0;
1265775cb093SVincent Donnefort }
1266775cb093SVincent Donnefort 
126707252915SVincent Donnefort static int trace_remote_init_eventfs(const char *remote_name, struct trace_remote *remote,
126807252915SVincent Donnefort 				     struct remote_event *evt)
126907252915SVincent Donnefort {
127007252915SVincent Donnefort 	struct eventfs_inode *eventfs = remote->eventfs;
1271775cb093SVincent Donnefort 	static struct eventfs_entry dir_entries[] = {
1272775cb093SVincent Donnefort 		{
1273775cb093SVincent Donnefort 			.name		= "enable",
1274775cb093SVincent Donnefort 			.callback	= remote_events_dir_callback,
1275775cb093SVincent Donnefort 		}, {
1276775cb093SVincent Donnefort 			.name		= "header_page",
1277775cb093SVincent Donnefort 			.callback	= remote_events_dir_callback,
1278775cb093SVincent Donnefort 		}, {
1279775cb093SVincent Donnefort 			.name		= "header_event",
1280775cb093SVincent Donnefort 			.callback	= remote_events_dir_callback,
1281775cb093SVincent Donnefort 		}
1282775cb093SVincent Donnefort 	};
128307252915SVincent Donnefort 	static struct eventfs_entry entries[] = {
128407252915SVincent Donnefort 		{
128507252915SVincent Donnefort 			.name		= "enable",
128607252915SVincent Donnefort 			.callback	= remote_event_callback,
128707252915SVincent Donnefort 		}, {
128807252915SVincent Donnefort 			.name		= "id",
128907252915SVincent Donnefort 			.callback	= remote_event_callback,
129007252915SVincent Donnefort 		}, {
129107252915SVincent Donnefort 			.name		= "format",
129207252915SVincent Donnefort 			.callback	= remote_event_callback,
129307252915SVincent Donnefort 		}
129407252915SVincent Donnefort 	};
129507252915SVincent Donnefort 	bool eventfs_create = false;
129607252915SVincent Donnefort 
129707252915SVincent Donnefort 	if (!eventfs) {
1298775cb093SVincent Donnefort 		eventfs = eventfs_create_events_dir("events", remote->dentry, dir_entries,
1299775cb093SVincent Donnefort 						    ARRAY_SIZE(dir_entries), remote);
130007252915SVincent Donnefort 		if (IS_ERR(eventfs))
130107252915SVincent Donnefort 			return PTR_ERR(eventfs);
130207252915SVincent Donnefort 
130307252915SVincent Donnefort 		/*
130407252915SVincent Donnefort 		 * Create similar hierarchy as local events even if a single system is supported at
130507252915SVincent Donnefort 		 * the moment
130607252915SVincent Donnefort 		 */
130707252915SVincent Donnefort 		eventfs = eventfs_create_dir(remote_name, eventfs, NULL, 0, NULL);
130807252915SVincent Donnefort 		if (IS_ERR(eventfs))
130907252915SVincent Donnefort 			return PTR_ERR(eventfs);
131007252915SVincent Donnefort 
131107252915SVincent Donnefort 		remote->eventfs = eventfs;
131207252915SVincent Donnefort 		eventfs_create = true;
131307252915SVincent Donnefort 	}
131407252915SVincent Donnefort 
131507252915SVincent Donnefort 	eventfs = eventfs_create_dir(evt->name, eventfs, entries, ARRAY_SIZE(entries), evt);
131607252915SVincent Donnefort 	if (IS_ERR(eventfs)) {
131707252915SVincent Donnefort 		if (eventfs_create) {
131807252915SVincent Donnefort 			eventfs_remove_events_dir(remote->eventfs);
131907252915SVincent Donnefort 			remote->eventfs = NULL;
132007252915SVincent Donnefort 		}
132107252915SVincent Donnefort 		return PTR_ERR(eventfs);
132207252915SVincent Donnefort 	}
132307252915SVincent Donnefort 
132407252915SVincent Donnefort 	return 0;
132507252915SVincent Donnefort }
132607252915SVincent Donnefort 
132707252915SVincent Donnefort static int trace_remote_attach_events(struct trace_remote *remote, struct remote_event *events,
132807252915SVincent Donnefort 				      size_t nr_events)
132907252915SVincent Donnefort {
133007252915SVincent Donnefort 	int i;
133107252915SVincent Donnefort 
133207252915SVincent Donnefort 	for (i = 0; i < nr_events; i++) {
133307252915SVincent Donnefort 		struct remote_event *evt = &events[i];
133407252915SVincent Donnefort 
133507252915SVincent Donnefort 		if (evt->remote)
133607252915SVincent Donnefort 			return -EEXIST;
133707252915SVincent Donnefort 
133807252915SVincent Donnefort 		evt->remote = remote;
133907252915SVincent Donnefort 
134007252915SVincent Donnefort 		/* We need events to be sorted for efficient lookup */
134107252915SVincent Donnefort 		if (i && evt->id <= events[i - 1].id)
134207252915SVincent Donnefort 			return -EINVAL;
134307252915SVincent Donnefort 	}
134407252915SVincent Donnefort 
134507252915SVincent Donnefort 	remote->events = events;
134607252915SVincent Donnefort 	remote->nr_events = nr_events;
134707252915SVincent Donnefort 
134807252915SVincent Donnefort 	return 0;
134907252915SVincent Donnefort }
135007252915SVincent Donnefort 
135107252915SVincent Donnefort static int trace_remote_register_events(const char *remote_name, struct trace_remote *remote,
135207252915SVincent Donnefort 					struct remote_event *events, size_t nr_events)
135307252915SVincent Donnefort {
135407252915SVincent Donnefort 	int i, ret;
135507252915SVincent Donnefort 
135607252915SVincent Donnefort 	ret = trace_remote_attach_events(remote, events, nr_events);
135707252915SVincent Donnefort 	if (ret)
135807252915SVincent Donnefort 		return ret;
135907252915SVincent Donnefort 
136007252915SVincent Donnefort 	for (i = 0; i < nr_events; i++) {
136107252915SVincent Donnefort 		struct remote_event *evt = &events[i];
136207252915SVincent Donnefort 
136307252915SVincent Donnefort 		ret = trace_remote_init_eventfs(remote_name, remote, evt);
136407252915SVincent Donnefort 		if (ret)
136507252915SVincent Donnefort 			pr_warn("Failed to init eventfs for event '%s' (%d)",
136607252915SVincent Donnefort 				evt->name, ret);
136707252915SVincent Donnefort 	}
136807252915SVincent Donnefort 
136907252915SVincent Donnefort 	return 0;
137007252915SVincent Donnefort }
137107252915SVincent Donnefort 
137207252915SVincent Donnefort static int __cmp_events(const void *key, const void *data)
137307252915SVincent Donnefort {
137407252915SVincent Donnefort 	const struct remote_event *evt = data;
137507252915SVincent Donnefort 	int id = (int)((long)key);
137607252915SVincent Donnefort 
137707252915SVincent Donnefort 	return id - (int)evt->id;
137807252915SVincent Donnefort }
137907252915SVincent Donnefort 
138007252915SVincent Donnefort static struct remote_event *trace_remote_find_event(struct trace_remote *remote, unsigned short id)
138107252915SVincent Donnefort {
138207252915SVincent Donnefort 	return bsearch((const void *)(unsigned long)id, remote->events, remote->nr_events,
138307252915SVincent Donnefort 		       sizeof(*remote->events), __cmp_events);
138407252915SVincent Donnefort }
1385