0cd7ca18858b54042879b6f4ddde1872960e96a3
[firefly-linux-kernel-4.4.55.git] / drivers / pci / pcie / aer / aer_inject.c
1 /*
2  * PCIE AER software error injection support.
3  *
4  * Debuging PCIE AER code is quite difficult because it is hard to
5  * trigger various real hardware errors. Software based error
6  * injection can fake almost all kinds of errors with the help of a
7  * user space helper tool aer-inject, which can be gotten from:
8  *   http://www.kernel.org/pub/linux/utils/pci/aer-inject/
9  *
10  * Copyright 2009 Intel Corporation.
11  *     Huang Ying <ying.huang@intel.com>
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; version 2
16  * of the License.
17  *
18  */
19
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/miscdevice.h>
23 #include <linux/pci.h>
24 #include <linux/fs.h>
25 #include <linux/uaccess.h>
26 #include "aerdrv.h"
27
28 struct aer_error_inj {
29         u8 bus;
30         u8 dev;
31         u8 fn;
32         u32 uncor_status;
33         u32 cor_status;
34         u32 header_log0;
35         u32 header_log1;
36         u32 header_log2;
37         u32 header_log3;
38 };
39
40 struct aer_error {
41         struct list_head list;
42         unsigned int bus;
43         unsigned int devfn;
44         int pos_cap_err;
45
46         u32 uncor_status;
47         u32 cor_status;
48         u32 header_log0;
49         u32 header_log1;
50         u32 header_log2;
51         u32 header_log3;
52         u32 root_status;
53         u32 source_id;
54 };
55
56 struct pci_bus_ops {
57         struct list_head list;
58         struct pci_bus *bus;
59         struct pci_ops *ops;
60 };
61
62 static LIST_HEAD(einjected);
63
64 static LIST_HEAD(pci_bus_ops_list);
65
66 /* Protect einjected and pci_bus_ops_list */
67 static DEFINE_SPINLOCK(inject_lock);
68
69 static void aer_error_init(struct aer_error *err, unsigned int bus,
70                            unsigned int devfn, int pos_cap_err)
71 {
72         INIT_LIST_HEAD(&err->list);
73         err->bus = bus;
74         err->devfn = devfn;
75         err->pos_cap_err = pos_cap_err;
76 }
77
78 /* inject_lock must be held before calling */
79 static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
80 {
81         struct aer_error *err;
82
83         list_for_each_entry(err, &einjected, list) {
84                 if (bus == err->bus && devfn == err->devfn)
85                         return err;
86         }
87         return NULL;
88 }
89
90 /* inject_lock must be held before calling */
91 static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev)
92 {
93         return __find_aer_error(dev->bus->number, dev->devfn);
94 }
95
96 /* inject_lock must be held before calling */
97 static struct pci_ops *__find_pci_bus_ops(struct pci_bus *bus)
98 {
99         struct pci_bus_ops *bus_ops;
100
101         list_for_each_entry(bus_ops, &pci_bus_ops_list, list) {
102                 if (bus_ops->bus == bus)
103                         return bus_ops->ops;
104         }
105         return NULL;
106 }
107
108 static struct pci_bus_ops *pci_bus_ops_pop(void)
109 {
110         unsigned long flags;
111         struct pci_bus_ops *bus_ops = NULL;
112
113         spin_lock_irqsave(&inject_lock, flags);
114         if (list_empty(&pci_bus_ops_list))
115                 bus_ops = NULL;
116         else {
117                 struct list_head *lh = pci_bus_ops_list.next;
118                 list_del(lh);
119                 bus_ops = list_entry(lh, struct pci_bus_ops, list);
120         }
121         spin_unlock_irqrestore(&inject_lock, flags);
122         return bus_ops;
123 }
124
125 static u32 *find_pci_config_dword(struct aer_error *err, int where,
126                                   int *prw1cs)
127 {
128         int rw1cs = 0;
129         u32 *target = NULL;
130
131         if (err->pos_cap_err == -1)
132                 return NULL;
133
134         switch (where - err->pos_cap_err) {
135         case PCI_ERR_UNCOR_STATUS:
136                 target = &err->uncor_status;
137                 rw1cs = 1;
138                 break;
139         case PCI_ERR_COR_STATUS:
140                 target = &err->cor_status;
141                 rw1cs = 1;
142                 break;
143         case PCI_ERR_HEADER_LOG:
144                 target = &err->header_log0;
145                 break;
146         case PCI_ERR_HEADER_LOG+4:
147                 target = &err->header_log1;
148                 break;
149         case PCI_ERR_HEADER_LOG+8:
150                 target = &err->header_log2;
151                 break;
152         case PCI_ERR_HEADER_LOG+12:
153                 target = &err->header_log3;
154                 break;
155         case PCI_ERR_ROOT_STATUS:
156                 target = &err->root_status;
157                 rw1cs = 1;
158                 break;
159         case PCI_ERR_ROOT_COR_SRC:
160                 target = &err->source_id;
161                 break;
162         }
163         if (prw1cs)
164                 *prw1cs = rw1cs;
165         return target;
166 }
167
168 static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
169                         int size, u32 *val)
170 {
171         u32 *sim;
172         struct aer_error *err;
173         unsigned long flags;
174         struct pci_ops *ops;
175
176         spin_lock_irqsave(&inject_lock, flags);
177         if (size != sizeof(u32))
178                 goto out;
179         err = __find_aer_error(bus->number, devfn);
180         if (!err)
181                 goto out;
182
183         sim = find_pci_config_dword(err, where, NULL);
184         if (sim) {
185                 *val = *sim;
186                 spin_unlock_irqrestore(&inject_lock, flags);
187                 return 0;
188         }
189 out:
190         ops = __find_pci_bus_ops(bus);
191         spin_unlock_irqrestore(&inject_lock, flags);
192         return ops->read(bus, devfn, where, size, val);
193 }
194
195 int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
196                   u32 val)
197 {
198         u32 *sim;
199         struct aer_error *err;
200         unsigned long flags;
201         int rw1cs;
202         struct pci_ops *ops;
203
204         spin_lock_irqsave(&inject_lock, flags);
205         if (size != sizeof(u32))
206                 goto out;
207         err = __find_aer_error(bus->number, devfn);
208         if (!err)
209                 goto out;
210
211         sim = find_pci_config_dword(err, where, &rw1cs);
212         if (sim) {
213                 if (rw1cs)
214                         *sim ^= val;
215                 else
216                         *sim = val;
217                 spin_unlock_irqrestore(&inject_lock, flags);
218                 return 0;
219         }
220 out:
221         ops = __find_pci_bus_ops(bus);
222         spin_unlock_irqrestore(&inject_lock, flags);
223         return ops->write(bus, devfn, where, size, val);
224 }
225
226 static struct pci_ops pci_ops_aer = {
227         .read = pci_read_aer,
228         .write = pci_write_aer,
229 };
230
231 static void pci_bus_ops_init(struct pci_bus_ops *bus_ops,
232                              struct pci_bus *bus,
233                              struct pci_ops *ops)
234 {
235         INIT_LIST_HEAD(&bus_ops->list);
236         bus_ops->bus = bus;
237         bus_ops->ops = ops;
238 }
239
240 static int pci_bus_set_aer_ops(struct pci_bus *bus)
241 {
242         struct pci_ops *ops;
243         struct pci_bus_ops *bus_ops;
244         unsigned long flags;
245
246         bus_ops = kmalloc(sizeof(*bus_ops), GFP_KERNEL);
247         if (!bus_ops)
248                 return -ENOMEM;
249         ops = pci_bus_set_ops(bus, &pci_ops_aer);
250         spin_lock_irqsave(&inject_lock, flags);
251         if (ops == &pci_ops_aer)
252                 goto out;
253         pci_bus_ops_init(bus_ops, bus, ops);
254         list_add(&bus_ops->list, &pci_bus_ops_list);
255         bus_ops = NULL;
256 out:
257         spin_unlock_irqrestore(&inject_lock, flags);
258         kfree(bus_ops);
259         return 0;
260 }
261
262 static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
263 {
264         while (1) {
265                 if (!dev->is_pcie)
266                         break;
267                 if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
268                         return dev;
269                 if (!dev->bus->self)
270                         break;
271                 dev = dev->bus->self;
272         }
273         return NULL;
274 }
275
276 static int find_aer_device_iter(struct device *device, void *data)
277 {
278         struct pcie_device **result = data;
279         struct pcie_device *pcie_dev;
280
281         if (device->bus == &pcie_port_bus_type) {
282                 pcie_dev = to_pcie_device(device);
283                 if (pcie_dev->service & PCIE_PORT_SERVICE_AER) {
284                         *result = pcie_dev;
285                         return 1;
286                 }
287         }
288         return 0;
289 }
290
291 static int find_aer_device(struct pci_dev *dev, struct pcie_device **result)
292 {
293         return device_for_each_child(&dev->dev, result, find_aer_device_iter);
294 }
295
296 static int aer_inject(struct aer_error_inj *einj)
297 {
298         struct aer_error *err, *rperr;
299         struct aer_error *err_alloc = NULL, *rperr_alloc = NULL;
300         struct pci_dev *dev, *rpdev;
301         struct pcie_device *edev;
302         unsigned long flags;
303         unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
304         int pos_cap_err, rp_pos_cap_err;
305         u32 sever, mask;
306         int ret = 0;
307
308         dev = pci_get_bus_and_slot(einj->bus, devfn);
309         if (!dev)
310                 return -EINVAL;
311         rpdev = pcie_find_root_port(dev);
312         if (!rpdev) {
313                 ret = -EINVAL;
314                 goto out_put;
315         }
316
317         pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
318         if (!pos_cap_err) {
319                 ret = -EIO;
320                 goto out_put;
321         }
322         pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
323
324         rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
325         if (!rp_pos_cap_err) {
326                 ret = -EIO;
327                 goto out_put;
328         }
329
330         err_alloc =  kzalloc(sizeof(struct aer_error), GFP_KERNEL);
331         if (!err_alloc) {
332                 ret = -ENOMEM;
333                 goto out_put;
334         }
335         rperr_alloc =  kzalloc(sizeof(struct aer_error), GFP_KERNEL);
336         if (!rperr_alloc) {
337                 ret = -ENOMEM;
338                 goto out_put;
339         }
340
341         spin_lock_irqsave(&inject_lock, flags);
342
343         err = __find_aer_error_by_dev(dev);
344         if (!err) {
345                 err = err_alloc;
346                 err_alloc = NULL;
347                 aer_error_init(err, einj->bus, devfn, pos_cap_err);
348                 list_add(&err->list, &einjected);
349         }
350         err->uncor_status |= einj->uncor_status;
351         err->cor_status |= einj->cor_status;
352         err->header_log0 = einj->header_log0;
353         err->header_log1 = einj->header_log1;
354         err->header_log2 = einj->header_log2;
355         err->header_log3 = einj->header_log3;
356
357         pci_read_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, &mask);
358         if (einj->cor_status && !(einj->cor_status & ~mask)) {
359                 ret = -EINVAL;
360                 printk(KERN_WARNING "The correctable error(s) is masked "
361                                 "by device\n");
362                 spin_unlock_irqrestore(&inject_lock, flags);
363                 goto out_put;
364         }
365
366         pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK, &mask);
367         if (einj->uncor_status && !(einj->uncor_status & ~mask)) {
368                 ret = -EINVAL;
369                 printk(KERN_WARNING "The uncorrectable error(s) is masked "
370                                 "by device\n");
371                 spin_unlock_irqrestore(&inject_lock, flags);
372                 goto out_put;
373         }
374
375         rperr = __find_aer_error_by_dev(rpdev);
376         if (!rperr) {
377                 rperr = rperr_alloc;
378                 rperr_alloc = NULL;
379                 aer_error_init(rperr, rpdev->bus->number, rpdev->devfn,
380                                rp_pos_cap_err);
381                 list_add(&rperr->list, &einjected);
382         }
383         if (einj->cor_status) {
384                 if (rperr->root_status & PCI_ERR_ROOT_COR_RCV)
385                         rperr->root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
386                 else
387                         rperr->root_status |= PCI_ERR_ROOT_COR_RCV;
388                 rperr->source_id &= 0xffff0000;
389                 rperr->source_id |= (einj->bus << 8) | devfn;
390         }
391         if (einj->uncor_status) {
392                 if (rperr->root_status & PCI_ERR_ROOT_UNCOR_RCV)
393                         rperr->root_status |= PCI_ERR_ROOT_MULTI_UNCOR_RCV;
394                 if (sever & einj->uncor_status) {
395                         rperr->root_status |= PCI_ERR_ROOT_FATAL_RCV;
396                         if (!(rperr->root_status & PCI_ERR_ROOT_UNCOR_RCV))
397                                 rperr->root_status |= PCI_ERR_ROOT_FIRST_FATAL;
398                 } else
399                         rperr->root_status |= PCI_ERR_ROOT_NONFATAL_RCV;
400                 rperr->root_status |= PCI_ERR_ROOT_UNCOR_RCV;
401                 rperr->source_id &= 0x0000ffff;
402                 rperr->source_id |= ((einj->bus << 8) | devfn) << 16;
403         }
404         spin_unlock_irqrestore(&inject_lock, flags);
405
406         ret = pci_bus_set_aer_ops(dev->bus);
407         if (ret)
408                 goto out_put;
409         ret = pci_bus_set_aer_ops(rpdev->bus);
410         if (ret)
411                 goto out_put;
412
413         if (find_aer_device(rpdev, &edev)) {
414                 if (!get_service_data(edev)) {
415                         printk(KERN_WARNING "AER service is not initialized\n");
416                         ret = -EINVAL;
417                         goto out_put;
418                 }
419                 aer_irq(-1, edev);
420         }
421         else
422                 ret = -EINVAL;
423 out_put:
424         kfree(err_alloc);
425         kfree(rperr_alloc);
426         pci_dev_put(dev);
427         return ret;
428 }
429
430 static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,
431                                 size_t usize, loff_t *off)
432 {
433         struct aer_error_inj einj;
434         int ret;
435
436         if (!capable(CAP_SYS_ADMIN))
437                 return -EPERM;
438
439         if (usize != sizeof(struct aer_error_inj))
440                 return -EINVAL;
441
442         if (copy_from_user(&einj, ubuf, usize))
443                 return -EFAULT;
444
445         ret = aer_inject(&einj);
446         return ret ? ret : usize;
447 }
448
449 static const struct file_operations aer_inject_fops = {
450         .write = aer_inject_write,
451         .owner = THIS_MODULE,
452 };
453
454 static struct miscdevice aer_inject_device = {
455         .minor = MISC_DYNAMIC_MINOR,
456         .name = "aer_inject",
457         .fops = &aer_inject_fops,
458 };
459
460 static int __init aer_inject_init(void)
461 {
462         return misc_register(&aer_inject_device);
463 }
464
465 static void __exit aer_inject_exit(void)
466 {
467         struct aer_error *err, *err_next;
468         unsigned long flags;
469         struct pci_bus_ops *bus_ops;
470
471         misc_deregister(&aer_inject_device);
472
473         while ((bus_ops = pci_bus_ops_pop())) {
474                 pci_bus_set_ops(bus_ops->bus, bus_ops->ops);
475                 kfree(bus_ops);
476         }
477
478         spin_lock_irqsave(&inject_lock, flags);
479         list_for_each_entry_safe(err, err_next, &pci_bus_ops_list, list) {
480                 list_del(&err->list);
481                 kfree(err);
482         }
483         spin_unlock_irqrestore(&inject_lock, flags);
484 }
485
486 module_init(aer_inject_init);
487 module_exit(aer_inject_exit);
488
489 MODULE_DESCRIPTION("PCIE AER software error injector");
490 MODULE_LICENSE("GPL");