GNU Linux-libre 4.9.333-gnu1
[releases.git] / drivers / pci / pcie / aer / aerdrv.c
1 /*
2  * drivers/pci/pcie/aer/aerdrv.c
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive
6  * for more details.
7  *
8  * This file implements the AER root port service driver. The driver will
9  * register an irq handler. When root port triggers an AER interrupt, the irq
10  * handler will collect root port status and schedule a work.
11  *
12  * Copyright (C) 2006 Intel Corp.
13  *      Tom Long Nguyen (tom.l.nguyen@intel.com)
14  *      Zhang Yanmin (yanmin.zhang@intel.com)
15  *
16  */
17
18 #include <linux/pci.h>
19 #include <linux/pci-acpi.h>
20 #include <linux/sched.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/pm.h>
24 #include <linux/init.h>
25 #include <linux/interrupt.h>
26 #include <linux/delay.h>
27 #include <linux/pcieport_if.h>
28 #include <linux/slab.h>
29
30 #include "aerdrv.h"
31 #include "../../pci.h"
32
33 /*
34  * Version Information
35  */
36 #define DRIVER_VERSION "v1.0"
37 #define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
38 #define DRIVER_DESC "Root Port Advanced Error Reporting Driver"
39
40 static int aer_probe(struct pcie_device *dev);
41 static void aer_remove(struct pcie_device *dev);
42 static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
43         enum pci_channel_state error);
44 static void aer_error_resume(struct pci_dev *dev);
45 static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
46
47 static const struct pci_error_handlers aer_error_handlers = {
48         .error_detected = aer_error_detected,
49         .resume         = aer_error_resume,
50 };
51
52 static struct pcie_port_service_driver aerdriver = {
53         .name           = "aer",
54         .port_type      = PCI_EXP_TYPE_ROOT_PORT,
55         .service        = PCIE_PORT_SERVICE_AER,
56
57         .probe          = aer_probe,
58         .remove         = aer_remove,
59
60         .err_handler    = &aer_error_handlers,
61
62         .reset_link     = aer_root_reset,
63 };
64
65 static int pcie_aer_disable;
66
67 void pci_no_aer(void)
68 {
69         pcie_aer_disable = 1;
70 }
71
72 bool pci_aer_available(void)
73 {
74         return !pcie_aer_disable && pci_msi_enabled();
75 }
76
77 static int set_device_error_reporting(struct pci_dev *dev, void *data)
78 {
79         bool enable = *((bool *)data);
80         int type = pci_pcie_type(dev);
81
82         if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
83             (type == PCI_EXP_TYPE_UPSTREAM) ||
84             (type == PCI_EXP_TYPE_DOWNSTREAM)) {
85                 if (enable)
86                         pci_enable_pcie_error_reporting(dev);
87                 else
88                         pci_disable_pcie_error_reporting(dev);
89         }
90
91         if (enable)
92                 pcie_set_ecrc_checking(dev);
93
94         return 0;
95 }
96
97 /**
98  * set_downstream_devices_error_reporting - enable/disable the error reporting  bits on the root port and its downstream ports.
99  * @dev: pointer to root port's pci_dev data structure
100  * @enable: true = enable error reporting, false = disable error reporting.
101  */
102 static void set_downstream_devices_error_reporting(struct pci_dev *dev,
103                                                    bool enable)
104 {
105         set_device_error_reporting(dev, &enable);
106
107         if (!dev->subordinate)
108                 return;
109         pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
110 }
111
112 /**
113  * aer_enable_rootport - enable Root Port's interrupts when receiving messages
114  * @rpc: pointer to a Root Port data structure
115  *
116  * Invoked when PCIe bus loads AER service driver.
117  */
118 static void aer_enable_rootport(struct aer_rpc *rpc)
119 {
120         struct pci_dev *pdev = rpc->rpd->port;
121         int aer_pos;
122         u16 reg16;
123         u32 reg32;
124
125         /* Clear PCIe Capability's Device Status */
126         pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, &reg16);
127         pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
128
129         /* Disable system error generation in response to error messages */
130         pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
131                                    SYSTEM_ERROR_INTR_ON_MESG_MASK);
132
133         aer_pos = pdev->aer_cap;
134         /* Clear error status */
135         pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
136         pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
137         pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
138         pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
139         pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
140         pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
141
142         /*
143          * Enable error reporting for the root port device and downstream port
144          * devices.
145          */
146         set_downstream_devices_error_reporting(pdev, true);
147
148         /* Enable Root Port's interrupt in response to error messages */
149         pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, &reg32);
150         reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
151         pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
152 }
153
154 /**
155  * aer_disable_rootport - disable Root Port's interrupts when receiving messages
156  * @rpc: pointer to a Root Port data structure
157  *
158  * Invoked when PCIe bus unloads AER service driver.
159  */
160 static void aer_disable_rootport(struct aer_rpc *rpc)
161 {
162         struct pci_dev *pdev = rpc->rpd->port;
163         u32 reg32;
164         int pos;
165
166         /*
167          * Disable error reporting for the root port device and downstream port
168          * devices.
169          */
170         set_downstream_devices_error_reporting(pdev, false);
171
172         pos = pdev->aer_cap;
173         /* Disable Root's interrupt in response to error messages */
174         pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
175         reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
176         pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
177
178         /* Clear Root's error status reg */
179         pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
180         pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
181 }
182
183 /**
184  * aer_irq - Root Port's ISR
185  * @irq: IRQ assigned to Root Port
186  * @context: pointer to Root Port data structure
187  *
188  * Invoked when Root Port detects AER messages.
189  */
190 irqreturn_t aer_irq(int irq, void *context)
191 {
192         unsigned int status, id;
193         struct pcie_device *pdev = (struct pcie_device *)context;
194         struct aer_rpc *rpc = get_service_data(pdev);
195         int next_prod_idx;
196         unsigned long flags;
197         int pos;
198
199         pos = pdev->port->aer_cap;
200         /*
201          * Must lock access to Root Error Status Reg, Root Error ID Reg,
202          * and Root error producer/consumer index
203          */
204         spin_lock_irqsave(&rpc->e_lock, flags);
205
206         /* Read error status */
207         pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
208         if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
209                 spin_unlock_irqrestore(&rpc->e_lock, flags);
210                 return IRQ_NONE;
211         }
212
213         /* Read error source and clear error status */
214         pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
215         pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
216
217         /* Store error source for later DPC handler */
218         next_prod_idx = rpc->prod_idx + 1;
219         if (next_prod_idx == AER_ERROR_SOURCES_MAX)
220                 next_prod_idx = 0;
221         if (next_prod_idx == rpc->cons_idx) {
222                 /*
223                  * Error Storm Condition - possibly the same error occurred.
224                  * Drop the error.
225                  */
226                 spin_unlock_irqrestore(&rpc->e_lock, flags);
227                 return IRQ_HANDLED;
228         }
229         rpc->e_sources[rpc->prod_idx].status =  status;
230         rpc->e_sources[rpc->prod_idx].id = id;
231         rpc->prod_idx = next_prod_idx;
232         spin_unlock_irqrestore(&rpc->e_lock, flags);
233
234         /*  Invoke DPC handler */
235         schedule_work(&rpc->dpc_handler);
236
237         return IRQ_HANDLED;
238 }
239 EXPORT_SYMBOL_GPL(aer_irq);
240
241 /**
242  * aer_alloc_rpc - allocate Root Port data structure
243  * @dev: pointer to the pcie_dev data structure
244  *
245  * Invoked when Root Port's AER service is loaded.
246  */
247 static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
248 {
249         struct aer_rpc *rpc;
250
251         rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
252         if (!rpc)
253                 return NULL;
254
255         /* Initialize Root lock access, e_lock, to Root Error Status Reg */
256         spin_lock_init(&rpc->e_lock);
257
258         rpc->rpd = dev;
259         INIT_WORK(&rpc->dpc_handler, aer_isr);
260         mutex_init(&rpc->rpc_mutex);
261
262         /* Use PCIe bus function to store rpc into PCIe device */
263         set_service_data(dev, rpc);
264
265         return rpc;
266 }
267
268 /**
269  * aer_remove - clean up resources
270  * @dev: pointer to the pcie_dev data structure
271  *
272  * Invoked when PCI Express bus unloads or AER probe fails.
273  */
274 static void aer_remove(struct pcie_device *dev)
275 {
276         struct aer_rpc *rpc = get_service_data(dev);
277
278         if (rpc) {
279                 /* If register interrupt service, it must be free. */
280                 if (rpc->isr)
281                         free_irq(dev->irq, dev);
282
283                 flush_work(&rpc->dpc_handler);
284                 aer_disable_rootport(rpc);
285                 kfree(rpc);
286                 set_service_data(dev, NULL);
287         }
288 }
289
290 /**
291  * aer_probe - initialize resources
292  * @dev: pointer to the pcie_dev data structure
293  *
294  * Invoked when PCI Express bus loads AER service driver.
295  */
296 static int aer_probe(struct pcie_device *dev)
297 {
298         int status;
299         struct aer_rpc *rpc;
300         struct device *device = &dev->device;
301
302         /* Alloc rpc data structure */
303         rpc = aer_alloc_rpc(dev);
304         if (!rpc) {
305                 dev_printk(KERN_DEBUG, device, "alloc rpc failed\n");
306                 aer_remove(dev);
307                 return -ENOMEM;
308         }
309
310         /* Request IRQ ISR */
311         status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
312         if (status) {
313                 dev_printk(KERN_DEBUG, device, "request IRQ failed\n");
314                 aer_remove(dev);
315                 return status;
316         }
317
318         rpc->isr = 1;
319
320         aer_enable_rootport(rpc);
321
322         return status;
323 }
324
325 /**
326  * aer_root_reset - reset link on Root Port
327  * @dev: pointer to Root Port's pci_dev data structure
328  *
329  * Invoked by Port Bus driver when performing link reset at Root Port.
330  */
331 static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
332 {
333         u32 reg32;
334         int pos;
335
336         pos = dev->aer_cap;
337
338         /* Disable Root's interrupt in response to error messages */
339         pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
340         reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
341         pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
342
343         pci_reset_bridge_secondary_bus(dev);
344         dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n");
345
346         /* Clear Root Error Status */
347         pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
348         pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
349
350         /* Enable Root Port's interrupt in response to error messages */
351         pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
352         reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
353         pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
354
355         return PCI_ERS_RESULT_RECOVERED;
356 }
357
358 /**
359  * aer_error_detected - update severity status
360  * @dev: pointer to Root Port's pci_dev data structure
361  * @error: error severity being notified by port bus
362  *
363  * Invoked by Port Bus driver during error recovery.
364  */
365 static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
366                         enum pci_channel_state error)
367 {
368         /* Root Port has no impact. Always recovers. */
369         return PCI_ERS_RESULT_CAN_RECOVER;
370 }
371
372 /**
373  * aer_error_resume - clean up corresponding error status bits
374  * @dev: pointer to Root Port's pci_dev data structure
375  *
376  * Invoked by Port Bus driver during nonfatal recovery.
377  */
378 static void aer_error_resume(struct pci_dev *dev)
379 {
380         int pos;
381         u32 status, mask;
382         u16 reg16;
383
384         /* Clean up Root device status */
385         pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
386         pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
387
388         /* Clean AER Root Error Status */
389         pos = dev->aer_cap;
390         pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
391         pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
392         if (dev->error_state == pci_channel_io_normal)
393                 status &= ~mask; /* Clear corresponding nonfatal bits */
394         else
395                 status &= mask; /* Clear corresponding fatal bits */
396         pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
397 }
398
399 /**
400  * aer_service_init - register AER root service driver
401  *
402  * Invoked when AER root service driver is loaded.
403  */
404 static int __init aer_service_init(void)
405 {
406         if (!pci_aer_available() || aer_acpi_firmware_first())
407                 return -ENXIO;
408         return pcie_port_service_register(&aerdriver);
409 }
410 device_initcall(aer_service_init);