Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  1/*
  2 * Copyright 2011 Tilera Corporation. All Rights Reserved.
  3 *
  4 *   This program is free software; you can redistribute it and/or
  5 *   modify it under the terms of the GNU General Public License
  6 *   as published by the Free Software Foundation, version 2.
  7 *
  8 *   This program is distributed in the hope that it will be useful, but
  9 *   WITHOUT ANY WARRANTY; without even the implied warranty of
 10 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 11 *   NON INFRINGEMENT.  See the GNU General Public License for
 12 *   more details.
 13 *
 14 * /sys entry support.
 15 */
 16
 17#include <linux/sysdev.h>
 18#include <linux/cpu.h>
 19#include <linux/slab.h>
 20#include <linux/smp.h>
 21#include <hv/hypervisor.h>
 22
 23/* Return a string queried from the hypervisor, truncated to page size. */
 24static ssize_t get_hv_confstr(char *page, int query)
 25{
 26	ssize_t n = hv_confstr(query, (unsigned long)page, PAGE_SIZE - 1);
 27	n = n < 0 ? 0 : min(n, (ssize_t)PAGE_SIZE - 1) - 1;
 28	if (n)
 29		page[n++] = '\n';
 30	page[n] = '\0';
 31	return n;
 32}
 33
 34static ssize_t chip_width_show(struct sysdev_class *dev,
 35			       struct sysdev_class_attribute *attr,
 36			       char *page)
 37{
 38	return sprintf(page, "%u\n", smp_width);
 39}
 40static SYSDEV_CLASS_ATTR(chip_width, 0444, chip_width_show, NULL);
 41
 42static ssize_t chip_height_show(struct sysdev_class *dev,
 43				struct sysdev_class_attribute *attr,
 44				char *page)
 45{
 46	return sprintf(page, "%u\n", smp_height);
 47}
 48static SYSDEV_CLASS_ATTR(chip_height, 0444, chip_height_show, NULL);
 49
 50static ssize_t chip_serial_show(struct sysdev_class *dev,
 51				struct sysdev_class_attribute *attr,
 52				char *page)
 53{
 54	return get_hv_confstr(page, HV_CONFSTR_CHIP_SERIAL_NUM);
 55}
 56static SYSDEV_CLASS_ATTR(chip_serial, 0444, chip_serial_show, NULL);
 57
 58static ssize_t chip_revision_show(struct sysdev_class *dev,
 59				  struct sysdev_class_attribute *attr,
 60				  char *page)
 61{
 62	return get_hv_confstr(page, HV_CONFSTR_CHIP_REV);
 63}
 64static SYSDEV_CLASS_ATTR(chip_revision, 0444, chip_revision_show, NULL);
 65
 66
 67static ssize_t type_show(struct sysdev_class *dev,
 68			    struct sysdev_class_attribute *attr,
 69			    char *page)
 70{
 71	return sprintf(page, "tilera\n");
 72}
 73static SYSDEV_CLASS_ATTR(type, 0444, type_show, NULL);
 74
 75#define HV_CONF_ATTR(name, conf)					\
 76	static ssize_t name ## _show(struct sysdev_class *dev,		\
 77				     struct sysdev_class_attribute *attr, \
 78				     char *page)			\
 79	{								\
 80		return get_hv_confstr(page, conf);			\
 81	}								\
 82	static SYSDEV_CLASS_ATTR(name, 0444, name ## _show, NULL);
 83
 84HV_CONF_ATTR(version,		HV_CONFSTR_HV_SW_VER)
 85HV_CONF_ATTR(config_version,	HV_CONFSTR_HV_CONFIG_VER)
 86
 87HV_CONF_ATTR(board_part,	HV_CONFSTR_BOARD_PART_NUM)
 88HV_CONF_ATTR(board_serial,	HV_CONFSTR_BOARD_SERIAL_NUM)
 89HV_CONF_ATTR(board_revision,	HV_CONFSTR_BOARD_REV)
 90HV_CONF_ATTR(board_description,	HV_CONFSTR_BOARD_DESC)
 91HV_CONF_ATTR(mezz_part,		HV_CONFSTR_MEZZ_PART_NUM)
 92HV_CONF_ATTR(mezz_serial,	HV_CONFSTR_MEZZ_SERIAL_NUM)
 93HV_CONF_ATTR(mezz_revision,	HV_CONFSTR_MEZZ_REV)
 94HV_CONF_ATTR(mezz_description,	HV_CONFSTR_MEZZ_DESC)
 95HV_CONF_ATTR(switch_control,	HV_CONFSTR_SWITCH_CONTROL)
 96
 97static struct attribute *board_attrs[] = {
 98	&attr_board_part.attr,
 99	&attr_board_serial.attr,
100	&attr_board_revision.attr,
101	&attr_board_description.attr,
102	&attr_mezz_part.attr,
103	&attr_mezz_serial.attr,
104	&attr_mezz_revision.attr,
105	&attr_mezz_description.attr,
106	&attr_switch_control.attr,
107	NULL
108};
109
110static struct attribute_group board_attr_group = {
111	.name   = "board",
112	.attrs  = board_attrs,
113};
114
115
116static struct bin_attribute hvconfig_bin;
117
118static ssize_t
119hvconfig_bin_read(struct file *filp, struct kobject *kobj,
120		  struct bin_attribute *bin_attr,
121		  char *buf, loff_t off, size_t count)
122{
123	static size_t size;
124
125	/* Lazily learn the true size (minus the trailing NUL). */
126	if (size == 0)
127		size = hv_confstr(HV_CONFSTR_HV_CONFIG, 0, 0) - 1;
128
129	/* Check and adjust input parameters. */
130	if (off > size)
131		return -EINVAL;
132	if (count > size - off)
133		count = size - off;
134
135	if (count) {
136		/* Get a copy of the hvc and copy out the relevant portion. */
137		char *hvc;
138
139		size = off + count;
140		hvc = kmalloc(size, GFP_KERNEL);
141		if (hvc == NULL)
142			return -ENOMEM;
143		hv_confstr(HV_CONFSTR_HV_CONFIG, (unsigned long)hvc, size);
144		memcpy(buf, hvc + off, count);
145		kfree(hvc);
146	}
147
148	return count;
149}
150
151static int __init create_sysfs_entries(void)
152{
153	struct sysdev_class *cls = &cpu_sysdev_class;
154	int err = 0;
155
156#define create_cpu_attr(name)						\
157	if (!err)							\
158		err = sysfs_create_file(&cls->kset.kobj, &attr_##name.attr);
159	create_cpu_attr(chip_width);
160	create_cpu_attr(chip_height);
161	create_cpu_attr(chip_serial);
162	create_cpu_attr(chip_revision);
163
164#define create_hv_attr(name)						\
165	if (!err)							\
166		err = sysfs_create_file(hypervisor_kobj, &attr_##name.attr);
167	create_hv_attr(type);
168	create_hv_attr(version);
169	create_hv_attr(config_version);
170
171	if (!err)
172		err = sysfs_create_group(hypervisor_kobj, &board_attr_group);
173
174	if (!err) {
175		sysfs_bin_attr_init(&hvconfig_bin);
176		hvconfig_bin.attr.name = "hvconfig";
177		hvconfig_bin.attr.mode = S_IRUGO;
178		hvconfig_bin.read = hvconfig_bin_read;
179		hvconfig_bin.size = PAGE_SIZE;
180		err = sysfs_create_bin_file(hypervisor_kobj, &hvconfig_bin);
181	}
182
183	return err;
184}
185subsys_initcall(create_sysfs_entries);