Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
aerdrv.c
Go to the documentation of this file.
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 ([email protected])
14  * Zhang Yanmin ([email protected])
15  *
16  */
17 
18 #include <linux/module.h>
19 #include <linux/pci.h>
20 #include <linux/pci-acpi.h>
21 #include <linux/sched.h>
22 #include <linux/kernel.h>
23 #include <linux/errno.h>
24 #include <linux/pm.h>
25 #include <linux/init.h>
26 #include <linux/interrupt.h>
27 #include <linux/delay.h>
28 #include <linux/pcieport_if.h>
29 #include <linux/slab.h>
30 
31 #include "aerdrv.h"
32 #include "../../pci.h"
33 
34 /*
35  * Version Information
36  */
37 #define DRIVER_VERSION "v1.0"
38 #define DRIVER_AUTHOR "[email protected]"
39 #define DRIVER_DESC "Root Port Advanced Error Reporting Driver"
42 MODULE_LICENSE("GPL");
43 
44 static int __devinit aer_probe(struct pcie_device *dev);
45 static void aer_remove(struct pcie_device *dev);
46 static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
48 static void aer_error_resume(struct pci_dev *dev);
49 static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
50 
51 static const struct pci_error_handlers aer_error_handlers = {
52  .error_detected = aer_error_detected,
53  .resume = aer_error_resume,
54 };
55 
56 static struct pcie_port_service_driver aerdriver = {
57  .name = "aer",
58  .port_type = PCI_EXP_TYPE_ROOT_PORT,
59  .service = PCIE_PORT_SERVICE_AER,
60 
61  .probe = aer_probe,
62  .remove = aer_remove,
63 
64  .err_handler = &aer_error_handlers,
65 
66  .reset_link = aer_root_reset,
67 };
68 
69 static int pcie_aer_disable;
70 
71 void pci_no_aer(void)
72 {
73  pcie_aer_disable = 1; /* has priority over 'forceload' */
74 }
75 
77 {
78  return !pcie_aer_disable && pci_msi_enabled();
79 }
80 
81 static int set_device_error_reporting(struct pci_dev *dev, void *data)
82 {
83  bool enable = *((bool *)data);
84  int type = pci_pcie_type(dev);
85 
86  if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
87  (type == PCI_EXP_TYPE_UPSTREAM) ||
88  (type == PCI_EXP_TYPE_DOWNSTREAM)) {
89  if (enable)
91  else
93  }
94 
95  if (enable)
97 
98  return 0;
99 }
100 
106 static void set_downstream_devices_error_reporting(struct pci_dev *dev,
107  bool enable)
108 {
109  set_device_error_reporting(dev, &enable);
110 
111  if (!dev->subordinate)
112  return;
113  pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
114 }
115 
122 static void aer_enable_rootport(struct aer_rpc *rpc)
123 {
124  struct pci_dev *pdev = rpc->rpd->port;
125  int aer_pos;
126  u16 reg16;
127  u32 reg32;
128 
129  /* Clear PCIe Capability's Device Status */
132 
133  /* Disable system error generation in response to error messages */
134  pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
136 
138  /* Clear error status */
139  pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
140  pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
141  pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
142  pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
143  pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
144  pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
145 
146  /*
147  * Enable error reporting for the root port device and downstream port
148  * devices.
149  */
150  set_downstream_devices_error_reporting(pdev, true);
151 
152  /* Enable Root Port's interrupt in response to error messages */
153  pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, &reg32);
155  pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
156 }
157 
164 static void aer_disable_rootport(struct aer_rpc *rpc)
165 {
166  struct pci_dev *pdev = rpc->rpd->port;
167  u32 reg32;
168  int pos;
169 
170  /*
171  * Disable error reporting for the root port device and downstream port
172  * devices.
173  */
174  set_downstream_devices_error_reporting(pdev, false);
175 
177  /* Disable Root's interrupt in response to error messages */
178  pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
179  reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
180  pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
181 
182  /* Clear Root's error status reg */
183  pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
184  pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
185 }
186 
195 {
196  unsigned int status, id;
197  struct pcie_device *pdev = (struct pcie_device *)context;
198  struct aer_rpc *rpc = get_service_data(pdev);
199  int next_prod_idx;
200  unsigned long flags;
201  int pos;
202 
204  /*
205  * Must lock access to Root Error Status Reg, Root Error ID Reg,
206  * and Root error producer/consumer index
207  */
208  spin_lock_irqsave(&rpc->e_lock, flags);
209 
210  /* Read error status */
211  pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
212  if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
213  spin_unlock_irqrestore(&rpc->e_lock, flags);
214  return IRQ_NONE;
215  }
216 
217  /* Read error source and clear error status */
218  pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
219  pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
220 
221  /* Store error source for later DPC handler */
222  next_prod_idx = rpc->prod_idx + 1;
223  if (next_prod_idx == AER_ERROR_SOURCES_MAX)
224  next_prod_idx = 0;
225  if (next_prod_idx == rpc->cons_idx) {
226  /*
227  * Error Storm Condition - possibly the same error occurred.
228  * Drop the error.
229  */
230  spin_unlock_irqrestore(&rpc->e_lock, flags);
231  return IRQ_HANDLED;
232  }
233  rpc->e_sources[rpc->prod_idx].status = status;
234  rpc->e_sources[rpc->prod_idx].id = id;
235  rpc->prod_idx = next_prod_idx;
236  spin_unlock_irqrestore(&rpc->e_lock, flags);
237 
238  /* Invoke DPC handler */
239  schedule_work(&rpc->dpc_handler);
240 
241  return IRQ_HANDLED;
242 }
244 
251 static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
252 {
253  struct aer_rpc *rpc;
254 
255  rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
256  if (!rpc)
257  return NULL;
258 
259  /* Initialize Root lock access, e_lock, to Root Error Status Reg */
260  spin_lock_init(&rpc->e_lock);
261 
262  rpc->rpd = dev;
263  INIT_WORK(&rpc->dpc_handler, aer_isr);
264  mutex_init(&rpc->rpc_mutex);
266 
267  /* Use PCIe bus function to store rpc into PCIe device */
268  set_service_data(dev, rpc);
269 
270  return rpc;
271 }
272 
279 static void aer_remove(struct pcie_device *dev)
280 {
281  struct aer_rpc *rpc = get_service_data(dev);
282 
283  if (rpc) {
284  /* If register interrupt service, it must be free. */
285  if (rpc->isr)
286  free_irq(dev->irq, dev);
287 
288  wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
289 
290  aer_disable_rootport(rpc);
291  kfree(rpc);
292  set_service_data(dev, NULL);
293  }
294 }
295 
303 static int __devinit aer_probe(struct pcie_device *dev)
304 {
305  int status;
306  struct aer_rpc *rpc;
307  struct device *device = &dev->device;
308 
309  /* Init */
310  status = aer_init(dev);
311  if (status)
312  return status;
313 
314  /* Alloc rpc data structure */
315  rpc = aer_alloc_rpc(dev);
316  if (!rpc) {
317  dev_printk(KERN_DEBUG, device, "alloc rpc failed\n");
318  aer_remove(dev);
319  return -ENOMEM;
320  }
321 
322  /* Request IRQ ISR */
323  status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
324  if (status) {
325  dev_printk(KERN_DEBUG, device, "request IRQ failed\n");
326  aer_remove(dev);
327  return status;
328  }
329 
330  rpc->isr = 1;
331 
332  aer_enable_rootport(rpc);
333 
334  return status;
335 }
336 
343 static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
344 {
345  u32 reg32;
346  int pos;
347 
349 
350  /* Disable Root'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 
356  dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n");
357 
358  /* Clear Root Error Status */
359  pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
360  pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
361 
362  /* Enable Root Port's interrupt in response to error messages */
363  pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
365  pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
366 
368 }
369 
377 static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
379 {
380  /* Root Port has no impact. Always recovers. */
382 }
383 
390 static void aer_error_resume(struct pci_dev *dev)
391 {
392  int pos;
393  u32 status, mask;
394  u16 reg16;
395 
396  /* Clean up Root device status */
399 
400  /* Clean AER Root Error Status */
402  pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
403  pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
405  status &= ~mask; /* Clear corresponding nonfatal bits */
406  else
407  status &= mask; /* Clear corresponding fatal bits */
408  pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
409 }
410 
416 static int __init aer_service_init(void)
417 {
418  if (!pci_aer_available() || aer_acpi_firmware_first())
419  return -ENXIO;
420  return pcie_port_service_register(&aerdriver);
421 }
422 
428 static void __exit aer_service_exit(void)
429 {
430  pcie_port_service_unregister(&aerdriver);
431 }
432 
433 module_init(aer_service_init);
434 module_exit(aer_service_exit);