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; 34*07252915SVincent 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; 46*07252915SVincent Donnefort struct dentry *dentry; 47*07252915SVincent Donnefort struct eventfs_inode *eventfs; 48*07252915SVincent Donnefort struct remote_event *events; 49*07252915SVincent 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 { 176*07252915SVincent Donnefort struct seq_file *seq = filp->private_data; 177*07252915SVincent 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 { 206*07252915SVincent Donnefort struct seq_file *seq = filp->private_data; 207*07252915SVincent 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 28596e43537SVincent Donnefort static void __poll_remote(struct work_struct *work) 28696e43537SVincent Donnefort { 28796e43537SVincent Donnefort struct delayed_work *dwork = to_delayed_work(work); 28896e43537SVincent Donnefort struct trace_remote_iterator *iter; 28996e43537SVincent Donnefort 29096e43537SVincent Donnefort iter = container_of(dwork, struct trace_remote_iterator, poll_work); 29196e43537SVincent Donnefort ring_buffer_poll_remote(iter->remote->trace_buffer, iter->cpu); 29296e43537SVincent Donnefort schedule_delayed_work((struct delayed_work *)work, 29396e43537SVincent Donnefort msecs_to_jiffies(iter->remote->poll_ms)); 29496e43537SVincent Donnefort } 29596e43537SVincent Donnefort 296330b0cceSVincent Donnefort static void __free_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu) 297330b0cceSVincent Donnefort { 298330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 299330b0cceSVincent Donnefort ring_buffer_read_finish(iter->rb_iter); 300330b0cceSVincent Donnefort return; 301330b0cceSVincent Donnefort } 302330b0cceSVincent Donnefort 303330b0cceSVincent Donnefort for_each_possible_cpu(cpu) { 304330b0cceSVincent Donnefort if (iter->rb_iters[cpu]) 305330b0cceSVincent Donnefort ring_buffer_read_finish(iter->rb_iters[cpu]); 306330b0cceSVincent Donnefort } 307330b0cceSVincent Donnefort 308330b0cceSVincent Donnefort kfree(iter->rb_iters); 309330b0cceSVincent Donnefort } 310330b0cceSVincent Donnefort 311330b0cceSVincent Donnefort static int __alloc_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu) 312330b0cceSVincent Donnefort { 313330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 314330b0cceSVincent Donnefort iter->rb_iter = ring_buffer_read_start(iter->remote->trace_buffer, cpu, GFP_KERNEL); 315330b0cceSVincent Donnefort 316330b0cceSVincent Donnefort return iter->rb_iter ? 0 : -ENOMEM; 317330b0cceSVincent Donnefort } 318330b0cceSVincent Donnefort 319330b0cceSVincent Donnefort iter->rb_iters = kcalloc(nr_cpu_ids, sizeof(*iter->rb_iters), GFP_KERNEL); 320330b0cceSVincent Donnefort if (!iter->rb_iters) 321330b0cceSVincent Donnefort return -ENOMEM; 322330b0cceSVincent Donnefort 323330b0cceSVincent Donnefort for_each_possible_cpu(cpu) { 324330b0cceSVincent Donnefort iter->rb_iters[cpu] = ring_buffer_read_start(iter->remote->trace_buffer, cpu, 325330b0cceSVincent Donnefort GFP_KERNEL); 326330b0cceSVincent Donnefort if (!iter->rb_iters[cpu]) { 327330b0cceSVincent Donnefort __free_ring_buffer_iter(iter, RING_BUFFER_ALL_CPUS); 328330b0cceSVincent Donnefort return -ENOMEM; 329330b0cceSVincent Donnefort } 330330b0cceSVincent Donnefort } 331330b0cceSVincent Donnefort 332330b0cceSVincent Donnefort return 0; 333330b0cceSVincent Donnefort } 334330b0cceSVincent Donnefort 335330b0cceSVincent Donnefort static struct trace_remote_iterator 336330b0cceSVincent Donnefort *trace_remote_iter(struct trace_remote *remote, int cpu, enum tri_type type) 33796e43537SVincent Donnefort { 33896e43537SVincent Donnefort struct trace_remote_iterator *iter = NULL; 33996e43537SVincent Donnefort int ret; 34096e43537SVincent Donnefort 34196e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 34296e43537SVincent Donnefort 343330b0cceSVincent Donnefort if (type == TRI_NONCONSUMING && !trace_remote_loaded(remote)) 344330b0cceSVincent Donnefort return NULL; 34596e43537SVincent Donnefort 34696e43537SVincent Donnefort ret = trace_remote_get(remote, cpu); 34796e43537SVincent Donnefort if (ret) 34896e43537SVincent Donnefort return ERR_PTR(ret); 34996e43537SVincent Donnefort 35096e43537SVincent Donnefort /* Test the CPU */ 35196e43537SVincent Donnefort ret = ring_buffer_poll_remote(remote->trace_buffer, cpu); 35296e43537SVincent Donnefort if (ret) 35396e43537SVincent Donnefort goto err; 35496e43537SVincent Donnefort 35596e43537SVincent Donnefort iter = kzalloc_obj(*iter); 35696e43537SVincent Donnefort if (iter) { 35796e43537SVincent Donnefort iter->remote = remote; 35896e43537SVincent Donnefort iter->cpu = cpu; 359330b0cceSVincent Donnefort iter->type = type; 36096e43537SVincent Donnefort trace_seq_init(&iter->seq); 361330b0cceSVincent Donnefort 362330b0cceSVincent Donnefort switch (type) { 363330b0cceSVincent Donnefort case TRI_CONSUMING: 36496e43537SVincent Donnefort INIT_DELAYED_WORK(&iter->poll_work, __poll_remote); 36596e43537SVincent Donnefort schedule_delayed_work(&iter->poll_work, msecs_to_jiffies(remote->poll_ms)); 366330b0cceSVincent Donnefort break; 367330b0cceSVincent Donnefort case TRI_NONCONSUMING: 368330b0cceSVincent Donnefort ret = __alloc_ring_buffer_iter(iter, cpu); 369330b0cceSVincent Donnefort break; 370330b0cceSVincent Donnefort } 371330b0cceSVincent Donnefort 372330b0cceSVincent Donnefort if (ret) 373330b0cceSVincent Donnefort goto err; 37496e43537SVincent Donnefort 37596e43537SVincent Donnefort return iter; 37696e43537SVincent Donnefort } 37796e43537SVincent Donnefort ret = -ENOMEM; 37896e43537SVincent Donnefort 37996e43537SVincent Donnefort err: 38096e43537SVincent Donnefort kfree(iter); 38196e43537SVincent Donnefort trace_remote_put(remote); 38296e43537SVincent Donnefort 38396e43537SVincent Donnefort return ERR_PTR(ret); 38496e43537SVincent Donnefort } 38596e43537SVincent Donnefort 38696e43537SVincent Donnefort static void trace_remote_iter_free(struct trace_remote_iterator *iter) 38796e43537SVincent Donnefort { 38896e43537SVincent Donnefort struct trace_remote *remote; 38996e43537SVincent Donnefort 39096e43537SVincent Donnefort if (!iter) 39196e43537SVincent Donnefort return; 39296e43537SVincent Donnefort 39396e43537SVincent Donnefort remote = iter->remote; 39496e43537SVincent Donnefort 39596e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 39696e43537SVincent Donnefort 397330b0cceSVincent Donnefort switch (iter->type) { 398330b0cceSVincent Donnefort case TRI_CONSUMING: 399330b0cceSVincent Donnefort cancel_delayed_work_sync(&iter->poll_work); 400330b0cceSVincent Donnefort break; 401330b0cceSVincent Donnefort case TRI_NONCONSUMING: 402330b0cceSVincent Donnefort __free_ring_buffer_iter(iter, iter->cpu); 403330b0cceSVincent Donnefort break; 404330b0cceSVincent Donnefort } 405330b0cceSVincent Donnefort 40696e43537SVincent Donnefort kfree(iter); 40796e43537SVincent Donnefort trace_remote_put(remote); 40896e43537SVincent Donnefort } 40996e43537SVincent Donnefort 410330b0cceSVincent Donnefort static void trace_remote_iter_read_start(struct trace_remote_iterator *iter) 411330b0cceSVincent Donnefort { 412330b0cceSVincent Donnefort struct trace_remote *remote = iter->remote; 413330b0cceSVincent Donnefort int cpu = iter->cpu; 414330b0cceSVincent Donnefort 415330b0cceSVincent Donnefort /* Acquire global reader lock */ 416330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING) 417330b0cceSVincent Donnefort down_write(&remote->reader_lock); 418330b0cceSVincent Donnefort else 419330b0cceSVincent Donnefort down_read(&remote->reader_lock); 420330b0cceSVincent Donnefort 421330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS) 422330b0cceSVincent Donnefort return; 423330b0cceSVincent Donnefort 424330b0cceSVincent Donnefort /* 425330b0cceSVincent Donnefort * No need for the remote lock here, iter holds a reference on 426330b0cceSVincent Donnefort * remote->nr_readers 427330b0cceSVincent Donnefort */ 428330b0cceSVincent Donnefort 429330b0cceSVincent Donnefort /* Get the per-CPU one */ 430330b0cceSVincent Donnefort if (WARN_ON_ONCE(!remote->pcpu_reader_locks)) 431330b0cceSVincent Donnefort return; 432330b0cceSVincent Donnefort 433330b0cceSVincent Donnefort if (iter->type == TRI_CONSUMING) 434330b0cceSVincent Donnefort down_write(&remote->pcpu_reader_locks[cpu]); 435330b0cceSVincent Donnefort else 436330b0cceSVincent Donnefort down_read(&remote->pcpu_reader_locks[cpu]); 437330b0cceSVincent Donnefort } 438330b0cceSVincent Donnefort 439330b0cceSVincent Donnefort static void trace_remote_iter_read_finished(struct trace_remote_iterator *iter) 440330b0cceSVincent Donnefort { 441330b0cceSVincent Donnefort struct trace_remote *remote = iter->remote; 442330b0cceSVincent Donnefort int cpu = iter->cpu; 443330b0cceSVincent Donnefort 444330b0cceSVincent Donnefort /* Release per-CPU reader lock */ 445330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 446330b0cceSVincent Donnefort /* 447330b0cceSVincent Donnefort * No need for the remote lock here, iter holds a reference on 448330b0cceSVincent Donnefort * remote->nr_readers 449330b0cceSVincent Donnefort */ 450330b0cceSVincent Donnefort if (iter->type == TRI_CONSUMING) 451330b0cceSVincent Donnefort up_write(&remote->pcpu_reader_locks[cpu]); 452330b0cceSVincent Donnefort else 453330b0cceSVincent Donnefort up_read(&remote->pcpu_reader_locks[cpu]); 454330b0cceSVincent Donnefort } 455330b0cceSVincent Donnefort 456330b0cceSVincent Donnefort /* Release global reader lock */ 457330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING) 458330b0cceSVincent Donnefort up_write(&remote->reader_lock); 459330b0cceSVincent Donnefort else 460330b0cceSVincent Donnefort up_read(&remote->reader_lock); 461330b0cceSVincent Donnefort } 462330b0cceSVincent Donnefort 463330b0cceSVincent Donnefort static struct ring_buffer_iter *__get_rb_iter(struct trace_remote_iterator *iter, int cpu) 464330b0cceSVincent Donnefort { 465330b0cceSVincent Donnefort return iter->cpu != RING_BUFFER_ALL_CPUS ? iter->rb_iter : iter->rb_iters[cpu]; 466330b0cceSVincent Donnefort } 467330b0cceSVincent Donnefort 468330b0cceSVincent Donnefort static struct ring_buffer_event * 469330b0cceSVincent Donnefort __peek_event(struct trace_remote_iterator *iter, int cpu, u64 *ts, unsigned long *lost_events) 470330b0cceSVincent Donnefort { 471330b0cceSVincent Donnefort struct ring_buffer_event *rb_evt; 472330b0cceSVincent Donnefort struct ring_buffer_iter *rb_iter; 473330b0cceSVincent Donnefort 474330b0cceSVincent Donnefort switch (iter->type) { 475330b0cceSVincent Donnefort case TRI_CONSUMING: 476330b0cceSVincent Donnefort return ring_buffer_peek(iter->remote->trace_buffer, cpu, ts, lost_events); 477330b0cceSVincent Donnefort case TRI_NONCONSUMING: 478330b0cceSVincent Donnefort rb_iter = __get_rb_iter(iter, cpu); 479330b0cceSVincent Donnefort rb_evt = ring_buffer_iter_peek(rb_iter, ts); 480330b0cceSVincent Donnefort if (!rb_evt) 481330b0cceSVincent Donnefort return NULL; 482330b0cceSVincent Donnefort 483330b0cceSVincent Donnefort *lost_events = ring_buffer_iter_dropped(rb_iter); 484330b0cceSVincent Donnefort 485330b0cceSVincent Donnefort return rb_evt; 486330b0cceSVincent Donnefort } 487330b0cceSVincent Donnefort 488330b0cceSVincent Donnefort return NULL; 489330b0cceSVincent Donnefort } 490330b0cceSVincent Donnefort 49196e43537SVincent Donnefort static bool trace_remote_iter_read_event(struct trace_remote_iterator *iter) 49296e43537SVincent Donnefort { 49396e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 494*07252915SVincent Donnefort struct ring_buffer_event *rb_evt; 49596e43537SVincent Donnefort int cpu = iter->cpu; 49696e43537SVincent Donnefort 49796e43537SVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 49896e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 49996e43537SVincent Donnefort return false; 50096e43537SVincent Donnefort 501*07252915SVincent Donnefort rb_evt = __peek_event(iter, cpu, &iter->ts, &iter->lost_events); 502*07252915SVincent Donnefort if (!rb_evt) 50396e43537SVincent Donnefort return false; 50496e43537SVincent Donnefort 50596e43537SVincent Donnefort iter->evt_cpu = cpu; 506*07252915SVincent Donnefort iter->evt = ring_buffer_event_data(rb_evt); 50796e43537SVincent Donnefort return true; 50896e43537SVincent Donnefort } 50996e43537SVincent Donnefort 51096e43537SVincent Donnefort iter->ts = U64_MAX; 51196e43537SVincent Donnefort for_each_possible_cpu(cpu) { 51296e43537SVincent Donnefort unsigned long lost_events; 51396e43537SVincent Donnefort u64 ts; 51496e43537SVincent Donnefort 51596e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 51696e43537SVincent Donnefort continue; 51796e43537SVincent Donnefort 518*07252915SVincent Donnefort rb_evt = __peek_event(iter, cpu, &ts, &lost_events); 519*07252915SVincent Donnefort if (!rb_evt) 52096e43537SVincent Donnefort continue; 52196e43537SVincent Donnefort 52296e43537SVincent Donnefort if (ts >= iter->ts) 52396e43537SVincent Donnefort continue; 52496e43537SVincent Donnefort 52596e43537SVincent Donnefort iter->ts = ts; 52696e43537SVincent Donnefort iter->evt_cpu = cpu; 527*07252915SVincent Donnefort iter->evt = ring_buffer_event_data(rb_evt); 52896e43537SVincent Donnefort iter->lost_events = lost_events; 52996e43537SVincent Donnefort } 53096e43537SVincent Donnefort 53196e43537SVincent Donnefort return iter->ts != U64_MAX; 53296e43537SVincent Donnefort } 53396e43537SVincent Donnefort 534330b0cceSVincent Donnefort static void trace_remote_iter_move(struct trace_remote_iterator *iter) 535330b0cceSVincent Donnefort { 536330b0cceSVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 537330b0cceSVincent Donnefort 538330b0cceSVincent Donnefort switch (iter->type) { 539330b0cceSVincent Donnefort case TRI_CONSUMING: 540330b0cceSVincent Donnefort ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL); 541330b0cceSVincent Donnefort break; 542330b0cceSVincent Donnefort case TRI_NONCONSUMING: 543330b0cceSVincent Donnefort ring_buffer_iter_advance(__get_rb_iter(iter, iter->evt_cpu)); 544330b0cceSVincent Donnefort break; 545330b0cceSVincent Donnefort } 546330b0cceSVincent Donnefort } 547330b0cceSVincent Donnefort 548*07252915SVincent Donnefort static struct remote_event *trace_remote_find_event(struct trace_remote *remote, unsigned short id); 549*07252915SVincent Donnefort 55096e43537SVincent Donnefort static int trace_remote_iter_print_event(struct trace_remote_iterator *iter) 55196e43537SVincent Donnefort { 552*07252915SVincent Donnefort struct remote_event *evt; 55396e43537SVincent Donnefort unsigned long usecs_rem; 55496e43537SVincent Donnefort u64 ts = iter->ts; 55596e43537SVincent Donnefort 55696e43537SVincent Donnefort if (iter->lost_events) 55796e43537SVincent Donnefort trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", 55896e43537SVincent Donnefort iter->evt_cpu, iter->lost_events); 55996e43537SVincent Donnefort 56096e43537SVincent Donnefort do_div(ts, 1000); 56196e43537SVincent Donnefort usecs_rem = do_div(ts, USEC_PER_SEC); 56296e43537SVincent Donnefort 56396e43537SVincent Donnefort trace_seq_printf(&iter->seq, "[%03d]\t%5llu.%06lu: ", iter->evt_cpu, 56496e43537SVincent Donnefort ts, usecs_rem); 56596e43537SVincent Donnefort 566*07252915SVincent Donnefort evt = trace_remote_find_event(iter->remote, iter->evt->id); 567*07252915SVincent Donnefort if (!evt) 568*07252915SVincent Donnefort trace_seq_printf(&iter->seq, "UNKNOWN id=%d\n", iter->evt->id); 569*07252915SVincent Donnefort else 570*07252915SVincent Donnefort evt->print(iter->evt, &iter->seq); 571*07252915SVincent Donnefort 57296e43537SVincent Donnefort return trace_seq_has_overflowed(&iter->seq) ? -EOVERFLOW : 0; 57396e43537SVincent Donnefort } 57496e43537SVincent Donnefort 57596e43537SVincent Donnefort static int trace_pipe_open(struct inode *inode, struct file *filp) 57696e43537SVincent Donnefort { 57796e43537SVincent Donnefort struct trace_remote *remote = inode->i_private; 57896e43537SVincent Donnefort struct trace_remote_iterator *iter; 579330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 58096e43537SVincent Donnefort 58196e43537SVincent Donnefort guard(mutex)(&remote->lock); 582330b0cceSVincent Donnefort 583330b0cceSVincent Donnefort iter = trace_remote_iter(remote, cpu, TRI_CONSUMING); 584330b0cceSVincent Donnefort if (IS_ERR(iter)) 585330b0cceSVincent Donnefort return PTR_ERR(iter); 586330b0cceSVincent Donnefort 58796e43537SVincent Donnefort filp->private_data = iter; 58896e43537SVincent Donnefort 58996e43537SVincent Donnefort return IS_ERR(iter) ? PTR_ERR(iter) : 0; 59096e43537SVincent Donnefort } 59196e43537SVincent Donnefort 59296e43537SVincent Donnefort static int trace_pipe_release(struct inode *inode, struct file *filp) 59396e43537SVincent Donnefort { 59496e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 59596e43537SVincent Donnefort struct trace_remote *remote = iter->remote; 59696e43537SVincent Donnefort 59796e43537SVincent Donnefort guard(mutex)(&remote->lock); 59896e43537SVincent Donnefort 59996e43537SVincent Donnefort trace_remote_iter_free(iter); 60096e43537SVincent Donnefort 60196e43537SVincent Donnefort return 0; 60296e43537SVincent Donnefort } 60396e43537SVincent Donnefort 60496e43537SVincent Donnefort static ssize_t trace_pipe_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 60596e43537SVincent Donnefort { 60696e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 60796e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 60896e43537SVincent Donnefort int ret; 60996e43537SVincent Donnefort 61096e43537SVincent Donnefort copy_to_user: 61196e43537SVincent Donnefort ret = trace_seq_to_user(&iter->seq, ubuf, cnt); 61296e43537SVincent Donnefort if (ret != -EBUSY) 61396e43537SVincent Donnefort return ret; 61496e43537SVincent Donnefort 61596e43537SVincent Donnefort trace_seq_init(&iter->seq); 61696e43537SVincent Donnefort 61796e43537SVincent Donnefort ret = ring_buffer_wait(trace_buffer, iter->cpu, 0, NULL, NULL); 61896e43537SVincent Donnefort if (ret < 0) 61996e43537SVincent Donnefort return ret; 62096e43537SVincent Donnefort 621330b0cceSVincent Donnefort trace_remote_iter_read_start(iter); 622330b0cceSVincent Donnefort 62396e43537SVincent Donnefort while (trace_remote_iter_read_event(iter)) { 62496e43537SVincent Donnefort int prev_len = iter->seq.seq.len; 62596e43537SVincent Donnefort 62696e43537SVincent Donnefort if (trace_remote_iter_print_event(iter)) { 62796e43537SVincent Donnefort iter->seq.seq.len = prev_len; 62896e43537SVincent Donnefort break; 62996e43537SVincent Donnefort } 63096e43537SVincent Donnefort 631330b0cceSVincent Donnefort trace_remote_iter_move(iter); 63296e43537SVincent Donnefort } 63396e43537SVincent Donnefort 634330b0cceSVincent Donnefort trace_remote_iter_read_finished(iter); 635330b0cceSVincent Donnefort 63696e43537SVincent Donnefort goto copy_to_user; 63796e43537SVincent Donnefort } 63896e43537SVincent Donnefort 63996e43537SVincent Donnefort static const struct file_operations trace_pipe_fops = { 64096e43537SVincent Donnefort .open = trace_pipe_open, 64196e43537SVincent Donnefort .read = trace_pipe_read, 64296e43537SVincent Donnefort .release = trace_pipe_release, 64396e43537SVincent Donnefort }; 64496e43537SVincent Donnefort 645330b0cceSVincent Donnefort static void *trace_next(struct seq_file *m, void *v, loff_t *pos) 646330b0cceSVincent Donnefort { 647330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 648330b0cceSVincent Donnefort 649330b0cceSVincent Donnefort ++*pos; 650330b0cceSVincent Donnefort 651330b0cceSVincent Donnefort if (!iter || !trace_remote_iter_read_event(iter)) 652330b0cceSVincent Donnefort return NULL; 653330b0cceSVincent Donnefort 654330b0cceSVincent Donnefort trace_remote_iter_move(iter); 655330b0cceSVincent Donnefort iter->pos++; 656330b0cceSVincent Donnefort 657330b0cceSVincent Donnefort return iter; 658330b0cceSVincent Donnefort } 659330b0cceSVincent Donnefort 660330b0cceSVincent Donnefort static void *trace_start(struct seq_file *m, loff_t *pos) 661330b0cceSVincent Donnefort { 662330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 663330b0cceSVincent Donnefort loff_t i; 664330b0cceSVincent Donnefort 665330b0cceSVincent Donnefort if (!iter) 666330b0cceSVincent Donnefort return NULL; 667330b0cceSVincent Donnefort 668330b0cceSVincent Donnefort trace_remote_iter_read_start(iter); 669330b0cceSVincent Donnefort 670330b0cceSVincent Donnefort if (!*pos) { 671330b0cceSVincent Donnefort iter->pos = -1; 672330b0cceSVincent Donnefort return trace_next(m, NULL, &i); 673330b0cceSVincent Donnefort } 674330b0cceSVincent Donnefort 675330b0cceSVincent Donnefort i = iter->pos; 676330b0cceSVincent Donnefort while (i < *pos) { 677330b0cceSVincent Donnefort iter = trace_next(m, NULL, &i); 678330b0cceSVincent Donnefort if (!iter) 679330b0cceSVincent Donnefort return NULL; 680330b0cceSVincent Donnefort } 681330b0cceSVincent Donnefort 682330b0cceSVincent Donnefort return iter; 683330b0cceSVincent Donnefort } 684330b0cceSVincent Donnefort 685330b0cceSVincent Donnefort static int trace_show(struct seq_file *m, void *v) 686330b0cceSVincent Donnefort { 687330b0cceSVincent Donnefort struct trace_remote_iterator *iter = v; 688330b0cceSVincent Donnefort 689330b0cceSVincent Donnefort trace_seq_init(&iter->seq); 690330b0cceSVincent Donnefort 691330b0cceSVincent Donnefort if (trace_remote_iter_print_event(iter)) { 692330b0cceSVincent Donnefort seq_printf(m, "[EVENT %d PRINT TOO BIG]\n", iter->evt->id); 693330b0cceSVincent Donnefort return 0; 694330b0cceSVincent Donnefort } 695330b0cceSVincent Donnefort 696330b0cceSVincent Donnefort return trace_print_seq(m, &iter->seq); 697330b0cceSVincent Donnefort } 698330b0cceSVincent Donnefort 699330b0cceSVincent Donnefort static void trace_stop(struct seq_file *m, void *v) 700330b0cceSVincent Donnefort { 701330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 702330b0cceSVincent Donnefort 703330b0cceSVincent Donnefort if (iter) 704330b0cceSVincent Donnefort trace_remote_iter_read_finished(iter); 705330b0cceSVincent Donnefort } 706330b0cceSVincent Donnefort 707330b0cceSVincent Donnefort static const struct seq_operations trace_sops = { 708330b0cceSVincent Donnefort .start = trace_start, 709330b0cceSVincent Donnefort .next = trace_next, 710330b0cceSVincent Donnefort .show = trace_show, 711330b0cceSVincent Donnefort .stop = trace_stop, 712330b0cceSVincent Donnefort }; 713330b0cceSVincent Donnefort 714330b0cceSVincent Donnefort static int trace_open(struct inode *inode, struct file *filp) 715330b0cceSVincent Donnefort { 716330b0cceSVincent Donnefort struct trace_remote *remote = inode->i_private; 717330b0cceSVincent Donnefort struct trace_remote_iterator *iter = NULL; 718330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 719330b0cceSVincent Donnefort int ret; 720330b0cceSVincent Donnefort 721330b0cceSVincent Donnefort if (!(filp->f_mode & FMODE_READ)) 722330b0cceSVincent Donnefort return 0; 723330b0cceSVincent Donnefort 724330b0cceSVincent Donnefort guard(mutex)(&remote->lock); 725330b0cceSVincent Donnefort 726330b0cceSVincent Donnefort iter = trace_remote_iter(remote, cpu, TRI_NONCONSUMING); 727330b0cceSVincent Donnefort if (IS_ERR(iter)) 728330b0cceSVincent Donnefort return PTR_ERR(iter); 729330b0cceSVincent Donnefort 730330b0cceSVincent Donnefort ret = seq_open(filp, &trace_sops); 731330b0cceSVincent Donnefort if (ret) { 732330b0cceSVincent Donnefort trace_remote_iter_free(iter); 733330b0cceSVincent Donnefort return ret; 734330b0cceSVincent Donnefort } 735330b0cceSVincent Donnefort 736330b0cceSVincent Donnefort ((struct seq_file *)filp->private_data)->private = (void *)iter; 737330b0cceSVincent Donnefort 738330b0cceSVincent Donnefort return 0; 739330b0cceSVincent Donnefort } 740330b0cceSVincent Donnefort 741330b0cceSVincent Donnefort static int trace_release(struct inode *inode, struct file *filp) 742330b0cceSVincent Donnefort { 743330b0cceSVincent Donnefort struct trace_remote_iterator *iter; 744330b0cceSVincent Donnefort 745330b0cceSVincent Donnefort if (!(filp->f_mode & FMODE_READ)) 746330b0cceSVincent Donnefort return 0; 747330b0cceSVincent Donnefort 748330b0cceSVincent Donnefort iter = ((struct seq_file *)filp->private_data)->private; 749330b0cceSVincent Donnefort seq_release(inode, filp); 750330b0cceSVincent Donnefort 751330b0cceSVincent Donnefort if (!iter) 752330b0cceSVincent Donnefort return 0; 753330b0cceSVincent Donnefort 754330b0cceSVincent Donnefort guard(mutex)(&iter->remote->lock); 755330b0cceSVincent Donnefort 756330b0cceSVincent Donnefort trace_remote_iter_free(iter); 757330b0cceSVincent Donnefort 758330b0cceSVincent Donnefort return 0; 759330b0cceSVincent Donnefort } 760330b0cceSVincent Donnefort 7619af4ab0eSVincent Donnefort static ssize_t trace_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) 7629af4ab0eSVincent Donnefort { 7639af4ab0eSVincent Donnefort struct inode *inode = file_inode(filp); 7649af4ab0eSVincent Donnefort struct trace_remote *remote = inode->i_private; 765330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 7669af4ab0eSVincent Donnefort 7679af4ab0eSVincent Donnefort guard(mutex)(&remote->lock); 7689af4ab0eSVincent Donnefort 7699af4ab0eSVincent Donnefort trace_remote_reset(remote, cpu); 7709af4ab0eSVincent Donnefort 7719af4ab0eSVincent Donnefort return cnt; 7729af4ab0eSVincent Donnefort } 7739af4ab0eSVincent Donnefort 7749af4ab0eSVincent Donnefort static const struct file_operations trace_fops = { 775330b0cceSVincent Donnefort .open = trace_open, 7769af4ab0eSVincent Donnefort .write = trace_write, 777330b0cceSVincent Donnefort .read = seq_read, 778330b0cceSVincent Donnefort .read_iter = seq_read_iter, 779330b0cceSVincent Donnefort .release = trace_release, 7809af4ab0eSVincent Donnefort }; 7819af4ab0eSVincent Donnefort 78296e43537SVincent Donnefort static int trace_remote_init_tracefs(const char *name, struct trace_remote *remote) 78396e43537SVincent Donnefort { 78496e43537SVincent Donnefort struct dentry *remote_d, *percpu_d, *d; 78596e43537SVincent Donnefort static struct dentry *root; 78696e43537SVincent Donnefort static DEFINE_MUTEX(lock); 78796e43537SVincent Donnefort bool root_inited = false; 78896e43537SVincent Donnefort int cpu; 78996e43537SVincent Donnefort 79096e43537SVincent Donnefort guard(mutex)(&lock); 79196e43537SVincent Donnefort 79296e43537SVincent Donnefort if (!root) { 79396e43537SVincent Donnefort root = tracefs_create_dir(TRACEFS_DIR, NULL); 79496e43537SVincent Donnefort if (!root) { 79596e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"\n"); 79696e43537SVincent Donnefort return -ENOMEM; 79796e43537SVincent Donnefort } 79896e43537SVincent Donnefort root_inited = true; 79996e43537SVincent Donnefort } 80096e43537SVincent Donnefort 80196e43537SVincent Donnefort remote_d = tracefs_create_dir(name, root); 80296e43537SVincent Donnefort if (!remote_d) { 80396e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/\n", name); 80496e43537SVincent Donnefort goto err; 80596e43537SVincent Donnefort } 80696e43537SVincent Donnefort 80796e43537SVincent Donnefort d = trace_create_file("tracing_on", TRACEFS_MODE_WRITE, remote_d, remote, &tracing_on_fops); 80896e43537SVincent Donnefort if (!d) 80996e43537SVincent Donnefort goto err; 81096e43537SVincent Donnefort 81196e43537SVincent Donnefort d = trace_create_file("buffer_size_kb", TRACEFS_MODE_WRITE, remote_d, remote, 81296e43537SVincent Donnefort &buffer_size_kb_fops); 81396e43537SVincent Donnefort if (!d) 81496e43537SVincent Donnefort goto err; 81596e43537SVincent Donnefort 81696e43537SVincent Donnefort d = trace_create_file("trace_pipe", TRACEFS_MODE_READ, remote_d, remote, &trace_pipe_fops); 81796e43537SVincent Donnefort if (!d) 81896e43537SVincent Donnefort goto err; 81996e43537SVincent Donnefort 8209af4ab0eSVincent Donnefort d = trace_create_file("trace", TRACEFS_MODE_WRITE, remote_d, remote, &trace_fops); 8219af4ab0eSVincent Donnefort if (!d) 8229af4ab0eSVincent Donnefort goto err; 8239af4ab0eSVincent Donnefort 82496e43537SVincent Donnefort percpu_d = tracefs_create_dir("per_cpu", remote_d); 82596e43537SVincent Donnefort if (!percpu_d) { 82696e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/per_cpu/\n", name); 82796e43537SVincent Donnefort goto err; 82896e43537SVincent Donnefort } 82996e43537SVincent Donnefort 83096e43537SVincent Donnefort for_each_possible_cpu(cpu) { 83196e43537SVincent Donnefort struct dentry *cpu_d; 83296e43537SVincent Donnefort char cpu_name[16]; 83396e43537SVincent Donnefort 83496e43537SVincent Donnefort snprintf(cpu_name, sizeof(cpu_name), "cpu%d", cpu); 83596e43537SVincent Donnefort cpu_d = tracefs_create_dir(cpu_name, percpu_d); 83696e43537SVincent Donnefort if (!cpu_d) { 83796e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/percpu/cpu%d\n", 83896e43537SVincent Donnefort name, cpu); 83996e43537SVincent Donnefort goto err; 84096e43537SVincent Donnefort } 84196e43537SVincent Donnefort 84296e43537SVincent Donnefort d = trace_create_cpu_file("trace_pipe", TRACEFS_MODE_READ, cpu_d, remote, cpu, 84396e43537SVincent Donnefort &trace_pipe_fops); 84496e43537SVincent Donnefort if (!d) 84596e43537SVincent Donnefort goto err; 8469af4ab0eSVincent Donnefort 8479af4ab0eSVincent Donnefort d = trace_create_cpu_file("trace", TRACEFS_MODE_WRITE, cpu_d, remote, cpu, 8489af4ab0eSVincent Donnefort &trace_fops); 8499af4ab0eSVincent Donnefort if (!d) 8509af4ab0eSVincent Donnefort goto err; 85196e43537SVincent Donnefort } 85296e43537SVincent Donnefort 853*07252915SVincent Donnefort remote->dentry = remote_d; 854*07252915SVincent Donnefort 85596e43537SVincent Donnefort return 0; 85696e43537SVincent Donnefort 85796e43537SVincent Donnefort err: 85896e43537SVincent Donnefort if (root_inited) { 85996e43537SVincent Donnefort tracefs_remove(root); 86096e43537SVincent Donnefort root = NULL; 86196e43537SVincent Donnefort } else { 86296e43537SVincent Donnefort tracefs_remove(remote_d); 86396e43537SVincent Donnefort } 86496e43537SVincent Donnefort 86596e43537SVincent Donnefort return -ENOMEM; 86696e43537SVincent Donnefort } 86796e43537SVincent Donnefort 868*07252915SVincent Donnefort static int trace_remote_register_events(const char *remote_name, struct trace_remote *remote, 869*07252915SVincent Donnefort struct remote_event *events, size_t nr_events); 870*07252915SVincent Donnefort 87196e43537SVincent Donnefort /** 87296e43537SVincent Donnefort * trace_remote_register() - Register a Tracefs remote 87396e43537SVincent Donnefort * @name: Name of the remote, used for the Tracefs remotes/ directory. 87496e43537SVincent Donnefort * @cbs: Set of callbacks used to control the remote. 87596e43537SVincent Donnefort * @priv: Private data, passed to each callback from @cbs. 87696e43537SVincent Donnefort * @events: Array of events. &remote_event.name and &remote_event.id must be 87796e43537SVincent Donnefort * filled by the caller. 87896e43537SVincent Donnefort * @nr_events: Number of events in the @events array. 87996e43537SVincent Donnefort * 88096e43537SVincent Donnefort * A trace remote is an entity, outside of the kernel (most likely firmware or 88196e43537SVincent Donnefort * hypervisor) capable of writing events into a Tracefs compatible ring-buffer. 88296e43537SVincent Donnefort * The kernel would then act as a reader. 88396e43537SVincent Donnefort * 88496e43537SVincent Donnefort * The registered remote will be found under the Tracefs directory 88596e43537SVincent Donnefort * remotes/<name>. 88696e43537SVincent Donnefort * 88796e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 88896e43537SVincent Donnefort */ 889*07252915SVincent Donnefort int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, void *priv, 890*07252915SVincent Donnefort struct remote_event *events, size_t nr_events) 89196e43537SVincent Donnefort { 89296e43537SVincent Donnefort struct trace_remote *remote; 893bf2ba0f8SVincent Donnefort int ret; 89496e43537SVincent Donnefort 89596e43537SVincent Donnefort remote = kzalloc_obj(*remote); 89696e43537SVincent Donnefort if (!remote) 89796e43537SVincent Donnefort return -ENOMEM; 89896e43537SVincent Donnefort 89996e43537SVincent Donnefort remote->cbs = cbs; 90096e43537SVincent Donnefort remote->priv = priv; 90196e43537SVincent Donnefort remote->trace_buffer_size = 7 << 10; 90296e43537SVincent Donnefort remote->poll_ms = 100; 90396e43537SVincent Donnefort mutex_init(&remote->lock); 904330b0cceSVincent Donnefort init_rwsem(&remote->reader_lock); 90596e43537SVincent Donnefort 90696e43537SVincent Donnefort if (trace_remote_init_tracefs(name, remote)) { 90796e43537SVincent Donnefort kfree(remote); 90896e43537SVincent Donnefort return -ENOMEM; 90996e43537SVincent Donnefort } 91096e43537SVincent Donnefort 911*07252915SVincent Donnefort ret = trace_remote_register_events(name, remote, events, nr_events); 912*07252915SVincent Donnefort if (ret) { 913*07252915SVincent Donnefort pr_err("Failed to register events for trace remote '%s' (%d)\n", 914*07252915SVincent Donnefort name, ret); 915*07252915SVincent Donnefort return ret; 916*07252915SVincent Donnefort } 917*07252915SVincent Donnefort 918bf2ba0f8SVincent Donnefort ret = cbs->init ? cbs->init(remote->dentry, priv) : 0; 919bf2ba0f8SVincent Donnefort if (ret) 920bf2ba0f8SVincent Donnefort pr_err("Init failed for trace remote '%s' (%d)\n", name, ret); 921bf2ba0f8SVincent Donnefort 922bf2ba0f8SVincent Donnefort return ret; 92396e43537SVincent Donnefort } 92496e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register); 92596e43537SVincent Donnefort 92696e43537SVincent Donnefort /** 92796e43537SVincent Donnefort * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer() 92896e43537SVincent Donnefort * @desc: Descriptor of the per-CPU ring-buffers, originally filled by 92996e43537SVincent Donnefort * trace_remote_alloc_buffer() 93096e43537SVincent Donnefort * 93196e43537SVincent Donnefort * Most likely called from &trace_remote_callbacks.unload_trace_buffer. 93296e43537SVincent Donnefort */ 93396e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc) 93496e43537SVincent Donnefort { 93596e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 93696e43537SVincent Donnefort int cpu; 93796e43537SVincent Donnefort 93896e43537SVincent Donnefort for_each_ring_buffer_desc(rb_desc, cpu, desc) { 93996e43537SVincent Donnefort unsigned int id; 94096e43537SVincent Donnefort 94196e43537SVincent Donnefort free_page(rb_desc->meta_va); 94296e43537SVincent Donnefort 94396e43537SVincent Donnefort for (id = 0; id < rb_desc->nr_page_va; id++) 94496e43537SVincent Donnefort free_page(rb_desc->page_va[id]); 94596e43537SVincent Donnefort } 94696e43537SVincent Donnefort } 94796e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer); 94896e43537SVincent Donnefort 94996e43537SVincent Donnefort /** 95096e43537SVincent Donnefort * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer 95196e43537SVincent Donnefort * @desc: Uninitialized trace_buffer_desc 95296e43537SVincent Donnefort * @desc_size: Size of the trace_buffer_desc. Must be at least equal to 95396e43537SVincent Donnefort * trace_buffer_desc_size() 95496e43537SVincent Donnefort * @buffer_size: Size in bytes of each per-CPU ring-buffer 95596e43537SVincent Donnefort * @cpumask: CPUs to allocate a ring-buffer for 95696e43537SVincent Donnefort * 95796e43537SVincent Donnefort * Helper to dynamically allocate a set of pages (enough to cover @buffer_size) 95896e43537SVincent Donnefort * for each CPU from @cpumask and fill @desc. Most likely called from 95996e43537SVincent Donnefort * &trace_remote_callbacks.load_trace_buffer. 96096e43537SVincent Donnefort * 96196e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 96296e43537SVincent Donnefort */ 96396e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size, 96496e43537SVincent Donnefort const struct cpumask *cpumask) 96596e43537SVincent Donnefort { 96696e43537SVincent Donnefort unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1; 96796e43537SVincent Donnefort void *desc_end = desc + desc_size; 96896e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 96996e43537SVincent Donnefort int cpu, ret = -ENOMEM; 97096e43537SVincent Donnefort 97196e43537SVincent Donnefort if (desc_size < struct_size(desc, __data, 0)) 97296e43537SVincent Donnefort return -EINVAL; 97396e43537SVincent Donnefort 97496e43537SVincent Donnefort desc->nr_cpus = 0; 97596e43537SVincent Donnefort desc->struct_len = struct_size(desc, __data, 0); 97696e43537SVincent Donnefort 97796e43537SVincent Donnefort rb_desc = (struct ring_buffer_desc *)&desc->__data[0]; 97896e43537SVincent Donnefort 97996e43537SVincent Donnefort for_each_cpu(cpu, cpumask) { 98096e43537SVincent Donnefort unsigned int id; 98196e43537SVincent Donnefort 98296e43537SVincent Donnefort if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) { 98396e43537SVincent Donnefort ret = -EINVAL; 98496e43537SVincent Donnefort goto err; 98596e43537SVincent Donnefort } 98696e43537SVincent Donnefort 98796e43537SVincent Donnefort rb_desc->cpu = cpu; 98896e43537SVincent Donnefort rb_desc->nr_page_va = 0; 98996e43537SVincent Donnefort rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL); 99096e43537SVincent Donnefort if (!rb_desc->meta_va) 99196e43537SVincent Donnefort goto err; 99296e43537SVincent Donnefort 99396e43537SVincent Donnefort for (id = 0; id < nr_pages; id++) { 99496e43537SVincent Donnefort rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL); 99596e43537SVincent Donnefort if (!rb_desc->page_va[id]) 99696e43537SVincent Donnefort goto err; 99796e43537SVincent Donnefort 99896e43537SVincent Donnefort rb_desc->nr_page_va++; 99996e43537SVincent Donnefort } 100096e43537SVincent Donnefort desc->nr_cpus++; 100196e43537SVincent Donnefort desc->struct_len += offsetof(struct ring_buffer_desc, page_va); 100296e43537SVincent Donnefort desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va); 100396e43537SVincent Donnefort rb_desc = __next_ring_buffer_desc(rb_desc); 100496e43537SVincent Donnefort } 100596e43537SVincent Donnefort 100696e43537SVincent Donnefort return 0; 100796e43537SVincent Donnefort 100896e43537SVincent Donnefort err: 100996e43537SVincent Donnefort trace_remote_free_buffer(desc); 101096e43537SVincent Donnefort return ret; 101196e43537SVincent Donnefort } 101296e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer); 1013*07252915SVincent Donnefort 1014*07252915SVincent Donnefort static int 1015*07252915SVincent Donnefort trace_remote_enable_event(struct trace_remote *remote, struct remote_event *evt, bool enable) 1016*07252915SVincent Donnefort { 1017*07252915SVincent Donnefort int ret; 1018*07252915SVincent Donnefort 1019*07252915SVincent Donnefort lockdep_assert_held(&remote->lock); 1020*07252915SVincent Donnefort 1021*07252915SVincent Donnefort if (evt->enabled == enable) 1022*07252915SVincent Donnefort return 0; 1023*07252915SVincent Donnefort 1024*07252915SVincent Donnefort ret = remote->cbs->enable_event(evt->id, enable, remote->priv); 1025*07252915SVincent Donnefort if (ret) 1026*07252915SVincent Donnefort return ret; 1027*07252915SVincent Donnefort 1028*07252915SVincent Donnefort evt->enabled = enable; 1029*07252915SVincent Donnefort 1030*07252915SVincent Donnefort return 0; 1031*07252915SVincent Donnefort } 1032*07252915SVincent Donnefort 1033*07252915SVincent Donnefort static int remote_event_enable_show(struct seq_file *s, void *unused) 1034*07252915SVincent Donnefort { 1035*07252915SVincent Donnefort struct remote_event *evt = s->private; 1036*07252915SVincent Donnefort 1037*07252915SVincent Donnefort seq_printf(s, "%d\n", evt->enabled); 1038*07252915SVincent Donnefort 1039*07252915SVincent Donnefort return 0; 1040*07252915SVincent Donnefort } 1041*07252915SVincent Donnefort 1042*07252915SVincent Donnefort static ssize_t remote_event_enable_write(struct file *filp, const char __user *ubuf, 1043*07252915SVincent Donnefort size_t count, loff_t *ppos) 1044*07252915SVincent Donnefort { 1045*07252915SVincent Donnefort struct seq_file *seq = filp->private_data; 1046*07252915SVincent Donnefort struct remote_event *evt = seq->private; 1047*07252915SVincent Donnefort struct trace_remote *remote = evt->remote; 1048*07252915SVincent Donnefort u8 enable; 1049*07252915SVincent Donnefort int ret; 1050*07252915SVincent Donnefort 1051*07252915SVincent Donnefort ret = kstrtou8_from_user(ubuf, count, 10, &enable); 1052*07252915SVincent Donnefort if (ret) 1053*07252915SVincent Donnefort return ret; 1054*07252915SVincent Donnefort 1055*07252915SVincent Donnefort guard(mutex)(&remote->lock); 1056*07252915SVincent Donnefort 1057*07252915SVincent Donnefort ret = trace_remote_enable_event(remote, evt, enable); 1058*07252915SVincent Donnefort if (ret) 1059*07252915SVincent Donnefort return ret; 1060*07252915SVincent Donnefort 1061*07252915SVincent Donnefort return count; 1062*07252915SVincent Donnefort } 1063*07252915SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(remote_event_enable); 1064*07252915SVincent Donnefort 1065*07252915SVincent Donnefort static int remote_event_id_show(struct seq_file *s, void *unused) 1066*07252915SVincent Donnefort { 1067*07252915SVincent Donnefort struct remote_event *evt = s->private; 1068*07252915SVincent Donnefort 1069*07252915SVincent Donnefort seq_printf(s, "%d\n", evt->id); 1070*07252915SVincent Donnefort 1071*07252915SVincent Donnefort return 0; 1072*07252915SVincent Donnefort } 1073*07252915SVincent Donnefort DEFINE_SHOW_ATTRIBUTE(remote_event_id); 1074*07252915SVincent Donnefort 1075*07252915SVincent Donnefort static int remote_event_format_show(struct seq_file *s, void *unused) 1076*07252915SVincent Donnefort { 1077*07252915SVincent Donnefort size_t offset = sizeof(struct remote_event_hdr); 1078*07252915SVincent Donnefort struct remote_event *evt = s->private; 1079*07252915SVincent Donnefort struct trace_event_fields *field; 1080*07252915SVincent Donnefort 1081*07252915SVincent Donnefort seq_printf(s, "name: %s\n", evt->name); 1082*07252915SVincent Donnefort seq_printf(s, "ID: %d\n", evt->id); 1083*07252915SVincent Donnefort seq_puts(s, 1084*07252915SVincent Donnefort "format:\n\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n\n"); 1085*07252915SVincent Donnefort 1086*07252915SVincent Donnefort field = &evt->fields[0]; 1087*07252915SVincent Donnefort while (field->name) { 1088*07252915SVincent Donnefort seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%u;\tsigned:%d;\n", 1089*07252915SVincent Donnefort field->type, field->name, offset, field->size, 1090*07252915SVincent Donnefort field->is_signed); 1091*07252915SVincent Donnefort offset += field->size; 1092*07252915SVincent Donnefort field++; 1093*07252915SVincent Donnefort } 1094*07252915SVincent Donnefort 1095*07252915SVincent Donnefort if (field != &evt->fields[0]) 1096*07252915SVincent Donnefort seq_puts(s, "\n"); 1097*07252915SVincent Donnefort 1098*07252915SVincent Donnefort seq_printf(s, "print fmt: %s\n", evt->print_fmt); 1099*07252915SVincent Donnefort 1100*07252915SVincent Donnefort return 0; 1101*07252915SVincent Donnefort } 1102*07252915SVincent Donnefort DEFINE_SHOW_ATTRIBUTE(remote_event_format); 1103*07252915SVincent Donnefort 1104*07252915SVincent Donnefort static int remote_event_callback(const char *name, umode_t *mode, void **data, 1105*07252915SVincent Donnefort const struct file_operations **fops) 1106*07252915SVincent Donnefort { 1107*07252915SVincent Donnefort if (!strcmp(name, "enable")) { 1108*07252915SVincent Donnefort *mode = TRACEFS_MODE_WRITE; 1109*07252915SVincent Donnefort *fops = &remote_event_enable_fops; 1110*07252915SVincent Donnefort return 1; 1111*07252915SVincent Donnefort } 1112*07252915SVincent Donnefort 1113*07252915SVincent Donnefort if (!strcmp(name, "id")) { 1114*07252915SVincent Donnefort *mode = TRACEFS_MODE_READ; 1115*07252915SVincent Donnefort *fops = &remote_event_id_fops; 1116*07252915SVincent Donnefort return 1; 1117*07252915SVincent Donnefort } 1118*07252915SVincent Donnefort 1119*07252915SVincent Donnefort if (!strcmp(name, "format")) { 1120*07252915SVincent Donnefort *mode = TRACEFS_MODE_READ; 1121*07252915SVincent Donnefort *fops = &remote_event_format_fops; 1122*07252915SVincent Donnefort return 1; 1123*07252915SVincent Donnefort } 1124*07252915SVincent Donnefort 1125*07252915SVincent Donnefort return 0; 1126*07252915SVincent Donnefort } 1127*07252915SVincent Donnefort 1128*07252915SVincent Donnefort static int trace_remote_init_eventfs(const char *remote_name, struct trace_remote *remote, 1129*07252915SVincent Donnefort struct remote_event *evt) 1130*07252915SVincent Donnefort { 1131*07252915SVincent Donnefort struct eventfs_inode *eventfs = remote->eventfs; 1132*07252915SVincent Donnefort static struct eventfs_entry entries[] = { 1133*07252915SVincent Donnefort { 1134*07252915SVincent Donnefort .name = "enable", 1135*07252915SVincent Donnefort .callback = remote_event_callback, 1136*07252915SVincent Donnefort }, { 1137*07252915SVincent Donnefort .name = "id", 1138*07252915SVincent Donnefort .callback = remote_event_callback, 1139*07252915SVincent Donnefort }, { 1140*07252915SVincent Donnefort .name = "format", 1141*07252915SVincent Donnefort .callback = remote_event_callback, 1142*07252915SVincent Donnefort } 1143*07252915SVincent Donnefort }; 1144*07252915SVincent Donnefort bool eventfs_create = false; 1145*07252915SVincent Donnefort 1146*07252915SVincent Donnefort if (!eventfs) { 1147*07252915SVincent Donnefort eventfs = eventfs_create_events_dir("events", remote->dentry, NULL, 0, NULL); 1148*07252915SVincent Donnefort if (IS_ERR(eventfs)) 1149*07252915SVincent Donnefort return PTR_ERR(eventfs); 1150*07252915SVincent Donnefort 1151*07252915SVincent Donnefort /* 1152*07252915SVincent Donnefort * Create similar hierarchy as local events even if a single system is supported at 1153*07252915SVincent Donnefort * the moment 1154*07252915SVincent Donnefort */ 1155*07252915SVincent Donnefort eventfs = eventfs_create_dir(remote_name, eventfs, NULL, 0, NULL); 1156*07252915SVincent Donnefort if (IS_ERR(eventfs)) 1157*07252915SVincent Donnefort return PTR_ERR(eventfs); 1158*07252915SVincent Donnefort 1159*07252915SVincent Donnefort remote->eventfs = eventfs; 1160*07252915SVincent Donnefort eventfs_create = true; 1161*07252915SVincent Donnefort } 1162*07252915SVincent Donnefort 1163*07252915SVincent Donnefort eventfs = eventfs_create_dir(evt->name, eventfs, entries, ARRAY_SIZE(entries), evt); 1164*07252915SVincent Donnefort if (IS_ERR(eventfs)) { 1165*07252915SVincent Donnefort if (eventfs_create) { 1166*07252915SVincent Donnefort eventfs_remove_events_dir(remote->eventfs); 1167*07252915SVincent Donnefort remote->eventfs = NULL; 1168*07252915SVincent Donnefort } 1169*07252915SVincent Donnefort return PTR_ERR(eventfs); 1170*07252915SVincent Donnefort } 1171*07252915SVincent Donnefort 1172*07252915SVincent Donnefort return 0; 1173*07252915SVincent Donnefort } 1174*07252915SVincent Donnefort 1175*07252915SVincent Donnefort static int trace_remote_attach_events(struct trace_remote *remote, struct remote_event *events, 1176*07252915SVincent Donnefort size_t nr_events) 1177*07252915SVincent Donnefort { 1178*07252915SVincent Donnefort int i; 1179*07252915SVincent Donnefort 1180*07252915SVincent Donnefort for (i = 0; i < nr_events; i++) { 1181*07252915SVincent Donnefort struct remote_event *evt = &events[i]; 1182*07252915SVincent Donnefort 1183*07252915SVincent Donnefort if (evt->remote) 1184*07252915SVincent Donnefort return -EEXIST; 1185*07252915SVincent Donnefort 1186*07252915SVincent Donnefort evt->remote = remote; 1187*07252915SVincent Donnefort 1188*07252915SVincent Donnefort /* We need events to be sorted for efficient lookup */ 1189*07252915SVincent Donnefort if (i && evt->id <= events[i - 1].id) 1190*07252915SVincent Donnefort return -EINVAL; 1191*07252915SVincent Donnefort } 1192*07252915SVincent Donnefort 1193*07252915SVincent Donnefort remote->events = events; 1194*07252915SVincent Donnefort remote->nr_events = nr_events; 1195*07252915SVincent Donnefort 1196*07252915SVincent Donnefort return 0; 1197*07252915SVincent Donnefort } 1198*07252915SVincent Donnefort 1199*07252915SVincent Donnefort static int trace_remote_register_events(const char *remote_name, struct trace_remote *remote, 1200*07252915SVincent Donnefort struct remote_event *events, size_t nr_events) 1201*07252915SVincent Donnefort { 1202*07252915SVincent Donnefort int i, ret; 1203*07252915SVincent Donnefort 1204*07252915SVincent Donnefort ret = trace_remote_attach_events(remote, events, nr_events); 1205*07252915SVincent Donnefort if (ret) 1206*07252915SVincent Donnefort return ret; 1207*07252915SVincent Donnefort 1208*07252915SVincent Donnefort for (i = 0; i < nr_events; i++) { 1209*07252915SVincent Donnefort struct remote_event *evt = &events[i]; 1210*07252915SVincent Donnefort 1211*07252915SVincent Donnefort ret = trace_remote_init_eventfs(remote_name, remote, evt); 1212*07252915SVincent Donnefort if (ret) 1213*07252915SVincent Donnefort pr_warn("Failed to init eventfs for event '%s' (%d)", 1214*07252915SVincent Donnefort evt->name, ret); 1215*07252915SVincent Donnefort } 1216*07252915SVincent Donnefort 1217*07252915SVincent Donnefort return 0; 1218*07252915SVincent Donnefort } 1219*07252915SVincent Donnefort 1220*07252915SVincent Donnefort static int __cmp_events(const void *key, const void *data) 1221*07252915SVincent Donnefort { 1222*07252915SVincent Donnefort const struct remote_event *evt = data; 1223*07252915SVincent Donnefort int id = (int)((long)key); 1224*07252915SVincent Donnefort 1225*07252915SVincent Donnefort return id - (int)evt->id; 1226*07252915SVincent Donnefort } 1227*07252915SVincent Donnefort 1228*07252915SVincent Donnefort static struct remote_event *trace_remote_find_event(struct trace_remote *remote, unsigned short id) 1229*07252915SVincent Donnefort { 1230*07252915SVincent Donnefort return bsearch((const void *)(unsigned long)id, remote->events, remote->nr_events, 1231*07252915SVincent Donnefort sizeof(*remote->events), __cmp_events); 1232*07252915SVincent Donnefort } 1233