Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/tile/kernel/sysfs.c
10817 views
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. */
24
static 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
34
static 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
}
40
static SYSDEV_CLASS_ATTR(chip_width, 0444, chip_width_show, NULL);
41
42
static 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
}
48
static SYSDEV_CLASS_ATTR(chip_height, 0444, chip_height_show, NULL);
49
50
static 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
}
56
static SYSDEV_CLASS_ATTR(chip_serial, 0444, chip_serial_show, NULL);
57
58
static 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
}
64
static SYSDEV_CLASS_ATTR(chip_revision, 0444, chip_revision_show, NULL);
65
66
67
static 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
}
73
static 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
84
HV_CONF_ATTR(version, HV_CONFSTR_HV_SW_VER)
85
HV_CONF_ATTR(config_version, HV_CONFSTR_HV_CONFIG_VER)
86
87
HV_CONF_ATTR(board_part, HV_CONFSTR_BOARD_PART_NUM)
88
HV_CONF_ATTR(board_serial, HV_CONFSTR_BOARD_SERIAL_NUM)
89
HV_CONF_ATTR(board_revision, HV_CONFSTR_BOARD_REV)
90
HV_CONF_ATTR(board_description, HV_CONFSTR_BOARD_DESC)
91
HV_CONF_ATTR(mezz_part, HV_CONFSTR_MEZZ_PART_NUM)
92
HV_CONF_ATTR(mezz_serial, HV_CONFSTR_MEZZ_SERIAL_NUM)
93
HV_CONF_ATTR(mezz_revision, HV_CONFSTR_MEZZ_REV)
94
HV_CONF_ATTR(mezz_description, HV_CONFSTR_MEZZ_DESC)
95
HV_CONF_ATTR(switch_control, HV_CONFSTR_SWITCH_CONTROL)
96
97
static 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
110
static struct attribute_group board_attr_group = {
111
.name = "board",
112
.attrs = board_attrs,
113
};
114
115
116
static struct bin_attribute hvconfig_bin;
117
118
static ssize_t
119
hvconfig_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
151
static 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
}
185
subsys_initcall(create_sysfs_entries);
186
187