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 pci_ers_result_t
aer_error_detected(struct pci_dev
*dev
,
36 enum pci_channel_state error
);
37 static void aer_error_resume(struct pci_dev
*dev
);
38 static pci_ers_result_t
aer_root_reset(struct pci_dev
*dev
);
40 static const struct pci_error_handlers aer_error_handlers
= {
41 .error_detected
= aer_error_detected
,
42 .resume
= aer_error_resume
,
45 static struct pcie_port_service_driver aerdriver
= {
47 .port_type
= PCI_EXP_TYPE_ROOT_PORT
,
48 .service
= PCIE_PORT_SERVICE_AER
,
53 .err_handler
= &aer_error_handlers
,
55 .reset_link
= aer_root_reset
,
58 static int pcie_aer_disable
;
65 bool pci_aer_available(void)
67 return !pcie_aer_disable
&& pci_msi_enabled();
70 static int set_device_error_reporting(struct pci_dev
*dev
, void *data
)
72 bool enable
= *((bool *)data
);
73 int type
= pci_pcie_type(dev
);
75 if ((type
== PCI_EXP_TYPE_ROOT_PORT
) ||
76 (type
== PCI_EXP_TYPE_UPSTREAM
) ||
77 (type
== PCI_EXP_TYPE_DOWNSTREAM
)) {
79 pci_enable_pcie_error_reporting(dev
);
81 pci_disable_pcie_error_reporting(dev
);
85 pcie_set_ecrc_checking(dev
);
91 * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports.
92 * @dev: pointer to root port's pci_dev data structure
93 * @enable: true = enable error reporting, false = disable error reporting.
95 static void set_downstream_devices_error_reporting(struct pci_dev
*dev
,
98 set_device_error_reporting(dev
, &enable
);
100 if (!dev
->subordinate
)
102 pci_walk_bus(dev
->subordinate
, set_device_error_reporting
, &enable
);
106 * aer_enable_rootport - enable Root Port's interrupts when receiving messages
107 * @rpc: pointer to a Root Port data structure
109 * Invoked when PCIe bus loads AER service driver.
111 static void aer_enable_rootport(struct aer_rpc
*rpc
)
113 struct pci_dev
*pdev
= rpc
->rpd
->port
;
118 /* Clear PCIe Capability's Device Status */
119 pcie_capability_read_word(pdev
, PCI_EXP_DEVSTA
, ®16
);
120 pcie_capability_write_word(pdev
, PCI_EXP_DEVSTA
, reg16
);
122 /* Disable system error generation in response to error messages */
123 pcie_capability_clear_word(pdev
, PCI_EXP_RTCTL
,
124 SYSTEM_ERROR_INTR_ON_MESG_MASK
);
126 aer_pos
= pdev
->aer_cap
;
127 /* Clear error status */
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
);
136 * Enable error reporting for the root port device and downstream port
139 set_downstream_devices_error_reporting(pdev
, true);
141 /* Enable Root Port's interrupt in response to error messages */
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
);
148 * aer_disable_rootport - disable Root Port's interrupts when receiving messages
149 * @rpc: pointer to a Root Port data structure
151 * Invoked when PCIe bus unloads AER service driver.
153 static void aer_disable_rootport(struct aer_rpc
*rpc
)
155 struct pci_dev
*pdev
= rpc
->rpd
->port
;
160 * Disable error reporting for the root port device and downstream port
163 set_downstream_devices_error_reporting(pdev
, false);
166 /* Disable Root's interrupt in response to error messages */
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
);
171 /* Clear Root's error status reg */
172 pci_read_config_dword(pdev
, pos
+ PCI_ERR_ROOT_STATUS
, ®32
);
173 pci_write_config_dword(pdev
, pos
+ PCI_ERR_ROOT_STATUS
, reg32
);
177 * aer_irq - Root Port's ISR
178 * @irq: IRQ assigned to Root Port
179 * @context: pointer to Root Port data structure
181 * Invoked when Root Port detects AER messages.
183 irqreturn_t
aer_irq(int irq
, void *context
)
185 unsigned int status
, id
;
186 struct pcie_device
*pdev
= (struct pcie_device
*)context
;
187 struct aer_rpc
*rpc
= get_service_data(pdev
);
192 pos
= pdev
->port
->aer_cap
;
194 * Must lock access to Root Error Status Reg, Root Error ID Reg,
195 * and Root error producer/consumer index
197 spin_lock_irqsave(&rpc
->e_lock
, flags
);
199 /* Read error status */
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
);
206 /* Read error source and clear error status */
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
);
210 /* Store error source for later DPC handler */
211 next_prod_idx
= rpc
->prod_idx
+ 1;
212 if (next_prod_idx
== AER_ERROR_SOURCES_MAX
)
214 if (next_prod_idx
== rpc
->cons_idx
) {
216 * Error Storm Condition - possibly the same error occurred.
219 spin_unlock_irqrestore(&rpc
->e_lock
, flags
);
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
);
227 /* Invoke DPC handler */
228 schedule_work(&rpc
->dpc_handler
);
232 EXPORT_SYMBOL_GPL(aer_irq
);
235 * aer_alloc_rpc - allocate Root Port data structure
236 * @dev: pointer to the pcie_dev data structure
238 * Invoked when Root Port's AER service is loaded.
240 static struct aer_rpc
*aer_alloc_rpc(struct pcie_device
*dev
)
244 rpc
= kzalloc(sizeof(struct aer_rpc
), GFP_KERNEL
);
248 /* Initialize Root lock access, e_lock, to Root Error Status Reg */
249 spin_lock_init(&rpc
->e_lock
);
252 INIT_WORK(&rpc
->dpc_handler
, aer_isr
);
253 mutex_init(&rpc
->rpc_mutex
);
255 /* Use PCIe bus function to store rpc into PCIe device */
256 set_service_data(dev
, rpc
);
262 * aer_remove - clean up resources
263 * @dev: pointer to the pcie_dev data structure
265 * Invoked when PCI Express bus unloads or AER probe fails.
267 static void aer_remove(struct pcie_device
*dev
)
269 struct aer_rpc
*rpc
= get_service_data(dev
);
272 /* If register interrupt service, it must be free. */
274 free_irq(dev
->irq
, dev
);
276 flush_work(&rpc
->dpc_handler
);
277 aer_disable_rootport(rpc
);
279 set_service_data(dev
, NULL
);
284 * aer_probe - initialize resources
285 * @dev: pointer to the pcie_dev data structure
287 * Invoked when PCI Express bus loads AER service driver.
289 static int aer_probe(struct pcie_device
*dev
)
293 struct device
*device
= &dev
->port
->dev
;
295 /* Alloc rpc data structure */
296 rpc
= aer_alloc_rpc(dev
);
298 dev_printk(KERN_DEBUG
, device
, "alloc AER rpc failed\n");
303 /* Request IRQ ISR */
304 status
= request_irq(dev
->irq
, aer_irq
, IRQF_SHARED
, "aerdrv", dev
);
306 dev_printk(KERN_DEBUG
, device
, "request AER IRQ %d failed\n",
314 aer_enable_rootport(rpc
);
315 dev_info(device
, "AER enabled with IRQ %d\n", dev
->irq
);
320 * aer_root_reset - reset link on Root Port
321 * @dev: pointer to Root Port's pci_dev data structure
323 * Invoked by Port Bus driver when performing link reset at Root Port.
325 static pci_ers_result_t
aer_root_reset(struct pci_dev
*dev
)
332 /* Disable Root's interrupt in response to error messages */
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
);
337 pci_reset_bridge_secondary_bus(dev
);
338 dev_printk(KERN_DEBUG
, &dev
->dev
, "Root Port link has been reset\n");
340 /* Clear Root Error Status */
341 pci_read_config_dword(dev
, pos
+ PCI_ERR_ROOT_STATUS
, ®32
);
342 pci_write_config_dword(dev
, pos
+ PCI_ERR_ROOT_STATUS
, reg32
);
344 /* Enable Root Port's interrupt in response to error messages */
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
);
349 return PCI_ERS_RESULT_RECOVERED
;
353 * aer_error_detected - update severity status
354 * @dev: pointer to Root Port's pci_dev data structure
355 * @error: error severity being notified by port bus
357 * Invoked by Port Bus driver during error recovery.
359 static pci_ers_result_t
aer_error_detected(struct pci_dev
*dev
,
360 enum pci_channel_state error
)
362 /* Root Port has no impact. Always recovers. */
363 return PCI_ERS_RESULT_CAN_RECOVER
;
367 * aer_error_resume - clean up corresponding error status bits
368 * @dev: pointer to Root Port's pci_dev data structure
370 * Invoked by Port Bus driver during nonfatal recovery.
372 static void aer_error_resume(struct pci_dev
*dev
)
378 /* Clean up Root device status */
379 pcie_capability_read_word(dev
, PCI_EXP_DEVSTA
, ®16
);
380 pcie_capability_write_word(dev
, PCI_EXP_DEVSTA
, reg16
);
382 /* Clean AER Root Error Status */
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
; /* Clear corresponding nonfatal bits */
389 status
&= mask
; /* Clear corresponding fatal bits */
390 pci_write_config_dword(dev
, pos
+ PCI_ERR_UNCOR_STATUS
, status
);
394 * aer_service_init - register AER root service driver
396 * Invoked when AER root service driver is loaded.
398 static int __init
aer_service_init(void)
400 if (!pci_aer_available() || aer_acpi_firmware_first())
402 return pcie_port_service_register(&aerdriver
);
404 device_initcall(aer_service_init
);