1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
33static int aer_probe(struct pcie_device *dev);
34static void aer_remove(struct pcie_device *dev);
35static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
36 enum pci_channel_state error);
37static void aer_error_resume(struct pci_dev *dev);
38static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
39
40static const struct pci_error_handlers aer_error_handlers = {
41 .error_detected = aer_error_detected,
42 .resume = aer_error_resume,
43};
44
45static struct pcie_port_service_driver aerdriver = {
46 .name = "aer",
47 .port_type = PCI_EXP_TYPE_ROOT_PORT,
48 .service = PCIE_PORT_SERVICE_AER,
49
50 .probe = aer_probe,
51 .remove = aer_remove,
52
53 .err_handler = &aer_error_handlers,
54
55 .reset_link = aer_root_reset,
56};
57
58static int pcie_aer_disable;
59
60void pci_no_aer(void)
61{
62 pcie_aer_disable = 1;
63}
64
65bool pci_aer_available(void)
66{
67 return !pcie_aer_disable && pci_msi_enabled();
68}
69
70static int set_device_error_reporting(struct pci_dev *dev, void *data)
71{
72 bool enable = *((bool *)data);
73 int type = pci_pcie_type(dev);
74
75 if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
76 (type == PCI_EXP_TYPE_UPSTREAM) ||
77 (type == PCI_EXP_TYPE_DOWNSTREAM)) {
78 if (enable)
79 pci_enable_pcie_error_reporting(dev);
80 else
81 pci_disable_pcie_error_reporting(dev);
82 }
83
84 if (enable)
85 pcie_set_ecrc_checking(dev);
86
87 return 0;
88}
89
90
91
92
93
94
95static void set_downstream_devices_error_reporting(struct pci_dev *dev,
96 bool enable)
97{
98 set_device_error_reporting(dev, &enable);
99
100 if (!dev->subordinate)
101 return;
102 pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
103}
104
105
106
107
108
109
110
111static void aer_enable_rootport(struct aer_rpc *rpc)
112{
113 struct pci_dev *pdev = rpc->rpd->port;
114 int aer_pos;
115 u16 reg16;
116 u32 reg32;
117
118
119 pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, ®16);
120 pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
121
122
123 pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
124 SYSTEM_ERROR_INTR_ON_MESG_MASK);
125
126 aer_pos = pdev->aer_cap;
127
128 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32);
129 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
130 pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, ®32);
131 pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
132 pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, ®32);
133 pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
134
135
136
137
138
139 set_downstream_devices_error_reporting(pdev, true);
140
141
142 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, ®32);
143 reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
144 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
145}
146
147
148
149
150
151
152
153static void aer_disable_rootport(struct aer_rpc *rpc)
154{
155 struct pci_dev *pdev = rpc->rpd->port;
156 u32 reg32;
157 int pos;
158
159
160
161
162
163 set_downstream_devices_error_reporting(pdev, false);
164
165 pos = pdev->aer_cap;
166
167 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32);
168 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
169 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
170
171
172 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, ®32);
173 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
174}
175
176
177
178
179
180
181
182
183irqreturn_t aer_irq(int irq, void *context)
184{
185 unsigned int status, id;
186 struct pcie_device *pdev = (struct pcie_device *)context;
187 struct aer_rpc *rpc = get_service_data(pdev);
188 int next_prod_idx;
189 unsigned long flags;
190 int pos;
191
192 pos = pdev->port->aer_cap;
193
194
195
196
197 spin_lock_irqsave(&rpc->e_lock, flags);
198
199
200 pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
201 if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
202 spin_unlock_irqrestore(&rpc->e_lock, flags);
203 return IRQ_NONE;
204 }
205
206
207 pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
208 pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
209
210
211 next_prod_idx = rpc->prod_idx + 1;
212 if (next_prod_idx == AER_ERROR_SOURCES_MAX)
213 next_prod_idx = 0;
214 if (next_prod_idx == rpc->cons_idx) {
215
216
217
218
219 spin_unlock_irqrestore(&rpc->e_lock, flags);
220 return IRQ_HANDLED;
221 }
222 rpc->e_sources[rpc->prod_idx].status = status;
223 rpc->e_sources[rpc->prod_idx].id = id;
224 rpc->prod_idx = next_prod_idx;
225 spin_unlock_irqrestore(&rpc->e_lock, flags);
226
227
228 schedule_work(&rpc->dpc_handler);
229
230 return IRQ_HANDLED;
231}
232EXPORT_SYMBOL_GPL(aer_irq);
233
234
235
236
237
238
239
240static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
241{
242 struct aer_rpc *rpc;
243
244 rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
245 if (!rpc)
246 return NULL;
247
248
249 spin_lock_init(&rpc->e_lock);
250
251 rpc->rpd = dev;
252 INIT_WORK(&rpc->dpc_handler, aer_isr);
253 mutex_init(&rpc->rpc_mutex);
254
255
256 set_service_data(dev, rpc);
257
258 return rpc;
259}
260
261
262
263
264
265
266
267static void aer_remove(struct pcie_device *dev)
268{
269 struct aer_rpc *rpc = get_service_data(dev);
270
271 if (rpc) {
272
273 if (rpc->isr)
274 free_irq(dev->irq, dev);
275
276 flush_work(&rpc->dpc_handler);
277 aer_disable_rootport(rpc);
278 kfree(rpc);
279 set_service_data(dev, NULL);
280 }
281}
282
283
284
285
286
287
288
289static int aer_probe(struct pcie_device *dev)
290{
291 int status;
292 struct aer_rpc *rpc;
293 struct device *device = &dev->port->dev;
294
295
296 rpc = aer_alloc_rpc(dev);
297 if (!rpc) {
298 dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
299 aer_remove(dev);
300 return -ENOMEM;
301 }
302
303
304 status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
305 if (status) {
306 dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
307 dev->irq);
308 aer_remove(dev);
309 return status;
310 }
311
312 rpc->isr = 1;
313
314 aer_enable_rootport(rpc);
315 dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
316 return 0;
317}
318
319
320
321
322
323
324
325static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
326{
327 u32 reg32;
328 int pos;
329
330 pos = dev->aer_cap;
331
332
333 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32);
334 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
335 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
336
337 pci_reset_bridge_secondary_bus(dev);
338 dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n");
339
340
341 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, ®32);
342 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
343
344
345 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32);
346 reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
347 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
348
349 return PCI_ERS_RESULT_RECOVERED;
350}
351
352
353
354
355
356
357
358
359static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
360 enum pci_channel_state error)
361{
362
363 return PCI_ERS_RESULT_CAN_RECOVER;
364}
365
366
367
368
369
370
371
372static void aer_error_resume(struct pci_dev *dev)
373{
374 int pos;
375 u32 status, mask;
376 u16 reg16;
377
378
379 pcie_capability_read_word(dev, PCI_EXP_DEVSTA, ®16);
380 pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
381
382
383 pos = dev->aer_cap;
384 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
385 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
386 if (dev->error_state == pci_channel_io_normal)
387 status &= ~mask;
388 else
389 status &= mask;
390 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
391}
392
393
394
395
396
397
398static int __init aer_service_init(void)
399{
400 if (!pci_aer_available() || aer_acpi_firmware_first())
401 return -ENXIO;
402 return pcie_port_service_register(&aerdriver);
403}
404device_initcall(aer_service_init);
405