xref: /linux/drivers/misc/genwqe/card_sysfs.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
1eb3ae0aaSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2*ac36fdb1SLee Jones /*
3b2a65138SFrank Haverkamp  * IBM Accelerator Family 'GenWQE'
4b2a65138SFrank Haverkamp  *
5b2a65138SFrank Haverkamp  * (C) Copyright IBM Corp. 2013
6b2a65138SFrank Haverkamp  *
7b2a65138SFrank Haverkamp  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
8b2a65138SFrank Haverkamp  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
926d8f6f1SFrank Haverkamp  * Author: Michael Jung <mijung@gmx.net>
10b2a65138SFrank Haverkamp  * Author: Michael Ruettger <michael@ibmra.de>
11b2a65138SFrank Haverkamp  */
12b2a65138SFrank Haverkamp 
13b2a65138SFrank Haverkamp /*
14b2a65138SFrank Haverkamp  * Sysfs interfaces for the GenWQE card. There are attributes to query
15b2a65138SFrank Haverkamp  * the version of the bitstream as well as some for the driver. For
16b2a65138SFrank Haverkamp  * debugging, please also see the debugfs interfaces of this driver.
17b2a65138SFrank Haverkamp  */
18b2a65138SFrank Haverkamp 
19b2a65138SFrank Haverkamp #include <linux/kernel.h>
20b2a65138SFrank Haverkamp #include <linux/types.h>
21b2a65138SFrank Haverkamp #include <linux/module.h>
22b2a65138SFrank Haverkamp #include <linux/pci.h>
23b2a65138SFrank Haverkamp #include <linux/string.h>
24b2a65138SFrank Haverkamp #include <linux/fs.h>
25b2a65138SFrank Haverkamp #include <linux/sysfs.h>
26b2a65138SFrank Haverkamp #include <linux/ctype.h>
27b2a65138SFrank Haverkamp #include <linux/device.h>
28b2a65138SFrank Haverkamp 
29b2a65138SFrank Haverkamp #include "card_base.h"
30b2a65138SFrank Haverkamp #include "card_ddcb.h"
31b2a65138SFrank Haverkamp 
32b2a65138SFrank Haverkamp static const char * const genwqe_types[] = {
33b2a65138SFrank Haverkamp 	[GENWQE_TYPE_ALTERA_230] = "GenWQE4-230",
34b2a65138SFrank Haverkamp 	[GENWQE_TYPE_ALTERA_530] = "GenWQE4-530",
35b2a65138SFrank Haverkamp 	[GENWQE_TYPE_ALTERA_A4]  = "GenWQE5-A4",
36b2a65138SFrank Haverkamp 	[GENWQE_TYPE_ALTERA_A7]  = "GenWQE5-A7",
37b2a65138SFrank Haverkamp };
38b2a65138SFrank Haverkamp 
status_show(struct device * dev,struct device_attribute * attr,char * buf)39b2a65138SFrank Haverkamp static ssize_t status_show(struct device *dev, struct device_attribute *attr,
40b2a65138SFrank Haverkamp 			   char *buf)
41b2a65138SFrank Haverkamp {
42b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
43b2a65138SFrank Haverkamp 	const char *cs[GENWQE_CARD_STATE_MAX] = { "unused", "used", "error" };
44b2a65138SFrank Haverkamp 
45b2a65138SFrank Haverkamp 	return sprintf(buf, "%s\n", cs[cd->card_state]);
46b2a65138SFrank Haverkamp }
47b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(status);
48b2a65138SFrank Haverkamp 
appid_show(struct device * dev,struct device_attribute * attr,char * buf)49b2a65138SFrank Haverkamp static ssize_t appid_show(struct device *dev, struct device_attribute *attr,
50b2a65138SFrank Haverkamp 			  char *buf)
51b2a65138SFrank Haverkamp {
52b2a65138SFrank Haverkamp 	char app_name[5];
53b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
54b2a65138SFrank Haverkamp 
55b2a65138SFrank Haverkamp 	genwqe_read_app_id(cd, app_name, sizeof(app_name));
56b2a65138SFrank Haverkamp 	return sprintf(buf, "%s\n", app_name);
57b2a65138SFrank Haverkamp }
58b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(appid);
59b2a65138SFrank Haverkamp 
version_show(struct device * dev,struct device_attribute * attr,char * buf)60b2a65138SFrank Haverkamp static ssize_t version_show(struct device *dev, struct device_attribute *attr,
61b2a65138SFrank Haverkamp 			    char *buf)
62b2a65138SFrank Haverkamp {
63b2a65138SFrank Haverkamp 	u64 slu_id, app_id;
64b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
65b2a65138SFrank Haverkamp 
66b2a65138SFrank Haverkamp 	slu_id = __genwqe_readq(cd, IO_SLU_UNITCFG);
67b2a65138SFrank Haverkamp 	app_id = __genwqe_readq(cd, IO_APP_UNITCFG);
68b2a65138SFrank Haverkamp 
69b2a65138SFrank Haverkamp 	return sprintf(buf, "%016llx.%016llx\n", slu_id, app_id);
70b2a65138SFrank Haverkamp }
71b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(version);
72b2a65138SFrank Haverkamp 
type_show(struct device * dev,struct device_attribute * attr,char * buf)73b2a65138SFrank Haverkamp static ssize_t type_show(struct device *dev, struct device_attribute *attr,
74b2a65138SFrank Haverkamp 			 char *buf)
75b2a65138SFrank Haverkamp {
76b2a65138SFrank Haverkamp 	u8 card_type;
77b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
78b2a65138SFrank Haverkamp 
79b2a65138SFrank Haverkamp 	card_type = genwqe_card_type(cd);
80b2a65138SFrank Haverkamp 	return sprintf(buf, "%s\n", (card_type >= ARRAY_SIZE(genwqe_types)) ?
81b2a65138SFrank Haverkamp 		       "invalid" : genwqe_types[card_type]);
82b2a65138SFrank Haverkamp }
83b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(type);
84b2a65138SFrank Haverkamp 
tempsens_show(struct device * dev,struct device_attribute * attr,char * buf)85b2a65138SFrank Haverkamp static ssize_t tempsens_show(struct device *dev, struct device_attribute *attr,
86b2a65138SFrank Haverkamp 			     char *buf)
87b2a65138SFrank Haverkamp {
88b2a65138SFrank Haverkamp 	u64 tempsens;
89b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
90b2a65138SFrank Haverkamp 
91b2a65138SFrank Haverkamp 	tempsens = __genwqe_readq(cd, IO_SLU_TEMPERATURE_SENSOR);
92b2a65138SFrank Haverkamp 	return sprintf(buf, "%016llx\n", tempsens);
93b2a65138SFrank Haverkamp }
94b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(tempsens);
95b2a65138SFrank Haverkamp 
freerunning_timer_show(struct device * dev,struct device_attribute * attr,char * buf)96b2a65138SFrank Haverkamp static ssize_t freerunning_timer_show(struct device *dev,
97b2a65138SFrank Haverkamp 				      struct device_attribute *attr,
98b2a65138SFrank Haverkamp 				      char *buf)
99b2a65138SFrank Haverkamp {
100b2a65138SFrank Haverkamp 	u64 t;
101b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
102b2a65138SFrank Haverkamp 
103b2a65138SFrank Haverkamp 	t = __genwqe_readq(cd, IO_SLC_FREE_RUNNING_TIMER);
104b2a65138SFrank Haverkamp 	return sprintf(buf, "%016llx\n", t);
105b2a65138SFrank Haverkamp }
106b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(freerunning_timer);
107b2a65138SFrank Haverkamp 
queue_working_time_show(struct device * dev,struct device_attribute * attr,char * buf)108b2a65138SFrank Haverkamp static ssize_t queue_working_time_show(struct device *dev,
109b2a65138SFrank Haverkamp 				       struct device_attribute *attr,
110b2a65138SFrank Haverkamp 				       char *buf)
111b2a65138SFrank Haverkamp {
112b2a65138SFrank Haverkamp 	u64 t;
113b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
114b2a65138SFrank Haverkamp 
115b2a65138SFrank Haverkamp 	t = __genwqe_readq(cd, IO_SLC_QUEUE_WTIME);
116b2a65138SFrank Haverkamp 	return sprintf(buf, "%016llx\n", t);
117b2a65138SFrank Haverkamp }
118b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(queue_working_time);
119b2a65138SFrank Haverkamp 
base_clock_show(struct device * dev,struct device_attribute * attr,char * buf)120b2a65138SFrank Haverkamp static ssize_t base_clock_show(struct device *dev,
121b2a65138SFrank Haverkamp 			       struct device_attribute *attr,
122b2a65138SFrank Haverkamp 			       char *buf)
123b2a65138SFrank Haverkamp {
124b2a65138SFrank Haverkamp 	u64 base_clock;
125b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
126b2a65138SFrank Haverkamp 
127b2a65138SFrank Haverkamp 	base_clock = genwqe_base_clock_frequency(cd);
128b2a65138SFrank Haverkamp 	return sprintf(buf, "%lld\n", base_clock);
129b2a65138SFrank Haverkamp }
130b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(base_clock);
131b2a65138SFrank Haverkamp 
132*ac36fdb1SLee Jones /*
133b2a65138SFrank Haverkamp  * curr_bitstream_show() - Show the current bitstream id
134b2a65138SFrank Haverkamp  *
135b2a65138SFrank Haverkamp  * There is a bug in some old versions of the CPLD which selects the
136b2a65138SFrank Haverkamp  * bitstream, which causes the IO_SLU_BITSTREAM register to report
137b2a65138SFrank Haverkamp  * unreliable data in very rare cases. This makes this sysfs
138b2a65138SFrank Haverkamp  * unreliable up to the point were a new CPLD version is being used.
139b2a65138SFrank Haverkamp  *
140b2a65138SFrank Haverkamp  * Unfortunately there is no automatic way yet to query the CPLD
141b2a65138SFrank Haverkamp  * version, such that you need to manually ensure via programming
142b2a65138SFrank Haverkamp  * tools that you have a recent version of the CPLD software.
143b2a65138SFrank Haverkamp  *
144b2a65138SFrank Haverkamp  * The proposed circumvention is to use a special recovery bitstream
145b2a65138SFrank Haverkamp  * on the backup partition (0) to identify problems while loading the
146b2a65138SFrank Haverkamp  * image.
147b2a65138SFrank Haverkamp  */
curr_bitstream_show(struct device * dev,struct device_attribute * attr,char * buf)148b2a65138SFrank Haverkamp static ssize_t curr_bitstream_show(struct device *dev,
149b2a65138SFrank Haverkamp 				   struct device_attribute *attr, char *buf)
150b2a65138SFrank Haverkamp {
151b2a65138SFrank Haverkamp 	int curr_bitstream;
152b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
153b2a65138SFrank Haverkamp 
154b2a65138SFrank Haverkamp 	curr_bitstream = __genwqe_readq(cd, IO_SLU_BITSTREAM) & 0x1;
155b2a65138SFrank Haverkamp 	return sprintf(buf, "%d\n", curr_bitstream);
156b2a65138SFrank Haverkamp }
157b2a65138SFrank Haverkamp static DEVICE_ATTR_RO(curr_bitstream);
158b2a65138SFrank Haverkamp 
159*ac36fdb1SLee Jones /*
160b2a65138SFrank Haverkamp  * next_bitstream_show() - Show the next activated bitstream
161b2a65138SFrank Haverkamp  *
162b2a65138SFrank Haverkamp  * IO_SLC_CFGREG_SOFTRESET: This register can only be accessed by the PF.
163b2a65138SFrank Haverkamp  */
next_bitstream_show(struct device * dev,struct device_attribute * attr,char * buf)164b2a65138SFrank Haverkamp static ssize_t next_bitstream_show(struct device *dev,
165b2a65138SFrank Haverkamp 				   struct device_attribute *attr, char *buf)
166b2a65138SFrank Haverkamp {
167b2a65138SFrank Haverkamp 	int next_bitstream;
168b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
169b2a65138SFrank Haverkamp 
170b2a65138SFrank Haverkamp 	switch ((cd->softreset & 0xc) >> 2) {
171b2a65138SFrank Haverkamp 	case 0x2:
172b2a65138SFrank Haverkamp 		next_bitstream =  0;
173b2a65138SFrank Haverkamp 		break;
174b2a65138SFrank Haverkamp 	case 0x3:
175b2a65138SFrank Haverkamp 		next_bitstream =  1;
176b2a65138SFrank Haverkamp 		break;
177b2a65138SFrank Haverkamp 	default:
178b2a65138SFrank Haverkamp 		next_bitstream = -1;
179b2a65138SFrank Haverkamp 		break;		/* error */
180b2a65138SFrank Haverkamp 	}
181b2a65138SFrank Haverkamp 	return sprintf(buf, "%d\n", next_bitstream);
182b2a65138SFrank Haverkamp }
183b2a65138SFrank Haverkamp 
next_bitstream_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)184b2a65138SFrank Haverkamp static ssize_t next_bitstream_store(struct device *dev,
185b2a65138SFrank Haverkamp 				    struct device_attribute *attr,
186b2a65138SFrank Haverkamp 				    const char *buf, size_t count)
187b2a65138SFrank Haverkamp {
188b2a65138SFrank Haverkamp 	int partition;
189b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
190b2a65138SFrank Haverkamp 
191b2a65138SFrank Haverkamp 	if (kstrtoint(buf, 0, &partition) < 0)
192b2a65138SFrank Haverkamp 		return -EINVAL;
193b2a65138SFrank Haverkamp 
194b2a65138SFrank Haverkamp 	switch (partition) {
195b2a65138SFrank Haverkamp 	case 0x0:
196b2a65138SFrank Haverkamp 		cd->softreset = 0x78;
197b2a65138SFrank Haverkamp 		break;
198b2a65138SFrank Haverkamp 	case 0x1:
199b2a65138SFrank Haverkamp 		cd->softreset = 0x7c;
200b2a65138SFrank Haverkamp 		break;
201b2a65138SFrank Haverkamp 	default:
202b2a65138SFrank Haverkamp 		return -EINVAL;
203b2a65138SFrank Haverkamp 	}
204b2a65138SFrank Haverkamp 
205b2a65138SFrank Haverkamp 	__genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET, cd->softreset);
206b2a65138SFrank Haverkamp 	return count;
207b2a65138SFrank Haverkamp }
208b2a65138SFrank Haverkamp static DEVICE_ATTR_RW(next_bitstream);
209b2a65138SFrank Haverkamp 
reload_bitstream_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)210c1f732adSKleber Sacilotto de Souza static ssize_t reload_bitstream_store(struct device *dev,
211c1f732adSKleber Sacilotto de Souza 				struct device_attribute *attr,
212c1f732adSKleber Sacilotto de Souza 				const char *buf, size_t count)
213c1f732adSKleber Sacilotto de Souza {
214c1f732adSKleber Sacilotto de Souza 	int reload;
215c1f732adSKleber Sacilotto de Souza 	struct genwqe_dev *cd = dev_get_drvdata(dev);
216c1f732adSKleber Sacilotto de Souza 
217c1f732adSKleber Sacilotto de Souza 	if (kstrtoint(buf, 0, &reload) < 0)
218c1f732adSKleber Sacilotto de Souza 		return -EINVAL;
219c1f732adSKleber Sacilotto de Souza 
220c1f732adSKleber Sacilotto de Souza 	if (reload == 0x1) {
221c1f732adSKleber Sacilotto de Souza 		if (cd->card_state == GENWQE_CARD_UNUSED ||
222c1f732adSKleber Sacilotto de Souza 		    cd->card_state == GENWQE_CARD_USED)
223c1f732adSKleber Sacilotto de Souza 			cd->card_state = GENWQE_CARD_RELOAD_BITSTREAM;
224c1f732adSKleber Sacilotto de Souza 		else
225c1f732adSKleber Sacilotto de Souza 			return -EIO;
226c1f732adSKleber Sacilotto de Souza 	} else {
227c1f732adSKleber Sacilotto de Souza 		return -EINVAL;
228c1f732adSKleber Sacilotto de Souza 	}
229c1f732adSKleber Sacilotto de Souza 
230c1f732adSKleber Sacilotto de Souza 	return count;
231c1f732adSKleber Sacilotto de Souza }
232c1f732adSKleber Sacilotto de Souza static DEVICE_ATTR_WO(reload_bitstream);
233c1f732adSKleber Sacilotto de Souza 
234b2a65138SFrank Haverkamp /*
235b2a65138SFrank Haverkamp  * Create device_attribute structures / params: name, mode, show, store
236b2a65138SFrank Haverkamp  * additional flag if valid in VF
237b2a65138SFrank Haverkamp  */
238b2a65138SFrank Haverkamp static struct attribute *genwqe_attributes[] = {
239b2a65138SFrank Haverkamp 	&dev_attr_tempsens.attr,
240b2a65138SFrank Haverkamp 	&dev_attr_next_bitstream.attr,
241b2a65138SFrank Haverkamp 	&dev_attr_curr_bitstream.attr,
242b2a65138SFrank Haverkamp 	&dev_attr_base_clock.attr,
243b2a65138SFrank Haverkamp 	&dev_attr_type.attr,
244b2a65138SFrank Haverkamp 	&dev_attr_version.attr,
245b2a65138SFrank Haverkamp 	&dev_attr_appid.attr,
246b2a65138SFrank Haverkamp 	&dev_attr_status.attr,
247b2a65138SFrank Haverkamp 	&dev_attr_freerunning_timer.attr,
248b2a65138SFrank Haverkamp 	&dev_attr_queue_working_time.attr,
249c1f732adSKleber Sacilotto de Souza 	&dev_attr_reload_bitstream.attr,
250b2a65138SFrank Haverkamp 	NULL,
251b2a65138SFrank Haverkamp };
252b2a65138SFrank Haverkamp 
253b2a65138SFrank Haverkamp static struct attribute *genwqe_normal_attributes[] = {
254b2a65138SFrank Haverkamp 	&dev_attr_type.attr,
255b2a65138SFrank Haverkamp 	&dev_attr_version.attr,
256b2a65138SFrank Haverkamp 	&dev_attr_appid.attr,
257b2a65138SFrank Haverkamp 	&dev_attr_status.attr,
258b2a65138SFrank Haverkamp 	&dev_attr_freerunning_timer.attr,
259b2a65138SFrank Haverkamp 	&dev_attr_queue_working_time.attr,
260b2a65138SFrank Haverkamp 	NULL,
261b2a65138SFrank Haverkamp };
262b2a65138SFrank Haverkamp 
263*ac36fdb1SLee Jones /*
264b2a65138SFrank Haverkamp  * genwqe_is_visible() - Determine if sysfs attribute should be visible or not
265b2a65138SFrank Haverkamp  *
266b2a65138SFrank Haverkamp  * VFs have restricted mmio capabilities, so not all sysfs entries
267b2a65138SFrank Haverkamp  * are allowed in VFs.
268b2a65138SFrank Haverkamp  */
genwqe_is_visible(struct kobject * kobj,struct attribute * attr,int n)269b2a65138SFrank Haverkamp static umode_t genwqe_is_visible(struct kobject *kobj,
270b2a65138SFrank Haverkamp 				 struct attribute *attr, int n)
271b2a65138SFrank Haverkamp {
272b2a65138SFrank Haverkamp 	unsigned int j;
2736908b45eSGeliang Tang 	struct device *dev = kobj_to_dev(kobj);
274b2a65138SFrank Haverkamp 	struct genwqe_dev *cd = dev_get_drvdata(dev);
275b2a65138SFrank Haverkamp 	umode_t mode = attr->mode;
276b2a65138SFrank Haverkamp 
277b2a65138SFrank Haverkamp 	if (genwqe_is_privileged(cd))
278b2a65138SFrank Haverkamp 		return mode;
279b2a65138SFrank Haverkamp 
280b2a65138SFrank Haverkamp 	for (j = 0; genwqe_normal_attributes[j] != NULL;  j++)
281b2a65138SFrank Haverkamp 		if (genwqe_normal_attributes[j] == attr)
282b2a65138SFrank Haverkamp 			return mode;
283b2a65138SFrank Haverkamp 
284b2a65138SFrank Haverkamp 	return 0;
285b2a65138SFrank Haverkamp }
286b2a65138SFrank Haverkamp 
287b2a65138SFrank Haverkamp static struct attribute_group genwqe_attribute_group = {
288b2a65138SFrank Haverkamp 	.is_visible = genwqe_is_visible,
289b2a65138SFrank Haverkamp 	.attrs      = genwqe_attributes,
290b2a65138SFrank Haverkamp };
291b2a65138SFrank Haverkamp 
292b2a65138SFrank Haverkamp const struct attribute_group *genwqe_attribute_groups[] = {
293b2a65138SFrank Haverkamp 	&genwqe_attribute_group,
294b2a65138SFrank Haverkamp 	NULL,
295b2a65138SFrank Haverkamp };
296