Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Driver for FPGA Management Engine Error Management
  4 *
  5 * Copyright 2019 Intel Corporation, Inc.
  6 *
  7 * Authors:
  8 *   Kang Luwei <luwei.kang@intel.com>
  9 *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
 10 *   Wu Hao <hao.wu@intel.com>
 11 *   Joseph Grecco <joe.grecco@intel.com>
 12 *   Enno Luebbers <enno.luebbers@intel.com>
 13 *   Tim Whisonant <tim.whisonant@intel.com>
 14 *   Ananda Ravuri <ananda.ravuri@intel.com>
 15 *   Mitchel, Henry <henry.mitchel@intel.com>
 16 */
 17
 18#include <linux/fpga-dfl.h>
 19#include <linux/uaccess.h>
 20
 21#include "dfl.h"
 22#include "dfl-fme.h"
 23
 24#define FME_ERROR_MASK		0x8
 25#define FME_ERROR		0x10
 26#define MBP_ERROR		BIT_ULL(6)
 27#define PCIE0_ERROR_MASK	0x18
 28#define PCIE0_ERROR		0x20
 29#define PCIE1_ERROR_MASK	0x28
 30#define PCIE1_ERROR		0x30
 31#define FME_FIRST_ERROR		0x38
 32#define FME_NEXT_ERROR		0x40
 33#define RAS_NONFAT_ERROR_MASK	0x48
 34#define RAS_NONFAT_ERROR	0x50
 35#define RAS_CATFAT_ERROR_MASK	0x58
 36#define RAS_CATFAT_ERROR	0x60
 37#define RAS_ERROR_INJECT	0x68
 38#define INJECT_ERROR_MASK	GENMASK_ULL(2, 0)
 39
 40#define ERROR_MASK		GENMASK_ULL(63, 0)
 41
 42static ssize_t pcie0_errors_show(struct device *dev,
 43				 struct device_attribute *attr, char *buf)
 44{
 45	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
 46	void __iomem *base;
 47	u64 value;
 48
 49	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
 50
 51	mutex_lock(&pdata->lock);
 52	value = readq(base + PCIE0_ERROR);
 53	mutex_unlock(&pdata->lock);
 54
 55	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
 56}
 57
 58static ssize_t pcie0_errors_store(struct device *dev,
 59				  struct device_attribute *attr,
 60				  const char *buf, size_t count)
 61{
 62	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
 63	void __iomem *base;
 64	int ret = 0;
 65	u64 v, val;
 66
 67	if (kstrtou64(buf, 0, &val))
 68		return -EINVAL;
 69
 70	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
 71
 72	mutex_lock(&pdata->lock);
 73	writeq(GENMASK_ULL(63, 0), base + PCIE0_ERROR_MASK);
 74
 75	v = readq(base + PCIE0_ERROR);
 76	if (val == v)
 77		writeq(v, base + PCIE0_ERROR);
 78	else
 79		ret = -EINVAL;
 80
 81	writeq(0ULL, base + PCIE0_ERROR_MASK);
 82	mutex_unlock(&pdata->lock);
 83	return ret ? ret : count;
 84}
 85static DEVICE_ATTR_RW(pcie0_errors);
 86
 87static ssize_t pcie1_errors_show(struct device *dev,
 88				 struct device_attribute *attr, char *buf)
 89{
 90	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
 91	void __iomem *base;
 92	u64 value;
 93
 94	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
 95
 96	mutex_lock(&pdata->lock);
 97	value = readq(base + PCIE1_ERROR);
 98	mutex_unlock(&pdata->lock);
 99
100	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
101}
102
103static ssize_t pcie1_errors_store(struct device *dev,
104				  struct device_attribute *attr,
105				  const char *buf, size_t count)
106{
107	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
108	void __iomem *base;
109	int ret = 0;
110	u64 v, val;
111
112	if (kstrtou64(buf, 0, &val))
113		return -EINVAL;
114
115	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
116
117	mutex_lock(&pdata->lock);
118	writeq(GENMASK_ULL(63, 0), base + PCIE1_ERROR_MASK);
119
120	v = readq(base + PCIE1_ERROR);
121	if (val == v)
122		writeq(v, base + PCIE1_ERROR);
123	else
124		ret = -EINVAL;
125
126	writeq(0ULL, base + PCIE1_ERROR_MASK);
127	mutex_unlock(&pdata->lock);
128	return ret ? ret : count;
129}
130static DEVICE_ATTR_RW(pcie1_errors);
131
132static ssize_t nonfatal_errors_show(struct device *dev,
133				    struct device_attribute *attr, char *buf)
134{
135	void __iomem *base;
136
137	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
138
139	return sprintf(buf, "0x%llx\n",
140		       (unsigned long long)readq(base + RAS_NONFAT_ERROR));
141}
142static DEVICE_ATTR_RO(nonfatal_errors);
143
144static ssize_t catfatal_errors_show(struct device *dev,
145				    struct device_attribute *attr, char *buf)
146{
147	void __iomem *base;
148
149	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
150
151	return sprintf(buf, "0x%llx\n",
152		       (unsigned long long)readq(base + RAS_CATFAT_ERROR));
153}
154static DEVICE_ATTR_RO(catfatal_errors);
155
156static ssize_t inject_errors_show(struct device *dev,
157				  struct device_attribute *attr, char *buf)
158{
159	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
160	void __iomem *base;
161	u64 v;
162
163	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
164
165	mutex_lock(&pdata->lock);
166	v = readq(base + RAS_ERROR_INJECT);
167	mutex_unlock(&pdata->lock);
168
169	return sprintf(buf, "0x%llx\n",
170		       (unsigned long long)FIELD_GET(INJECT_ERROR_MASK, v));
171}
172
173static ssize_t inject_errors_store(struct device *dev,
174				   struct device_attribute *attr,
175				   const char *buf, size_t count)
176{
177	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
178	void __iomem *base;
179	u8 inject_error;
180	u64 v;
181
182	if (kstrtou8(buf, 0, &inject_error))
183		return -EINVAL;
184
185	if (inject_error & ~INJECT_ERROR_MASK)
186		return -EINVAL;
187
188	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
189
190	mutex_lock(&pdata->lock);
191	v = readq(base + RAS_ERROR_INJECT);
192	v &= ~INJECT_ERROR_MASK;
193	v |= FIELD_PREP(INJECT_ERROR_MASK, inject_error);
194	writeq(v, base + RAS_ERROR_INJECT);
195	mutex_unlock(&pdata->lock);
196
197	return count;
198}
199static DEVICE_ATTR_RW(inject_errors);
200
201static ssize_t fme_errors_show(struct device *dev,
202			       struct device_attribute *attr, char *buf)
203{
204	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
205	void __iomem *base;
206	u64 value;
207
208	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
209
210	mutex_lock(&pdata->lock);
211	value = readq(base + FME_ERROR);
212	mutex_unlock(&pdata->lock);
213
214	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
215}
216
217static ssize_t fme_errors_store(struct device *dev,
218				struct device_attribute *attr,
219				const char *buf, size_t count)
220{
221	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
222	void __iomem *base;
223	u64 v, val;
224	int ret = 0;
225
226	if (kstrtou64(buf, 0, &val))
227		return -EINVAL;
228
229	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
230
231	mutex_lock(&pdata->lock);
232	writeq(GENMASK_ULL(63, 0), base + FME_ERROR_MASK);
233
234	v = readq(base + FME_ERROR);
235	if (val == v)
236		writeq(v, base + FME_ERROR);
237	else
238		ret = -EINVAL;
239
240	/* Workaround: disable MBP_ERROR if feature revision is 0 */
241	writeq(dfl_feature_revision(base) ? 0ULL : MBP_ERROR,
242	       base + FME_ERROR_MASK);
243	mutex_unlock(&pdata->lock);
244	return ret ? ret : count;
245}
246static DEVICE_ATTR_RW(fme_errors);
247
248static ssize_t first_error_show(struct device *dev,
249				struct device_attribute *attr, char *buf)
250{
251	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
252	void __iomem *base;
253	u64 value;
254
255	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
256
257	mutex_lock(&pdata->lock);
258	value = readq(base + FME_FIRST_ERROR);
259	mutex_unlock(&pdata->lock);
260
261	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
262}
263static DEVICE_ATTR_RO(first_error);
264
265static ssize_t next_error_show(struct device *dev,
266			       struct device_attribute *attr, char *buf)
267{
268	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
269	void __iomem *base;
270	u64 value;
271
272	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
273
274	mutex_lock(&pdata->lock);
275	value = readq(base + FME_NEXT_ERROR);
276	mutex_unlock(&pdata->lock);
277
278	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
279}
280static DEVICE_ATTR_RO(next_error);
281
282static struct attribute *fme_global_err_attrs[] = {
283	&dev_attr_pcie0_errors.attr,
284	&dev_attr_pcie1_errors.attr,
285	&dev_attr_nonfatal_errors.attr,
286	&dev_attr_catfatal_errors.attr,
287	&dev_attr_inject_errors.attr,
288	&dev_attr_fme_errors.attr,
289	&dev_attr_first_error.attr,
290	&dev_attr_next_error.attr,
291	NULL,
292};
293
294static umode_t fme_global_err_attrs_visible(struct kobject *kobj,
295					    struct attribute *attr, int n)
296{
297	struct device *dev = kobj_to_dev(kobj);
298
299	/*
300	 * sysfs entries are visible only if related private feature is
301	 * enumerated.
302	 */
303	if (!dfl_get_feature_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR))
304		return 0;
305
306	return attr->mode;
307}
308
309const struct attribute_group fme_global_err_group = {
310	.name       = "errors",
311	.attrs      = fme_global_err_attrs,
312	.is_visible = fme_global_err_attrs_visible,
313};
314
315static void fme_err_mask(struct device *dev, bool mask)
316{
317	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
318	void __iomem *base;
319
320	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
321
322	mutex_lock(&pdata->lock);
323
324	/* Workaround: keep MBP_ERROR always masked if revision is 0 */
325	if (dfl_feature_revision(base))
326		writeq(mask ? ERROR_MASK : 0, base + FME_ERROR_MASK);
327	else
328		writeq(mask ? ERROR_MASK : MBP_ERROR, base + FME_ERROR_MASK);
329
330	writeq(mask ? ERROR_MASK : 0, base + PCIE0_ERROR_MASK);
331	writeq(mask ? ERROR_MASK : 0, base + PCIE1_ERROR_MASK);
332	writeq(mask ? ERROR_MASK : 0, base + RAS_NONFAT_ERROR_MASK);
333	writeq(mask ? ERROR_MASK : 0, base + RAS_CATFAT_ERROR_MASK);
334
335	mutex_unlock(&pdata->lock);
336}
337
338static int fme_global_err_init(struct platform_device *pdev,
339			       struct dfl_feature *feature)
340{
341	fme_err_mask(&pdev->dev, false);
342
343	return 0;
344}
345
346static void fme_global_err_uinit(struct platform_device *pdev,
347				 struct dfl_feature *feature)
348{
349	fme_err_mask(&pdev->dev, true);
350}
351
352static long
353fme_global_error_ioctl(struct platform_device *pdev,
354		       struct dfl_feature *feature,
355		       unsigned int cmd, unsigned long arg)
356{
357	switch (cmd) {
358	case DFL_FPGA_FME_ERR_GET_IRQ_NUM:
359		return dfl_feature_ioctl_get_num_irqs(pdev, feature, arg);
360	case DFL_FPGA_FME_ERR_SET_IRQ:
361		return dfl_feature_ioctl_set_irq(pdev, feature, arg);
362	default:
363		dev_dbg(&pdev->dev, "%x cmd not handled", cmd);
364		return -ENODEV;
365	}
366}
367
368const struct dfl_feature_id fme_global_err_id_table[] = {
369	{.id = FME_FEATURE_ID_GLOBAL_ERR,},
370	{0,}
371};
372
373const struct dfl_feature_ops fme_global_err_ops = {
374	.init = fme_global_err_init,
375	.uinit = fme_global_err_uinit,
376	.ioctl = fme_global_error_ioctl,
377};
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Driver for FPGA Management Engine Error Management
  4 *
  5 * Copyright 2019 Intel Corporation, Inc.
  6 *
  7 * Authors:
  8 *   Kang Luwei <luwei.kang@intel.com>
  9 *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
 10 *   Wu Hao <hao.wu@intel.com>
 11 *   Joseph Grecco <joe.grecco@intel.com>
 12 *   Enno Luebbers <enno.luebbers@intel.com>
 13 *   Tim Whisonant <tim.whisonant@intel.com>
 14 *   Ananda Ravuri <ananda.ravuri@intel.com>
 15 *   Mitchel, Henry <henry.mitchel@intel.com>
 16 */
 17
 
 18#include <linux/uaccess.h>
 19
 20#include "dfl.h"
 21#include "dfl-fme.h"
 22
 23#define FME_ERROR_MASK		0x8
 24#define FME_ERROR		0x10
 25#define MBP_ERROR		BIT_ULL(6)
 26#define PCIE0_ERROR_MASK	0x18
 27#define PCIE0_ERROR		0x20
 28#define PCIE1_ERROR_MASK	0x28
 29#define PCIE1_ERROR		0x30
 30#define FME_FIRST_ERROR		0x38
 31#define FME_NEXT_ERROR		0x40
 32#define RAS_NONFAT_ERROR_MASK	0x48
 33#define RAS_NONFAT_ERROR	0x50
 34#define RAS_CATFAT_ERROR_MASK	0x58
 35#define RAS_CATFAT_ERROR	0x60
 36#define RAS_ERROR_INJECT	0x68
 37#define INJECT_ERROR_MASK	GENMASK_ULL(2, 0)
 38
 39#define ERROR_MASK		GENMASK_ULL(63, 0)
 40
 41static ssize_t pcie0_errors_show(struct device *dev,
 42				 struct device_attribute *attr, char *buf)
 43{
 44	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
 45	void __iomem *base;
 46	u64 value;
 47
 48	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
 49
 50	mutex_lock(&pdata->lock);
 51	value = readq(base + PCIE0_ERROR);
 52	mutex_unlock(&pdata->lock);
 53
 54	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
 55}
 56
 57static ssize_t pcie0_errors_store(struct device *dev,
 58				  struct device_attribute *attr,
 59				  const char *buf, size_t count)
 60{
 61	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
 62	void __iomem *base;
 63	int ret = 0;
 64	u64 v, val;
 65
 66	if (kstrtou64(buf, 0, &val))
 67		return -EINVAL;
 68
 69	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
 70
 71	mutex_lock(&pdata->lock);
 72	writeq(GENMASK_ULL(63, 0), base + PCIE0_ERROR_MASK);
 73
 74	v = readq(base + PCIE0_ERROR);
 75	if (val == v)
 76		writeq(v, base + PCIE0_ERROR);
 77	else
 78		ret = -EINVAL;
 79
 80	writeq(0ULL, base + PCIE0_ERROR_MASK);
 81	mutex_unlock(&pdata->lock);
 82	return ret ? ret : count;
 83}
 84static DEVICE_ATTR_RW(pcie0_errors);
 85
 86static ssize_t pcie1_errors_show(struct device *dev,
 87				 struct device_attribute *attr, char *buf)
 88{
 89	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
 90	void __iomem *base;
 91	u64 value;
 92
 93	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
 94
 95	mutex_lock(&pdata->lock);
 96	value = readq(base + PCIE1_ERROR);
 97	mutex_unlock(&pdata->lock);
 98
 99	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
100}
101
102static ssize_t pcie1_errors_store(struct device *dev,
103				  struct device_attribute *attr,
104				  const char *buf, size_t count)
105{
106	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
107	void __iomem *base;
108	int ret = 0;
109	u64 v, val;
110
111	if (kstrtou64(buf, 0, &val))
112		return -EINVAL;
113
114	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
115
116	mutex_lock(&pdata->lock);
117	writeq(GENMASK_ULL(63, 0), base + PCIE1_ERROR_MASK);
118
119	v = readq(base + PCIE1_ERROR);
120	if (val == v)
121		writeq(v, base + PCIE1_ERROR);
122	else
123		ret = -EINVAL;
124
125	writeq(0ULL, base + PCIE1_ERROR_MASK);
126	mutex_unlock(&pdata->lock);
127	return ret ? ret : count;
128}
129static DEVICE_ATTR_RW(pcie1_errors);
130
131static ssize_t nonfatal_errors_show(struct device *dev,
132				    struct device_attribute *attr, char *buf)
133{
134	void __iomem *base;
135
136	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
137
138	return sprintf(buf, "0x%llx\n",
139		       (unsigned long long)readq(base + RAS_NONFAT_ERROR));
140}
141static DEVICE_ATTR_RO(nonfatal_errors);
142
143static ssize_t catfatal_errors_show(struct device *dev,
144				    struct device_attribute *attr, char *buf)
145{
146	void __iomem *base;
147
148	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
149
150	return sprintf(buf, "0x%llx\n",
151		       (unsigned long long)readq(base + RAS_CATFAT_ERROR));
152}
153static DEVICE_ATTR_RO(catfatal_errors);
154
155static ssize_t inject_errors_show(struct device *dev,
156				  struct device_attribute *attr, char *buf)
157{
158	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
159	void __iomem *base;
160	u64 v;
161
162	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
163
164	mutex_lock(&pdata->lock);
165	v = readq(base + RAS_ERROR_INJECT);
166	mutex_unlock(&pdata->lock);
167
168	return sprintf(buf, "0x%llx\n",
169		       (unsigned long long)FIELD_GET(INJECT_ERROR_MASK, v));
170}
171
172static ssize_t inject_errors_store(struct device *dev,
173				   struct device_attribute *attr,
174				   const char *buf, size_t count)
175{
176	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
177	void __iomem *base;
178	u8 inject_error;
179	u64 v;
180
181	if (kstrtou8(buf, 0, &inject_error))
182		return -EINVAL;
183
184	if (inject_error & ~INJECT_ERROR_MASK)
185		return -EINVAL;
186
187	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
188
189	mutex_lock(&pdata->lock);
190	v = readq(base + RAS_ERROR_INJECT);
191	v &= ~INJECT_ERROR_MASK;
192	v |= FIELD_PREP(INJECT_ERROR_MASK, inject_error);
193	writeq(v, base + RAS_ERROR_INJECT);
194	mutex_unlock(&pdata->lock);
195
196	return count;
197}
198static DEVICE_ATTR_RW(inject_errors);
199
200static ssize_t fme_errors_show(struct device *dev,
201			       struct device_attribute *attr, char *buf)
202{
203	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
204	void __iomem *base;
205	u64 value;
206
207	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
208
209	mutex_lock(&pdata->lock);
210	value = readq(base + FME_ERROR);
211	mutex_unlock(&pdata->lock);
212
213	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
214}
215
216static ssize_t fme_errors_store(struct device *dev,
217				struct device_attribute *attr,
218				const char *buf, size_t count)
219{
220	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
221	void __iomem *base;
222	u64 v, val;
223	int ret = 0;
224
225	if (kstrtou64(buf, 0, &val))
226		return -EINVAL;
227
228	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
229
230	mutex_lock(&pdata->lock);
231	writeq(GENMASK_ULL(63, 0), base + FME_ERROR_MASK);
232
233	v = readq(base + FME_ERROR);
234	if (val == v)
235		writeq(v, base + FME_ERROR);
236	else
237		ret = -EINVAL;
238
239	/* Workaround: disable MBP_ERROR if feature revision is 0 */
240	writeq(dfl_feature_revision(base) ? 0ULL : MBP_ERROR,
241	       base + FME_ERROR_MASK);
242	mutex_unlock(&pdata->lock);
243	return ret ? ret : count;
244}
245static DEVICE_ATTR_RW(fme_errors);
246
247static ssize_t first_error_show(struct device *dev,
248				struct device_attribute *attr, char *buf)
249{
250	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
251	void __iomem *base;
252	u64 value;
253
254	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
255
256	mutex_lock(&pdata->lock);
257	value = readq(base + FME_FIRST_ERROR);
258	mutex_unlock(&pdata->lock);
259
260	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
261}
262static DEVICE_ATTR_RO(first_error);
263
264static ssize_t next_error_show(struct device *dev,
265			       struct device_attribute *attr, char *buf)
266{
267	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
268	void __iomem *base;
269	u64 value;
270
271	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
272
273	mutex_lock(&pdata->lock);
274	value = readq(base + FME_NEXT_ERROR);
275	mutex_unlock(&pdata->lock);
276
277	return sprintf(buf, "0x%llx\n", (unsigned long long)value);
278}
279static DEVICE_ATTR_RO(next_error);
280
281static struct attribute *fme_global_err_attrs[] = {
282	&dev_attr_pcie0_errors.attr,
283	&dev_attr_pcie1_errors.attr,
284	&dev_attr_nonfatal_errors.attr,
285	&dev_attr_catfatal_errors.attr,
286	&dev_attr_inject_errors.attr,
287	&dev_attr_fme_errors.attr,
288	&dev_attr_first_error.attr,
289	&dev_attr_next_error.attr,
290	NULL,
291};
292
293static umode_t fme_global_err_attrs_visible(struct kobject *kobj,
294					    struct attribute *attr, int n)
295{
296	struct device *dev = kobj_to_dev(kobj);
297
298	/*
299	 * sysfs entries are visible only if related private feature is
300	 * enumerated.
301	 */
302	if (!dfl_get_feature_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR))
303		return 0;
304
305	return attr->mode;
306}
307
308const struct attribute_group fme_global_err_group = {
309	.name       = "errors",
310	.attrs      = fme_global_err_attrs,
311	.is_visible = fme_global_err_attrs_visible,
312};
313
314static void fme_err_mask(struct device *dev, bool mask)
315{
316	struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
317	void __iomem *base;
318
319	base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_GLOBAL_ERR);
320
321	mutex_lock(&pdata->lock);
322
323	/* Workaround: keep MBP_ERROR always masked if revision is 0 */
324	if (dfl_feature_revision(base))
325		writeq(mask ? ERROR_MASK : 0, base + FME_ERROR_MASK);
326	else
327		writeq(mask ? ERROR_MASK : MBP_ERROR, base + FME_ERROR_MASK);
328
329	writeq(mask ? ERROR_MASK : 0, base + PCIE0_ERROR_MASK);
330	writeq(mask ? ERROR_MASK : 0, base + PCIE1_ERROR_MASK);
331	writeq(mask ? ERROR_MASK : 0, base + RAS_NONFAT_ERROR_MASK);
332	writeq(mask ? ERROR_MASK : 0, base + RAS_CATFAT_ERROR_MASK);
333
334	mutex_unlock(&pdata->lock);
335}
336
337static int fme_global_err_init(struct platform_device *pdev,
338			       struct dfl_feature *feature)
339{
340	fme_err_mask(&pdev->dev, false);
341
342	return 0;
343}
344
345static void fme_global_err_uinit(struct platform_device *pdev,
346				 struct dfl_feature *feature)
347{
348	fme_err_mask(&pdev->dev, true);
349}
350
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351const struct dfl_feature_id fme_global_err_id_table[] = {
352	{.id = FME_FEATURE_ID_GLOBAL_ERR,},
353	{0,}
354};
355
356const struct dfl_feature_ops fme_global_err_ops = {
357	.init = fme_global_err_init,
358	.uinit = fme_global_err_uinit,
 
359};