sh_eth: fix EESIPR values for SH77{34|63}
[linux/fpc-iii.git] / drivers / pci / pcie / aer / aerdrv.c
blobdea186a9d6b698488384153348389f7c9715e775
1 /*
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
6 * for more details.
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>
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>
30 #include "aerdrv.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 = {
46 .name = "aer",
47 .port_type = PCI_EXP_TYPE_ROOT_PORT,
48 .service = PCIE_PORT_SERVICE_AER,
50 .probe = aer_probe,
51 .remove = aer_remove,
53 .err_handler = &aer_error_handlers,
55 .reset_link = aer_root_reset,
58 static int pcie_aer_disable;
60 void pci_no_aer(void)
62 pcie_aer_disable = 1;
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)) {
78 if (enable)
79 pci_enable_pcie_error_reporting(dev);
80 else
81 pci_disable_pcie_error_reporting(dev);
84 if (enable)
85 pcie_set_ecrc_checking(dev);
87 return 0;
90 /**
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,
96 bool enable)
98 set_device_error_reporting(dev, &enable);
100 if (!dev->subordinate)
101 return;
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;
114 int aer_pos;
115 u16 reg16;
116 u32 reg32;
118 /* Clear PCIe Capability's Device Status */
119 pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, &reg16);
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, &reg32);
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, &reg32);
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, &reg32);
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
137 * devices.
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, &reg32);
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;
156 u32 reg32;
157 int pos;
160 * Disable error reporting for the root port device and downstream port
161 * devices.
163 set_downstream_devices_error_reporting(pdev, false);
165 pos = pdev->aer_cap;
166 /* Disable Root's interrupt in response to error messages */
167 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
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, &reg32);
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);
188 int next_prod_idx;
189 unsigned long flags;
190 int pos;
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);
203 return IRQ_NONE;
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)
213 next_prod_idx = 0;
214 if (next_prod_idx == rpc->cons_idx) {
216 * Error Storm Condition - possibly the same error occurred.
217 * Drop the error.
219 spin_unlock_irqrestore(&rpc->e_lock, flags);
220 return IRQ_HANDLED;
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);
230 return IRQ_HANDLED;
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)
242 struct aer_rpc *rpc;
244 rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
245 if (!rpc)
246 return NULL;
248 /* Initialize Root lock access, e_lock, to Root Error Status Reg */
249 spin_lock_init(&rpc->e_lock);
251 rpc->rpd = dev;
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);
258 return 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);
271 if (rpc) {
272 /* If register interrupt service, it must be free. */
273 if (rpc->isr)
274 free_irq(dev->irq, dev);
276 flush_work(&rpc->dpc_handler);
277 aer_disable_rootport(rpc);
278 kfree(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)
291 int status;
292 struct aer_rpc *rpc;
293 struct device *device = &dev->port->dev;
295 /* Alloc rpc data structure */
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;
303 /* Request IRQ ISR */
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;
312 rpc->isr = 1;
314 aer_enable_rootport(rpc);
315 dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
316 return 0;
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)
327 u32 reg32;
328 int pos;
330 pos = dev->aer_cap;
332 /* Disable Root's interrupt in response to error messages */
333 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
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, &reg32);
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, &reg32);
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)
374 int pos;
375 u32 status, mask;
376 u16 reg16;
378 /* Clean up Root device status */
379 pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
380 pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
382 /* Clean AER Root Error Status */
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; /* Clear corresponding nonfatal bits */
388 else
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())
401 return -ENXIO;
402 return pcie_port_service_register(&aerdriver);
404 device_initcall(aer_service_init);