1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
3 */
4
5 #include "ifpga_feature_dev.h"
6
fme_err_get_errors(struct ifpga_fme_hw * fme,u64 * val)7 static int fme_err_get_errors(struct ifpga_fme_hw *fme, u64 *val)
8 {
9 struct feature_fme_err *fme_err
10 = get_fme_feature_ioaddr_by_index(fme,
11 FME_FEATURE_ID_GLOBAL_ERR);
12 struct feature_fme_error0 fme_error0;
13
14 fme_error0.csr = readq(&fme_err->fme_err);
15 *val = fme_error0.csr;
16
17 return 0;
18 }
19
fme_err_get_first_error(struct ifpga_fme_hw * fme,u64 * val)20 static int fme_err_get_first_error(struct ifpga_fme_hw *fme, u64 *val)
21 {
22 struct feature_fme_err *fme_err
23 = get_fme_feature_ioaddr_by_index(fme,
24 FME_FEATURE_ID_GLOBAL_ERR);
25 struct feature_fme_first_error fme_first_err;
26
27 fme_first_err.csr = readq(&fme_err->fme_first_err);
28 *val = fme_first_err.err_reg_status;
29
30 return 0;
31 }
32
fme_err_get_next_error(struct ifpga_fme_hw * fme,u64 * val)33 static int fme_err_get_next_error(struct ifpga_fme_hw *fme, u64 *val)
34 {
35 struct feature_fme_err *fme_err
36 = get_fme_feature_ioaddr_by_index(fme,
37 FME_FEATURE_ID_GLOBAL_ERR);
38 struct feature_fme_next_error fme_next_err;
39
40 fme_next_err.csr = readq(&fme_err->fme_next_err);
41 *val = fme_next_err.err_reg_status;
42
43 return 0;
44 }
45
fme_err_set_clear(struct ifpga_fme_hw * fme,u64 val)46 static int fme_err_set_clear(struct ifpga_fme_hw *fme, u64 val)
47 {
48 struct feature_fme_err *fme_err
49 = get_fme_feature_ioaddr_by_index(fme,
50 FME_FEATURE_ID_GLOBAL_ERR);
51
52 spinlock_lock(&fme->lock);
53
54 writeq(val, &fme_err->fme_err);
55
56 spinlock_unlock(&fme->lock);
57
58 return 0;
59 }
60
fme_err_get_revision(struct ifpga_fme_hw * fme,u64 * val)61 static int fme_err_get_revision(struct ifpga_fme_hw *fme, u64 *val)
62 {
63 struct feature_fme_err *fme_err
64 = get_fme_feature_ioaddr_by_index(fme,
65 FME_FEATURE_ID_GLOBAL_ERR);
66 struct feature_header header;
67
68 header.csr = readq(&fme_err->header);
69 *val = header.revision;
70
71 return 0;
72 }
73
fme_err_get_pcie0_errors(struct ifpga_fme_hw * fme,u64 * val)74 static int fme_err_get_pcie0_errors(struct ifpga_fme_hw *fme, u64 *val)
75 {
76 struct feature_fme_err *fme_err
77 = get_fme_feature_ioaddr_by_index(fme,
78 FME_FEATURE_ID_GLOBAL_ERR);
79 struct feature_fme_pcie0_error pcie0_err;
80
81 pcie0_err.csr = readq(&fme_err->pcie0_err);
82 *val = pcie0_err.csr;
83
84 return 0;
85 }
86
fme_err_set_pcie0_errors(struct ifpga_fme_hw * fme,u64 val)87 static int fme_err_set_pcie0_errors(struct ifpga_fme_hw *fme, u64 val)
88 {
89 struct feature_fme_err *fme_err
90 = get_fme_feature_ioaddr_by_index(fme,
91 FME_FEATURE_ID_GLOBAL_ERR);
92 struct feature_fme_pcie0_error pcie0_err;
93 int ret = 0;
94
95 spinlock_lock(&fme->lock);
96 writeq(FME_PCIE0_ERROR_MASK, &fme_err->pcie0_err_mask);
97
98 pcie0_err.csr = readq(&fme_err->pcie0_err);
99 if (val != pcie0_err.csr)
100 ret = -EBUSY;
101 else
102 writeq(pcie0_err.csr & FME_PCIE0_ERROR_MASK,
103 &fme_err->pcie0_err);
104
105 writeq(0UL, &fme_err->pcie0_err_mask);
106 spinlock_unlock(&fme->lock);
107
108 return ret;
109 }
110
fme_err_get_pcie1_errors(struct ifpga_fme_hw * fme,u64 * val)111 static int fme_err_get_pcie1_errors(struct ifpga_fme_hw *fme, u64 *val)
112 {
113 struct feature_fme_err *fme_err
114 = get_fme_feature_ioaddr_by_index(fme,
115 FME_FEATURE_ID_GLOBAL_ERR);
116 struct feature_fme_pcie1_error pcie1_err;
117
118 pcie1_err.csr = readq(&fme_err->pcie1_err);
119 *val = pcie1_err.csr;
120
121 return 0;
122 }
123
fme_err_set_pcie1_errors(struct ifpga_fme_hw * fme,u64 val)124 static int fme_err_set_pcie1_errors(struct ifpga_fme_hw *fme, u64 val)
125 {
126 struct feature_fme_err *fme_err
127 = get_fme_feature_ioaddr_by_index(fme,
128 FME_FEATURE_ID_GLOBAL_ERR);
129 struct feature_fme_pcie1_error pcie1_err;
130 int ret = 0;
131
132 spinlock_lock(&fme->lock);
133 writeq(FME_PCIE1_ERROR_MASK, &fme_err->pcie1_err_mask);
134
135 pcie1_err.csr = readq(&fme_err->pcie1_err);
136 if (val != pcie1_err.csr)
137 ret = -EBUSY;
138 else
139 writeq(pcie1_err.csr & FME_PCIE1_ERROR_MASK,
140 &fme_err->pcie1_err);
141
142 writeq(0UL, &fme_err->pcie1_err_mask);
143 spinlock_unlock(&fme->lock);
144
145 return ret;
146 }
147
fme_err_get_nonfatal_errors(struct ifpga_fme_hw * fme,u64 * val)148 static int fme_err_get_nonfatal_errors(struct ifpga_fme_hw *fme, u64 *val)
149 {
150 struct feature_fme_err *fme_err
151 = get_fme_feature_ioaddr_by_index(fme,
152 FME_FEATURE_ID_GLOBAL_ERR);
153 struct feature_fme_ras_nonfaterror ras_nonfaterr;
154
155 ras_nonfaterr.csr = readq(&fme_err->ras_nonfaterr);
156 *val = ras_nonfaterr.csr;
157
158 return 0;
159 }
160
fme_err_get_catfatal_errors(struct ifpga_fme_hw * fme,u64 * val)161 static int fme_err_get_catfatal_errors(struct ifpga_fme_hw *fme, u64 *val)
162 {
163 struct feature_fme_err *fme_err
164 = get_fme_feature_ioaddr_by_index(fme,
165 FME_FEATURE_ID_GLOBAL_ERR);
166 struct feature_fme_ras_catfaterror ras_catfaterr;
167
168 ras_catfaterr.csr = readq(&fme_err->ras_catfaterr);
169 *val = ras_catfaterr.csr;
170
171 return 0;
172 }
173
fme_err_get_inject_errors(struct ifpga_fme_hw * fme,u64 * val)174 static int fme_err_get_inject_errors(struct ifpga_fme_hw *fme, u64 *val)
175 {
176 struct feature_fme_err *fme_err
177 = get_fme_feature_ioaddr_by_index(fme,
178 FME_FEATURE_ID_GLOBAL_ERR);
179 struct feature_fme_ras_error_inj ras_error_inj;
180
181 ras_error_inj.csr = readq(&fme_err->ras_error_inj);
182 *val = ras_error_inj.csr & FME_RAS_ERROR_INJ_MASK;
183
184 return 0;
185 }
186
fme_err_set_inject_errors(struct ifpga_fme_hw * fme,u64 val)187 static int fme_err_set_inject_errors(struct ifpga_fme_hw *fme, u64 val)
188 {
189 struct feature_fme_err *fme_err
190 = get_fme_feature_ioaddr_by_index(fme,
191 FME_FEATURE_ID_GLOBAL_ERR);
192 struct feature_fme_ras_error_inj ras_error_inj;
193
194 spinlock_lock(&fme->lock);
195 ras_error_inj.csr = readq(&fme_err->ras_error_inj);
196
197 if (val <= FME_RAS_ERROR_INJ_MASK) {
198 ras_error_inj.csr = val;
199 } else {
200 spinlock_unlock(&fme->lock);
201 return -EINVAL;
202 }
203
204 writeq(ras_error_inj.csr, &fme_err->ras_error_inj);
205 spinlock_unlock(&fme->lock);
206
207 return 0;
208 }
209
fme_error_enable(struct ifpga_fme_hw * fme)210 static void fme_error_enable(struct ifpga_fme_hw *fme)
211 {
212 struct feature_fme_err *fme_err
213 = get_fme_feature_ioaddr_by_index(fme,
214 FME_FEATURE_ID_GLOBAL_ERR);
215
216 writeq(FME_ERROR0_MASK_DEFAULT, &fme_err->fme_err_mask);
217 writeq(0UL, &fme_err->pcie0_err_mask);
218 writeq(0UL, &fme_err->pcie1_err_mask);
219 writeq(0UL, &fme_err->ras_nonfat_mask);
220 writeq(0UL, &fme_err->ras_catfat_mask);
221 }
222
fme_global_error_init(struct ifpga_feature * feature)223 static int fme_global_error_init(struct ifpga_feature *feature)
224 {
225 struct ifpga_fme_hw *fme = feature->parent;
226
227 fme_error_enable(fme);
228
229 if (feature->ctx_num)
230 fme->capability |= FPGA_FME_CAP_ERR_IRQ;
231
232 return 0;
233 }
234
fme_global_error_uinit(struct ifpga_feature * feature)235 static void fme_global_error_uinit(struct ifpga_feature *feature)
236 {
237 UNUSED(feature);
238 }
239
fme_err_check_seu(struct feature_fme_err * fme_err)240 static int fme_err_check_seu(struct feature_fme_err *fme_err)
241 {
242 struct feature_fme_error_capability error_cap;
243
244 error_cap.csr = readq(&fme_err->fme_err_capability);
245
246 return error_cap.seu_support ? 1 : 0;
247 }
248
fme_err_get_seu_emr(struct ifpga_fme_hw * fme,u64 * val,bool high)249 static int fme_err_get_seu_emr(struct ifpga_fme_hw *fme,
250 u64 *val, bool high)
251 {
252 struct feature_fme_err *fme_err
253 = get_fme_feature_ioaddr_by_index(fme,
254 FME_FEATURE_ID_GLOBAL_ERR);
255
256 if (!fme_err_check_seu(fme_err))
257 return -ENODEV;
258
259 if (high)
260 *val = readq(&fme_err->seu_emr_h);
261 else
262 *val = readq(&fme_err->seu_emr_l);
263
264 return 0;
265 }
266
fme_err_fme_err_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)267 static int fme_err_fme_err_get_prop(struct ifpga_feature *feature,
268 struct feature_prop *prop)
269 {
270 struct ifpga_fme_hw *fme = feature->parent;
271 u16 id = GET_FIELD(PROP_ID, prop->prop_id);
272
273 switch (id) {
274 case 0x1: /* ERRORS */
275 return fme_err_get_errors(fme, &prop->data);
276 case 0x2: /* FIRST_ERROR */
277 return fme_err_get_first_error(fme, &prop->data);
278 case 0x3: /* NEXT_ERROR */
279 return fme_err_get_next_error(fme, &prop->data);
280 case 0x5: /* SEU EMR LOW */
281 return fme_err_get_seu_emr(fme, &prop->data, 0);
282 case 0x6: /* SEU EMR HIGH */
283 return fme_err_get_seu_emr(fme, &prop->data, 1);
284 }
285
286 return -ENOENT;
287 }
288
fme_err_root_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)289 static int fme_err_root_get_prop(struct ifpga_feature *feature,
290 struct feature_prop *prop)
291 {
292 struct ifpga_fme_hw *fme = feature->parent;
293 u16 id = GET_FIELD(PROP_ID, prop->prop_id);
294
295 switch (id) {
296 case 0x5: /* REVISION */
297 return fme_err_get_revision(fme, &prop->data);
298 case 0x6: /* PCIE0_ERRORS */
299 return fme_err_get_pcie0_errors(fme, &prop->data);
300 case 0x7: /* PCIE1_ERRORS */
301 return fme_err_get_pcie1_errors(fme, &prop->data);
302 case 0x8: /* NONFATAL_ERRORS */
303 return fme_err_get_nonfatal_errors(fme, &prop->data);
304 case 0x9: /* CATFATAL_ERRORS */
305 return fme_err_get_catfatal_errors(fme, &prop->data);
306 case 0xa: /* INJECT_ERRORS */
307 return fme_err_get_inject_errors(fme, &prop->data);
308 case 0xb: /* REVISION*/
309 return fme_err_get_revision(fme, &prop->data);
310 }
311
312 return -ENOENT;
313 }
314
fme_global_error_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)315 static int fme_global_error_get_prop(struct ifpga_feature *feature,
316 struct feature_prop *prop)
317 {
318 u8 top = GET_FIELD(PROP_TOP, prop->prop_id);
319 u8 sub = GET_FIELD(PROP_SUB, prop->prop_id);
320
321 /* PROP_SUB is never used */
322 if (sub != PROP_SUB_UNUSED)
323 return -ENOENT;
324
325 switch (top) {
326 case ERR_PROP_TOP_FME_ERR:
327 return fme_err_fme_err_get_prop(feature, prop);
328 case ERR_PROP_TOP_UNUSED:
329 return fme_err_root_get_prop(feature, prop);
330 }
331
332 return -ENOENT;
333 }
334
fme_err_fme_err_set_prop(struct ifpga_feature * feature,struct feature_prop * prop)335 static int fme_err_fme_err_set_prop(struct ifpga_feature *feature,
336 struct feature_prop *prop)
337 {
338 struct ifpga_fme_hw *fme = feature->parent;
339 u16 id = GET_FIELD(PROP_ID, prop->prop_id);
340
341 switch (id) {
342 case 0x4: /* CLEAR */
343 return fme_err_set_clear(fme, prop->data);
344 }
345
346 return -ENOENT;
347 }
348
fme_err_root_set_prop(struct ifpga_feature * feature,struct feature_prop * prop)349 static int fme_err_root_set_prop(struct ifpga_feature *feature,
350 struct feature_prop *prop)
351 {
352 struct ifpga_fme_hw *fme = feature->parent;
353 u16 id = GET_FIELD(PROP_ID, prop->prop_id);
354
355 switch (id) {
356 case 0x6: /* PCIE0_ERRORS */
357 return fme_err_set_pcie0_errors(fme, prop->data);
358 case 0x7: /* PCIE1_ERRORS */
359 return fme_err_set_pcie1_errors(fme, prop->data);
360 case 0xa: /* INJECT_ERRORS */
361 return fme_err_set_inject_errors(fme, prop->data);
362 }
363
364 return -ENOENT;
365 }
366
fme_global_error_set_prop(struct ifpga_feature * feature,struct feature_prop * prop)367 static int fme_global_error_set_prop(struct ifpga_feature *feature,
368 struct feature_prop *prop)
369 {
370 u8 top = GET_FIELD(PROP_TOP, prop->prop_id);
371 u8 sub = GET_FIELD(PROP_SUB, prop->prop_id);
372
373 /* PROP_SUB is never used */
374 if (sub != PROP_SUB_UNUSED)
375 return -ENOENT;
376
377 switch (top) {
378 case ERR_PROP_TOP_FME_ERR:
379 return fme_err_fme_err_set_prop(feature, prop);
380 case ERR_PROP_TOP_UNUSED:
381 return fme_err_root_set_prop(feature, prop);
382 }
383
384 return -ENOENT;
385 }
386
fme_global_err_set_irq(struct ifpga_feature * feature,void * irq_set)387 static int fme_global_err_set_irq(struct ifpga_feature *feature, void *irq_set)
388 {
389 struct fpga_fme_err_irq_set *err_irq_set = irq_set;
390 struct ifpga_fme_hw *fme;
391 int ret;
392
393 fme = (struct ifpga_fme_hw *)feature->parent;
394
395 if (!(fme->capability & FPGA_FME_CAP_ERR_IRQ))
396 return -ENODEV;
397
398 spinlock_lock(&fme->lock);
399 ret = fpga_msix_set_block(feature, 0, 1, &err_irq_set->evtfd);
400 spinlock_unlock(&fme->lock);
401
402 return ret;
403 }
404
405 struct ifpga_feature_ops fme_global_err_ops = {
406 .init = fme_global_error_init,
407 .uinit = fme_global_error_uinit,
408 .get_prop = fme_global_error_get_prop,
409 .set_prop = fme_global_error_set_prop,
410 .set_irq = fme_global_err_set_irq,
411 };
412