GNU Linux-libre 4.14.324-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 static int aer_probe(struct pcie_device *dev);
34 static void aer_remove(struct pcie_device *dev);
35 static void aer_error_resume(struct pci_dev *dev);
36 static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
37
38 static struct pcie_port_service_driver aerdriver = {
39         .name           = "aer",
40         .port_type      = PCI_EXP_TYPE_ROOT_PORT,
41         .service        = PCIE_PORT_SERVICE_AER,
42
43         .probe          = aer_probe,
44         .remove         = aer_remove,
45         .error_resume   = aer_error_resume,
46         .reset_link     = aer_root_reset,
47 };
48
49 static int pcie_aer_disable;
50
51 void pci_no_aer(void)
52 {
53         pcie_aer_disable = 1;
54 }
55
56 bool pci_aer_available(void)
57 {
58         return !pcie_aer_disable && pci_msi_enabled();
59 }
60
61 static int set_device_error_reporting(struct pci_dev *dev, void *data)
62 {
63         bool enable = *((bool *)data);
64         int type = pci_pcie_type(dev);
65
66         if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
67             (type == PCI_EXP_TYPE_UPSTREAM) ||
68             (type == PCI_EXP_TYPE_DOWNSTREAM)) {
69                 if (enable)
70                         pci_enable_pcie_error_reporting(dev);
71                 else
72                         pci_disable_pcie_error_reporting(dev);
73         }
74
75         if (enable)
76                 pcie_set_ecrc_checking(dev);
77
78         return 0;
79 }
80
81 /**
82  * set_downstream_devices_error_reporting - enable/disable the error reporting  bits on the root port and its downstream ports.
83  * @dev: pointer to root port's pci_dev data structure
84  * @enable: true = enable error reporting, false = disable error reporting.
85  */
86 static void set_downstream_devices_error_reporting(struct pci_dev *dev,
87                                                    bool enable)
88 {
89         set_device_error_reporting(dev, &enable);
90
91         if (!dev->subordinate)
92                 return;
93         pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
94 }
95
96 /**
97  * aer_enable_rootport - enable Root Port's interrupts when receiving messages
98  * @rpc: pointer to a Root Port data structure
99  *
100  * Invoked when PCIe bus loads AER service driver.
101  */
102 static void aer_enable_rootport(struct aer_rpc *rpc)
103 {
104         struct pci_dev *pdev = rpc->rpd->port;
105         int aer_pos;
106         u16 reg16;
107         u32 reg32;
108
109         /* Clear PCIe Capability's Device Status */
110         pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, &reg16);
111         pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
112
113         /* Disable system error generation in response to error messages */
114         pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
115                                    SYSTEM_ERROR_INTR_ON_MESG_MASK);
116
117         aer_pos = pdev->aer_cap;
118         /* Clear error status */
119         pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
120         pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
121         pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
122         pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
123         pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
124         pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
125
126         /*
127          * Enable error reporting for the root port device and downstream port
128          * devices.
129          */
130         set_downstream_devices_error_reporting(pdev, true);
131
132         /* Enable Root Port's interrupt in response to error messages */
133         pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, &reg32);
134         reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
135         pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
136 }
137
138 /**
139  * aer_disable_rootport - disable Root Port's interrupts when receiving messages
140  * @rpc: pointer to a Root Port data structure
141  *
142  * Invoked when PCIe bus unloads AER service driver.
143  */
144 static void aer_disable_rootport(struct aer_rpc *rpc)
145 {
146         struct pci_dev *pdev = rpc->rpd->port;
147         u32 reg32;
148         int pos;
149
150         /*
151          * Disable error reporting for the root port device and downstream port
152          * devices.
153          */
154         set_downstream_devices_error_reporting(pdev, false);
155
156         pos = pdev->aer_cap;
157         /* Disable Root's interrupt in response to error messages */
158         pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
159         reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
160         pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
161
162         /* Clear Root's error status reg */
163         pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
164         pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
165 }
166
167 /**
168  * aer_irq - Root Port's ISR
169  * @irq: IRQ assigned to Root Port
170  * @context: pointer to Root Port data structure
171  *
172  * Invoked when Root Port detects AER messages.
173  */
174 irqreturn_t aer_irq(int irq, void *context)
175 {
176         unsigned int status, id;
177         struct pcie_device *pdev = (struct pcie_device *)context;
178         struct aer_rpc *rpc = get_service_data(pdev);
179         int next_prod_idx;
180         unsigned long flags;
181         int pos;
182
183         pos = pdev->port->aer_cap;
184         /*
185          * Must lock access to Root Error Status Reg, Root Error ID Reg,
186          * and Root error producer/consumer index
187          */
188         spin_lock_irqsave(&rpc->e_lock, flags);
189
190         /* Read error status */
191         pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
192         if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
193                 spin_unlock_irqrestore(&rpc->e_lock, flags);
194                 return IRQ_NONE;
195         }
196
197         /* Read error source and clear error status */
198         pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
199         pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
200
201         /* Store error source for later DPC handler */
202         next_prod_idx = rpc->prod_idx + 1;
203         if (next_prod_idx == AER_ERROR_SOURCES_MAX)
204                 next_prod_idx = 0;
205         if (next_prod_idx == rpc->cons_idx) {
206                 /*
207                  * Error Storm Condition - possibly the same error occurred.
208                  * Drop the error.
209                  */
210                 spin_unlock_irqrestore(&rpc->e_lock, flags);
211                 return IRQ_HANDLED;
212         }
213         rpc->e_sources[rpc->prod_idx].status =  status;
214         rpc->e_sources[rpc->prod_idx].id = id;
215         rpc->prod_idx = next_prod_idx;
216         spin_unlock_irqrestore(&rpc->e_lock, flags);
217
218         /*  Invoke DPC handler */
219         schedule_work(&rpc->dpc_handler);
220
221         return IRQ_HANDLED;
222 }
223 EXPORT_SYMBOL_GPL(aer_irq);
224
225 /**
226  * aer_alloc_rpc - allocate Root Port data structure
227  * @dev: pointer to the pcie_dev data structure
228  *
229  * Invoked when Root Port's AER service is loaded.
230  */
231 static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
232 {
233         struct aer_rpc *rpc;
234
235         rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
236         if (!rpc)
237                 return NULL;
238
239         /* Initialize Root lock access, e_lock, to Root Error Status Reg */
240         spin_lock_init(&rpc->e_lock);
241
242         rpc->rpd = dev;
243         INIT_WORK(&rpc->dpc_handler, aer_isr);
244         mutex_init(&rpc->rpc_mutex);
245
246         /* Use PCIe bus function to store rpc into PCIe device */
247         set_service_data(dev, rpc);
248
249         return rpc;
250 }
251
252 /**
253  * aer_remove - clean up resources
254  * @dev: pointer to the pcie_dev data structure
255  *
256  * Invoked when PCI Express bus unloads or AER probe fails.
257  */
258 static void aer_remove(struct pcie_device *dev)
259 {
260         struct aer_rpc *rpc = get_service_data(dev);
261
262         if (rpc) {
263                 /* If register interrupt service, it must be free. */
264                 if (rpc->isr)
265                         free_irq(dev->irq, dev);
266
267                 flush_work(&rpc->dpc_handler);
268                 aer_disable_rootport(rpc);
269                 kfree(rpc);
270                 set_service_data(dev, NULL);
271         }
272 }
273
274 /**
275  * aer_probe - initialize resources
276  * @dev: pointer to the pcie_dev data structure
277  *
278  * Invoked when PCI Express bus loads AER service driver.
279  */
280 static int aer_probe(struct pcie_device *dev)
281 {
282         int status;
283         struct aer_rpc *rpc;
284         struct device *device = &dev->port->dev;
285
286         /* Alloc rpc data structure */
287         rpc = aer_alloc_rpc(dev);
288         if (!rpc) {
289                 dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
290                 aer_remove(dev);
291                 return -ENOMEM;
292         }
293
294         /* Request IRQ ISR */
295         status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
296         if (status) {
297                 dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
298                            dev->irq);
299                 aer_remove(dev);
300                 return status;
301         }
302
303         rpc->isr = 1;
304
305         aer_enable_rootport(rpc);
306         dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
307         return 0;
308 }
309
310 /**
311  * aer_root_reset - reset link on Root Port
312  * @dev: pointer to Root Port's pci_dev data structure
313  *
314  * Invoked by Port Bus driver when performing link reset at Root Port.
315  */
316 static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
317 {
318         u32 reg32;
319         int pos;
320
321         pos = dev->aer_cap;
322
323         /* Disable Root's interrupt in response to error messages */
324         pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
325         reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
326         pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
327
328         pci_reset_bridge_secondary_bus(dev);
329         dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n");
330
331         /* Clear Root Error Status */
332         pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
333         pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
334
335         /* Enable Root Port's interrupt in response to error messages */
336         pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
337         reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
338         pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
339
340         return PCI_ERS_RESULT_RECOVERED;
341 }
342
343 /**
344  * aer_error_resume - clean up corresponding error status bits
345  * @dev: pointer to Root Port's pci_dev data structure
346  *
347  * Invoked by Port Bus driver during nonfatal recovery.
348  */
349 static void aer_error_resume(struct pci_dev *dev)
350 {
351         int pos;
352         u32 status, mask;
353         u16 reg16;
354
355         /* Clean up Root device status */
356         pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
357         pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
358
359         /* Clean AER Root Error Status */
360         pos = dev->aer_cap;
361         pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
362         pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
363         if (dev->error_state == pci_channel_io_normal)
364                 status &= ~mask; /* Clear corresponding nonfatal bits */
365         else
366                 status &= mask; /* Clear corresponding fatal bits */
367         pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
368 }
369
370 /**
371  * aer_service_init - register AER root service driver
372  *
373  * Invoked when AER root service driver is loaded.
374  */
375 static int __init aer_service_init(void)
376 {
377         if (!pci_aer_available() || aer_acpi_firmware_first())
378                 return -ENXIO;
379         return pcie_port_service_register(&aerdriver);
380 }
381 device_initcall(aer_service_init);