raw/ifpga/base: clean FME errors
[dpdk.git] / drivers / raw / ifpga / base / ifpga_fme_error.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4
5 #include "ifpga_feature_dev.h"
6
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
235 static void fme_global_error_uinit(struct ifpga_feature *feature)
236 {
237         UNUSED(feature);
238 }
239
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
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
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
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
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
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
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
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
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 };