2 * drivers/pci/pcie/aer/aerdrv.c
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
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.
12 * Copyright (C) 2006 Intel Corp.
13 * Tom Long Nguyen (tom.l.nguyen@intel.com)
14 * Zhang Yanmin (yanmin.zhang@intel.com)
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>
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>
31 #include "../../pci.h"
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);
38 static struct pcie_port_service_driver aerdriver = {
40 .port_type = PCI_EXP_TYPE_ROOT_PORT,
41 .service = PCIE_PORT_SERVICE_AER,
45 .error_resume = aer_error_resume,
46 .reset_link = aer_root_reset,
49 static int pcie_aer_disable;
56 bool pci_aer_available(void)
58 return !pcie_aer_disable && pci_msi_enabled();
61 static int set_device_error_reporting(struct pci_dev *dev, void *data)
63 bool enable = *((bool *)data);
64 int type = pci_pcie_type(dev);
66 if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
67 (type == PCI_EXP_TYPE_UPSTREAM) ||
68 (type == PCI_EXP_TYPE_DOWNSTREAM)) {
70 pci_enable_pcie_error_reporting(dev);
72 pci_disable_pcie_error_reporting(dev);
76 pcie_set_ecrc_checking(dev);
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.
86 static void set_downstream_devices_error_reporting(struct pci_dev *dev,
89 set_device_error_reporting(dev, &enable);
91 if (!dev->subordinate)
93 pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
97 * aer_enable_rootport - enable Root Port's interrupts when receiving messages
98 * @rpc: pointer to a Root Port data structure
100 * Invoked when PCIe bus loads AER service driver.
102 static void aer_enable_rootport(struct aer_rpc *rpc)
104 struct pci_dev *pdev = rpc->rpd->port;
109 /* Clear PCIe Capability's Device Status */
110 pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, ®16);
111 pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
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);
117 aer_pos = pdev->aer_cap;
118 /* Clear error status */
119 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32);
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, ®32);
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, ®32);
124 pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
127 * Enable error reporting for the root port device and downstream port
130 set_downstream_devices_error_reporting(pdev, true);
132 /* Enable Root Port's interrupt in response to error messages */
133 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, ®32);
134 reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
135 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
139 * aer_disable_rootport - disable Root Port's interrupts when receiving messages
140 * @rpc: pointer to a Root Port data structure
142 * Invoked when PCIe bus unloads AER service driver.
144 static void aer_disable_rootport(struct aer_rpc *rpc)
146 struct pci_dev *pdev = rpc->rpd->port;
151 * Disable error reporting for the root port device and downstream port
154 set_downstream_devices_error_reporting(pdev, false);
157 /* Disable Root's interrupt in response to error messages */
158 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32);
159 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
160 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
162 /* Clear Root's error status reg */
163 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, ®32);
164 pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
168 * aer_irq - Root Port's ISR
169 * @irq: IRQ assigned to Root Port
170 * @context: pointer to Root Port data structure
172 * Invoked when Root Port detects AER messages.
174 irqreturn_t aer_irq(int irq, void *context)
176 unsigned int status, id;
177 struct pcie_device *pdev = (struct pcie_device *)context;
178 struct aer_rpc *rpc = get_service_data(pdev);
183 pos = pdev->port->aer_cap;
185 * Must lock access to Root Error Status Reg, Root Error ID Reg,
186 * and Root error producer/consumer index
188 spin_lock_irqsave(&rpc->e_lock, flags);
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);
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);
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)
205 if (next_prod_idx == rpc->cons_idx) {
207 * Error Storm Condition - possibly the same error occurred.
210 spin_unlock_irqrestore(&rpc->e_lock, flags);
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);
218 /* Invoke DPC handler */
219 schedule_work(&rpc->dpc_handler);
223 EXPORT_SYMBOL_GPL(aer_irq);
226 * aer_alloc_rpc - allocate Root Port data structure
227 * @dev: pointer to the pcie_dev data structure
229 * Invoked when Root Port's AER service is loaded.
231 static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
235 rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
239 /* Initialize Root lock access, e_lock, to Root Error Status Reg */
240 spin_lock_init(&rpc->e_lock);
243 INIT_WORK(&rpc->dpc_handler, aer_isr);
244 mutex_init(&rpc->rpc_mutex);
246 /* Use PCIe bus function to store rpc into PCIe device */
247 set_service_data(dev, rpc);
253 * aer_remove - clean up resources
254 * @dev: pointer to the pcie_dev data structure
256 * Invoked when PCI Express bus unloads or AER probe fails.
258 static void aer_remove(struct pcie_device *dev)
260 struct aer_rpc *rpc = get_service_data(dev);
263 /* If register interrupt service, it must be free. */
265 free_irq(dev->irq, dev);
267 flush_work(&rpc->dpc_handler);
268 aer_disable_rootport(rpc);
270 set_service_data(dev, NULL);
275 * aer_probe - initialize resources
276 * @dev: pointer to the pcie_dev data structure
278 * Invoked when PCI Express bus loads AER service driver.
280 static int aer_probe(struct pcie_device *dev)
284 struct device *device = &dev->port->dev;
286 /* Alloc rpc data structure */
287 rpc = aer_alloc_rpc(dev);
289 dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
294 /* Request IRQ ISR */
295 status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
297 dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
305 aer_enable_rootport(rpc);
306 dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
311 * aer_root_reset - reset link on Root Port
312 * @dev: pointer to Root Port's pci_dev data structure
314 * Invoked by Port Bus driver when performing link reset at Root Port.
316 static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
323 /* Disable Root's interrupt in response to error messages */
324 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32);
325 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
326 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
328 pci_reset_bridge_secondary_bus(dev);
329 dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n");
331 /* Clear Root Error Status */
332 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, ®32);
333 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
335 /* Enable Root Port's interrupt in response to error messages */
336 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32);
337 reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
338 pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
340 return PCI_ERS_RESULT_RECOVERED;
344 * aer_error_resume - clean up corresponding error status bits
345 * @dev: pointer to Root Port's pci_dev data structure
347 * Invoked by Port Bus driver during nonfatal recovery.
349 static void aer_error_resume(struct pci_dev *dev)
355 /* Clean up Root device status */
356 pcie_capability_read_word(dev, PCI_EXP_DEVSTA, ®16);
357 pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
359 /* Clean AER Root Error Status */
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 */
366 status &= mask; /* Clear corresponding fatal bits */
367 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
371 * aer_service_init - register AER root service driver
373 * Invoked when AER root service driver is loaded.
375 static int __init aer_service_init(void)
377 if (!pci_aer_available() || aer_acpi_firmware_first())
379 return pcie_port_service_register(&aerdriver);
381 device_initcall(aer_service_init);