cpu: convert 'cpu' and 'machinecheck' sysdev_class to a regular subsystem
[deliverable/linux.git] / arch / tile / kernel / sysfs.c
CommitLineData
f133ecca
CM
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
8a25a2fd 17#include <linux/device.h>
f133ecca
CM
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
8a25a2fd
KS
34static ssize_t chip_width_show(struct device *dev,
35 struct device_attribute *attr,
f133ecca
CM
36 char *page)
37{
38 return sprintf(page, "%u\n", smp_width);
39}
8a25a2fd 40static DEVICE_ATTR(chip_width, 0444, chip_width_show, NULL);
f133ecca 41
8a25a2fd
KS
42static ssize_t chip_height_show(struct device *dev,
43 struct device_attribute *attr,
f133ecca
CM
44 char *page)
45{
46 return sprintf(page, "%u\n", smp_height);
47}
8a25a2fd 48static DEVICE_ATTR(chip_height, 0444, chip_height_show, NULL);
f133ecca 49
8a25a2fd
KS
50static ssize_t chip_serial_show(struct device *dev,
51 struct device_attribute *attr,
f133ecca
CM
52 char *page)
53{
54 return get_hv_confstr(page, HV_CONFSTR_CHIP_SERIAL_NUM);
55}
8a25a2fd 56static DEVICE_ATTR(chip_serial, 0444, chip_serial_show, NULL);
f133ecca 57
8a25a2fd
KS
58static ssize_t chip_revision_show(struct device *dev,
59 struct device_attribute *attr,
f133ecca
CM
60 char *page)
61{
62 return get_hv_confstr(page, HV_CONFSTR_CHIP_REV);
63}
8a25a2fd 64static DEVICE_ATTR(chip_revision, 0444, chip_revision_show, NULL);
f133ecca
CM
65
66
8a25a2fd
KS
67static ssize_t type_show(struct device *dev,
68 struct device_attribute *attr,
f133ecca
CM
69 char *page)
70{
71 return sprintf(page, "tilera\n");
72}
8a25a2fd 73static DEVICE_ATTR(type, 0444, type_show, NULL);
f133ecca
CM
74
75#define HV_CONF_ATTR(name, conf) \
8a25a2fd
KS
76 static ssize_t name ## _show(struct device *dev, \
77 struct device_attribute *attr, \
f133ecca
CM
78 char *page) \
79 { \
80 return get_hv_confstr(page, conf); \
81 } \
8a25a2fd 82 static DEVICE_ATTR(name, 0444, name ## _show, NULL);
f133ecca
CM
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[] = {
8a25a2fd
KS
98 &dev_attr_board_part.attr,
99 &dev_attr_board_serial.attr,
100 &dev_attr_board_revision.attr,
101 &dev_attr_board_description.attr,
102 &dev_attr_mezz_part.attr,
103 &dev_attr_mezz_serial.attr,
104 &dev_attr_mezz_revision.attr,
105 &dev_attr_mezz_description.attr,
106 &dev_attr_switch_control.attr,
f133ecca
CM
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{
f133ecca
CM
153 int err = 0;
154
155#define create_cpu_attr(name) \
156 if (!err) \
8a25a2fd 157 err = device_create_file(cpu_subsys.dev_root, &dev_attr_##name);
f133ecca
CM
158 create_cpu_attr(chip_width);
159 create_cpu_attr(chip_height);
160 create_cpu_attr(chip_serial);
161 create_cpu_attr(chip_revision);
162
163#define create_hv_attr(name) \
164 if (!err) \
8a25a2fd 165 err = sysfs_create_file(hypervisor_kobj, &dev_attr_##name);
f133ecca
CM
166 create_hv_attr(type);
167 create_hv_attr(version);
168 create_hv_attr(config_version);
169
170 if (!err)
171 err = sysfs_create_group(hypervisor_kobj, &board_attr_group);
172
173 if (!err) {
174 sysfs_bin_attr_init(&hvconfig_bin);
175 hvconfig_bin.attr.name = "hvconfig";
176 hvconfig_bin.attr.mode = S_IRUGO;
177 hvconfig_bin.read = hvconfig_bin_read;
178 hvconfig_bin.size = PAGE_SIZE;
179 err = sysfs_create_bin_file(hypervisor_kobj, &hvconfig_bin);
180 }
181
182 return err;
183}
184subsys_initcall(create_sysfs_entries);
This page took 0.054314 seconds and 5 git commands to generate.