Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1/**
  2 * arch/s390/oprofile/init.c
  3 *
  4 * S390 Version
  5 *   Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6 *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
  7 *   Author(s): Mahesh Salgaonkar (mahesh@linux.vnet.ibm.com)
  8 *   Author(s): Heinz Graalfs (graalfs@linux.vnet.ibm.com)
  9 *
 10 * @remark Copyright 2002-2011 OProfile authors
 11 */
 12
 13#include <linux/oprofile.h>
 14#include <linux/init.h>
 15#include <linux/errno.h>
 16#include <linux/fs.h>
 17
 18#include "../../../drivers/oprofile/oprof.h"
 19
 20extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth);
 21
 22#ifdef CONFIG_64BIT
 23
 24#include "hwsampler.h"
 25
 26#define DEFAULT_INTERVAL	4127518
 27
 28#define DEFAULT_SDBT_BLOCKS	1
 29#define DEFAULT_SDB_BLOCKS	511
 30
 31static unsigned long oprofile_hw_interval = DEFAULT_INTERVAL;
 32static unsigned long oprofile_min_interval;
 33static unsigned long oprofile_max_interval;
 34
 35static unsigned long oprofile_sdbt_blocks = DEFAULT_SDBT_BLOCKS;
 36static unsigned long oprofile_sdb_blocks = DEFAULT_SDB_BLOCKS;
 37
 38static int hwsampler_file;
 39static int hwsampler_running;	/* start_mutex must be held to change */
 40
 41static struct oprofile_operations timer_ops;
 42
 43static int oprofile_hwsampler_start(void)
 44{
 45	int retval;
 46
 47	hwsampler_running = hwsampler_file;
 48
 49	if (!hwsampler_running)
 50		return timer_ops.start();
 51
 52	retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks);
 53	if (retval)
 54		return retval;
 55
 56	retval = hwsampler_start_all(oprofile_hw_interval);
 57	if (retval)
 58		hwsampler_deallocate();
 59
 60	return retval;
 61}
 62
 63static void oprofile_hwsampler_stop(void)
 64{
 65	if (!hwsampler_running) {
 66		timer_ops.stop();
 67		return;
 68	}
 69
 70	hwsampler_stop_all();
 71	hwsampler_deallocate();
 72	return;
 73}
 74
 75static ssize_t hwsampler_read(struct file *file, char __user *buf,
 76		size_t count, loff_t *offset)
 77{
 78	return oprofilefs_ulong_to_user(hwsampler_file, buf, count, offset);
 79}
 80
 81static ssize_t hwsampler_write(struct file *file, char const __user *buf,
 82		size_t count, loff_t *offset)
 83{
 84	unsigned long val;
 85	int retval;
 86
 87	if (*offset)
 88		return -EINVAL;
 89
 90	retval = oprofilefs_ulong_from_user(&val, buf, count);
 91	if (retval)
 92		return retval;
 93
 94	if (oprofile_started)
 95		/*
 96		 * save to do without locking as we set
 97		 * hwsampler_running in start() when start_mutex is
 98		 * held
 99		 */
100		return -EBUSY;
101
102	hwsampler_file = val;
103
104	return count;
105}
106
107static const struct file_operations hwsampler_fops = {
108	.read		= hwsampler_read,
109	.write		= hwsampler_write,
110};
111
112static int oprofile_create_hwsampling_files(struct super_block *sb,
113						struct dentry *root)
114{
115	struct dentry *hw_dir;
116
117	/* reinitialize default values */
118	hwsampler_file = 1;
119
120	hw_dir = oprofilefs_mkdir(sb, root, "hwsampling");
121	if (!hw_dir)
122		return -EINVAL;
123
124	oprofilefs_create_file(sb, hw_dir, "hwsampler", &hwsampler_fops);
125	oprofilefs_create_ulong(sb, hw_dir, "hw_interval",
126				&oprofile_hw_interval);
127	oprofilefs_create_ro_ulong(sb, hw_dir, "hw_min_interval",
128				&oprofile_min_interval);
129	oprofilefs_create_ro_ulong(sb, hw_dir, "hw_max_interval",
130				&oprofile_max_interval);
131	oprofilefs_create_ulong(sb, hw_dir, "hw_sdbt_blocks",
132				&oprofile_sdbt_blocks);
133
134	return 0;
135}
136
137static int oprofile_hwsampler_init(struct oprofile_operations *ops)
138{
139	if (hwsampler_setup())
140		return -ENODEV;
141
142	/*
143	 * create hwsampler files only if hwsampler_setup() succeeds.
144	 */
145	oprofile_min_interval = hwsampler_query_min_interval();
146	if (oprofile_min_interval == 0)
147		return -ENODEV;
148	oprofile_max_interval = hwsampler_query_max_interval();
149	if (oprofile_max_interval == 0)
150		return -ENODEV;
151
152	/* The initial value should be sane */
153	if (oprofile_hw_interval < oprofile_min_interval)
154		oprofile_hw_interval = oprofile_min_interval;
155	if (oprofile_hw_interval > oprofile_max_interval)
156		oprofile_hw_interval = oprofile_max_interval;
157
158	if (oprofile_timer_init(ops))
159		return -ENODEV;
160
161	printk(KERN_INFO "oprofile: using hardware sampling\n");
162
163	memcpy(&timer_ops, ops, sizeof(timer_ops));
164
165	ops->start = oprofile_hwsampler_start;
166	ops->stop = oprofile_hwsampler_stop;
167	ops->create_files = oprofile_create_hwsampling_files;
168
169	return 0;
170}
171
172static void oprofile_hwsampler_exit(void)
173{
174	oprofile_timer_exit();
175	hwsampler_shutdown();
176}
177
178#endif /* CONFIG_64BIT */
179
180int __init oprofile_arch_init(struct oprofile_operations *ops)
181{
182	ops->backtrace = s390_backtrace;
183
184#ifdef CONFIG_64BIT
185	return oprofile_hwsampler_init(ops);
186#else
187	return -ENODEV;
188#endif
189}
190
191void oprofile_arch_exit(void)
192{
193#ifdef CONFIG_64BIT
194	oprofile_hwsampler_exit();
195#endif
196}