ia64/linux-2.6.18-xen.hg

changeset 742:6591b4869889

merge with linux-2.6.18-xen.hg
author Isaku Yamahata <yamahata@valinux.co.jp>
date Wed Nov 26 10:24:15 2008 +0900 (2008-11-26)
parents 61d1f2810617 f236d7def994
children 6743af9fffc6 0b859c9516ba
files
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Documentation/pcieaer-howto.txt	Wed Nov 26 10:24:15 2008 +0900
     1.3 @@ -0,0 +1,253 @@
     1.4 +   The PCI Express Advanced Error Reporting Driver Guide HOWTO
     1.5 +		T. Long Nguyen	<tom.l.nguyen@intel.com>
     1.6 +		Yanmin Zhang	<yanmin.zhang@intel.com>
     1.7 +				07/29/2006
     1.8 +
     1.9 +
    1.10 +1. Overview
    1.11 +
    1.12 +1.1 About this guide
    1.13 +
    1.14 +This guide describes the basics of the PCI Express Advanced Error
    1.15 +Reporting (AER) driver and provides information on how to use it, as
    1.16 +well as how to enable the drivers of endpoint devices to conform with
    1.17 +PCI Express AER driver.
    1.18 +
    1.19 +1.2 Copyright  Intel Corporation 2006.
    1.20 +
    1.21 +1.3 What is the PCI Express AER Driver?
    1.22 +
    1.23 +PCI Express error signaling can occur on the PCI Express link itself
    1.24 +or on behalf of transactions initiated on the link. PCI Express
    1.25 +defines two error reporting paradigms: the baseline capability and
    1.26 +the Advanced Error Reporting capability. The baseline capability is
    1.27 +required of all PCI Express components providing a minimum defined
    1.28 +set of error reporting requirements. Advanced Error Reporting
    1.29 +capability is implemented with a PCI Express advanced error reporting
    1.30 +extended capability structure providing more robust error reporting.
    1.31 +
    1.32 +The PCI Express AER driver provides the infrastructure to support PCI
    1.33 +Express Advanced Error Reporting capability. The PCI Express AER
    1.34 +driver provides three basic functions:
    1.35 +
    1.36 +-	Gathers the comprehensive error information if errors occurred.
    1.37 +-	Reports error to the users.
    1.38 +-	Performs error recovery actions.
    1.39 +
    1.40 +AER driver only attaches root ports which support PCI-Express AER
    1.41 +capability.
    1.42 +
    1.43 +
    1.44 +2. User Guide
    1.45 +
    1.46 +2.1 Include the PCI Express AER Root Driver into the Linux Kernel
    1.47 +
    1.48 +The PCI Express AER Root driver is a Root Port service driver attached
    1.49 +to the PCI Express Port Bus driver. If a user wants to use it, the driver
    1.50 +has to be compiled. Option CONFIG_PCIEAER supports this capability. It
    1.51 +depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
    1.52 +CONFIG_PCIEAER = y.
    1.53 +
    1.54 +2.2 Load PCI Express AER Root Driver
    1.55 +There is a case where a system has AER support in BIOS. Enabling the AER
    1.56 +Root driver and having AER support in BIOS may result unpredictable
    1.57 +behavior. To avoid this conflict, a successful load of the AER Root driver
    1.58 +requires ACPI _OSC support in the BIOS to allow the AER Root driver to
    1.59 +request for native control of AER. See the PCI FW 3.0 Specification for
    1.60 +details regarding OSC usage. Currently, lots of firmwares don't provide
    1.61 +_OSC support while they use PCI Express. To support such firmwares,
    1.62 +forceload, a parameter of type bool, could enable AER to continue to
    1.63 +be initiated although firmwares have no _OSC support. To enable the
    1.64 +walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
    1.65 +when booting kernel. Note that forceload=n by default.
    1.66 +
    1.67 +2.3 AER error output
    1.68 +When a PCI-E AER error is captured, an error message will be outputed to
    1.69 +console. If it's a correctable error, it is outputed as a warning.
    1.70 +Otherwise, it is printed as an error. So users could choose different
    1.71 +log level to filter out correctable error messages.
    1.72 +
    1.73 +Below shows an example.
    1.74 ++------ PCI-Express Device Error -----+
    1.75 +Error Severity          : Uncorrected (Fatal)
    1.76 +PCIE Bus Error type     : Transaction Layer
    1.77 +Unsupported Request     : First
    1.78 +Requester ID            : 0500
    1.79 +VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
    1.80 +TLB Header:
    1.81 +04000001 00200a03 05010000 00050100
    1.82 +
    1.83 +In the example, 'Requester ID' means the ID of the device who sends
    1.84 +the error message to root port. Pls. refer to pci express specs for
    1.85 +other fields.
    1.86 +
    1.87 +
    1.88 +3. Developer Guide
    1.89 +
    1.90 +To enable AER aware support requires a software driver to configure
    1.91 +the AER capability structure within its device and to provide callbacks.
    1.92 +
    1.93 +To support AER better, developers need understand how AER does work
    1.94 +firstly.
    1.95 +
    1.96 +PCI Express errors are classified into two types: correctable errors
    1.97 +and uncorrectable errors. This classification is based on the impacts
    1.98 +of those errors, which may result in degraded performance or function
    1.99 +failure.
   1.100 +
   1.101 +Correctable errors pose no impacts on the functionality of the
   1.102 +interface. The PCI Express protocol can recover without any software
   1.103 +intervention or any loss of data. These errors are detected and
   1.104 +corrected by hardware. Unlike correctable errors, uncorrectable
   1.105 +errors impact functionality of the interface. Uncorrectable errors
   1.106 +can cause a particular transaction or a particular PCI Express link
   1.107 +to be unreliable. Depending on those error conditions, uncorrectable
   1.108 +errors are further classified into non-fatal errors and fatal errors.
   1.109 +Non-fatal errors cause the particular transaction to be unreliable,
   1.110 +but the PCI Express link itself is fully functional. Fatal errors, on
   1.111 +the other hand, cause the link to be unreliable.
   1.112 +
   1.113 +When AER is enabled, a PCI Express device will automatically send an
   1.114 +error message to the PCIE root port above it when the device captures
   1.115 +an error. The Root Port, upon receiving an error reporting message,
   1.116 +internally processes and logs the error message in its PCI Express
   1.117 +capability structure. Error information being logged includes storing
   1.118 +the error reporting agent's requestor ID into the Error Source
   1.119 +Identification Registers and setting the error bits of the Root Error
   1.120 +Status Register accordingly. If AER error reporting is enabled in Root
   1.121 +Error Command Register, the Root Port generates an interrupt if an
   1.122 +error is detected.
   1.123 +
   1.124 +Note that the errors as described above are related to the PCI Express
   1.125 +hierarchy and links. These errors do not include any device specific
   1.126 +errors because device specific errors will still get sent directly to
   1.127 +the device driver.
   1.128 +
   1.129 +3.1 Configure the AER capability structure
   1.130 +
   1.131 +AER aware drivers of PCI Express component need change the device
   1.132 +control registers to enable AER. They also could change AER registers,
   1.133 +including mask and severity registers. Helper function
   1.134 +pci_enable_pcie_error_reporting could be used to enable AER. See
   1.135 +section 3.3.
   1.136 +
   1.137 +3.2. Provide callbacks
   1.138 +
   1.139 +3.2.1 callback reset_link to reset pci express link
   1.140 +
   1.141 +This callback is used to reset the pci express physical link when a
   1.142 +fatal error happens. The root port aer service driver provides a
   1.143 +default reset_link function, but different upstream ports might
   1.144 +have different specifications to reset pci express link, so all
   1.145 +upstream ports should provide their own reset_link functions.
   1.146 +
   1.147 +In struct pcie_port_service_driver, a new pointer, reset_link, is
   1.148 +added.
   1.149 +
   1.150 +pci_ers_result_t (*reset_link) (struct pci_dev *dev);
   1.151 +
   1.152 +Section 3.2.2.2 provides more detailed info on when to call
   1.153 +reset_link.
   1.154 +
   1.155 +3.2.2 PCI error-recovery callbacks
   1.156 +
   1.157 +The PCI Express AER Root driver uses error callbacks to coordinate
   1.158 +with downstream device drivers associated with a hierarchy in question
   1.159 +when performing error recovery actions.
   1.160 +
   1.161 +Data struct pci_driver has a pointer, err_handler, to point to
   1.162 +pci_error_handlers who consists of a couple of callback function
   1.163 +pointers. AER driver follows the rules defined in
   1.164 +pci-error-recovery.txt except pci express specific parts (e.g.
   1.165 +reset_link). Pls. refer to pci-error-recovery.txt for detailed
   1.166 +definitions of the callbacks.
   1.167 +
   1.168 +Below sections specify when to call the error callback functions.
   1.169 +
   1.170 +3.2.2.1 Correctable errors
   1.171 +
   1.172 +Correctable errors pose no impacts on the functionality of
   1.173 +the interface. The PCI Express protocol can recover without any
   1.174 +software intervention or any loss of data. These errors do not
   1.175 +require any recovery actions. The AER driver clears the device's
   1.176 +correctable error status register accordingly and logs these errors.
   1.177 +
   1.178 +3.2.2.2 Non-correctable (non-fatal and fatal) errors
   1.179 +
   1.180 +If an error message indicates a non-fatal error, performing link reset
   1.181 +at upstream is not required. The AER driver calls error_detected(dev,
   1.182 +pci_channel_io_normal) to all drivers associated within a hierarchy in
   1.183 +question. for example,
   1.184 +EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
   1.185 +If Upstream port A captures an AER error, the hierarchy consists of
   1.186 +Downstream port B and EndPoint.
   1.187 +
   1.188 +A driver may return PCI_ERS_RESULT_CAN_RECOVER,
   1.189 +PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
   1.190 +whether it can recover or the AER driver calls mmio_enabled as next.
   1.191 +
   1.192 +If an error message indicates a fatal error, kernel will broadcast
   1.193 +error_detected(dev, pci_channel_io_frozen) to all drivers within
   1.194 +a hierarchy in question. Then, performing link reset at upstream is
   1.195 +necessary. As different kinds of devices might use different approaches
   1.196 +to reset link, AER port service driver is required to provide the
   1.197 +function to reset link. Firstly, kernel looks for if the upstream
   1.198 +component has an aer driver. If it has, kernel uses the reset_link
   1.199 +callback of the aer driver. If the upstream component has no aer driver
   1.200 +and the port is downstream port, we will use the aer driver of the
   1.201 +root port who reports the AER error. As for upstream ports,
   1.202 +they should provide their own aer service drivers with reset_link
   1.203 +function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
   1.204 +reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
   1.205 +to mmio_enabled.
   1.206 +
   1.207 +3.3 helper functions
   1.208 +
   1.209 +3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
   1.210 +pci_find_aer_capability locates the PCI Express AER capability
   1.211 +in the device configuration space. If the device doesn't support
   1.212 +PCI-Express AER, the function returns 0.
   1.213 +
   1.214 +3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
   1.215 +pci_enable_pcie_error_reporting enables the device to send error
   1.216 +messages to root port when an error is detected. Note that devices
   1.217 +don't enable the error reporting by default, so device drivers need
   1.218 +call this function to enable it.
   1.219 +
   1.220 +3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
   1.221 +pci_disable_pcie_error_reporting disables the device to send error
   1.222 +messages to root port when an error is detected.
   1.223 +
   1.224 +3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
   1.225 +pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
   1.226 +error status register.
   1.227 +
   1.228 +3.4 Frequent Asked Questions
   1.229 +
   1.230 +Q: What happens if a PCI Express device driver does not provide an
   1.231 +error recovery handler (pci_driver->err_handler is equal to NULL)?
   1.232 +
   1.233 +A: The devices attached with the driver won't be recovered. If the
   1.234 +error is fatal, kernel will print out warning messages. Please refer
   1.235 +to section 3 for more information.
   1.236 +
   1.237 +Q: What happens if an upstream port service driver does not provide
   1.238 +callback reset_link?
   1.239 +
   1.240 +A: Fatal error recovery will fail if the errors are reported by the
   1.241 +upstream ports who are attached by the service driver.
   1.242 +
   1.243 +Q: How does this infrastructure deal with driver that is not PCI
   1.244 +Express aware?
   1.245 +
   1.246 +A: This infrastructure calls the error callback functions of the
   1.247 +driver when an error happens. But if the driver is not aware of
   1.248 +PCI Express, the device might not report its own errors to root
   1.249 +port.
   1.250 +
   1.251 +Q: What modifications will that driver need to make it compatible
   1.252 +with the PCI Express AER Root driver?
   1.253 +
   1.254 +A: It could call the helper functions to enable AER in devices and
   1.255 +cleanup uncorrectable status register. Pls. refer to section 3.3.
   1.256 +
     2.1 --- a/arch/i386/kernel/io_apic-xen.c	Tue Nov 04 12:43:37 2008 +0900
     2.2 +++ b/arch/i386/kernel/io_apic-xen.c	Wed Nov 26 10:24:15 2008 +0900
     2.3 @@ -1216,6 +1216,9 @@ int assign_irq_vector(int irq)
     2.4  
     2.5  	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
     2.6  
     2.7 +	if (irq < PIRQ_BASE || irq - PIRQ_BASE > NR_PIRQS)
     2.8 +		return -EINVAL;
     2.9 +
    2.10  	spin_lock_irqsave(&vector_lock, flags);
    2.11  
    2.12  	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
    2.13 @@ -2567,8 +2570,10 @@ static int ioapic_resume(struct sys_devi
    2.14  
    2.15  static struct sysdev_class ioapic_sysdev_class = {
    2.16  	set_kset_name("ioapic"),
    2.17 +#ifndef CONFIG_XEN
    2.18  	.suspend = ioapic_suspend,
    2.19  	.resume = ioapic_resume,
    2.20 +#endif
    2.21  };
    2.22  
    2.23  static int __init ioapic_init_sysfs(void)
     3.1 --- a/arch/i386/pci/irq.c	Tue Nov 04 12:43:37 2008 +0900
     3.2 +++ b/arch/i386/pci/irq.c	Wed Nov 26 10:24:15 2008 +0900
     3.3 @@ -558,6 +558,15 @@ static __init int intel_router_probe(str
     3.4  			r->set = pirq_piix_set;
     3.5  			return 1;
     3.6  	}
     3.7 +
     3.8 +	if ((device >= PCI_DEVICE_ID_INTEL_PCH_LPC_MIN) && 
     3.9 +		(device <= PCI_DEVICE_ID_INTEL_PCH_LPC_MAX)) {
    3.10 +		r->name = "PIIX/ICH";
    3.11 +		r->get = pirq_piix_get;
    3.12 +		r->set = pirq_piix_set;
    3.13 +		return 1;
    3.14 +	}
    3.15 +
    3.16  	return 0;
    3.17  }
    3.18  
     4.1 --- a/arch/x86_64/kernel/io_apic-xen.c	Tue Nov 04 12:43:37 2008 +0900
     4.2 +++ b/arch/x86_64/kernel/io_apic-xen.c	Wed Nov 26 10:24:15 2008 +0900
     4.3 @@ -895,6 +895,9 @@ int assign_irq_vector(int irq)
     4.4    
     4.5    	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
     4.6  
     4.7 +	if (irq < PIRQ_BASE || irq - PIRQ_BASE > NR_PIRQS)
     4.8 +		return -EINVAL;
     4.9 +
    4.10  	spin_lock_irqsave(&vector_lock, flags);
    4.11  
    4.12    	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
    4.13 @@ -2104,8 +2107,10 @@ static int ioapic_resume(struct sys_devi
    4.14  
    4.15  static struct sysdev_class ioapic_sysdev_class = {
    4.16  	set_kset_name("ioapic"),
    4.17 +#ifndef CONFIG_XEN
    4.18  	.suspend = ioapic_suspend,
    4.19  	.resume = ioapic_resume,
    4.20 +#endif
    4.21  };
    4.22  
    4.23  static int __init ioapic_init_sysfs(void)
     5.1 --- a/drivers/i2c/busses/Kconfig	Tue Nov 04 12:43:37 2008 +0900
     5.2 +++ b/drivers/i2c/busses/Kconfig	Wed Nov 26 10:24:15 2008 +0900
     5.3 @@ -127,6 +127,7 @@ config I2C_I801
     5.4  	    ICH8
     5.5  	    ICH9
     5.6  	    ICH10
     5.7 +            PCH
     5.8  
     5.9  	  This driver can also be built as a module.  If so, the module
    5.10  	  will be called i2c-i801.
     6.1 --- a/drivers/i2c/busses/i2c-i801.c	Tue Nov 04 12:43:37 2008 +0900
     6.2 +++ b/drivers/i2c/busses/i2c-i801.c	Wed Nov 26 10:24:15 2008 +0900
     6.3 @@ -36,6 +36,7 @@
     6.4      ICH9		2930
     6.5      ICH10		3A30
     6.6      ICH10		3A60
     6.7 +    PCH			3B30
     6.8      This driver supports several versions of Intel's I/O Controller Hubs (ICH).
     6.9      For SMBus support, they are similar to the PIIX4 and are part
    6.10      of Intel's '810' and other chipsets.
    6.11 @@ -463,6 +464,7 @@ static struct pci_device_id i801_ids[] =
    6.12  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
    6.13  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
    6.14  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
    6.15 +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) },
    6.16  	{ 0, }
    6.17  };
    6.18  
     7.1 --- a/drivers/pci/msi-xen.c	Tue Nov 04 12:43:37 2008 +0900
     7.2 +++ b/drivers/pci/msi-xen.c	Wed Nov 26 10:24:15 2008 +0900
     7.3 @@ -48,6 +48,13 @@ struct msi_pirq_entry {
     7.4  	struct list_head list;
     7.5  	int pirq;
     7.6  	int entry_nr;
     7.7 +#ifdef CONFIG_PM
     7.8 +	/* PM save area for MSIX address/data */
     7.9 +	void __iomem *mask_base;
    7.10 +	u32	address_hi_save;
    7.11 +	u32	address_lo_save;
    7.12 +	u32	data_save;
    7.13 +#endif
    7.14  };
    7.15  
    7.16  static struct msi_dev_list *get_msi_dev_pirq_list(struct pci_dev *dev)
    7.17 @@ -83,7 +90,7 @@ static struct msi_dev_list *get_msi_dev_
    7.18  	return ret;
    7.19  }
    7.20  
    7.21 -static int attach_pirq_entry(int pirq, int entry_nr,
    7.22 +static int attach_pirq_entry(int pirq, int entry_nr, u64 table_base,
    7.23                               struct msi_dev_list *msi_dev_entry)
    7.24  {
    7.25  	struct msi_pirq_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
    7.26 @@ -93,6 +100,9 @@ static int attach_pirq_entry(int pirq, i
    7.27  		return -ENOMEM;
    7.28  	entry->pirq = pirq;
    7.29  	entry->entry_nr = entry_nr;
    7.30 +#ifdef COMFIG_PM
    7.31 +	entry->mask_base = table_base;
    7.32 +#endif
    7.33  	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
    7.34  	list_add_tail(&entry->list, &msi_dev_entry->pirq_list_head);
    7.35  	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
    7.36 @@ -299,104 +309,173 @@ static void enable_msi_mode(struct pci_d
    7.37  #ifdef CONFIG_PM
    7.38  int pci_save_msi_state(struct pci_dev *dev)
    7.39  {
    7.40 -	int pos;
    7.41 +	int pos, i = 0;
    7.42 +	u16 control;
    7.43 +	struct pci_cap_saved_state *save_state;
    7.44 +	u32 *cap;
    7.45  
    7.46  	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
    7.47  	if (pos <= 0 || dev->no_msi)
    7.48  		return 0;
    7.49  
    7.50 -	if (!dev->msi_enabled)
    7.51 +	pci_read_config_word(dev, msi_control_reg(pos), &control);
    7.52 +	if (!(control & PCI_MSI_FLAGS_ENABLE))
    7.53  		return 0;
    7.54  
    7.55 -	/* Restore dev->irq to its default pin-assertion vector */
    7.56 -	msi_unmap_pirq(dev, dev->irq);
    7.57 -	/* Disable MSI mode */
    7.58 -	disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
    7.59 -	/* Set the flags for use of restore */
    7.60 -	dev->msi_enabled = 1;
    7.61 +	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
    7.62 +		GFP_KERNEL);
    7.63 +	if (!save_state) {
    7.64 +		printk(KERN_ERR "Out of memory in pci_save_msi_state\n");
    7.65 +		return -ENOMEM;
    7.66 +	}
    7.67 +	cap = &save_state->data[0];
    7.68 +
    7.69 +	pci_read_config_dword(dev, pos, &cap[i++]);
    7.70 +	control = cap[0] >> 16;
    7.71 +	pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]);
    7.72 +	if (control & PCI_MSI_FLAGS_64BIT) {
    7.73 +		pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]);
    7.74 +		pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]);
    7.75 +	} else
    7.76 +		pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
    7.77 +	if (control & PCI_MSI_FLAGS_MASKBIT)
    7.78 +		pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
    7.79 +	save_state->cap_nr = PCI_CAP_ID_MSI;
    7.80 +	pci_add_saved_cap(dev, save_state);
    7.81  	return 0;
    7.82  }
    7.83  
    7.84  void pci_restore_msi_state(struct pci_dev *dev)
    7.85  {
    7.86 -	int pos, pirq;
    7.87 -
    7.88 -	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
    7.89 -	if (pos <= 0)
    7.90 -		return;
    7.91 +	int i = 0, pos;
    7.92 +	u16 control;
    7.93 +	struct pci_cap_saved_state *save_state;
    7.94 +	u32 *cap;
    7.95  
    7.96 -	if (!dev->msi_enabled)
    7.97 +	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
    7.98 +	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
    7.99 +	if (!save_state || pos <= 0)
   7.100  		return;
   7.101 +	cap = &save_state->data[0];
   7.102  
   7.103 -	pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 0);
   7.104 -	if (pirq < 0)
   7.105 -		return;
   7.106 +	control = cap[i++] >> 16;
   7.107 +	pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
   7.108 +	if (control & PCI_MSI_FLAGS_64BIT) {
   7.109 +		pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
   7.110 +		pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]);
   7.111 +	} else
   7.112 +		pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]);
   7.113 +	if (control & PCI_MSI_FLAGS_MASKBIT)
   7.114 +		pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
   7.115 +	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
   7.116  	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
   7.117 +	pci_remove_saved_cap(save_state);
   7.118 +	kfree(save_state);
   7.119  }
   7.120  
   7.121  int pci_save_msix_state(struct pci_dev *dev)
   7.122  {
   7.123  	int pos;
   7.124 +	u16 control;
   7.125 +	struct pci_cap_saved_state *save_state;
   7.126  	unsigned long flags;
   7.127  	struct msi_dev_list *msi_dev_entry;
   7.128 -	struct msi_pirq_entry *pirq_entry, *tmp;
   7.129 +	struct msi_pirq_entry *pirq_entry;
   7.130  
   7.131  	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   7.132  	if (pos <= 0 || dev->no_msi)
   7.133  		return 0;
   7.134  
   7.135 +	printk(KERN_CRIT "Saving MSIX cap\n");
   7.136 +
   7.137  	/* save the capability */
   7.138 -	if (!dev->msix_enabled)
   7.139 +	pci_read_config_word(dev, msi_control_reg(pos), &control);
   7.140 +	if (!(control & PCI_MSIX_FLAGS_ENABLE))
   7.141  		return 0;
   7.142 +	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
   7.143 +		GFP_KERNEL);
   7.144 +	if (!save_state) {
   7.145 +		printk(KERN_ERR "Out of memory in pci_save_msix_state\n");
   7.146 +		return -ENOMEM;
   7.147 +	}
   7.148 +	*((u16 *)&save_state->data[0]) = control;
   7.149  
   7.150  	msi_dev_entry = get_msi_dev_pirq_list(dev);
   7.151  
   7.152  	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   7.153 -        list_for_each_entry_safe(pirq_entry, tmp,
   7.154 -                                 &msi_dev_entry->pirq_list_head, list)
   7.155 -		msi_unmap_pirq(dev, pirq_entry->pirq);
   7.156 +	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
   7.157 +		int j;
   7.158 +		void __iomem *base;
   7.159 +
   7.160 +		/* save the table */
   7.161 +		base = pirq_entry->mask_base;
   7.162 +		j = pirq_entry->entry_nr;
   7.163 +		printk(KERN_CRIT "Save msix table entry %d pirq %x base %p\n",
   7.164 +		       j, pirq_entry->pirq, base);
   7.165 +
   7.166 +		pirq_entry->address_lo_save =
   7.167 +			readl(base + j * PCI_MSIX_ENTRY_SIZE +
   7.168 +			      PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
   7.169 +		pirq_entry->address_hi_save =
   7.170 +			readl(base + j * PCI_MSIX_ENTRY_SIZE +
   7.171 +			      PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
   7.172 +		pirq_entry->data_save =
   7.173 +			readl(base + j * PCI_MSIX_ENTRY_SIZE +
   7.174 +			      PCI_MSIX_ENTRY_DATA_OFFSET);
   7.175 +	}
   7.176  	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
   7.177  
   7.178 -	disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
   7.179 -	/* Set the flags for use of restore */
   7.180 -	dev->msix_enabled = 1;
   7.181 -
   7.182 +	save_state->cap_nr = PCI_CAP_ID_MSIX;
   7.183 +	pci_add_saved_cap(dev, save_state);
   7.184  	return 0;
   7.185  }
   7.186  
   7.187  void pci_restore_msix_state(struct pci_dev *dev)
   7.188  {
   7.189 -	int pos;
   7.190 +	u16 save;
   7.191 +	int pos, j;
   7.192 +	void __iomem *base;
   7.193 +	struct pci_cap_saved_state *save_state;
   7.194  	unsigned long flags;
   7.195 -	u64 table_base;
   7.196  	struct msi_dev_list *msi_dev_entry;
   7.197 -	struct msi_pirq_entry *pirq_entry, *tmp;
   7.198 +	struct msi_pirq_entry *pirq_entry;
   7.199 +
   7.200 +	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
   7.201 +	if (!save_state)
   7.202 +		return;
   7.203 +	printk(KERN_CRIT "Restoring MSIX cap\n");
   7.204 +
   7.205 +	save = *((u16 *)&save_state->data[0]);
   7.206 +	pci_remove_saved_cap(save_state);
   7.207 +	kfree(save_state);
   7.208  
   7.209  	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
   7.210  	if (pos <= 0)
   7.211  		return;
   7.212  
   7.213 -	if (!dev->msix_enabled)
   7.214 -		return;
   7.215 -
   7.216  	msi_dev_entry = get_msi_dev_pirq_list(dev);
   7.217 -	table_base = find_table_base(dev, pos);
   7.218 -	if (!table_base)
   7.219 -		return;
   7.220  
   7.221  	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   7.222 -	list_for_each_entry_safe(pirq_entry, tmp,
   7.223 -				 &msi_dev_entry->pirq_list_head, list) {
   7.224 -		int rc = msi_map_pirq_to_vector(dev, pirq_entry->pirq,
   7.225 -						pirq_entry->entry_nr, table_base);
   7.226 -		if (rc < 0)
   7.227 -			printk(KERN_WARNING
   7.228 -			       "%s: re-mapping irq #%d (pirq%d) failed: %d\n",
   7.229 -			       pci_name(dev), pirq_entry->entry_nr,
   7.230 -			       pirq_entry->pirq, rc);
   7.231 +	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
   7.232 +		/* route the table */
   7.233 +		base = pirq_entry->mask_base;
   7.234 +		j = pirq_entry->entry_nr;
   7.235 +
   7.236 +		printk(KERN_CRIT "Restore msix table entry %d pirq %x base %p\n",
   7.237 +		       j, pirq_entry->pirq, base);
   7.238 +		writel(pirq_entry->address_lo_save,
   7.239 +			base + j * PCI_MSIX_ENTRY_SIZE +
   7.240 +			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
   7.241 +		writel(pirq_entry->address_hi_save,
   7.242 +			base + j * PCI_MSIX_ENTRY_SIZE +
   7.243 +			PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
   7.244 +		writel(pirq_entry->data_save,
   7.245 +			base + j * PCI_MSIX_ENTRY_SIZE +
   7.246 +			PCI_MSIX_ENTRY_DATA_OFFSET);
   7.247  	}
   7.248  	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
   7.249  
   7.250 +	pci_write_config_word(dev, msi_control_reg(pos), save);
   7.251  	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
   7.252  }
   7.253  #endif
   7.254 @@ -475,7 +554,7 @@ static int msix_capability_init(struct p
   7.255  		pirq = msi_map_vector(dev, entries[i].entry, table_base);
   7.256  		if (pirq < 0)
   7.257  			break;
   7.258 -		attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
   7.259 +		attach_pirq_entry(pirq, entries[i].entry, table_base, msi_dev_entry);
   7.260  		(entries + i)->vector = pirq;
   7.261  	}
   7.262  
   7.263 @@ -660,7 +739,7 @@ int pci_enable_msix(struct pci_dev* dev,
   7.264  			if (mapped)
   7.265  				continue;
   7.266  			irq = evtchn_map_pirq(-1, entries[i].vector);
   7.267 -			attach_pirq_entry(irq, entries[i].entry, msi_dev_entry);
   7.268 +			attach_pirq_entry(irq, entries[i].entry, 0, msi_dev_entry);
   7.269  			entries[i].vector = irq;
   7.270  		}
   7.271          return 0;
     8.1 --- a/drivers/pci/pcie/Kconfig	Tue Nov 04 12:43:37 2008 +0900
     8.2 +++ b/drivers/pci/pcie/Kconfig	Wed Nov 26 10:24:15 2008 +0900
     8.3 @@ -34,3 +34,4 @@ config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
     8.4  	   
     8.5  	  When in doubt, say N.
     8.6  
     8.7 +source "drivers/pci/pcie/aer/Kconfig"
     9.1 --- a/drivers/pci/pcie/Makefile	Tue Nov 04 12:43:37 2008 +0900
     9.2 +++ b/drivers/pci/pcie/Makefile	Wed Nov 26 10:24:15 2008 +0900
     9.3 @@ -5,3 +5,6 @@
     9.4  pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o
     9.5  
     9.6  obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o
     9.7 +
     9.8 +# Build PCI Express AER if needed
     9.9 +obj-$(CONFIG_PCIEAER)		+= aer/
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/drivers/pci/pcie/aer/Kconfig	Wed Nov 26 10:24:15 2008 +0900
    10.3 @@ -0,0 +1,12 @@
    10.4 +#
    10.5 +# PCI Express Root Port Device AER Configuration
    10.6 +#
    10.7 +
    10.8 +config PCIEAER
    10.9 +	boolean "Root Port Advanced Error Reporting support"
   10.10 +	depends on PCIEPORTBUS && ACPI
   10.11 +	default y
   10.12 +	help
   10.13 +	  This enables PCI Express Root Port Advanced Error Reporting
   10.14 +	  (AER) driver support. Error reporting messages sent to Root
   10.15 +	  Port will be handled by PCI Express AER driver.
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/drivers/pci/pcie/aer/Makefile	Wed Nov 26 10:24:15 2008 +0900
    11.3 @@ -0,0 +1,8 @@
    11.4 +#
    11.5 +# Makefile for PCI-Express Root Port Advanced Error Reporting Driver
    11.6 +#
    11.7 +
    11.8 +obj-$(CONFIG_PCIEAER) += aerdriver.o
    11.9 +
   11.10 +aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o aerdrv_acpi.o
   11.11 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/drivers/pci/pcie/aer/aerdrv.c	Wed Nov 26 10:24:15 2008 +0900
    12.3 @@ -0,0 +1,346 @@
    12.4 +/*
    12.5 + * drivers/pci/pcie/aer/aerdrv.c
    12.6 + *
    12.7 + * This file is subject to the terms and conditions of the GNU General Public
    12.8 + * License.  See the file "COPYING" in the main directory of this archive
    12.9 + * for more details.
   12.10 + *
   12.11 + * This file implements the AER root port service driver. The driver will
   12.12 + * register an irq handler. When root port triggers an AER interrupt, the irq
   12.13 + * handler will collect root port status and schedule a work.
   12.14 + *
   12.15 + * Copyright (C) 2006 Intel Corp.
   12.16 + *	Tom Long Nguyen (tom.l.nguyen@intel.com)
   12.17 + *	Zhang Yanmin (yanmin.zhang@intel.com)
   12.18 + *
   12.19 + */
   12.20 +
   12.21 +#include <linux/module.h>
   12.22 +#include <linux/pci.h>
   12.23 +#include <linux/kernel.h>
   12.24 +#include <linux/errno.h>
   12.25 +#include <linux/pm.h>
   12.26 +#include <linux/init.h>
   12.27 +#include <linux/interrupt.h>
   12.28 +#include <linux/delay.h>
   12.29 +#include <linux/pcieport_if.h>
   12.30 +
   12.31 +#include "aerdrv.h"
   12.32 +
   12.33 +/*
   12.34 + * Version Information
   12.35 + */
   12.36 +#define DRIVER_VERSION "v1.0"
   12.37 +#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
   12.38 +#define DRIVER_DESC "Root Port Advanced Error Reporting Driver"
   12.39 +MODULE_AUTHOR(DRIVER_AUTHOR);
   12.40 +MODULE_DESCRIPTION(DRIVER_DESC);
   12.41 +MODULE_LICENSE("GPL");
   12.42 +
   12.43 +static int __devinit aer_probe (struct pcie_device *dev,
   12.44 +	const struct pcie_port_service_id *id );
   12.45 +static void aer_remove(struct pcie_device *dev);
   12.46 +static int aer_suspend(struct pcie_device *dev, pm_message_t state)
   12.47 +{return 0;}
   12.48 +static int aer_resume(struct pcie_device *dev) {return 0;}
   12.49 +static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
   12.50 +	enum pci_channel_state error);
   12.51 +static void aer_error_resume(struct pci_dev *dev);
   12.52 +static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
   12.53 +
   12.54 +/*
   12.55 + * PCI Express bus's AER Root service driver data structure
   12.56 + */
   12.57 +static struct pcie_port_service_id aer_id[] = {
   12.58 +	{
   12.59 +	.vendor 	= PCI_ANY_ID,
   12.60 +	.device 	= PCI_ANY_ID,
   12.61 +	.port_type 	= PCIE_RC_PORT,
   12.62 +	.service_type 	= PCIE_PORT_SERVICE_AER,
   12.63 +	},
   12.64 +	{ /* end: all zeroes */ }
   12.65 +};
   12.66 +
   12.67 +static struct pci_error_handlers aer_error_handlers = {
   12.68 +	.error_detected = aer_error_detected,
   12.69 +	.resume = aer_error_resume,
   12.70 +};
   12.71 +
   12.72 +static struct pcie_port_service_driver aerdrv = {
   12.73 +	.name		= "aer",
   12.74 +	.id_table	= &aer_id[0],
   12.75 +
   12.76 +	.probe		= aer_probe,
   12.77 +	.remove		= aer_remove,
   12.78 +
   12.79 +	.suspend	= aer_suspend,
   12.80 +	.resume		= aer_resume,
   12.81 +
   12.82 +	.err_handler	= &aer_error_handlers,
   12.83 +
   12.84 +	.reset_link	= aer_root_reset,
   12.85 +};
   12.86 +
   12.87 +/**
   12.88 + * aer_irq - Root Port's ISR
   12.89 + * @irq: IRQ assigned to Root Port
   12.90 + * @context: pointer to Root Port data structure
   12.91 + * @r: pointer struct pt_regs
   12.92 + *
   12.93 + * Invoked when Root Port detects AER messages.
   12.94 + **/
   12.95 +static irqreturn_t aer_irq(int irq, void *context, struct pt_regs * r)
   12.96 +{
   12.97 +	unsigned int status, id;
   12.98 +	struct pcie_device *pdev = (struct pcie_device *)context;
   12.99 +	struct aer_rpc *rpc = get_service_data(pdev);
  12.100 +	int next_prod_idx;
  12.101 +	unsigned long flags;
  12.102 +	int pos;
  12.103 +
  12.104 +	pos = pci_find_aer_capability(pdev->port);
  12.105 +	/*
  12.106 +	 * Must lock access to Root Error Status Reg, Root Error ID Reg,
  12.107 +	 * and Root error producer/consumer index
  12.108 +	 */
  12.109 +	spin_lock_irqsave(&rpc->e_lock, flags);
  12.110 +
  12.111 +	/* Read error status */
  12.112 +	pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
  12.113 +	if (!(status & ROOT_ERR_STATUS_MASKS)) {
  12.114 +		spin_unlock_irqrestore(&rpc->e_lock, flags);
  12.115 +		return IRQ_NONE;
  12.116 +	}
  12.117 +
  12.118 +	/* Read error source and clear error status */
  12.119 +	pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_COR_SRC, &id);
  12.120 +	pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
  12.121 +
  12.122 +	/* Store error source for later DPC handler */
  12.123 +	next_prod_idx = rpc->prod_idx + 1;
  12.124 +	if (next_prod_idx == AER_ERROR_SOURCES_MAX)
  12.125 +		next_prod_idx = 0;
  12.126 +	if (next_prod_idx == rpc->cons_idx) {
  12.127 +		/*
  12.128 +		 * Error Storm Condition - possibly the same error occurred.
  12.129 +		 * Drop the error.
  12.130 +		 */
  12.131 +		spin_unlock_irqrestore(&rpc->e_lock, flags);
  12.132 +		return IRQ_HANDLED;
  12.133 +	}
  12.134 +	rpc->e_sources[rpc->prod_idx].status =  status;
  12.135 +	rpc->e_sources[rpc->prod_idx].id = id;
  12.136 +	rpc->prod_idx = next_prod_idx;
  12.137 +	spin_unlock_irqrestore(&rpc->e_lock, flags);
  12.138 +
  12.139 +	/*  Invoke DPC handler */
  12.140 +	schedule_work(&rpc->dpc_handler);
  12.141 +
  12.142 +	return IRQ_HANDLED;
  12.143 +}
  12.144 +
  12.145 +/**
  12.146 + * aer_alloc_rpc - allocate Root Port data structure
  12.147 + * @dev: pointer to the pcie_dev data structure
  12.148 + *
  12.149 + * Invoked when Root Port's AER service is loaded.
  12.150 + **/
  12.151 +static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev)
  12.152 +{
  12.153 +	struct aer_rpc *rpc;
  12.154 +
  12.155 +	if (!(rpc = (struct aer_rpc *)kmalloc(sizeof(struct aer_rpc),
  12.156 +		GFP_KERNEL)))
  12.157 +		return NULL;
  12.158 +
  12.159 +	memset(rpc, 0, sizeof(struct aer_rpc));
  12.160 +	/*
  12.161 +	 * Initialize Root lock access, e_lock, to Root Error Status Reg,
  12.162 +	 * Root Error ID Reg, and Root error producer/consumer index.
  12.163 +	 */
  12.164 +	rpc->e_lock = SPIN_LOCK_UNLOCKED;
  12.165 +
  12.166 +	rpc->rpd = dev;
  12.167 +	INIT_WORK(&rpc->dpc_handler, aer_isr, (void *)dev);
  12.168 +	rpc->prod_idx = rpc->cons_idx = 0;
  12.169 +	mutex_init(&rpc->rpc_mutex);
  12.170 +	init_waitqueue_head(&rpc->wait_release);
  12.171 +
  12.172 +	/* Use PCIE bus function to store rpc into PCIE device */
  12.173 +	set_service_data(dev, rpc);
  12.174 +
  12.175 +	return rpc;
  12.176 +}
  12.177 +
  12.178 +/**
  12.179 + * aer_remove - clean up resources
  12.180 + * @dev: pointer to the pcie_dev data structure
  12.181 + *
  12.182 + * Invoked when PCI Express bus unloads or AER probe fails.
  12.183 + **/
  12.184 +static void aer_remove(struct pcie_device *dev)
  12.185 +{
  12.186 +	struct aer_rpc *rpc = get_service_data(dev);
  12.187 +
  12.188 +	if (rpc) {
  12.189 +		/* If register interrupt service, it must be free. */
  12.190 +		if (rpc->isr)
  12.191 +			free_irq(dev->irq, dev);
  12.192 +
  12.193 +		wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
  12.194 +
  12.195 +		aer_delete_rootport(rpc);
  12.196 +		set_service_data(dev, NULL);
  12.197 +	}
  12.198 +}
  12.199 +
  12.200 +/**
  12.201 + * aer_probe - initialize resources
  12.202 + * @dev: pointer to the pcie_dev data structure
  12.203 + * @id: pointer to the service id data structure
  12.204 + *
  12.205 + * Invoked when PCI Express bus loads AER service driver.
  12.206 + **/
  12.207 +static int __devinit aer_probe (struct pcie_device *dev,
  12.208 +				const struct pcie_port_service_id *id )
  12.209 +{
  12.210 +	int status;
  12.211 +	struct aer_rpc *rpc;
  12.212 +	struct device *device = &dev->device;
  12.213 +
  12.214 +	/* Init */
  12.215 +	if ((status = aer_init(dev)))
  12.216 +		return status;
  12.217 +
  12.218 +	/* Alloc rpc data structure */
  12.219 +	if (!(rpc = aer_alloc_rpc(dev))) {
  12.220 +		printk(KERN_DEBUG "%s: Alloc rpc fails on PCIE device[%s]\n",
  12.221 +			__FUNCTION__, device->bus_id);
  12.222 +		aer_remove(dev);
  12.223 +		return -ENOMEM;
  12.224 +	}
  12.225 +
  12.226 +	/* Request IRQ ISR */
  12.227 +	if ((status = request_irq(dev->irq, aer_irq, SA_SHIRQ, "aerdrv",
  12.228 +				dev))) {
  12.229 +		printk(KERN_DEBUG "%s: Request ISR fails on PCIE device[%s]\n",
  12.230 +			__FUNCTION__, device->bus_id);
  12.231 +		aer_remove(dev);
  12.232 +		return status;
  12.233 +	}
  12.234 +
  12.235 +	rpc->isr = 1;
  12.236 +
  12.237 +	aer_enable_rootport(rpc);
  12.238 +
  12.239 +	return status;
  12.240 +}
  12.241 +
  12.242 +/**
  12.243 + * aer_root_reset - reset link on Root Port
  12.244 + * @dev: pointer to Root Port's pci_dev data structure
  12.245 + *
  12.246 + * Invoked by Port Bus driver when performing link reset at Root Port.
  12.247 + **/
  12.248 +static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
  12.249 +{
  12.250 +	u16 p2p_ctrl;
  12.251 +	u32 status;
  12.252 +	int pos;
  12.253 +
  12.254 +	pos = pci_find_aer_capability(dev);
  12.255 +
  12.256 +	/* Disable Root's interrupt in response to error messages */
  12.257 +	pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0);
  12.258 +
  12.259 +	/* Assert Secondary Bus Reset */
  12.260 +	pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &p2p_ctrl);
  12.261 +	p2p_ctrl |= PCI_CB_BRIDGE_CTL_CB_RESET;
  12.262 +	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
  12.263 +
  12.264 +	/* De-assert Secondary Bus Reset */
  12.265 +	p2p_ctrl &= ~PCI_CB_BRIDGE_CTL_CB_RESET;
  12.266 +	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
  12.267 +
  12.268 +	/*
  12.269 +	 * System software must wait for at least 100ms from the end
  12.270 +	 * of a reset of one or more device before it is permitted
  12.271 +	 * to issue Configuration Requests to those devices.
  12.272 +	 */
  12.273 +	msleep(200);
  12.274 +	printk(KERN_DEBUG "Complete link reset at Root[%s]\n", dev->dev.bus_id);
  12.275 +
  12.276 +	/* Enable Root Port's interrupt in response to error messages */
  12.277 +	pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
  12.278 +	pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
  12.279 +	pci_write_config_dword(dev,
  12.280 +		pos + PCI_ERR_ROOT_COMMAND,
  12.281 +		ROOT_PORT_INTR_ON_MESG_MASK);
  12.282 +
  12.283 +	return PCI_ERS_RESULT_RECOVERED;
  12.284 +}
  12.285 +
  12.286 +/**
  12.287 + * aer_error_detected - update severity status
  12.288 + * @dev: pointer to Root Port's pci_dev data structure
  12.289 + * @error: error severity being notified by port bus
  12.290 + *
  12.291 + * Invoked by Port Bus driver during error recovery.
  12.292 + **/
  12.293 +static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
  12.294 +			enum pci_channel_state error)
  12.295 +{
  12.296 +	/* Root Port has no impact. Always recovers. */
  12.297 +	return PCI_ERS_RESULT_CAN_RECOVER;
  12.298 +}
  12.299 +
  12.300 +/**
  12.301 + * aer_error_resume - clean up corresponding error status bits
  12.302 + * @dev: pointer to Root Port's pci_dev data structure
  12.303 + *
  12.304 + * Invoked by Port Bus driver during nonfatal recovery.
  12.305 + **/
  12.306 +static void aer_error_resume(struct pci_dev *dev)
  12.307 +{
  12.308 +	int pos;
  12.309 +	u32 status, mask;
  12.310 +	u16 reg16;
  12.311 +
  12.312 +	/* Clean up Root device status */
  12.313 +	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
  12.314 +	pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
  12.315 +	pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
  12.316 +
  12.317 +	/* Clean AER Root Error Status */
  12.318 +	pos = pci_find_aer_capability(dev);
  12.319 +	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
  12.320 +	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
  12.321 +	if (dev->error_state == pci_channel_io_normal)
  12.322 +		status &= ~mask; /* Clear corresponding nonfatal bits */
  12.323 +	else
  12.324 +		status &= mask; /* Clear corresponding fatal bits */
  12.325 +	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
  12.326 +}
  12.327 +
  12.328 +/**
  12.329 + * aer_service_init - register AER root service driver
  12.330 + *
  12.331 + * Invoked when AER root service driver is loaded.
  12.332 + **/
  12.333 +static int __init aer_service_init(void)
  12.334 +{
  12.335 +	return pcie_port_service_register(&aerdrv);
  12.336 +}
  12.337 +
  12.338 +/**
  12.339 + * aer_service_exit - unregister AER root service driver
  12.340 + *
  12.341 + * Invoked when AER root service driver is unloaded.
  12.342 + **/
  12.343 +static void __exit aer_service_exit(void)
  12.344 +{
  12.345 +	pcie_port_service_unregister(&aerdrv);
  12.346 +}
  12.347 +
  12.348 +module_init(aer_service_init);
  12.349 +module_exit(aer_service_exit);
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/drivers/pci/pcie/aer/aerdrv.h	Wed Nov 26 10:24:15 2008 +0900
    13.3 @@ -0,0 +1,125 @@
    13.4 +/*
    13.5 + * Copyright (C) 2006 Intel Corp.
    13.6 + *	Tom Long Nguyen (tom.l.nguyen@intel.com)
    13.7 + *	Zhang Yanmin (yanmin.zhang@intel.com)
    13.8 + *
    13.9 + */
   13.10 +
   13.11 +#ifndef _AERDRV_H_
   13.12 +#define _AERDRV_H_
   13.13 +
   13.14 +#include <linux/pcieport_if.h>
   13.15 +#include <linux/aer.h>
   13.16 +
   13.17 +#define AER_NONFATAL			0
   13.18 +#define AER_FATAL			1
   13.19 +#define AER_CORRECTABLE			2
   13.20 +#define AER_UNCORRECTABLE		4
   13.21 +#define AER_ERROR_MASK			0x001fffff
   13.22 +#define AER_ERROR(d)			(d & AER_ERROR_MASK)
   13.23 +
   13.24 +#define OSC_METHOD_RUN_SUCCESS		0
   13.25 +#define OSC_METHOD_NOT_SUPPORTED	1
   13.26 +#define OSC_METHOD_RUN_FAILURE		2
   13.27 +
   13.28 +/* Root Error Status Register Bits */
   13.29 +#define ROOT_ERR_STATUS_MASKS			0x0f
   13.30 +
   13.31 +#define SYSTEM_ERROR_INTR_ON_MESG_MASK	(PCI_EXP_RTCTL_SECEE|	\
   13.32 +					PCI_EXP_RTCTL_SENFEE|	\
   13.33 +					PCI_EXP_RTCTL_SEFEE)
   13.34 +#define ROOT_PORT_INTR_ON_MESG_MASK	(PCI_ERR_ROOT_CMD_COR_EN|	\
   13.35 +					PCI_ERR_ROOT_CMD_NONFATAL_EN|	\
   13.36 +					PCI_ERR_ROOT_CMD_FATAL_EN)
   13.37 +#define ERR_COR_ID(d)			(d & 0xffff)
   13.38 +#define ERR_UNCOR_ID(d)			(d >> 16)
   13.39 +
   13.40 +#define AER_SUCCESS			0
   13.41 +#define AER_UNSUCCESS			1
   13.42 +#define AER_ERROR_SOURCES_MAX		100
   13.43 +
   13.44 +#define AER_LOG_TLP_MASKS		(PCI_ERR_UNC_POISON_TLP|	\
   13.45 +					PCI_ERR_UNC_ECRC|		\
   13.46 +					PCI_ERR_UNC_UNSUP|		\
   13.47 +					PCI_ERR_UNC_COMP_ABORT|		\
   13.48 +					PCI_ERR_UNC_UNX_COMP|		\
   13.49 +					PCI_ERR_UNC_MALF_TLP)
   13.50 +
   13.51 +/* AER Error Info Flags */
   13.52 +#define AER_TLP_HEADER_VALID_FLAG	0x00000001
   13.53 +#define AER_MULTI_ERROR_VALID_FLAG	0x00000002
   13.54 +
   13.55 +#define ERR_CORRECTABLE_ERROR_MASK	0x000031c1
   13.56 +#define ERR_UNCORRECTABLE_ERROR_MASK	0x001ff010
   13.57 +
   13.58 +struct header_log_regs {
   13.59 +	unsigned int dw0;
   13.60 +	unsigned int dw1;
   13.61 +	unsigned int dw2;
   13.62 +	unsigned int dw3;
   13.63 +};
   13.64 +
   13.65 +struct aer_err_info {
   13.66 +	int severity;			/* 0:NONFATAL | 1:FATAL | 2:COR */
   13.67 +	int flags;
   13.68 +	unsigned int status;		/* COR/UNCOR Error Status */
   13.69 +	struct header_log_regs tlp; 	/* TLP Header */
   13.70 +};
   13.71 +
   13.72 +struct aer_err_source {
   13.73 +	unsigned int status;
   13.74 +	unsigned int id;
   13.75 +};
   13.76 +
   13.77 +struct aer_rpc {
   13.78 +	struct pcie_device *rpd;	/* Root Port device */
   13.79 +	struct work_struct dpc_handler;
   13.80 +	struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
   13.81 +	unsigned short prod_idx;	/* Error Producer Index */
   13.82 +	unsigned short cons_idx;	/* Error Consumer Index */
   13.83 +	int isr;
   13.84 +	spinlock_t e_lock;		/*
   13.85 +					 * Lock access to Error Status/ID Regs
   13.86 +					 * and error producer/consumer index
   13.87 +					 */
   13.88 +	struct mutex rpc_mutex;		/*
   13.89 +					 * only one thread could do
   13.90 +					 * recovery on the same
   13.91 +					 * root port hierachy
   13.92 +					 */
   13.93 +	wait_queue_head_t wait_release;
   13.94 +};
   13.95 +
   13.96 +struct aer_broadcast_data {
   13.97 +	enum pci_channel_state state;
   13.98 +	enum pci_ers_result result;
   13.99 +};
  13.100 +
  13.101 +static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
  13.102 +		enum pci_ers_result new)
  13.103 +{
  13.104 +	switch (orig) {
  13.105 +	case PCI_ERS_RESULT_CAN_RECOVER:
  13.106 +	case PCI_ERS_RESULT_RECOVERED:
  13.107 +		orig = new;
  13.108 +		break;
  13.109 +	case PCI_ERS_RESULT_DISCONNECT:
  13.110 +		if (new == PCI_ERS_RESULT_NEED_RESET)
  13.111 +			orig = new;
  13.112 +		break;
  13.113 +	default:
  13.114 +		break;
  13.115 +	}
  13.116 +
  13.117 +	return orig;
  13.118 +}
  13.119 +
  13.120 +extern struct bus_type pcie_port_bus_type;
  13.121 +extern void aer_enable_rootport(struct aer_rpc *rpc);
  13.122 +extern void aer_delete_rootport(struct aer_rpc *rpc);
  13.123 +extern int aer_init(struct pcie_device *dev);
  13.124 +extern void aer_isr(void *context);
  13.125 +extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
  13.126 +extern int aer_osc_setup(struct pci_dev *dev);
  13.127 +
  13.128 +#endif //_AERDRV_H_
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c	Wed Nov 26 10:24:15 2008 +0900
    14.3 @@ -0,0 +1,68 @@
    14.4 +/*
    14.5 + * Access ACPI _OSC method
    14.6 + *
    14.7 + * Copyright (C) 2006 Intel Corp.
    14.8 + *	Tom Long Nguyen (tom.l.nguyen@intel.com)
    14.9 + *	Zhang Yanmin (yanmin.zhang@intel.com)
   14.10 + *
   14.11 + */
   14.12 +
   14.13 +#include <linux/module.h>
   14.14 +#include <linux/pci.h>
   14.15 +#include <linux/kernel.h>
   14.16 +#include <linux/errno.h>
   14.17 +#include <linux/pm.h>
   14.18 +#include <linux/suspend.h>
   14.19 +#include <linux/acpi.h>
   14.20 +#include <linux/pci-acpi.h>
   14.21 +#include <linux/delay.h>
   14.22 +#include "aerdrv.h"
   14.23 +
   14.24 +/**
   14.25 + * aer_osc_setup - run ACPI _OSC method
   14.26 + *
   14.27 + * Return:
   14.28 + *	Zero if success. Nonzero for otherwise.
   14.29 + *
   14.30 + * Invoked when PCIE bus loads AER service driver. To avoid conflict with
   14.31 + * BIOS AER support requires BIOS to yield AER control to OS native driver.
   14.32 + **/
   14.33 +int aer_osc_setup(struct pci_dev *dev)
   14.34 +{
   14.35 +	int retval = OSC_METHOD_RUN_SUCCESS;
   14.36 +	acpi_status status;
   14.37 +	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
   14.38 +	struct pci_dev *pdev = dev;
   14.39 +	struct pci_bus *parent;
   14.40 +
   14.41 +	while (!handle) {
   14.42 +		if (!pdev || !pdev->bus->parent)
   14.43 +			break;
   14.44 +		parent = pdev->bus->parent;
   14.45 +		if (!parent->self)
   14.46 +			/* Parent must be a host bridge */
   14.47 +			handle = acpi_get_pci_rootbridge_handle(
   14.48 +					pci_domain_nr(parent),
   14.49 +					parent->number);
   14.50 +		else
   14.51 +			handle = DEVICE_ACPI_HANDLE(
   14.52 +					&(parent->self->dev));
   14.53 +		pdev = parent->self;
   14.54 +	}
   14.55 +
   14.56 +	if (!handle)
   14.57 +		return OSC_METHOD_NOT_SUPPORTED;
   14.58 +
   14.59 +	pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
   14.60 +	status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_AER_CONTROL |
   14.61 +		OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
   14.62 +	if (ACPI_FAILURE(status)) {
   14.63 +		if (status == AE_SUPPORT)
   14.64 +			retval = OSC_METHOD_NOT_SUPPORTED;
   14.65 +	 	else
   14.66 +			retval = OSC_METHOD_RUN_FAILURE;
   14.67 +	}
   14.68 +
   14.69 +	return retval;
   14.70 +}
   14.71 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/drivers/pci/pcie/aer/aerdrv_core.c	Wed Nov 26 10:24:15 2008 +0900
    15.3 @@ -0,0 +1,757 @@
    15.4 +/*
    15.5 + * drivers/pci/pcie/aer/aerdrv_core.c
    15.6 + *
    15.7 + * This file is subject to the terms and conditions of the GNU General Public
    15.8 + * License.  See the file "COPYING" in the main directory of this archive
    15.9 + * for more details.
   15.10 + *
   15.11 + * This file implements the core part of PCI-Express AER. When an pci-express
   15.12 + * error is delivered, an error message will be collected and printed to
   15.13 + * console, then, an error recovery procedure will be executed by following
   15.14 + * the pci error recovery rules.
   15.15 + *
   15.16 + * Copyright (C) 2006 Intel Corp.
   15.17 + *	Tom Long Nguyen (tom.l.nguyen@intel.com)
   15.18 + *	Zhang Yanmin (yanmin.zhang@intel.com)
   15.19 + *
   15.20 + */
   15.21 +
   15.22 +#include <linux/module.h>
   15.23 +#include <linux/pci.h>
   15.24 +#include <linux/kernel.h>
   15.25 +#include <linux/errno.h>
   15.26 +#include <linux/pm.h>
   15.27 +#include <linux/suspend.h>
   15.28 +#include <linux/acpi.h>
   15.29 +#include <linux/pci-acpi.h>
   15.30 +#include <linux/delay.h>
   15.31 +#include "aerdrv.h"
   15.32 +
   15.33 +static int forceload;
   15.34 +module_param(forceload, bool, 0);
   15.35 +
   15.36 +#define PCI_CFG_SPACE_SIZE	(0x100)
   15.37 +int pci_find_aer_capability(struct pci_dev *dev)
   15.38 +{
   15.39 +	int pos;
   15.40 +	u32 reg32 = 0;
   15.41 +
   15.42 +	/* Check if it's a pci-express device */
   15.43 +	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
   15.44 +	if (!pos)
   15.45 +		return 0;
   15.46 +
   15.47 +	/* Check if it supports pci-express AER */
   15.48 +	pos = PCI_CFG_SPACE_SIZE;
   15.49 +	while (pos) {
   15.50 +		if (pci_read_config_dword(dev, pos, &reg32))
   15.51 +			return 0;
   15.52 +
   15.53 +		/* some broken boards return ~0 */
   15.54 +		if (reg32 == 0xffffffff)
   15.55 +			return 0;
   15.56 +
   15.57 +		if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
   15.58 +			break;
   15.59 +
   15.60 +		pos = reg32 >> 20;
   15.61 +	}
   15.62 +
   15.63 +	return pos;
   15.64 +}
   15.65 +
   15.66 +int pci_enable_pcie_error_reporting(struct pci_dev *dev)
   15.67 +{
   15.68 +	u16 reg16 = 0;
   15.69 +	int pos;
   15.70 +
   15.71 +	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
   15.72 +	if (!pos)
   15.73 +		return -EIO;
   15.74 +
   15.75 +	pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
   15.76 +	reg16 = reg16 |
   15.77 +		PCI_EXP_DEVCTL_CERE |
   15.78 +		PCI_EXP_DEVCTL_NFERE |
   15.79 +		PCI_EXP_DEVCTL_FERE |
   15.80 +		PCI_EXP_DEVCTL_URRE;
   15.81 +	pci_write_config_word(dev, pos+PCI_EXP_DEVCTL,
   15.82 +			reg16);
   15.83 +	return 0;
   15.84 +}
   15.85 +
   15.86 +int pci_disable_pcie_error_reporting(struct pci_dev *dev)
   15.87 +{
   15.88 +	u16 reg16 = 0;
   15.89 +	int pos;
   15.90 +
   15.91 +	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
   15.92 +	if (!pos)
   15.93 +		return -EIO;
   15.94 +
   15.95 +	pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
   15.96 +	reg16 = reg16 & ~(PCI_EXP_DEVCTL_CERE |
   15.97 +			PCI_EXP_DEVCTL_NFERE |
   15.98 +			PCI_EXP_DEVCTL_FERE |
   15.99 +			PCI_EXP_DEVCTL_URRE);
  15.100 +	pci_write_config_word(dev, pos+PCI_EXP_DEVCTL,
  15.101 +			reg16);
  15.102 +	return 0;
  15.103 +}
  15.104 +
  15.105 +int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
  15.106 +{
  15.107 +	int pos;
  15.108 +	u32 status, mask;
  15.109 +
  15.110 +	pos = pci_find_aer_capability(dev);
  15.111 +	if (!pos)
  15.112 +		return -EIO;
  15.113 +
  15.114 +	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
  15.115 +	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
  15.116 +	if (dev->error_state == pci_channel_io_normal)
  15.117 +		status &= ~mask; /* Clear corresponding nonfatal bits */
  15.118 +	else
  15.119 +		status &= mask; /* Clear corresponding fatal bits */
  15.120 +	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
  15.121 +
  15.122 +	return 0;
  15.123 +}
  15.124 +
  15.125 +static int find_device_iter(struct device *device, void *data)
  15.126 +{
  15.127 +	struct pci_dev *dev;
  15.128 +	u16 id = *(unsigned long *)data;
  15.129 +	u8 secondary, subordinate, d_bus = id >> 8;
  15.130 +
  15.131 +	if (device->bus == &pci_bus_type) {
  15.132 +		dev = to_pci_dev(device);
  15.133 +		if (id == ((dev->bus->number << 8) | dev->devfn)) {
  15.134 +			/*
  15.135 +			 * Device ID match
  15.136 +			 */
  15.137 +			*(unsigned long*)data = (unsigned long)device;
  15.138 +			return 1;
  15.139 +		}
  15.140 +
  15.141 +		/*
  15.142 +		 * If device is P2P, check if it is an upstream?
  15.143 +		 */
  15.144 +		if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
  15.145 +			pci_read_config_byte(dev, PCI_SECONDARY_BUS,
  15.146 +				&secondary);
  15.147 +			pci_read_config_byte(dev, PCI_SUBORDINATE_BUS,
  15.148 +				&subordinate);
  15.149 +			if (d_bus >= secondary && d_bus <= subordinate) {
  15.150 +				*(unsigned long*)data = (unsigned long)device;
  15.151 +				return 1;
  15.152 +			}
  15.153 +		}
  15.154 +	}
  15.155 +
  15.156 +	return 0;
  15.157 +}
  15.158 +
  15.159 +/**
  15.160 + * find_source_device - search through device hierarchy for source device
  15.161 + * @p_dev: pointer to Root Port pci_dev data structure
  15.162 + * @id: device ID of agent who sends an error message to this Root Port
  15.163 + *
  15.164 + * Invoked when error is detected at the Root Port.
  15.165 + **/
  15.166 +static struct device* find_source_device(struct pci_dev *parent, u16 id)
  15.167 +{
  15.168 +	struct pci_dev *dev = parent;
  15.169 +	struct device *device;
  15.170 +	unsigned long device_addr;
  15.171 +	int status;
  15.172 +
  15.173 +	/* Is Root Port an agent that sends error message? */
  15.174 +	if (id == ((dev->bus->number << 8) | dev->devfn))
  15.175 +		return &dev->dev;
  15.176 +
  15.177 +	do {
  15.178 +		device_addr = id;
  15.179 + 		if ((status = device_for_each_child(&dev->dev,
  15.180 +			&device_addr, find_device_iter))) {
  15.181 +			device = (struct device*)device_addr;
  15.182 +			dev = to_pci_dev(device);
  15.183 +			if (id == ((dev->bus->number << 8) | dev->devfn))
  15.184 +				return device;
  15.185 +		}
  15.186 + 	}while (status);
  15.187 +
  15.188 +	return NULL;
  15.189 +}
  15.190 +
  15.191 +static void report_error_detected(struct pci_dev *dev, void *data)
  15.192 +{
  15.193 +	pci_ers_result_t vote;
  15.194 +	struct pci_error_handlers *err_handler;
  15.195 +	struct aer_broadcast_data *result_data;
  15.196 +	result_data = (struct aer_broadcast_data *) data;
  15.197 +
  15.198 +	dev->error_state = result_data->state;
  15.199 +
  15.200 +	if (!dev->driver ||
  15.201 +		!dev->driver->err_handler ||
  15.202 +		!dev->driver->err_handler->error_detected) {
  15.203 +		if (result_data->state == pci_channel_io_frozen &&
  15.204 +			!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) {
  15.205 +			/*
  15.206 +			 * In case of fatal recovery, if one of down-
  15.207 +			 * stream device has no driver. We might be
  15.208 +			 * unable to recover because a later insmod
  15.209 +			 * of a driver for this device is unaware of
  15.210 +			 * its hw state.
  15.211 +			 */
  15.212 +			printk(KERN_DEBUG "Device ID[%s] has %s\n",
  15.213 +					dev->dev.bus_id, (dev->driver) ?
  15.214 +					"no AER-aware driver" : "no driver");
  15.215 +		}
  15.216 +		return;
  15.217 +	}
  15.218 +
  15.219 +	err_handler = dev->driver->err_handler;
  15.220 +	vote = err_handler->error_detected(dev, result_data->state);
  15.221 +	result_data->result = merge_result(result_data->result, vote);
  15.222 +	return;
  15.223 +}
  15.224 +
  15.225 +static void report_mmio_enabled(struct pci_dev *dev, void *data)
  15.226 +{
  15.227 +	pci_ers_result_t vote;
  15.228 +	struct pci_error_handlers *err_handler;
  15.229 +	struct aer_broadcast_data *result_data;
  15.230 +	result_data = (struct aer_broadcast_data *) data;
  15.231 +
  15.232 +	if (!dev->driver ||
  15.233 +		!dev->driver->err_handler ||
  15.234 +		!dev->driver->err_handler->mmio_enabled)
  15.235 +		return;
  15.236 +
  15.237 +	err_handler = dev->driver->err_handler;
  15.238 +	vote = err_handler->mmio_enabled(dev);
  15.239 +	result_data->result = merge_result(result_data->result, vote);
  15.240 +	return;
  15.241 +}
  15.242 +
  15.243 +static void report_slot_reset(struct pci_dev *dev, void *data)
  15.244 +{
  15.245 +	pci_ers_result_t vote;
  15.246 +	struct pci_error_handlers *err_handler;
  15.247 +	struct aer_broadcast_data *result_data;
  15.248 +	result_data = (struct aer_broadcast_data *) data;
  15.249 +
  15.250 +	if (!dev->driver ||
  15.251 +		!dev->driver->err_handler ||
  15.252 +		!dev->driver->err_handler->slot_reset)
  15.253 +		return;
  15.254 +
  15.255 +	err_handler = dev->driver->err_handler;
  15.256 +	vote = err_handler->slot_reset(dev);
  15.257 +	result_data->result = merge_result(result_data->result, vote);
  15.258 +	return;
  15.259 +}
  15.260 +
  15.261 +static void report_resume(struct pci_dev *dev, void *data)
  15.262 +{
  15.263 +	struct pci_error_handlers *err_handler;
  15.264 +
  15.265 +	dev->error_state = pci_channel_io_normal;
  15.266 +
  15.267 +	if (!dev->driver ||
  15.268 +		!dev->driver->err_handler ||
  15.269 +		!dev->driver->err_handler->resume)
  15.270 +		return;
  15.271 +
  15.272 +	err_handler = dev->driver->err_handler;
  15.273 +	err_handler->resume(dev);
  15.274 +	return;
  15.275 +}
  15.276 +
  15.277 +/**
  15.278 + * broadcast_error_message - handle message broadcast to downstream drivers
  15.279 + * @device: pointer to from where in a hierarchy message is broadcasted down
  15.280 + * @api: callback to be broadcasted
  15.281 + * @state: error state
  15.282 + *
  15.283 + * Invoked during error recovery process. Once being invoked, the content
  15.284 + * of error severity will be broadcasted to all downstream drivers in a
  15.285 + * hierarchy in question.
  15.286 + **/
  15.287 +static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
  15.288 +	enum pci_channel_state state,
  15.289 +	char *error_mesg,
  15.290 +	void (*cb)(struct pci_dev *, void *))
  15.291 +{
  15.292 +	struct aer_broadcast_data result_data;
  15.293 +
  15.294 +	printk(KERN_DEBUG "Broadcast %s message\n", error_mesg);
  15.295 +	result_data.state = state;
  15.296 +	if (cb == report_error_detected)
  15.297 +		result_data.result = PCI_ERS_RESULT_CAN_RECOVER;
  15.298 +	else
  15.299 +		result_data.result = PCI_ERS_RESULT_RECOVERED;
  15.300 +
  15.301 +	if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
  15.302 +		/*
  15.303 +		 * If the error is reported by a bridge, we think this error
  15.304 +		 * is related to the downstream link of the bridge, so we
  15.305 +		 * do error recovery on all subordinates of the bridge instead
  15.306 +		 * of the bridge and clear the error status of the bridge.
  15.307 +		 */
  15.308 +		if (cb == report_error_detected)
  15.309 +			dev->error_state = state;
  15.310 +		pci_walk_bus(dev->subordinate, cb, &result_data);
  15.311 +		if (cb == report_resume) {
  15.312 +			pci_cleanup_aer_uncorrect_error_status(dev);
  15.313 +			dev->error_state = pci_channel_io_normal;
  15.314 +		}
  15.315 +	}
  15.316 +	else {
  15.317 +		/*
  15.318 +		 * If the error is reported by an end point, we think this
  15.319 +		 * error is related to the upstream link of the end point.
  15.320 +		 */
  15.321 +		pci_walk_bus(dev->bus, cb, &result_data);
  15.322 +	}
  15.323 +
  15.324 +	return result_data.result;
  15.325 +}
  15.326 +
  15.327 +struct find_aer_service_data {
  15.328 +	struct pcie_port_service_driver *aer_driver;
  15.329 +	int is_downstream;
  15.330 +};
  15.331 +
  15.332 +static int find_aer_service_iter(struct device *device, void *data)
  15.333 +{
  15.334 +	struct device_driver *driver;
  15.335 +	struct pcie_port_service_driver *service_driver;
  15.336 +	struct pcie_device *pcie_dev;
  15.337 +	struct find_aer_service_data *result;
  15.338 +
  15.339 +	result = (struct find_aer_service_data *) data;
  15.340 +
  15.341 +	if (device->bus == &pcie_port_bus_type) {
  15.342 +		pcie_dev = to_pcie_device(device);
  15.343 +		if (pcie_dev->id.port_type == PCIE_SW_DOWNSTREAM_PORT)
  15.344 +			result->is_downstream = 1;
  15.345 +
  15.346 +		driver = device->driver;
  15.347 +		if (driver) {
  15.348 +			service_driver = to_service_driver(driver);
  15.349 +			if (service_driver->id_table->service_type ==
  15.350 +					PCIE_PORT_SERVICE_AER) {
  15.351 +				result->aer_driver = service_driver;
  15.352 +				return 1;
  15.353 +			}
  15.354 +		}
  15.355 +	}
  15.356 +
  15.357 +	return 0;
  15.358 +}
  15.359 +
  15.360 +static void find_aer_service(struct pci_dev *dev,
  15.361 +		struct find_aer_service_data *data)
  15.362 +{
  15.363 +	device_for_each_child(&dev->dev, data, find_aer_service_iter);
  15.364 +}
  15.365 +
  15.366 +static pci_ers_result_t reset_link(struct pcie_device *aerdev,
  15.367 +		struct pci_dev *dev)
  15.368 +{
  15.369 +	struct pci_dev *udev;
  15.370 +	pci_ers_result_t status;
  15.371 +	struct find_aer_service_data data;
  15.372 +
  15.373 +	if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)
  15.374 +		udev = dev;
  15.375 +	else
  15.376 +		udev= dev->bus->self;
  15.377 +
  15.378 +	data.is_downstream = 0;
  15.379 +	data.aer_driver = NULL;
  15.380 +	find_aer_service(udev, &data);
  15.381 +
  15.382 +	/*
  15.383 +	 * Use the aer driver of the error agent firstly.
  15.384 +	 * If it hasn't the aer driver, use the root port's
  15.385 +	 */
  15.386 +	if (!data.aer_driver || !data.aer_driver->reset_link) {
  15.387 +		if (data.is_downstream &&
  15.388 +			aerdev->device.driver &&
  15.389 +			to_service_driver(aerdev->device.driver)->reset_link) {
  15.390 +			data.aer_driver =
  15.391 +				to_service_driver(aerdev->device.driver);
  15.392 +		} else {
  15.393 +			printk(KERN_DEBUG "No link-reset support to Device ID"
  15.394 +				"[%s]\n",
  15.395 +				dev->dev.bus_id);
  15.396 +			return PCI_ERS_RESULT_DISCONNECT;
  15.397 +		}
  15.398 +	}
  15.399 +
  15.400 +	status = data.aer_driver->reset_link(udev);
  15.401 +	if (status != PCI_ERS_RESULT_RECOVERED) {
  15.402 +		printk(KERN_DEBUG "Link reset at upstream Device ID"
  15.403 +			"[%s] failed\n",
  15.404 +			udev->dev.bus_id);
  15.405 +		return PCI_ERS_RESULT_DISCONNECT;
  15.406 +	}
  15.407 +
  15.408 +	return status;
  15.409 +}
  15.410 +
  15.411 +/**
  15.412 + * do_recovery - handle nonfatal/fatal error recovery process
  15.413 + * @aerdev: pointer to a pcie_device data structure of root port
  15.414 + * @dev: pointer to a pci_dev data structure of agent detecting an error
  15.415 + * @severity: error severity type
  15.416 + *
  15.417 + * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast
  15.418 + * error detected message to all downstream drivers within a hierarchy in
  15.419 + * question and return the returned code.
  15.420 + **/
  15.421 +static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
  15.422 +		struct pci_dev *dev,
  15.423 +		int severity)
  15.424 +{
  15.425 +	pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED;
  15.426 +	enum pci_channel_state state;
  15.427 +
  15.428 +	if (severity == AER_FATAL)
  15.429 +		state = pci_channel_io_frozen;
  15.430 +	else
  15.431 +		state = pci_channel_io_normal;
  15.432 +
  15.433 +	status = broadcast_error_message(dev,
  15.434 +			state,
  15.435 +			"error_detected",
  15.436 +			report_error_detected);
  15.437 +
  15.438 +	if (severity == AER_FATAL) {
  15.439 +		result = reset_link(aerdev, dev);
  15.440 +		if (result != PCI_ERS_RESULT_RECOVERED) {
  15.441 +			/* TODO: Should panic here? */
  15.442 +			return result;
  15.443 +		}
  15.444 +	}
  15.445 +
  15.446 +	if (status == PCI_ERS_RESULT_CAN_RECOVER)
  15.447 +		status = broadcast_error_message(dev,
  15.448 +				state,
  15.449 +				"mmio_enabled",
  15.450 +				report_mmio_enabled);
  15.451 +
  15.452 +	if (status == PCI_ERS_RESULT_NEED_RESET) {
  15.453 +		/*
  15.454 +		 * TODO: Should call platform-specific
  15.455 +		 * functions to reset slot before calling
  15.456 +		 * drivers' slot_reset callbacks?
  15.457 +		 */
  15.458 +		status = broadcast_error_message(dev,
  15.459 +				state,
  15.460 +				"slot_reset",
  15.461 +				report_slot_reset);
  15.462 +	}
  15.463 +
  15.464 +	if (status == PCI_ERS_RESULT_RECOVERED)
  15.465 +		broadcast_error_message(dev,
  15.466 +				state,
  15.467 +				"resume",
  15.468 +				report_resume);
  15.469 +
  15.470 +	return status;
  15.471 +}
  15.472 +
  15.473 +/**
  15.474 + * handle_error_source - handle logging error into an event log
  15.475 + * @aerdev: pointer to pcie_device data structure of the root port
  15.476 + * @dev: pointer to pci_dev data structure of error source device
  15.477 + * @info: comprehensive error information
  15.478 + *
  15.479 + * Invoked when an error being detected by Root Port.
  15.480 + **/
  15.481 +static void handle_error_source(struct pcie_device * aerdev,
  15.482 +	struct pci_dev *dev,
  15.483 +	struct aer_err_info info)
  15.484 +{
  15.485 +	pci_ers_result_t status = 0;
  15.486 +	int pos;
  15.487 +
  15.488 +	if (info.severity == AER_CORRECTABLE) {
  15.489 +		/*
  15.490 +		 * Correctable error does not need software intevention.
  15.491 +		 * No need to go through error recovery process.
  15.492 +		 */
  15.493 +		pos = pci_find_aer_capability(dev);
  15.494 +		if (pos)
  15.495 +			pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
  15.496 +					info.status);
  15.497 +	} else {
  15.498 +		status = do_recovery(aerdev, dev, info.severity);
  15.499 +		if (status == PCI_ERS_RESULT_RECOVERED) {
  15.500 +			printk(KERN_DEBUG "AER driver successfully recovered\n");
  15.501 +		} else {
  15.502 +			/* TODO: Should kernel panic here? */
  15.503 +			printk(KERN_DEBUG "AER driver didn't recover\n");
  15.504 +		}
  15.505 +	}
  15.506 +}
  15.507 +
  15.508 +/**
  15.509 + * aer_enable_rootport - enable Root Port's interrupts when receiving messages
  15.510 + * @rpc: pointer to a Root Port data structure
  15.511 + *
  15.512 + * Invoked when PCIE bus loads AER service driver.
  15.513 + **/
  15.514 +void aer_enable_rootport(struct aer_rpc *rpc)
  15.515 +{
  15.516 +	struct pci_dev *pdev = rpc->rpd->port;
  15.517 +	int pos, aer_pos;
  15.518 +	u16 reg16;
  15.519 +	u32 reg32;
  15.520 +
  15.521 +	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
  15.522 +	/* Clear PCIE Capability's Device Status */
  15.523 +	pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
  15.524 +	pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
  15.525 +
  15.526 +	/* Disable system error generation in response to error messages */
  15.527 +	pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, &reg16);
  15.528 +	reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
  15.529 +	pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16);
  15.530 +
  15.531 +	aer_pos = pci_find_aer_capability(pdev);
  15.532 +	/* Clear error status */
  15.533 +	pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
  15.534 +	pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
  15.535 +	pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
  15.536 +	pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
  15.537 +	pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
  15.538 +	pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
  15.539 +
  15.540 +	/* Enable Root Port device reporting error itself */
  15.541 +	pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, &reg16);
  15.542 +	reg16 = reg16 |
  15.543 +		PCI_EXP_DEVCTL_CERE |
  15.544 +		PCI_EXP_DEVCTL_NFERE |
  15.545 +		PCI_EXP_DEVCTL_FERE |
  15.546 +		PCI_EXP_DEVCTL_URRE;
  15.547 +	pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL,
  15.548 +		reg16);
  15.549 +
  15.550 +	/* Enable Root Port's interrupt in response to error messages */
  15.551 +	pci_write_config_dword(pdev,
  15.552 +		aer_pos + PCI_ERR_ROOT_COMMAND,
  15.553 +		ROOT_PORT_INTR_ON_MESG_MASK);
  15.554 +}
  15.555 +
  15.556 +/**
  15.557 + * disable_root_aer - disable Root Port's interrupts when receiving messages
  15.558 + * @rpc: pointer to a Root Port data structure
  15.559 + *
  15.560 + * Invoked when PCIE bus unloads AER service driver.
  15.561 + **/
  15.562 +static void disable_root_aer(struct aer_rpc *rpc)
  15.563 +{
  15.564 +	struct pci_dev *pdev = rpc->rpd->port;
  15.565 +	u32 reg32;
  15.566 +	int pos;
  15.567 +
  15.568 +	pos = pci_find_aer_capability(pdev);
  15.569 +	/* Disable Root's interrupt in response to error messages */
  15.570 +	pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0);
  15.571 +
  15.572 +	/* Clear Root's error status reg */
  15.573 +	pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
  15.574 +	pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
  15.575 +}
  15.576 +
  15.577 +/**
  15.578 + * get_e_source - retrieve an error source
  15.579 + * @rpc: pointer to the root port which holds an error
  15.580 + *
  15.581 + * Invoked by DPC handler to consume an error.
  15.582 + **/
  15.583 +static struct aer_err_source* get_e_source(struct aer_rpc *rpc)
  15.584 +{
  15.585 +	struct aer_err_source *e_source;
  15.586 +	unsigned long flags;
  15.587 +
  15.588 +	/* Lock access to Root error producer/consumer index */
  15.589 +	spin_lock_irqsave(&rpc->e_lock, flags);
  15.590 +	if (rpc->prod_idx == rpc->cons_idx) {
  15.591 +		spin_unlock_irqrestore(&rpc->e_lock, flags);
  15.592 +		return NULL;
  15.593 +	}
  15.594 +	e_source = &rpc->e_sources[rpc->cons_idx];
  15.595 +	rpc->cons_idx++;
  15.596 +	if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
  15.597 +		rpc->cons_idx = 0;
  15.598 +	spin_unlock_irqrestore(&rpc->e_lock, flags);
  15.599 +
  15.600 +	return e_source;
  15.601 +}
  15.602 +
  15.603 +static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
  15.604 +{
  15.605 +	int pos;
  15.606 +
  15.607 +	pos = pci_find_aer_capability(dev);
  15.608 +
  15.609 +	/* The device might not support AER */
  15.610 +	if (!pos)
  15.611 +		return AER_SUCCESS;
  15.612 +
  15.613 +	if (info->severity == AER_CORRECTABLE) {
  15.614 +		pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS,
  15.615 +			&info->status);
  15.616 +		if (!(info->status & ERR_CORRECTABLE_ERROR_MASK))
  15.617 +			return AER_UNSUCCESS;
  15.618 +	} else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE ||
  15.619 +		info->severity == AER_NONFATAL) {
  15.620 +
  15.621 +		/* Link is still healthy for IO reads */
  15.622 +		pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
  15.623 +			&info->status);
  15.624 +		if (!(info->status & ERR_UNCORRECTABLE_ERROR_MASK))
  15.625 +			return AER_UNSUCCESS;
  15.626 +
  15.627 +		if (info->status & AER_LOG_TLP_MASKS) {
  15.628 +			info->flags |= AER_TLP_HEADER_VALID_FLAG;
  15.629 +			pci_read_config_dword(dev,
  15.630 +				pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
  15.631 +			pci_read_config_dword(dev,
  15.632 +				pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
  15.633 +			pci_read_config_dword(dev,
  15.634 +				pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
  15.635 +			pci_read_config_dword(dev,
  15.636 +				pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
  15.637 +		}
  15.638 +	}
  15.639 +
  15.640 +	return AER_SUCCESS;
  15.641 +}
  15.642 +
  15.643 +/**
  15.644 + * aer_isr_one_error - consume an error detected by root port
  15.645 + * @p_device: pointer to error root port service device
  15.646 + * @e_src: pointer to an error source
  15.647 + **/
  15.648 +static void aer_isr_one_error(struct pcie_device *p_device,
  15.649 +		struct aer_err_source *e_src)
  15.650 +{
  15.651 +	struct device *s_device;
  15.652 +	struct aer_err_info e_info = {0, 0, 0,};
  15.653 +	int i;
  15.654 +	u16 id;
  15.655 +
  15.656 +	/*
  15.657 +	 * There is a possibility that both correctable error and
  15.658 +	 * uncorrectable error being logged. Report correctable error first.
  15.659 +	 */
  15.660 +	for (i = 1; i & ROOT_ERR_STATUS_MASKS ; i <<= 2) {
  15.661 +		if (i > 4)
  15.662 +			break;
  15.663 +		if (!(e_src->status & i))
  15.664 +			continue;
  15.665 +
  15.666 +		/* Init comprehensive error information */
  15.667 +		if (i & PCI_ERR_ROOT_COR_RCV) {
  15.668 +			id = ERR_COR_ID(e_src->id);
  15.669 +			e_info.severity = AER_CORRECTABLE;
  15.670 +		} else {
  15.671 +			id = ERR_UNCOR_ID(e_src->id);
  15.672 +			e_info.severity = ((e_src->status >> 6) & 1);
  15.673 +		}
  15.674 +		if (e_src->status &
  15.675 +			(PCI_ERR_ROOT_MULTI_COR_RCV |
  15.676 +			 PCI_ERR_ROOT_MULTI_UNCOR_RCV))
  15.677 +			e_info.flags |= AER_MULTI_ERROR_VALID_FLAG;
  15.678 +		if (!(s_device = find_source_device(p_device->port, id))) {
  15.679 +			printk(KERN_DEBUG "%s->can't find device of ID%04x\n",
  15.680 +				__FUNCTION__, id);
  15.681 +			continue;
  15.682 +		}
  15.683 +		if (get_device_error_info(to_pci_dev(s_device), &e_info) ==
  15.684 +				AER_SUCCESS) {
  15.685 +			aer_print_error(to_pci_dev(s_device), &e_info);
  15.686 +			handle_error_source(p_device,
  15.687 +				to_pci_dev(s_device),
  15.688 +				e_info);
  15.689 +		}
  15.690 +	}
  15.691 +}
  15.692 +
  15.693 +/**
  15.694 + * aer_isr - consume errors detected by root port
  15.695 + * @context: pointer to a private data of pcie device
  15.696 + *
  15.697 + * Invoked, as DPC, when root port records new detected error
  15.698 + **/
  15.699 +void aer_isr(void *context)
  15.700 +{
  15.701 +	struct pcie_device *p_device = (struct pcie_device *) context;
  15.702 +	struct aer_rpc *rpc = get_service_data(p_device);
  15.703 +	struct aer_err_source *e_src;
  15.704 +
  15.705 +	mutex_lock(&rpc->rpc_mutex);
  15.706 +	e_src = get_e_source(rpc);
  15.707 +	while (e_src) {
  15.708 +		aer_isr_one_error(p_device, e_src);
  15.709 +		e_src = get_e_source(rpc);
  15.710 +	}
  15.711 +	mutex_unlock(&rpc->rpc_mutex);
  15.712 +
  15.713 +	wake_up(&rpc->wait_release);
  15.714 +}
  15.715 +
  15.716 +/**
  15.717 + * aer_delete_rootport - disable root port aer and delete service data
  15.718 + * @rpc: pointer to a root port device being deleted
  15.719 + *
  15.720 + * Invoked when AER service unloaded on a specific Root Port
  15.721 + **/
  15.722 +void aer_delete_rootport(struct aer_rpc *rpc)
  15.723 +{
  15.724 +	/* Disable root port AER itself */
  15.725 +	disable_root_aer(rpc);
  15.726 +
  15.727 +	kfree(rpc);
  15.728 +}
  15.729 +
  15.730 +/**
  15.731 + * aer_init - provide AER initialization
  15.732 + * @dev: pointer to AER pcie device
  15.733 + *
  15.734 + * Invoked when AER service driver is loaded.
  15.735 + **/
  15.736 +int aer_init(struct pcie_device *dev)
  15.737 +{
  15.738 +	int status;
  15.739 +
  15.740 +	/* Run _OSC Method */
  15.741 +	status = aer_osc_setup(dev->port);
  15.742 +
  15.743 +	if(status != OSC_METHOD_RUN_SUCCESS) {
  15.744 +		printk(KERN_DEBUG "%s: AER service init fails - %s\n",
  15.745 +		__FUNCTION__,
  15.746 +		(status == OSC_METHOD_NOT_SUPPORTED) ?
  15.747 +			"No ACPI _OSC support" : "Run ACPI _OSC fails");
  15.748 +
  15.749 +		if (!forceload)
  15.750 +			return status;
  15.751 +	}
  15.752 +
  15.753 +	return AER_SUCCESS;
  15.754 +}
  15.755 +
  15.756 +EXPORT_SYMBOL_GPL(pci_find_aer_capability);
  15.757 +EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
  15.758 +EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
  15.759 +EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
  15.760 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c	Wed Nov 26 10:24:15 2008 +0900
    16.3 @@ -0,0 +1,248 @@
    16.4 +/*
    16.5 + * drivers/pci/pcie/aer/aerdrv_errprint.c
    16.6 + *
    16.7 + * This file is subject to the terms and conditions of the GNU General Public
    16.8 + * License.  See the file "COPYING" in the main directory of this archive
    16.9 + * for more details.
   16.10 + *
   16.11 + * Format error messages and print them to console.
   16.12 + *
   16.13 + * Copyright (C) 2006 Intel Corp.
   16.14 + *	Tom Long Nguyen (tom.l.nguyen@intel.com)
   16.15 + *	Zhang Yanmin (yanmin.zhang@intel.com)
   16.16 + *
   16.17 + */
   16.18 +
   16.19 +#include <linux/module.h>
   16.20 +#include <linux/pci.h>
   16.21 +#include <linux/kernel.h>
   16.22 +#include <linux/errno.h>
   16.23 +#include <linux/pm.h>
   16.24 +#include <linux/suspend.h>
   16.25 +
   16.26 +#include "aerdrv.h"
   16.27 +
   16.28 +#define AER_AGENT_RECEIVER		0
   16.29 +#define AER_AGENT_REQUESTER		1
   16.30 +#define AER_AGENT_COMPLETER		2
   16.31 +#define AER_AGENT_TRANSMITTER		3
   16.32 +
   16.33 +#define AER_AGENT_REQUESTER_MASK	(PCI_ERR_UNC_COMP_TIME|	\
   16.34 +					PCI_ERR_UNC_UNSUP)
   16.35 +
   16.36 +#define AER_AGENT_COMPLETER_MASK	PCI_ERR_UNC_COMP_ABORT
   16.37 +
   16.38 +#define AER_AGENT_TRANSMITTER_MASK(t, e) (e & (PCI_ERR_COR_REP_ROLL| \
   16.39 +	((t == AER_CORRECTABLE) ? PCI_ERR_COR_REP_TIMER: 0)))
   16.40 +
   16.41 +#define AER_GET_AGENT(t, e)						\
   16.42 +	((e & AER_AGENT_COMPLETER_MASK) ? AER_AGENT_COMPLETER :		\
   16.43 +	(e & AER_AGENT_REQUESTER_MASK) ? AER_AGENT_REQUESTER :		\
   16.44 +	(AER_AGENT_TRANSMITTER_MASK(t, e)) ? AER_AGENT_TRANSMITTER :	\
   16.45 +	AER_AGENT_RECEIVER)
   16.46 +
   16.47 +#define AER_PHYSICAL_LAYER_ERROR_MASK	PCI_ERR_COR_RCVR
   16.48 +#define AER_DATA_LINK_LAYER_ERROR_MASK(t, e)	\
   16.49 +		(PCI_ERR_UNC_DLP|		\
   16.50 +		PCI_ERR_COR_BAD_TLP| 		\
   16.51 +		PCI_ERR_COR_BAD_DLLP|		\
   16.52 +		PCI_ERR_COR_REP_ROLL| 		\
   16.53 +		((t == AER_CORRECTABLE) ?	\
   16.54 +		PCI_ERR_COR_REP_TIMER: 0))
   16.55 +
   16.56 +#define AER_PHYSICAL_LAYER_ERROR	0
   16.57 +#define AER_DATA_LINK_LAYER_ERROR	1
   16.58 +#define AER_TRANSACTION_LAYER_ERROR	2
   16.59 +
   16.60 +#define AER_GET_LAYER_ERROR(t, e)				\
   16.61 +	((e & AER_PHYSICAL_LAYER_ERROR_MASK) ?			\
   16.62 +	AER_PHYSICAL_LAYER_ERROR :				\
   16.63 +	(e & AER_DATA_LINK_LAYER_ERROR_MASK(t, e)) ?		\
   16.64 +		AER_DATA_LINK_LAYER_ERROR : 			\
   16.65 +		AER_TRANSACTION_LAYER_ERROR)
   16.66 +
   16.67 +/*
   16.68 + * AER error strings
   16.69 + */
   16.70 +static char* aer_error_severity_string[] = {
   16.71 +	"Uncorrected (Non-Fatal)",
   16.72 +	"Uncorrected (Fatal)",
   16.73 +	"Corrected"
   16.74 +};
   16.75 +
   16.76 +static char* aer_error_layer[] = {
   16.77 +	"Physical Layer",
   16.78 +	"Data Link Layer",
   16.79 +	"Transaction Layer"
   16.80 +};
   16.81 +static char* aer_correctable_error_string[] = {
   16.82 +	"Receiver Error        ",	/* Bit Position 0 	*/
   16.83 +	NULL,
   16.84 +	NULL,
   16.85 +	NULL,
   16.86 +	NULL,
   16.87 +	NULL,
   16.88 +	"Bad TLP               ",	/* Bit Position 6 	*/
   16.89 +	"Bad DLLP              ",	/* Bit Position 7 	*/
   16.90 +	"RELAY_NUM Rollover    ",	/* Bit Position 8 	*/
   16.91 +	NULL,
   16.92 +	NULL,
   16.93 +	NULL,
   16.94 +	"Replay Timer Timeout  ",	/* Bit Position 12 	*/
   16.95 +	"Advisory Non-Fatal    ", 	/* Bit Position 13	*/
   16.96 +	NULL,
   16.97 +	NULL,
   16.98 +	NULL,
   16.99 +	NULL,
  16.100 +	NULL,
  16.101 +	NULL,
  16.102 +	NULL,
  16.103 +	NULL,
  16.104 +	NULL,
  16.105 +	NULL,
  16.106 +	NULL,
  16.107 +	NULL,
  16.108 +	NULL,
  16.109 +	NULL,
  16.110 +	NULL,
  16.111 +	NULL,
  16.112 +	NULL,
  16.113 +	NULL,
  16.114 +};
  16.115 +
  16.116 +static char* aer_uncorrectable_error_string[] = {
  16.117 +	NULL,
  16.118 +	NULL,
  16.119 +	NULL,
  16.120 +	NULL,
  16.121 +	"Data Link Protocol    ",	/* Bit Position 4	*/
  16.122 +	NULL,
  16.123 +	NULL,
  16.124 +	NULL,
  16.125 +	NULL,
  16.126 +	NULL,
  16.127 +	NULL,
  16.128 +	NULL,
  16.129 +	"Poisoned TLP          ",	/* Bit Position 12 	*/
  16.130 +	"Flow Control Protocol ",	/* Bit Position 13	*/
  16.131 +	"Completion Timeout    ",	/* Bit Position 14 	*/
  16.132 +	"Completer Abort       ",	/* Bit Position 15 	*/
  16.133 +	"Unexpected Completion ",	/* Bit Position 16	*/
  16.134 +	"Receiver Overflow     ",	/* Bit Position 17	*/
  16.135 +	"Malformed TLP         ",	/* Bit Position 18	*/
  16.136 +	"ECRC                  ",	/* Bit Position 19	*/
  16.137 +	"Unsupported Request   ",	/* Bit Position 20	*/
  16.138 +	NULL,
  16.139 +	NULL,
  16.140 +	NULL,
  16.141 +	NULL,
  16.142 +	NULL,
  16.143 +	NULL,
  16.144 +	NULL,
  16.145 +	NULL,
  16.146 +	NULL,
  16.147 +	NULL,
  16.148 +	NULL,
  16.149 +};
  16.150 +
  16.151 +static char* aer_agent_string[] = {
  16.152 +	"Receiver ID",
  16.153 +	"Requester ID",
  16.154 +	"Completer ID",
  16.155 +	"Transmitter ID"
  16.156 +};
  16.157 +
  16.158 +static char * aer_get_error_source_name(int severity,
  16.159 +			unsigned int status,
  16.160 +			char errmsg_buff[])
  16.161 +{
  16.162 +	int i;
  16.163 +	char * errmsg = NULL;
  16.164 +
  16.165 +	for (i = 0; i < 32; i++) {
  16.166 +		if (!(status & (1 << i)))
  16.167 +			continue;
  16.168 +
  16.169 +		if (severity == AER_CORRECTABLE)
  16.170 +			errmsg = aer_correctable_error_string[i];
  16.171 +		else
  16.172 +			errmsg = aer_uncorrectable_error_string[i];
  16.173 +
  16.174 +		if (!errmsg) {
  16.175 +			sprintf(errmsg_buff, "Unknown Error Bit %2d  ", i);
  16.176 +			errmsg = errmsg_buff;
  16.177 +		}
  16.178 +
  16.179 +		break;
  16.180 +	}
  16.181 +
  16.182 +	return errmsg;
  16.183 +}
  16.184 +
  16.185 +static DEFINE_SPINLOCK(logbuf_lock);
  16.186 +static char errmsg_buff[100];
  16.187 +void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
  16.188 +{
  16.189 +	char * errmsg;
  16.190 +	int err_layer, agent;
  16.191 +	char * loglevel;
  16.192 +
  16.193 +	if (info->severity == AER_CORRECTABLE)
  16.194 +		loglevel = KERN_WARNING;
  16.195 +	else
  16.196 +		loglevel = KERN_ERR;
  16.197 +
  16.198 +	printk("%s+------ PCI-Express Device Error ------+\n", loglevel);
  16.199 +	printk("%sError Severity\t\t: %s\n", loglevel,
  16.200 +		aer_error_severity_string[info->severity]);
  16.201 +
  16.202 +	if ( info->status == 0) {
  16.203 +		printk("%sPCIE Bus Error type\t: (Unaccessible)\n", loglevel);
  16.204 +		printk("%sUnaccessible Received\t: %s\n", loglevel,
  16.205 +			info->flags & AER_MULTI_ERROR_VALID_FLAG ?
  16.206 +				"Multiple" : "First");
  16.207 +		printk("%sUnregistered Agent ID\t: %04x\n", loglevel,
  16.208 +			(dev->bus->number << 8) | dev->devfn);
  16.209 +	} else {
  16.210 +		err_layer = AER_GET_LAYER_ERROR(info->severity, info->status);
  16.211 +		printk("%sPCIE Bus Error type\t: %s\n", loglevel,
  16.212 +			aer_error_layer[err_layer]);
  16.213 +
  16.214 +		spin_lock(&logbuf_lock);
  16.215 +		errmsg = aer_get_error_source_name(info->severity,
  16.216 +				info->status,
  16.217 +				errmsg_buff);
  16.218 +		printk("%s%s\t: %s\n", loglevel, errmsg,
  16.219 +			info->flags & AER_MULTI_ERROR_VALID_FLAG ?
  16.220 +				"Multiple" : "First");
  16.221 +		spin_unlock(&logbuf_lock);
  16.222 +
  16.223 +		agent = AER_GET_AGENT(info->severity, info->status);
  16.224 +		printk("%s%s\t\t: %04x\n", loglevel,
  16.225 +			aer_agent_string[agent],
  16.226 +			(dev->bus->number << 8) | dev->devfn);
  16.227 +
  16.228 +		printk("%sVendorID=%04xh, DeviceID=%04xh,"
  16.229 +			" Bus=%02xh, Device=%02xh, Function=%02xh\n",
  16.230 +			loglevel,
  16.231 +			dev->vendor,
  16.232 +			dev->device,
  16.233 +			dev->bus->number,
  16.234 +			PCI_SLOT(dev->devfn),
  16.235 +			PCI_FUNC(dev->devfn));
  16.236 +
  16.237 +		if (info->flags & AER_TLP_HEADER_VALID_FLAG) {
  16.238 +			unsigned char *tlp = (unsigned char *) &info->tlp;
  16.239 +			printk("%sTLB Header:\n", loglevel);
  16.240 +			printk("%s%02x%02x%02x%02x %02x%02x%02x%02x"
  16.241 +				" %02x%02x%02x%02x %02x%02x%02x%02x\n",
  16.242 +				loglevel,
  16.243 +				*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
  16.244 +				*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
  16.245 +				*(tlp + 11), *(tlp + 10), *(tlp + 9),
  16.246 +				*(tlp + 8), *(tlp + 15), *(tlp + 14),
  16.247 +				*(tlp + 13), *(tlp + 12));
  16.248 +		}
  16.249 +	}
  16.250 +}
  16.251 +
    17.1 --- a/drivers/pci/pcie/portdrv_bus.c	Tue Nov 04 12:43:37 2008 +0900
    17.2 +++ b/drivers/pci/pcie/portdrv_bus.c	Wed Nov 26 10:24:15 2008 +0900
    17.3 @@ -24,6 +24,7 @@ struct bus_type pcie_port_bus_type = {
    17.4  	.suspend	= pcie_port_bus_suspend,
    17.5  	.resume		= pcie_port_bus_resume, 
    17.6  };
    17.7 +EXPORT_SYMBOL_GPL(pcie_port_bus_type);
    17.8  
    17.9  static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
   17.10  {
    18.1 --- a/drivers/pci/pcie/portdrv_pci.c	Tue Nov 04 12:43:37 2008 +0900
    18.2 +++ b/drivers/pci/pcie/portdrv_pci.c	Wed Nov 26 10:24:15 2008 +0900
    18.3 @@ -14,8 +14,10 @@
    18.4  #include <linux/init.h>
    18.5  #include <linux/slab.h>
    18.6  #include <linux/pcieport_if.h>
    18.7 +#include <linux/aer.h>
    18.8  
    18.9  #include "portdrv.h"
   18.10 +#include "aer/aerdrv.h"
   18.11  
   18.12  /*
   18.13   * Version Information
   18.14 @@ -30,6 +32,43 @@ MODULE_LICENSE("GPL");
   18.15  /* global data */
   18.16  static const char device_name[] = "pcieport-driver";
   18.17  
   18.18 +static int pcie_portdrv_save_config(struct pci_dev *dev)
   18.19 +{
   18.20 +	return pci_save_state(dev);
   18.21 +}
   18.22 +
   18.23 +#ifdef CONFIG_PM
   18.24 +static int pcie_portdrv_restore_config(struct pci_dev *dev)
   18.25 +{
   18.26 +	int retval;
   18.27 +
   18.28 +	pci_restore_state(dev);
   18.29 +	retval = pci_enable_device(dev);
   18.30 +	if (retval)
   18.31 +		return retval;
   18.32 +	pci_set_master(dev);
   18.33 +	return 0;
   18.34 +}
   18.35 +
   18.36 +static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
   18.37 +{
   18.38 +	int ret = pcie_port_device_suspend(dev, state);
   18.39 +
   18.40 +	if (!ret)
   18.41 +		ret = pcie_portdrv_save_config(dev);
   18.42 +	return ret;
   18.43 +}
   18.44 +
   18.45 +static int pcie_portdrv_resume(struct pci_dev *dev)
   18.46 +{
   18.47 +	pcie_portdrv_restore_config(dev);
   18.48 +	return pcie_port_device_resume(dev);
   18.49 +}
   18.50 +#else
   18.51 +#define pcie_portdrv_suspend NULL
   18.52 +#define pcie_portdrv_resume NULL
   18.53 +#endif
   18.54 +
   18.55  /*
   18.56   * pcie_portdrv_probe - Probe PCI-Express port devices
   18.57   * @dev: PCI-Express port device being probed
   18.58 @@ -61,6 +100,10 @@ static int __devinit pcie_portdrv_probe 
   18.59  		return -ENOMEM;
   18.60  	}
   18.61  
   18.62 +	pcie_portdrv_save_config(dev);
   18.63 +
   18.64 +	pci_enable_pcie_error_reporting(dev);
   18.65 +
   18.66  	return 0;
   18.67  }
   18.68  
   18.69 @@ -70,39 +113,143 @@ static void pcie_portdrv_remove (struct 
   18.70  	kfree(pci_get_drvdata(dev));
   18.71  }
   18.72  
   18.73 -#ifdef CONFIG_PM
   18.74 -static int pcie_portdrv_save_config(struct pci_dev *dev)
   18.75 +static int error_detected_iter(struct device *device, void *data)
   18.76  {
   18.77 -	return pci_save_state(dev);
   18.78 -}
   18.79 +	struct pcie_device *pcie_device;
   18.80 +	struct pcie_port_service_driver *driver;
   18.81 +	struct aer_broadcast_data *result_data;
   18.82 +	pci_ers_result_t status;
   18.83  
   18.84 -static int pcie_portdrv_restore_config(struct pci_dev *dev)
   18.85 -{
   18.86 -	int retval;
   18.87 +	result_data = (struct aer_broadcast_data *) data;
   18.88  
   18.89 -	pci_restore_state(dev);
   18.90 -	retval = pci_enable_device(dev);
   18.91 -	if (retval)
   18.92 -		return retval;
   18.93 -	pci_set_master(dev);
   18.94 +	if (device->bus == &pcie_port_bus_type && device->driver) {
   18.95 +		driver = to_service_driver(device->driver);
   18.96 +		if (!driver ||
   18.97 +			!driver->err_handler ||
   18.98 +			!driver->err_handler->error_detected)
   18.99 +			return 0;
  18.100 +
  18.101 +		pcie_device = to_pcie_device(device);
  18.102 +
  18.103 +		/* Forward error detected message to service drivers */
  18.104 +		status = driver->err_handler->error_detected(
  18.105 +			pcie_device->port,
  18.106 +			result_data->state);
  18.107 +		result_data->result =
  18.108 +			merge_result(result_data->result, status);
  18.109 +	}
  18.110 +
  18.111  	return 0;
  18.112  }
  18.113  
  18.114 -static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state)
  18.115 +static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
  18.116 +					enum pci_channel_state error)
  18.117  {
  18.118 -	int ret = pcie_port_device_suspend(dev, state);
  18.119 +	struct aer_broadcast_data result_data =
  18.120 +			{error, PCI_ERS_RESULT_CAN_RECOVER};
  18.121  
  18.122 -	if (!ret)
  18.123 -		ret = pcie_portdrv_save_config(dev);
  18.124 -	return ret;
  18.125 +	device_for_each_child(&dev->dev, &result_data, error_detected_iter);
  18.126 +
  18.127 +	return result_data.result;
  18.128  }
  18.129  
  18.130 -static int pcie_portdrv_resume (struct pci_dev *dev)
  18.131 +static int mmio_enabled_iter(struct device *device, void *data)
  18.132  {
  18.133 -	pcie_portdrv_restore_config(dev);
  18.134 -	return pcie_port_device_resume(dev);
  18.135 +	struct pcie_device *pcie_device;
  18.136 +	struct pcie_port_service_driver *driver;
  18.137 +	pci_ers_result_t status, *result;
  18.138 +
  18.139 +	result = (pci_ers_result_t *) data;
  18.140 +
  18.141 +	if (device->bus == &pcie_port_bus_type && device->driver) {
  18.142 +		driver = to_service_driver(device->driver);
  18.143 +		if (driver &&
  18.144 +			driver->err_handler &&
  18.145 +			driver->err_handler->mmio_enabled) {
  18.146 +			pcie_device = to_pcie_device(device);
  18.147 +
  18.148 +			/* Forward error message to service drivers */
  18.149 +			status = driver->err_handler->mmio_enabled(
  18.150 +					pcie_device->port);
  18.151 +			*result = merge_result(*result, status);
  18.152 +		}
  18.153 +	}
  18.154 +
  18.155 +	return 0;
  18.156  }
  18.157 -#endif
  18.158 +
  18.159 +static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
  18.160 +{
  18.161 +	pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
  18.162 +
  18.163 +	device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
  18.164 +	return status;
  18.165 +}
  18.166 +
  18.167 +static int slot_reset_iter(struct device *device, void *data)
  18.168 +{
  18.169 +	struct pcie_device *pcie_device;
  18.170 +	struct pcie_port_service_driver *driver;
  18.171 +	pci_ers_result_t status, *result;
  18.172 +
  18.173 +	result = (pci_ers_result_t *) data;
  18.174 +
  18.175 +	if (device->bus == &pcie_port_bus_type && device->driver) {
  18.176 +		driver = to_service_driver(device->driver);
  18.177 +		if (driver &&
  18.178 +			driver->err_handler &&
  18.179 +			driver->err_handler->slot_reset) {
  18.180 +			pcie_device = to_pcie_device(device);
  18.181 +
  18.182 +			/* Forward error message to service drivers */
  18.183 +			status = driver->err_handler->slot_reset(
  18.184 +					pcie_device->port);
  18.185 +			*result = merge_result(*result, status);
  18.186 +		}
  18.187 +	}
  18.188 +
  18.189 +	return 0;
  18.190 +}
  18.191 +
  18.192 +static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
  18.193 +{
  18.194 +	pci_ers_result_t status;
  18.195 +
  18.196 +	/* If fatal, restore cfg space for possible link reset at upstream */
  18.197 +	if (dev->error_state == pci_channel_io_frozen) {
  18.198 +		pcie_portdrv_restore_config(dev);
  18.199 +		pci_enable_pcie_error_reporting(dev);
  18.200 +	}
  18.201 +
  18.202 +	device_for_each_child(&dev->dev, &status, slot_reset_iter);
  18.203 +
  18.204 +	return status;
  18.205 +}
  18.206 +
  18.207 +static int resume_iter(struct device *device, void *data)
  18.208 +{
  18.209 +	struct pcie_device *pcie_device;
  18.210 +	struct pcie_port_service_driver *driver;
  18.211 +
  18.212 +	if (device->bus == &pcie_port_bus_type && device->driver) {
  18.213 +		driver = to_service_driver(device->driver);
  18.214 +		if (driver &&
  18.215 +			driver->err_handler &&
  18.216 +			driver->err_handler->resume) {
  18.217 +			pcie_device = to_pcie_device(device);
  18.218 +
  18.219 +			/* Forward error message to service drivers */
  18.220 +			driver->err_handler->resume(pcie_device->port);
  18.221 +		}
  18.222 +	}
  18.223 +
  18.224 +	return 0;
  18.225 +}
  18.226 +
  18.227 +static void pcie_portdrv_err_resume(struct pci_dev *dev)
  18.228 +{
  18.229 +	device_for_each_child(&dev->dev, NULL, resume_iter);
  18.230 +}
  18.231  
  18.232  /*
  18.233   * LINUX Device Driver Model
  18.234 @@ -114,6 +261,13 @@ static const struct pci_device_id port_p
  18.235  };
  18.236  MODULE_DEVICE_TABLE(pci, port_pci_ids);
  18.237  
  18.238 +static struct pci_error_handlers pcie_portdrv_err_handler = {
  18.239 +		.error_detected = pcie_portdrv_error_detected,
  18.240 +		.mmio_enabled = pcie_portdrv_mmio_enabled,
  18.241 +		.slot_reset = pcie_portdrv_slot_reset,
  18.242 +		.resume = pcie_portdrv_err_resume,
  18.243 +};
  18.244 +
  18.245  static struct pci_driver pcie_portdrv = {
  18.246  	.name		= (char *)device_name,
  18.247  	.id_table	= &port_pci_ids[0],
  18.248 @@ -121,10 +275,10 @@ static struct pci_driver pcie_portdrv = 
  18.249  	.probe		= pcie_portdrv_probe,
  18.250  	.remove		= pcie_portdrv_remove,
  18.251  
  18.252 -#ifdef	CONFIG_PM
  18.253  	.suspend	= pcie_portdrv_suspend,
  18.254  	.resume		= pcie_portdrv_resume,
  18.255 -#endif	/* PM */
  18.256 +
  18.257 +	.err_handler 	= &pcie_portdrv_err_handler,
  18.258  };
  18.259  
  18.260  static int __init pcie_portdrv_init(void)
    19.1 --- a/drivers/pci/search.c	Tue Nov 04 12:43:37 2008 +0900
    19.2 +++ b/drivers/pci/search.c	Wed Nov 26 10:24:15 2008 +0900
    19.3 @@ -380,6 +380,36 @@ exit:
    19.4  	up_read(&pci_bus_sem);
    19.5  	return found;
    19.6  }
    19.7 +
    19.8 +/**
    19.9 + * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
   19.10 + * @bus: number of PCI bus on which desired PCI device resides
   19.11 + * @devfn: encodes number of PCI slot in which the desired PCI
   19.12 + * device resides and the logical device number within that slot
   19.13 + * in case of multi-function devices.
   19.14 + *
   19.15 + * Note: the bus/slot search is limited to PCI domain (segment) 0.
   19.16 + *
   19.17 + * Given a PCI bus and slot/function number, the desired PCI device
   19.18 + * is located in system global list of PCI devices.  If the device
   19.19 + * is found, a pointer to its data structure is returned.  If no
   19.20 + * device is found, %NULL is returned. The returned device has its
   19.21 + * reference count bumped by one.
   19.22 + */
   19.23 +
   19.24 +struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
   19.25 +{
   19.26 +	struct pci_dev *dev = NULL;
   19.27 +
   19.28 +	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
   19.29 +		if (pci_domain_nr(dev->bus) == 0 &&
   19.30 +		   (dev->bus->number == bus && dev->devfn == devfn))
   19.31 +			return dev;
   19.32 +	}
   19.33 +	return NULL;
   19.34 +}
   19.35 +
   19.36 +
   19.37  EXPORT_SYMBOL(pci_dev_present);
   19.38  
   19.39  EXPORT_SYMBOL(pci_find_bus);
   19.40 @@ -390,4 +420,5 @@ EXPORT_SYMBOL(pci_find_slot);
   19.41  EXPORT_SYMBOL(pci_get_device);
   19.42  EXPORT_SYMBOL(pci_get_subsys);
   19.43  EXPORT_SYMBOL(pci_get_slot);
   19.44 +EXPORT_SYMBOL(pci_get_bus_and_slot);
   19.45  EXPORT_SYMBOL(pci_get_class);
    20.1 --- a/drivers/scsi/ahci.c	Tue Nov 04 12:43:37 2008 +0900
    20.2 +++ b/drivers/scsi/ahci.c	Wed Nov 26 10:24:15 2008 +0900
    20.3 @@ -370,6 +370,31 @@ static const struct pci_device_id ahci_p
    20.4  	  board_ahci }, /* ICH10 */
    20.5  	{ PCI_VENDOR_ID_INTEL, 0x3a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    20.6  	  board_ahci }, /* ICH10 */
    20.7 +	/* SATA Controller AHCI (PCH) */
    20.8 +	{ PCI_VENDOR_ID_INTEL, 0x3b22, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    20.9 +	 board_ahci },
   20.10 +	/* SATA Controller AHCI (PCH) */
   20.11 +	{ PCI_VENDOR_ID_INTEL, 0x3b23, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
   20.12 +	 board_ahci },
   20.13 +	/* SATA Controller RAID (PCH) */
   20.14 +	{ PCI_VENDOR_ID_INTEL, 0x3b24, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
   20.15 +	 board_ahci },
   20.16 +	/* SATA Controller RAID (PCH) */
   20.17 +	{ PCI_VENDOR_ID_INTEL, 0x3b25, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
   20.18 +	 board_ahci },
   20.19 +	/* SATA Controller Mobile AHCI (PCH) */
   20.20 +	{ PCI_VENDOR_ID_INTEL, 0x3b29, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
   20.21 +	 board_ahci },
   20.22 +	/* SATA Controller Mobile AHCI (PCH) */
   20.23 +	{ PCI_VENDOR_ID_INTEL, 0x3b2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
   20.24 +	 board_ahci },
   20.25 +	/* SATA Controller Mobile RAID (PCH) */
   20.26 +	{ PCI_VENDOR_ID_INTEL, 0x3b2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
   20.27 +	 board_ahci },
   20.28 +	/* SATA Controller Mobile RAID (PCH) */
   20.29 +	{ PCI_VENDOR_ID_INTEL, 0x3b2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
   20.30 +	 board_ahci },
   20.31 +
   20.32  
   20.33  	/* JMicron */
   20.34  	{ 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    21.1 --- a/drivers/scsi/ata_piix.c	Tue Nov 04 12:43:37 2008 +0900
    21.2 +++ b/drivers/scsi/ata_piix.c	Wed Nov 26 10:24:15 2008 +0900
    21.3 @@ -220,6 +220,18 @@ static const struct pci_device_id piix_p
    21.4  	{ 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
    21.5  	/* SATA Controller IDE (ICH10) */
    21.6  	{ 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
    21.7 +	/* SATA Controller IDE (PCH) */
    21.8 +	{ 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
    21.9 +	/* SATA Controller IDE (PCH) */
   21.10 +	{ 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
   21.11 +	/* SATA Controller IDE (PCH) */
   21.12 +	{ 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
   21.13 +	/* SATA Controller IDE (PCH) */
   21.14 +	{ 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
   21.15 +	/* SATA Controller IDE (PCH) */
   21.16 +	{ 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
   21.17 +	/* SATA Controller IDE (PCH) */
   21.18 +	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
   21.19  
   21.20  	{ }	/* terminate list */
   21.21  };
    22.1 --- a/drivers/xen/balloon/balloon.c	Tue Nov 04 12:43:37 2008 +0900
    22.2 +++ b/drivers/xen/balloon/balloon.c	Wed Nov 26 10:24:15 2008 +0900
    22.3 @@ -577,8 +577,8 @@ subsys_initcall(balloon_init);
    22.4  
    22.5  static void __exit balloon_exit(void)
    22.6  {
    22.7 -    /* XXX - release balloon here */
    22.8 -    return; 
    22.9 +	balloon_sysfs_exit();
   22.10 +	/* XXX - release balloon here */
   22.11  }
   22.12  
   22.13  module_exit(balloon_exit); 
    23.1 --- a/drivers/xen/balloon/sysfs.c	Tue Nov 04 12:43:37 2008 +0900
    23.2 +++ b/drivers/xen/balloon/sysfs.c	Wed Nov 26 10:24:15 2008 +0900
    23.3 @@ -30,6 +30,7 @@
    23.4  
    23.5  #include <linux/capability.h>
    23.6  #include <linux/errno.h>
    23.7 +#include <linux/init.h>
    23.8  #include <linux/stat.h>
    23.9  #include <linux/string.h>
   23.10  #include <linux/sysdev.h>
   23.11 @@ -111,7 +112,7 @@ static struct sysdev_class balloon_sysde
   23.12  
   23.13  static struct sys_device balloon_sysdev;
   23.14  
   23.15 -static int register_balloon(struct sys_device *sysdev)
   23.16 +static int __init register_balloon(struct sys_device *sysdev)
   23.17  {
   23.18  	int i, error;
   23.19  
   23.20 @@ -148,7 +149,7 @@ static int register_balloon(struct sys_d
   23.21  	return error;
   23.22  }
   23.23  
   23.24 -static void unregister_balloon(struct sys_device *sysdev)
   23.25 +static __exit void unregister_balloon(struct sys_device *sysdev)
   23.26  {
   23.27  	int i;
   23.28  
   23.29 @@ -159,12 +160,12 @@ static void unregister_balloon(struct sy
   23.30  	sysdev_class_unregister(&balloon_sysdev_class);
   23.31  }
   23.32  
   23.33 -int balloon_sysfs_init(void)
   23.34 +int __init balloon_sysfs_init(void)
   23.35  {
   23.36  	return register_balloon(&balloon_sysdev);
   23.37  }
   23.38  
   23.39 -void balloon_sysfs_exit(void)
   23.40 +void __exit balloon_sysfs_exit(void)
   23.41  {
   23.42  	unregister_balloon(&balloon_sysdev);
   23.43  }
    24.1 --- a/drivers/xen/blkback/blkback.c	Tue Nov 04 12:43:37 2008 +0900
    24.2 +++ b/drivers/xen/blkback/blkback.c	Wed Nov 26 10:24:15 2008 +0900
    24.3 @@ -151,9 +151,9 @@ static void unplug_queue(blkif_t *blkif)
    24.4  	blkif->plug = NULL;
    24.5  }
    24.6  
    24.7 -static void plug_queue(blkif_t *blkif, struct bio *bio)
    24.8 +static void plug_queue(blkif_t *blkif, struct block_device *bdev)
    24.9  {
   24.10 -	request_queue_t *q = bdev_get_queue(bio->bi_bdev);
   24.11 +	request_queue_t *q = bdev_get_queue(bdev);
   24.12  
   24.13  	if (q == blkif->plug)
   24.14  		return;
   24.15 @@ -389,8 +389,8 @@ static void dispatch_rw_block_io(blkif_t
   24.16  		unsigned long buf; unsigned int nsec;
   24.17  	} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   24.18  	unsigned int nseg;
   24.19 -	struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   24.20 -	int ret, i, nbio = 0;
   24.21 +	struct bio *bio = NULL;
   24.22 +	int ret, i;
   24.23  	int operation;
   24.24  
   24.25  	switch (req->operation) {
   24.26 @@ -477,6 +477,10 @@ static void dispatch_rw_block_io(blkif_t
   24.27  		goto fail_flush;
   24.28  	}
   24.29  
   24.30 +	plug_queue(blkif, preq.bdev);
   24.31 +	atomic_set(&pending_req->pendcnt, 1);
   24.32 +	blkif_get(blkif);
   24.33 +
   24.34  	for (i = 0; i < nseg; i++) {
   24.35  		if (((int)preq.sector_number|(int)seg[i].nsec) &
   24.36  		    ((bdev_hardsect_size(preq.bdev) >> 9) - 1)) {
   24.37 @@ -490,7 +494,12 @@ static void dispatch_rw_block_io(blkif_t
   24.38  				     virt_to_page(vaddr(pending_req, i)),
   24.39  				     seg[i].nsec << 9,
   24.40  				     seg[i].buf & ~PAGE_MASK) == 0)) {
   24.41 -			bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i);
   24.42 +			if (bio) {
   24.43 +				atomic_inc(&pending_req->pendcnt);
   24.44 +				submit_bio(operation, bio);
   24.45 +			}
   24.46 +
   24.47 +			bio = bio_alloc(GFP_KERNEL, nseg-i);
   24.48  			if (unlikely(bio == NULL))
   24.49  				goto fail_put_bio;
   24.50  
   24.51 @@ -505,7 +514,7 @@ static void dispatch_rw_block_io(blkif_t
   24.52  
   24.53  	if (!bio) {
   24.54  		BUG_ON(operation != WRITE_BARRIER);
   24.55 -		bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0);
   24.56 +		bio = bio_alloc(GFP_KERNEL, 0);
   24.57  		if (unlikely(bio == NULL))
   24.58  			goto fail_put_bio;
   24.59  
   24.60 @@ -515,12 +524,7 @@ static void dispatch_rw_block_io(blkif_t
   24.61  		bio->bi_sector  = -1;
   24.62  	}
   24.63  
   24.64 -	plug_queue(blkif, bio);
   24.65 -	atomic_set(&pending_req->pendcnt, nbio);
   24.66 -	blkif_get(blkif);
   24.67 -
   24.68 -	for (i = 0; i < nbio; i++)
   24.69 -		submit_bio(operation, biolist[i]);
   24.70 +	submit_bio(operation, bio);
   24.71  
   24.72  	if (operation == READ)
   24.73  		blkif->st_rd_sect += preq.nr_sects;
   24.74 @@ -529,16 +533,22 @@ static void dispatch_rw_block_io(blkif_t
   24.75  
   24.76  	return;
   24.77  
   24.78 - fail_put_bio:
   24.79 -	for (i = 0; i < (nbio-1); i++)
   24.80 -		bio_put(biolist[i]);
   24.81   fail_flush:
   24.82  	fast_flush_area(pending_req);
   24.83   fail_response:
   24.84  	make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
   24.85  	free_req(pending_req);
   24.86  	msleep(1); /* back off a bit */
   24.87 -} 
   24.88 +	return;
   24.89 +
   24.90 + fail_put_bio:
   24.91 +	__end_block_io_op(pending_req, -EINVAL);
   24.92 +	if (bio)
   24.93 +		bio_put(bio);
   24.94 +	unplug_queue(blkif);
   24.95 +	msleep(1); /* back off a bit */
   24.96 +	return;
   24.97 +}
   24.98  
   24.99  
  24.100  
    25.1 --- a/drivers/xen/blktap/blktap.c	Tue Nov 04 12:43:37 2008 +0900
    25.2 +++ b/drivers/xen/blktap/blktap.c	Wed Nov 26 10:24:15 2008 +0900
    25.3 @@ -611,9 +611,13 @@ static int blktap_release(struct inode *
    25.4  
    25.5  	/* Clear any active mappings and free foreign map table */
    25.6  	if (info->vma) {
    25.7 +		struct mm_struct *mm = info->vma->vm_mm;
    25.8 +
    25.9 +		down_write(&mm->mmap_sem);
   25.10  		zap_page_range(
   25.11  			info->vma, info->vma->vm_start, 
   25.12  			info->vma->vm_end - info->vma->vm_start, NULL);
   25.13 +		up_write(&mm->mmap_sem);
   25.14  
   25.15  		kfree(info->vma->vm_private_data);
   25.16  
   25.17 @@ -992,12 +996,13 @@ static void fast_flush_area(pending_req_
   25.18  			    int tapidx)
   25.19  {
   25.20  	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
   25.21 -	unsigned int i, invcount = 0;
   25.22 +	unsigned int i, invcount = 0, locked = 0;
   25.23  	struct grant_handle_pair *khandle;
   25.24  	uint64_t ptep;
   25.25  	int ret, mmap_idx;
   25.26  	unsigned long kvaddr, uvaddr;
   25.27  	tap_blkif_t *info;
   25.28 +	struct mm_struct *mm;
   25.29  	
   25.30  
   25.31  	info = tapfds[tapidx];
   25.32 @@ -1007,13 +1012,15 @@ static void fast_flush_area(pending_req_
   25.33  		return;
   25.34  	}
   25.35  
   25.36 +	mm = info->vma ? info->vma->vm_mm : NULL;
   25.37 +
   25.38  	if (info->vma != NULL &&
   25.39  	    xen_feature(XENFEAT_auto_translated_physmap)) {
   25.40 -		down_write(&info->vma->vm_mm->mmap_sem);
   25.41 +		down_write(&mm->mmap_sem);
   25.42  		zap_page_range(info->vma, 
   25.43  			       MMAP_VADDR(info->user_vstart, u_idx, 0), 
   25.44  			       req->nr_pages << PAGE_SHIFT, NULL);
   25.45 -		up_write(&info->vma->vm_mm->mmap_sem);
   25.46 +		up_write(&mm->mmap_sem);
   25.47  		return;
   25.48  	}
   25.49  
   25.50 @@ -1038,10 +1045,13 @@ static void fast_flush_area(pending_req_
   25.51  
   25.52  		if (khandle->user != INVALID_GRANT_HANDLE) {
   25.53  			BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
   25.54 +			if (!locked++)
   25.55 +				down_write(&mm->mmap_sem);
   25.56  			if (create_lookup_pte_addr(
   25.57 -				info->vma->vm_mm,
   25.58 +				mm,
   25.59  				MMAP_VADDR(info->user_vstart, u_idx, i),
   25.60  				&ptep) !=0) {
   25.61 +				up_write(&mm->mmap_sem);
   25.62  				WPRINTK("Couldn't get a pte addr!\n");
   25.63  				return;
   25.64  			}
   25.65 @@ -1060,10 +1070,17 @@ static void fast_flush_area(pending_req_
   25.66  		GNTTABOP_unmap_grant_ref, unmap, invcount);
   25.67  	BUG_ON(ret);
   25.68  	
   25.69 -	if (info->vma != NULL && !xen_feature(XENFEAT_auto_translated_physmap))
   25.70 +	if (info->vma != NULL &&
   25.71 +	    !xen_feature(XENFEAT_auto_translated_physmap)) {
   25.72 +		if (!locked++)
   25.73 +			down_write(&mm->mmap_sem);
   25.74  		zap_page_range(info->vma, 
   25.75  			       MMAP_VADDR(info->user_vstart, u_idx, 0), 
   25.76  			       req->nr_pages << PAGE_SHIFT, NULL);
   25.77 +	}
   25.78 +
   25.79 +	if (locked)
   25.80 +		up_write(&mm->mmap_sem);
   25.81  }
   25.82  
   25.83  /******************************************************************
   25.84 @@ -1346,6 +1363,7 @@ static void dispatch_rw_block_io(blkif_t
   25.85  	int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx);
   25.86  	int usr_idx;
   25.87  	uint16_t mmap_idx = pending_req->mem_idx;
   25.88 +	struct mm_struct *mm;
   25.89  
   25.90  	if (blkif->dev_num < 0 || blkif->dev_num > MAX_TAP_DEV)
   25.91  		goto fail_response;
   25.92 @@ -1389,6 +1407,9 @@ static void dispatch_rw_block_io(blkif_t
   25.93  	pending_req->status    = BLKIF_RSP_OKAY;
   25.94  	pending_req->nr_pages  = nseg;
   25.95  	op = 0;
   25.96 +	mm = info->vma->vm_mm;
   25.97 +	if (!xen_feature(XENFEAT_auto_translated_physmap))
   25.98 +		down_write(&mm->mmap_sem);
   25.99  	for (i = 0; i < nseg; i++) {
  25.100  		unsigned long uvaddr;
  25.101  		unsigned long kvaddr;
  25.102 @@ -1407,9 +1428,9 @@ static void dispatch_rw_block_io(blkif_t
  25.103  
  25.104  		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
  25.105  			/* Now map it to user. */
  25.106 -			ret = create_lookup_pte_addr(info->vma->vm_mm, 
  25.107 -						     uvaddr, &ptep);
  25.108 +			ret = create_lookup_pte_addr(mm, uvaddr, &ptep);
  25.109  			if (ret) {
  25.110 +				up_write(&mm->mmap_sem);
  25.111  				WPRINTK("Couldn't get a pte addr!\n");
  25.112  				goto fail_flush;
  25.113  			}
  25.114 @@ -1431,6 +1452,8 @@ static void dispatch_rw_block_io(blkif_t
  25.115  	BUG_ON(ret);
  25.116  
  25.117  	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
  25.118 +		up_write(&mm->mmap_sem);
  25.119 +
  25.120  		for (i = 0; i < (nseg*2); i+=2) {
  25.121  			unsigned long uvaddr;
  25.122  			unsigned long kvaddr;
  25.123 @@ -1504,7 +1527,7 @@ static void dispatch_rw_block_io(blkif_t
  25.124  		goto fail_flush;
  25.125  
  25.126  	if (xen_feature(XENFEAT_auto_translated_physmap))
  25.127 -		down_write(&info->vma->vm_mm->mmap_sem);
  25.128 +		down_write(&mm->mmap_sem);
  25.129  	/* Mark mapped pages as reserved: */
  25.130  	for (i = 0; i < req->nr_segments; i++) {
  25.131  		unsigned long kvaddr;
  25.132 @@ -1518,13 +1541,13 @@ static void dispatch_rw_block_io(blkif_t
  25.133  					     MMAP_VADDR(info->user_vstart,
  25.134  							usr_idx, i), pg);
  25.135  			if (ret) {
  25.136 -				up_write(&info->vma->vm_mm->mmap_sem);
  25.137 +				up_write(&mm->mmap_sem);
  25.138  				goto fail_flush;
  25.139  			}
  25.140  		}
  25.141  	}
  25.142  	if (xen_feature(XENFEAT_auto_translated_physmap))
  25.143 -		up_write(&info->vma->vm_mm->mmap_sem);
  25.144 +		up_write(&mm->mmap_sem);
  25.145  	
  25.146  	/*record [mmap_idx,pending_idx] to [usr_idx] mapping*/
  25.147  	info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx);
    26.1 --- a/drivers/xen/core/evtchn.c	Tue Nov 04 12:43:37 2008 +0900
    26.2 +++ b/drivers/xen/core/evtchn.c	Wed Nov 26 10:24:15 2008 +0900
    26.3 @@ -756,71 +756,6 @@ static struct hw_interrupt_type dynirq_t
    26.4  	.retrigger = resend_irq_on_evtchn,
    26.5  };
    26.6  
    26.7 -void evtchn_register_pirq(int irq)
    26.8 -{
    26.9 -	struct irq_desc *desc;
   26.10 -	unsigned long flags;
   26.11 -
   26.12 -	irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
   26.13 -
   26.14 -	/* Cannot call set_irq_probe(), as that's marked __init. */
   26.15 -	desc = irq_desc + irq;
   26.16 -	spin_lock_irqsave(&desc->lock, flags);
   26.17 -	desc->status &= ~IRQ_NOPROBE;
   26.18 -	spin_unlock_irqrestore(&desc->lock, flags);
   26.19 -}
   26.20 -
   26.21 -#if defined(CONFIG_X86_IO_APIC)
   26.22 -#define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
   26.23 -#elif defined(CONFIG_X86)
   26.24 -#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < 16)
   26.25 -#else
   26.26 -#define identity_mapped_irq(irq) (1)
   26.27 -#endif
   26.28 -
   26.29 -int evtchn_map_pirq(int irq, int xen_pirq)
   26.30 -{
   26.31 -	if (irq < 0) {
   26.32 -		static DEFINE_SPINLOCK(irq_alloc_lock);
   26.33 -
   26.34 -		irq = PIRQ_BASE + NR_PIRQS - 1;
   26.35 -		spin_lock(&irq_alloc_lock);
   26.36 -		do {
   26.37 -			if (identity_mapped_irq(irq))
   26.38 -				continue;
   26.39 -			if (!index_from_irq(irq)) {
   26.40 -				BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
   26.41 -				irq_info[irq] = mk_irq_info(IRQT_PIRQ,
   26.42 -							    xen_pirq, 0);
   26.43 -				break;
   26.44 -			}
   26.45 -		} while (--irq >= PIRQ_BASE);
   26.46 -		spin_unlock(&irq_alloc_lock);
   26.47 -		if (irq < PIRQ_BASE)
   26.48 -			return -ENOSPC;
   26.49 -	} else if (!xen_pirq) {
   26.50 -		if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
   26.51 -			return -EINVAL;
   26.52 -		irq_info[irq] = IRQ_UNBOUND;
   26.53 -		return 0;
   26.54 -	} else if (type_from_irq(irq) != IRQT_PIRQ
   26.55 -		   || index_from_irq(irq) != xen_pirq) {
   26.56 -		printk(KERN_ERR "IRQ#%d is already mapped to %d:%u - "
   26.57 -				"cannot map to PIRQ#%u\n",
   26.58 -		       irq, type_from_irq(irq), index_from_irq(irq), xen_pirq);
   26.59 -		return -EINVAL;
   26.60 -	}
   26.61 -	return index_from_irq(irq) ? irq : -EINVAL;
   26.62 -}
   26.63 -
   26.64 -int evtchn_get_xen_pirq(int irq)
   26.65 -{
   26.66 -	if (identity_mapped_irq(irq))
   26.67 -		return irq;
   26.68 -	BUG_ON(type_from_irq(irq) != IRQT_PIRQ);
   26.69 -	return index_from_irq(irq);
   26.70 -}
   26.71 -
   26.72  static inline void pirq_unmask_notify(int irq)
   26.73  {
   26.74  	struct physdev_eoi eoi = { .irq = evtchn_get_xen_pirq(irq) };
   26.75 @@ -1098,6 +1033,68 @@ void irq_resume(void)
   26.76  
   26.77  }
   26.78  
   26.79 +#if defined(CONFIG_X86_IO_APIC)
   26.80 +#define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
   26.81 +#elif defined(CONFIG_X86)
   26.82 +#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < 16)
   26.83 +#else
   26.84 +#define identity_mapped_irq(irq) (1)
   26.85 +#endif
   26.86 +
   26.87 +void evtchn_register_pirq(int irq)
   26.88 +{
   26.89 +	BUG_ON(irq < PIRQ_BASE || irq - PIRQ_BASE > NR_PIRQS);
   26.90 +	if (identity_mapped_irq(irq))
   26.91 +		return;
   26.92 +	irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
   26.93 +	irq_desc[irq].chip = &pirq_type;
   26.94 +}
   26.95 +
   26.96 +int evtchn_map_pirq(int irq, int xen_pirq)
   26.97 +{
   26.98 +	if (irq < 0) {
   26.99 +		static DEFINE_SPINLOCK(irq_alloc_lock);
  26.100 +
  26.101 +		irq = PIRQ_BASE + NR_PIRQS - 1;
  26.102 +		spin_lock(&irq_alloc_lock);
  26.103 +		do {
  26.104 +			if (identity_mapped_irq(irq))
  26.105 +				continue;
  26.106 +			if (!index_from_irq(irq)) {
  26.107 +				BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
  26.108 +				irq_info[irq] = mk_irq_info(IRQT_PIRQ,
  26.109 +							    xen_pirq, 0);
  26.110 +				break;
  26.111 +			}
  26.112 +		} while (--irq >= PIRQ_BASE);
  26.113 +		spin_unlock(&irq_alloc_lock);
  26.114 +		if (irq < PIRQ_BASE)
  26.115 +			return -ENOSPC;
  26.116 +		irq_desc[irq].chip = &pirq_type;
  26.117 +	} else if (!xen_pirq) {
  26.118 +		if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
  26.119 +			return -EINVAL;
  26.120 +		irq_desc[irq].chip = &no_irq_type;
  26.121 +		irq_info[irq] = IRQ_UNBOUND;
  26.122 +		return 0;
  26.123 +	} else if (type_from_irq(irq) != IRQT_PIRQ
  26.124 +		   || index_from_irq(irq) != xen_pirq) {
  26.125 +		printk(KERN_ERR "IRQ#%d is already mapped to %d:%u - "
  26.126 +				"cannot map to PIRQ#%u\n",
  26.127 +		       irq, type_from_irq(irq), index_from_irq(irq), xen_pirq);
  26.128 +		return -EINVAL;
  26.129 +	}
  26.130 +	return index_from_irq(irq) ? irq : -EINVAL;
  26.131 +}
  26.132 +
  26.133 +int evtchn_get_xen_pirq(int irq)
  26.134 +{
  26.135 +	if (identity_mapped_irq(irq))
  26.136 +		return irq;
  26.137 +	BUG_ON(type_from_irq(irq) != IRQT_PIRQ);
  26.138 +	return index_from_irq(irq);
  26.139 +}
  26.140 +
  26.141  void __init xen_init_IRQ(void)
  26.142  {
  26.143  	unsigned int i;
  26.144 @@ -1126,16 +1123,16 @@ void __init xen_init_IRQ(void)
  26.145  	for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_PIRQS); i++) {
  26.146  		irq_bindcount[i] = 1;
  26.147  
  26.148 +		if (!identity_mapped_irq(i))
  26.149 +			continue;
  26.150 +
  26.151  #ifdef RTC_IRQ
  26.152  		/* If not domain 0, force our RTC driver to fail its probe. */
  26.153 -		if (identity_mapped_irq(i) && ((i - PIRQ_BASE) == RTC_IRQ)
  26.154 -		    && !is_initial_xendomain())
  26.155 +		if (i - PIRQ_BASE == RTC_IRQ && !is_initial_xendomain())
  26.156  			continue;
  26.157  #endif
  26.158  
  26.159  		irq_desc[i].status = IRQ_DISABLED;
  26.160 -		if (!identity_mapped_irq(i))
  26.161 -			irq_desc[i].status |= IRQ_NOPROBE;
  26.162  		irq_desc[i].action = NULL;
  26.163  		irq_desc[i].depth = 1;
  26.164  		irq_desc[i].chip = &pirq_type;
    27.1 --- a/drivers/xen/core/pci.c	Tue Nov 04 12:43:37 2008 +0900
    27.2 +++ b/drivers/xen/core/pci.c	Wed Nov 26 10:24:15 2008 +0900
    27.3 @@ -23,14 +23,6 @@ static int pci_bus_probe_wrapper(struct 
    27.4  		return r;
    27.5  
    27.6  	r = pci_bus_probe(dev);
    27.7 -	if (r) {
    27.8 -		int ret;
    27.9 -
   27.10 -		ret = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
   27.11 -					    &manage_pci);
   27.12 -		WARN_ON(ret && ret != -ENOSYS);
   27.13 -	}
   27.14 -
   27.15  	return r;
   27.16  }
   27.17  
    28.1 --- a/drivers/xen/fbfront/xenfb.c	Tue Nov 04 12:43:37 2008 +0900
    28.2 +++ b/drivers/xen/fbfront/xenfb.c	Wed Nov 26 10:24:15 2008 +0900
    28.3 @@ -662,6 +662,10 @@ static int __devinit xenfb_probe(struct 
    28.4  	}
    28.5  	info->fb_info = fb_info;
    28.6  
    28.7 +	ret = xenfb_connect_backend(dev, info);
    28.8 +	if (ret < 0)
    28.9 +		goto error;
   28.10 +
   28.11  	/* FIXME should this be delayed until backend XenbusStateConnected? */
   28.12  	info->kthread = kthread_run(xenfb_thread, info, "xenfb thread");
   28.13  	if (IS_ERR(info->kthread)) {
   28.14 @@ -671,10 +675,6 @@ static int __devinit xenfb_probe(struct 
   28.15  		goto error;
   28.16  	}
   28.17  
   28.18 -	ret = xenfb_connect_backend(dev, info);
   28.19 -	if (ret < 0)
   28.20 -		goto error;
   28.21 -
   28.22  	return 0;
   28.23  
   28.24   error_nomem:
    29.1 --- a/drivers/xen/pciback/controller.c	Tue Nov 04 12:43:37 2008 +0900
    29.2 +++ b/drivers/xen/pciback/controller.c	Wed Nov 26 10:24:15 2008 +0900
    29.3 @@ -406,3 +406,38 @@ void pciback_release_devices(struct pcib
    29.4  	kfree(dev_data);
    29.5  	pdev->pci_dev_data = NULL;
    29.6  }
    29.7 +
    29.8 +int pciback_get_pcifront_dev(struct pci_dev *pcidev, 
    29.9 +		struct pciback_device *pdev, 
   29.10 +		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
   29.11 +{
   29.12 +	struct controller_dev_data *dev_data = pdev->pci_dev_data;
   29.13 +	struct controller_dev_entry *dev_entry;
   29.14 +	struct controller_list_entry *cntrl_entry;
   29.15 +	unsigned long flags;
   29.16 +	int found = 0;
   29.17 +	spin_lock_irqsave(&dev_data->lock, flags);
   29.18 +
   29.19 +	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
   29.20 +		list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
   29.21 +			if ( (dev_entry->dev->bus->number == 
   29.22 +					pcidev->bus->number) &&
   29.23 +			  	(dev_entry->dev->devfn ==
   29.24 +					pcidev->devfn) &&
   29.25 +				(pci_domain_nr(dev_entry->dev->bus) ==
   29.26 +					pci_domain_nr(pcidev->bus)))
   29.27 +			{
   29.28 +				found = 1;
   29.29 +				*domain = cntrl_entry->domain;
   29.30 +				*bus = cntrl_entry->bus;
   29.31 +				*devfn = dev_entry->devfn;
   29.32 +				goto out;
   29.33 +			}
   29.34 +		}
   29.35 +	}
   29.36 +out:
   29.37 +	spin_unlock_irqrestore(&dev_data->lock, flags);
   29.38 +	return found;
   29.39 +
   29.40 +}
   29.41 +
    30.1 --- a/drivers/xen/pciback/passthrough.c	Tue Nov 04 12:43:37 2008 +0900
    30.2 +++ b/drivers/xen/pciback/passthrough.c	Wed Nov 26 10:24:15 2008 +0900
    30.3 @@ -164,3 +164,13 @@ void pciback_release_devices(struct pcib
    30.4  	kfree(dev_data);
    30.5  	pdev->pci_dev_data = NULL;
    30.6  }
    30.7 +
    30.8 +int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
    30.9 +		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
   30.10 +
   30.11 +{
   30.12 +	*domain = pci_domain_nr(pcidev->bus);
   30.13 +	*bus = pcidev->bus->number;
   30.14 +	*devfn = pcidev->devfn;
   30.15 +	return 1;
   30.16 +}
    31.1 --- a/drivers/xen/pciback/pci_stub.c	Tue Nov 04 12:43:37 2008 +0900
    31.2 +++ b/drivers/xen/pciback/pci_stub.c	Wed Nov 26 10:24:15 2008 +0900
    31.3 @@ -6,15 +6,24 @@
    31.4   */
    31.5  #include <linux/module.h>
    31.6  #include <linux/init.h>
    31.7 +#include <linux/rwsem.h>
    31.8  #include <linux/list.h>
    31.9  #include <linux/spinlock.h>
   31.10  #include <linux/kref.h>
   31.11 +#include <linux/pci.h>
   31.12 +#include <linux/wait.h>
   31.13  #include <asm/atomic.h>
   31.14 +#include <xen/evtchn.h>
   31.15  #include "pciback.h"
   31.16  #include "conf_space.h"
   31.17  #include "conf_space_quirks.h"
   31.18  
   31.19  static char *pci_devs_to_hide = NULL;
   31.20 +wait_queue_head_t aer_wait_queue;
   31.21 +/*Add sem for sync AER handling and pciback remove/reconfigue ops,
   31.22 +* We want to avoid in middle of AER ops, pciback devices is being removed
   31.23 +*/
   31.24 +static DECLARE_RWSEM(pcistub_sem);
   31.25  module_param_named(hide, pci_devs_to_hide, charp, 0444);
   31.26  
   31.27  struct pcistub_device_id {
   31.28 @@ -207,6 +216,10 @@ void pcistub_put_pci_dev(struct pci_dev 
   31.29  
   31.30  	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
   31.31  
   31.32 +	/*hold this lock for avoiding breaking link between
   31.33 +	* pcistub and pciback when AER is in processing
   31.34 +	*/
   31.35 +	down_write(&pcistub_sem);
   31.36  	/* Cleanup our device
   31.37  	 * (so it's ready for the next domain)
   31.38  	 */
   31.39 @@ -219,6 +232,7 @@ void pcistub_put_pci_dev(struct pci_dev 
   31.40  	spin_unlock_irqrestore(&found_psdev->lock, flags);
   31.41  
   31.42  	pcistub_device_put(found_psdev);
   31.43 +	up_write(&pcistub_sem);
   31.44  }
   31.45  
   31.46  static int __devinit pcistub_match_one(struct pci_dev *dev,
   31.47 @@ -279,6 +293,8 @@ static int __devinit pcistub_init_device
   31.48  	pci_set_drvdata(dev, dev_data);
   31.49  
   31.50  	dev_dbg(&dev->dev, "initializing config\n");
   31.51 +
   31.52 +	init_waitqueue_head(&aer_wait_queue);
   31.53  	err = pciback_config_init_dev(dev);
   31.54  	if (err)
   31.55  		goto out;
   31.56 @@ -477,6 +493,308 @@ static const struct pci_device_id pcistu
   31.57  	{0,},
   31.58  };
   31.59  
   31.60 +static void kill_domain_by_device(struct pcistub_device *psdev)
   31.61 +{
   31.62 +	struct xenbus_transaction xbt;
   31.63 +	int err;
   31.64 +	char nodename[1024];
   31.65 +
   31.66 +	if (!psdev) 
   31.67 +		dev_err(&psdev->dev->dev,
   31.68 +			"device is NULL when do AER recovery/kill_domain\n");
   31.69 +	sprintf(nodename, "/local/domain/0/backend/pci/%d/0", 
   31.70 +		psdev->pdev->xdev->otherend_id);
   31.71 +	nodename[strlen(nodename)] = '\0';
   31.72 +
   31.73 +again:
   31.74 +	err = xenbus_transaction_start(&xbt);
   31.75 +	if (err)
   31.76 +	{
   31.77 +		dev_err(&psdev->dev->dev,
   31.78 +			"error %d when start xenbus transaction\n", err);
   31.79 +		return;
   31.80 +	}
   31.81 +	/*PV AER handlers will set this flag*/
   31.82 +	xenbus_printf(xbt, nodename, "aerState" , "aerfail" );
   31.83 +	err = xenbus_transaction_end(xbt, 0);
   31.84 +	if (err)
   31.85 +	{
   31.86 +		if (err == -EAGAIN)
   31.87 +			goto again;
   31.88 +		dev_err(&psdev->dev->dev,
   31.89 +			"error %d when end xenbus transaction\n", err);
   31.90 +		return;
   31.91 +	}
   31.92 +}
   31.93 +
   31.94 +/* For each aer recovery step error_detected, mmio_enabled, etc, front_end and
   31.95 + * backend need to have cooperation. In pciback, those steps will do similar
   31.96 + * jobs: send service request and waiting for front_end response. 
   31.97 +*/
   31.98 +static pci_ers_result_t common_process(struct pcistub_device *psdev, 
   31.99 +		pci_channel_state_t state, int aer_cmd, pci_ers_result_t result)
  31.100 +{
  31.101 +	pci_ers_result_t res = result;
  31.102 +	struct xen_pcie_aer_op *aer_op;
  31.103 +	int ret;
  31.104 +
  31.105 +	/*with PV AER drivers*/
  31.106 +	aer_op = &(psdev->pdev->sh_info->aer_op);
  31.107 +	aer_op->cmd = aer_cmd ;
  31.108 +	/*useful for error_detected callback*/
  31.109 +	aer_op->err = state;
  31.110 +	/*pcifront_end BDF*/
  31.111 +	ret = pciback_get_pcifront_dev(psdev->dev, psdev->pdev,
  31.112 +		&aer_op->domain, &aer_op->bus, &aer_op->devfn);
  31.113 +	if (!ret) {
  31.114 +		dev_err(&psdev->dev->dev,
  31.115 +			"pciback: failed to get pcifront device\n");
  31.116 +		return PCI_ERS_RESULT_NONE; 
  31.117 +	}
  31.118 +	wmb();
  31.119 +
  31.120 +	dev_dbg(&psdev->dev->dev, 
  31.121 +			"pciback: aer_op %x dom %x bus %x devfn %x\n",  
  31.122 +			aer_cmd, aer_op->domain, aer_op->bus, aer_op->devfn);
  31.123 +	/*local flag to mark there's aer request, pciback callback will use this
  31.124 +	* flag to judge whether we need to check pci-front give aer service
  31.125 +	* ack signal
  31.126 +	*/
  31.127 +	set_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
  31.128 +
  31.129 +	/*It is possible that a pcifront conf_read_write ops request invokes
  31.130 +	* the callback which cause the spurious execution of wake_up. 
  31.131 +	* Yet it is harmless and better than a spinlock here
  31.132 +	*/
  31.133 +	set_bit(_XEN_PCIB_active, 
  31.134 +		(unsigned long *)&psdev->pdev->sh_info->flags);
  31.135 +	wmb();
  31.136 +	notify_remote_via_irq(psdev->pdev->evtchn_irq);
  31.137 +
  31.138 +	ret = wait_event_timeout(aer_wait_queue, !(test_bit(_XEN_PCIB_active,
  31.139 +                (unsigned long *)&psdev->pdev->sh_info->flags)), 300*HZ);
  31.140 +
  31.141 +	if (!ret) {
  31.142 +		if (test_bit(_XEN_PCIB_active, 
  31.143 +			(unsigned long *)&psdev->pdev->sh_info->flags)) {
  31.144 +			dev_err(&psdev->dev->dev, 
  31.145 +				"pcifront aer process not responding!\n");
  31.146 +			clear_bit(_XEN_PCIB_active,
  31.147 +			  (unsigned long *)&psdev->pdev->sh_info->flags);
  31.148 +			aer_op->err = PCI_ERS_RESULT_NONE;
  31.149 +			return res;
  31.150 +		}
  31.151 +	}
  31.152 +	clear_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
  31.153 +
  31.154 +	if ( test_bit( _XEN_PCIF_active,
  31.155 +		(unsigned long*)&psdev->pdev->sh_info->flags)) {
  31.156 +		dev_dbg(&psdev->dev->dev, 
  31.157 +			"schedule pci_conf service in pciback \n");
  31.158 +		test_and_schedule_op(psdev->pdev);
  31.159 +	}
  31.160 +
  31.161 +	res = (pci_ers_result_t)aer_op->err;
  31.162 +	return res;
  31.163 +} 
  31.164 +
  31.165 +/*
  31.166 +* pciback_slot_reset: it will send the slot_reset request to  pcifront in case
  31.167 +* of the device driver could provide this service, and then wait for pcifront
  31.168 +* ack.
  31.169 +* @dev: pointer to PCI devices
  31.170 +* return value is used by aer_core do_recovery policy
  31.171 +*/
  31.172 +static pci_ers_result_t pciback_slot_reset(struct pci_dev *dev)
  31.173 +{
  31.174 +	struct pcistub_device *psdev;
  31.175 +	pci_ers_result_t result;
  31.176 +
  31.177 +	result = PCI_ERS_RESULT_RECOVERED;
  31.178 +	dev_dbg(&dev->dev, "pciback_slot_reset(bus:%x,devfn:%x)\n",
  31.179 +		dev->bus->number, dev->devfn);
  31.180 +
  31.181 +	down_write(&pcistub_sem);
  31.182 +	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
  31.183 +				dev->bus->number,
  31.184 +				PCI_SLOT(dev->devfn),
  31.185 +				PCI_FUNC(dev->devfn));
  31.186 +	if ( !psdev || !psdev->pdev || !psdev->pdev->sh_info )
  31.187 +	{
  31.188 +		dev_err(&dev->dev, 
  31.189 +			"pciback device is not found/in use/connected!\n");
  31.190 +		goto end;
  31.191 +	}
  31.192 +	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
  31.193 +		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
  31.194 +		dev_err(&dev->dev, 
  31.195 +			"guest with no AER driver should have been killed\n");
  31.196 +		goto release;
  31.197 +	}
  31.198 +	result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result);
  31.199 +
  31.200 +	if (result == PCI_ERS_RESULT_NONE ||
  31.201 +		result == PCI_ERS_RESULT_DISCONNECT) {
  31.202 +		dev_dbg(&dev->dev, 
  31.203 +			"No AER slot_reset service or disconnected!\n");
  31.204 +		kill_domain_by_device(psdev);
  31.205 +	}
  31.206 +release:
  31.207 +	pcistub_device_put(psdev);
  31.208 +end:
  31.209 +	up_write(&pcistub_sem);
  31.210 +	return result;
  31.211 +
  31.212 +}
  31.213 +
  31.214 +
  31.215 +/*pciback_mmio_enabled: it will send the mmio_enabled request to  pcifront 
  31.216 +* in case of the device driver could provide this service, and then wait 
  31.217 +* for pcifront ack.
  31.218 +* @dev: pointer to PCI devices
  31.219 +* return value is used by aer_core do_recovery policy
  31.220 +*/
  31.221 +
  31.222 +static pci_ers_result_t pciback_mmio_enabled(struct pci_dev *dev)
  31.223 +{
  31.224 +	struct pcistub_device *psdev;
  31.225 +	pci_ers_result_t result;
  31.226 +
  31.227 +	result = PCI_ERS_RESULT_RECOVERED;
  31.228 +	dev_dbg(&dev->dev, "pciback_mmio_enabled(bus:%x,devfn:%x)\n",
  31.229 +		dev->bus->number, dev->devfn);
  31.230 +
  31.231 +	down_write(&pcistub_sem);
  31.232 +	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
  31.233 +				dev->bus->number,
  31.234 +				PCI_SLOT(dev->devfn),
  31.235 +				PCI_FUNC(dev->devfn));
  31.236 +	if ( !psdev || !psdev->pdev || !psdev->pdev->sh_info)
  31.237 +	{
  31.238 +		dev_err(&dev->dev, 
  31.239 +			"pciback device is not found/in use/connected!\n");
  31.240 +		goto end;
  31.241 +	}
  31.242 +	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
  31.243 +		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
  31.244 +		dev_err(&dev->dev, 
  31.245 +			"guest with no AER driver should have been killed\n");
  31.246 +		goto release;
  31.247 +	}
  31.248 +	result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result);
  31.249 +
  31.250 +	if (result == PCI_ERS_RESULT_NONE ||
  31.251 +		result == PCI_ERS_RESULT_DISCONNECT) {
  31.252 +		dev_dbg(&dev->dev, 
  31.253 +			"No AER mmio_enabled service or disconnected!\n");
  31.254 +		kill_domain_by_device(psdev);
  31.255 +	}
  31.256 +release:
  31.257 +	pcistub_device_put(psdev);
  31.258 +end:
  31.259 +	up_write(&pcistub_sem);
  31.260 +	return result;
  31.261 +}
  31.262 +
  31.263 +/*pciback_error_detected: it will send the error_detected request to  pcifront 
  31.264 +* in case of the device driver could provide this service, and then wait 
  31.265 +* for pcifront ack.
  31.266 +* @dev: pointer to PCI devices
  31.267 +* @error: the current PCI connection state
  31.268 +* return value is used by aer_core do_recovery policy
  31.269 +*/
  31.270 +
  31.271 +static pci_ers_result_t pciback_error_detected(struct pci_dev *dev,
  31.272 +	pci_channel_state_t error)
  31.273 +{
  31.274 +	struct pcistub_device *psdev;
  31.275 +	pci_ers_result_t result;
  31.276 +
  31.277 +	result = PCI_ERS_RESULT_CAN_RECOVER;
  31.278 +	dev_dbg(&dev->dev, "pciback_error_detected(bus:%x,devfn:%x)\n",
  31.279 +		dev->bus->number, dev->devfn);
  31.280 +
  31.281 +	down_write(&pcistub_sem);
  31.282 +	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
  31.283 +				dev->bus->number,
  31.284 +				PCI_SLOT(dev->devfn),
  31.285 +				PCI_FUNC(dev->devfn));
  31.286 +	if ( !psdev || !psdev->pdev || !psdev->pdev->sh_info)
  31.287 +	{
  31.288 +		dev_err(&dev->dev, 
  31.289 +			"pciback device is not found/in use/connected!\n");
  31.290 +		goto end;
  31.291 +	}
  31.292 +	/*Guest owns the device yet no aer handler regiested, kill guest*/
  31.293 +	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
  31.294 +		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
  31.295 +		dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n");
  31.296 +		kill_domain_by_device(psdev);
  31.297 +		goto release;
  31.298 +	}
  31.299 +	result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result);
  31.300 +
  31.301 +	if (result == PCI_ERS_RESULT_NONE ||
  31.302 +		result == PCI_ERS_RESULT_DISCONNECT) {
  31.303 +		dev_dbg(&dev->dev, 
  31.304 +			"No AER error_detected service or disconnected!\n");
  31.305 +		kill_domain_by_device(psdev);
  31.306 +	}
  31.307 +release:
  31.308 +	pcistub_device_put(psdev);
  31.309 +end:
  31.310 +	up_write(&pcistub_sem);
  31.311 +	return result;
  31.312 +}
  31.313 +
  31.314 +/*pciback_error_resume: it will send the error_resume request to  pcifront 
  31.315 +* in case of the device driver could provide this service, and then wait 
  31.316 +* for pcifront ack.
  31.317 +* @dev: pointer to PCI devices
  31.318 +*/
  31.319 +
  31.320 +static void pciback_error_resume(struct pci_dev *dev)
  31.321 +{
  31.322 +	struct pcistub_device *psdev;
  31.323 +
  31.324 +	dev_dbg(&dev->dev, "pciback_error_resume(bus:%x,devfn:%x)\n",
  31.325 +		dev->bus->number, dev->devfn);
  31.326 +
  31.327 +	down_write(&pcistub_sem);
  31.328 +	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
  31.329 +				dev->bus->number,
  31.330 +				PCI_SLOT(dev->devfn),
  31.331 +				PCI_FUNC(dev->devfn));
  31.332 +	if ( !psdev || !psdev->pdev || !psdev->pdev->sh_info)
  31.333 +	{
  31.334 +		dev_err(&dev->dev, 
  31.335 +			"pciback device is not found/in use/connected!\n");
  31.336 +		goto end;
  31.337 +	}
  31.338 +
  31.339 +	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
  31.340 +		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
  31.341 +		dev_err(&dev->dev, 
  31.342 +			"guest with no AER driver should have been killed\n");
  31.343 +		kill_domain_by_device(psdev);
  31.344 +		goto release;
  31.345 +	}
  31.346 +	common_process(psdev, 1, XEN_PCI_OP_aer_resume, PCI_ERS_RESULT_RECOVERED);
  31.347 +release:
  31.348 +	pcistub_device_put(psdev);
  31.349 +end:
  31.350 +	up_write(&pcistub_sem);
  31.351 +	return;
  31.352 +}
  31.353 +
  31.354 +/*add pciback AER handling*/
  31.355 +static struct pci_error_handlers pciback_error_handler = {
  31.356 +	.error_detected = pciback_error_detected,
  31.357 +	.mmio_enabled = pciback_mmio_enabled,
  31.358 +	.slot_reset = pciback_slot_reset,
  31.359 +	.resume = pciback_error_resume,
  31.360 +};
  31.361 +
  31.362  /*
  31.363   * Note: There is no MODULE_DEVICE_TABLE entry here because this isn't
  31.364   * for a normal device. I don't want it to be loaded automatically.
  31.365 @@ -487,6 +805,7 @@ static struct pci_driver pciback_pci_dri
  31.366  	.id_table = pcistub_ids,
  31.367  	.probe = pcistub_probe,
  31.368  	.remove = pcistub_remove,
  31.369 +	.err_handler = &pciback_error_handler,
  31.370  };
  31.371  
  31.372  static inline int str_to_slot(const char *buf, int *domain, int *bus,
    32.1 --- a/drivers/xen/pciback/pciback.h	Tue Nov 04 12:43:37 2008 +0900
    32.2 +++ b/drivers/xen/pciback/pciback.h	Wed Nov 26 10:24:15 2008 +0900
    32.3 @@ -22,6 +22,8 @@ struct pci_dev_entry {
    32.4  
    32.5  #define _PDEVF_op_active 	(0)
    32.6  #define PDEVF_op_active 	(1<<(_PDEVF_op_active))
    32.7 +#define _PCIB_op_pending	(1)
    32.8 +#define PCIB_op_pending		(1<<(_PCIB_op_pending))
    32.9  
   32.10  struct pciback_device {
   32.11  	void *pci_dev_data;
   32.12 @@ -81,6 +83,16 @@ void pciback_release_pci_dev(struct pcib
   32.13  struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
   32.14  				    unsigned int domain, unsigned int bus,
   32.15  				    unsigned int devfn);
   32.16 +
   32.17 +/** 
   32.18 +* Add for domain0 PCIE-AER handling. Get guest domain/bus/devfn in pciback
   32.19 +* before sending aer request to pcifront, so that guest could identify 
   32.20 +* device, coopearte with pciback to finish aer recovery job if device driver
   32.21 +* has the capability
   32.22 +*/
   32.23 +
   32.24 +int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
   32.25 +				unsigned int *domain, unsigned int *bus, unsigned int *devfn);
   32.26  int pciback_init_devices(struct pciback_device *pdev);
   32.27  int pciback_publish_pci_roots(struct pciback_device *pdev,
   32.28  			      publish_pci_root_cb cb);
   32.29 @@ -108,4 +120,7 @@ int pciback_disable_msix(struct pciback_
   32.30                          struct pci_dev *dev, struct xen_pci_op *op);
   32.31  #endif
   32.32  extern int verbose_request;
   32.33 +
   32.34 +void test_and_schedule_op(struct pciback_device *pdev);
   32.35  #endif
   32.36 +
    33.1 --- a/drivers/xen/pciback/pciback_ops.c	Tue Nov 04 12:43:37 2008 +0900
    33.2 +++ b/drivers/xen/pciback/pciback_ops.c	Wed Nov 26 10:24:15 2008 +0900
    33.3 @@ -4,6 +4,7 @@
    33.4   *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    33.5   */
    33.6  #include <linux/module.h>
    33.7 +#include <linux/wait.h>
    33.8  #include <asm/bitops.h>
    33.9  #include <xen/evtchn.h>
   33.10  #include "pciback.h"
   33.11 @@ -37,14 +38,29 @@ void pciback_reset_device(struct pci_dev
   33.12  		}
   33.13  	}
   33.14  }
   33.15 -
   33.16 -static inline void test_and_schedule_op(struct pciback_device *pdev)
   33.17 +extern wait_queue_head_t aer_wait_queue;
   33.18 +extern struct workqueue_struct *pciback_wq;
   33.19 +/*
   33.20 +* Now the same evtchn is used for both pcifront conf_read_write request
   33.21 +* as well as pcie aer front end ack. We use a new work_queue to schedule
   33.22 +* pciback conf_read_write service for avoiding confict with aer_core 
   33.23 +* do_recovery job which also use the system default work_queue
   33.24 +*/
   33.25 +void test_and_schedule_op(struct pciback_device *pdev)
   33.26  {
   33.27  	/* Check that frontend is requesting an operation and that we are not
   33.28  	 * already processing a request */
   33.29  	if (test_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)
   33.30  	    && !test_and_set_bit(_PDEVF_op_active, &pdev->flags))
   33.31 -		schedule_work(&pdev->op_work);
   33.32 +	{
   33.33 +		queue_work(pciback_wq, &pdev->op_work);
   33.34 +	}
   33.35 +	/*_XEN_PCIB_active should have been cleared by pcifront. And also make
   33.36 +	sure pciback is waiting for ack by checking _PCIB_op_pending*/
   33.37 +	if (!test_bit(_XEN_PCIB_active,(unsigned long *)&pdev->sh_info->flags)
   33.38 +	    &&test_bit(_PCIB_op_pending, &pdev->flags)) {
   33.39 +		wake_up(&aer_wait_queue);
   33.40 +	}
   33.41  }
   33.42  
   33.43  /* Performing the configuration space reads/writes must not be done in atomic
   33.44 @@ -103,7 +119,8 @@ void pciback_do_op(void *data)
   33.45  	smp_mb__after_clear_bit(); /* /before/ final check for work */
   33.46  
   33.47  	/* Check to see if the driver domain tried to start another request in
   33.48 -	 * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active. */
   33.49 +	 * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active. 
   33.50 +	*/
   33.51  	test_and_schedule_op(pdev);
   33.52  }
   33.53  
    34.1 --- a/drivers/xen/pciback/slot.c	Tue Nov 04 12:43:37 2008 +0900
    34.2 +++ b/drivers/xen/pciback/slot.c	Wed Nov 26 10:24:15 2008 +0900
    34.3 @@ -155,3 +155,33 @@ void pciback_release_devices(struct pcib
    34.4  	kfree(slot_dev);
    34.5  	pdev->pci_dev_data = NULL;
    34.6  }
    34.7 +
    34.8 +int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
    34.9 +		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
   34.10 +{
   34.11 +	int slot, busnr;
   34.12 +	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
   34.13 +	struct pci_dev *dev;
   34.14 +	int found = 0;
   34.15 +	unsigned long flags;
   34.16 +
   34.17 +	spin_lock_irqsave(&slot_dev->lock, flags);
   34.18 +
   34.19 +	for (busnr = 0; busnr < PCI_BUS_NBR; bus++)
   34.20 +		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
   34.21 +			dev = slot_dev->slots[busnr][slot];
   34.22 +			if (dev && dev->bus->number == pcidev->bus->number
   34.23 +				&& dev->devfn == pcidev->devfn
   34.24 +				&& pci_domain_nr(dev->bus) == pci_domain_nr(pcidev->bus)) {
   34.25 +				found = 1;
   34.26 +				*domain = 0;
   34.27 +				*bus = busnr;
   34.28 +				*devfn = PCI_DEVFN(slot,0);
   34.29 +				goto out;
   34.30 +			}
   34.31 +		}
   34.32 +out:
   34.33 +	spin_unlock_irqrestore(&slot_dev->lock, flags);
   34.34 +	return found;
   34.35 +
   34.36 +}
    35.1 --- a/drivers/xen/pciback/vpci.c	Tue Nov 04 12:43:37 2008 +0900
    35.2 +++ b/drivers/xen/pciback/vpci.c	Wed Nov 26 10:24:15 2008 +0900
    35.3 @@ -210,3 +210,33 @@ void pciback_release_devices(struct pcib
    35.4  	kfree(vpci_dev);
    35.5  	pdev->pci_dev_data = NULL;
    35.6  }
    35.7 +
    35.8 +int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
    35.9 +		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
   35.10 +{
   35.11 +	struct pci_dev_entry *entry;
   35.12 +	struct pci_dev *dev = NULL;
   35.13 +	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
   35.14 +	unsigned long flags;
   35.15 +	int found = 0, slot;
   35.16 +
   35.17 +	spin_lock_irqsave(&vpci_dev->lock, flags);
   35.18 +	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
   35.19 +		list_for_each_entry(entry,
   35.20 +			    &vpci_dev->dev_list[slot],
   35.21 +			    list) {
   35.22 +			dev = entry->dev;
   35.23 +			if (dev && dev->bus->number == pcidev->bus->number
   35.24 +				&& pci_domain_nr(dev->bus) == pci_domain_nr(pcidev->bus)
   35.25 +				&& dev->devfn == pcidev->devfn)
   35.26 +			{
   35.27 +				found = 1;
   35.28 +				*domain = 0;
   35.29 +				*bus = 0;
   35.30 +				*devfn = PCI_DEVFN(slot, PCI_FUNC(pcidev->devfn));
   35.31 +			}
   35.32 +		}		
   35.33 +	}
   35.34 +	spin_unlock_irqrestore(&vpci_dev->lock, flags);
   35.35 +	return found;
   35.36 +}
    36.1 --- a/drivers/xen/pciback/xenbus.c	Tue Nov 04 12:43:37 2008 +0900
    36.2 +++ b/drivers/xen/pciback/xenbus.c	Wed Nov 26 10:24:15 2008 +0900
    36.3 @@ -12,6 +12,7 @@
    36.4  #include "pciback.h"
    36.5  
    36.6  #define INVALID_EVTCHN_IRQ  (-1)
    36.7 +struct workqueue_struct *pciback_wq;
    36.8  
    36.9  static struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
   36.10  {
   36.11 @@ -694,11 +695,17 @@ int __init pciback_xenbus_register(void)
   36.12  {
   36.13  	if (!is_running_on_xen())
   36.14  		return -ENODEV;
   36.15 -
   36.16 +	pciback_wq = create_workqueue("pciback_workqueue");
   36.17 +	if (!pciback_wq) {
   36.18 +		printk(KERN_ERR "pciback_xenbus_register: create"
   36.19 +			"pciback_workqueue failed\n");
   36.20 +		return -EFAULT;
   36.21 +	}
   36.22  	return xenbus_register_backend(&xenbus_pciback_driver);
   36.23  }
   36.24  
   36.25  void __exit pciback_xenbus_unregister(void)
   36.26  {
   36.27 +	destroy_workqueue(pciback_wq);
   36.28  	xenbus_unregister_driver(&xenbus_pciback_driver);
   36.29  }
    37.1 --- a/drivers/xen/pcifront/pci_op.c	Tue Nov 04 12:43:37 2008 +0900
    37.2 +++ b/drivers/xen/pcifront/pci_op.c	Wed Nov 26 10:24:15 2008 +0900
    37.3 @@ -8,6 +8,7 @@
    37.4  #include <linux/init.h>
    37.5  #include <linux/pci.h>
    37.6  #include <linux/spinlock.h>
    37.7 +#include <asm/bitops.h>
    37.8  #include <linux/time.h>
    37.9  #include <xen/evtchn.h>
   37.10  #include "pcifront.h"
   37.11 @@ -153,6 +154,15 @@ static int errno_to_pcibios_err(int errn
   37.12  	return errno;
   37.13  }
   37.14  
   37.15 +static inline void schedule_pcifront_aer_op(struct pcifront_device *pdev)
   37.16 +{
   37.17 +	if (test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags)
   37.18 +		&& !test_and_set_bit(_PDEVB_op_active, &pdev->flags)) {
   37.19 +		dev_dbg(&pdev->xdev->dev, "schedule aer frontend job\n");
   37.20 +		schedule_work(&pdev->op_work);
   37.21 +	}
   37.22 +}
   37.23 +
   37.24  static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
   37.25  {
   37.26  	int err = 0;
   37.27 @@ -199,6 +209,18 @@ static int do_pci_op(struct pcifront_dev
   37.28  		}
   37.29  	}
   37.30  
   37.31 +	/*
   37.32 +	* We might lose backend service request since we 
   37.33 +	* reuse same evtchn with pci_conf backend response. So re-schedule
   37.34 +	* aer pcifront service.
   37.35 +	*/
   37.36 +	if (test_bit(_XEN_PCIB_active, 
   37.37 +			(unsigned long*)&pdev->sh_info->flags)) {
   37.38 +		dev_err(&pdev->xdev->dev, 
   37.39 +			"schedule aer pcifront service\n");
   37.40 +		schedule_pcifront_aer_op(pdev);
   37.41 +	}
   37.42 +
   37.43  	memcpy(op, active_op, sizeof(struct xen_pci_op));
   37.44  
   37.45  	err = op->err;
   37.46 @@ -549,3 +571,96 @@ void pcifront_free_roots(struct pcifront
   37.47  		kfree(bus_entry);
   37.48  	}
   37.49  }
   37.50 +
   37.51 +static pci_ers_result_t pcifront_common_process( int cmd, struct pcifront_device *pdev,
   37.52 +	pci_channel_state_t state)
   37.53 +{
   37.54 +	pci_ers_result_t result;
   37.55 +	struct pci_driver *pdrv;
   37.56 +	int bus = pdev->sh_info->aer_op.bus;
   37.57 +	int devfn = pdev->sh_info->aer_op.devfn;
   37.58 +	struct pci_dev *pcidev;
   37.59 +	int flag = 0;
   37.60 +
   37.61 +	dev_dbg(&pdev->xdev->dev, 
   37.62 +		"pcifront AER process: cmd %x (bus:%x, devfn%x)",
   37.63 +		cmd, bus, devfn);
   37.64 +	result = PCI_ERS_RESULT_NONE;
   37.65 +
   37.66 +	pcidev = pci_get_bus_and_slot(bus, devfn);
   37.67 +	if (!pcidev || !pcidev->driver){
   37.68 +		dev_err(&pcidev->dev, 
   37.69 +			"device or driver is NULL\n");
   37.70 +		return result;
   37.71 +	}
   37.72 +	pdrv = pcidev->driver;
   37.73 +
   37.74 +	if (get_driver(&pdrv->driver)) {
   37.75 +		if (pdrv->err_handler && pdrv->err_handler->error_detected) {
   37.76 +			dev_dbg(&pcidev->dev,
   37.77 +				"trying to call AER service\n");
   37.78 +			if (pcidev) {
   37.79 +				flag = 1;
   37.80 +				switch(cmd) {
   37.81 +				case XEN_PCI_OP_aer_detected:
   37.82 +					result = pdrv->err_handler->error_detected(pcidev, state);
   37.83 +					break;
   37.84 +				case XEN_PCI_OP_aer_mmio:
   37.85 +					result = pdrv->err_handler->mmio_enabled(pcidev);
   37.86 +					break;
   37.87 +				case XEN_PCI_OP_aer_slotreset:
   37.88 +					result = pdrv->err_handler->slot_reset(pcidev);
   37.89 +					break;
   37.90 +				case XEN_PCI_OP_aer_resume:
   37.91 +					pdrv->err_handler->resume(pcidev);
   37.92 +					break;
   37.93 +				default:
   37.94 +					dev_err(&pdev->xdev->dev,
   37.95 +						"bad request in aer recovery operation!\n");
   37.96 +
   37.97 +				}
   37.98 +			}
   37.99 +		}
  37.100 +		put_driver(&pdrv->driver);
  37.101 +	}
  37.102 +	if (!flag)
  37.103 +		result = PCI_ERS_RESULT_NONE;
  37.104 +
  37.105 +	return result;
  37.106 +}
  37.107 +
  37.108 +
  37.109 +void pcifront_do_aer(void *data)
  37.110 +{
  37.111 +	struct pcifront_device *pdev = data;
  37.112 +	int cmd = pdev->sh_info->aer_op.cmd;
  37.113 +	pci_channel_state_t state = 
  37.114 +		(pci_channel_state_t)pdev->sh_info->aer_op.err;
  37.115 +
  37.116 +	/*If a pci_conf op is in progress, 
  37.117 +		we have to wait until it is done before service aer op*/
  37.118 +	dev_dbg(&pdev->xdev->dev, 
  37.119 +		"pcifront service aer bus %x devfn %x\n", pdev->sh_info->aer_op.bus,
  37.120 +		pdev->sh_info->aer_op.devfn);
  37.121 +
  37.122 +	pdev->sh_info->aer_op.err = pcifront_common_process(cmd, pdev, state);
  37.123 +
  37.124 +	wmb();
  37.125 +	clear_bit(_XEN_PCIB_active, (unsigned long*)&pdev->sh_info->flags);
  37.126 +	notify_remote_via_evtchn(pdev->evtchn);
  37.127 +
  37.128 +	/*in case of we lost an aer request in four lines time_window*/
  37.129 +	smp_mb__before_clear_bit();
  37.130 +	clear_bit( _PDEVB_op_active, &pdev->flags);
  37.131 +	smp_mb__after_clear_bit();
  37.132 +
  37.133 +	schedule_pcifront_aer_op(pdev);
  37.134 +
  37.135 +}
  37.136 +
  37.137 +irqreturn_t pcifront_handler_aer(int irq, void *dev, struct pt_regs *regs)
  37.138 +{
  37.139 +	struct pcifront_device *pdev = dev;
  37.140 +	schedule_pcifront_aer_op(pdev);
  37.141 +	return IRQ_HANDLED;
  37.142 +}
    38.1 --- a/drivers/xen/pcifront/pcifront.h	Tue Nov 04 12:43:37 2008 +0900
    38.2 +++ b/drivers/xen/pcifront/pcifront.h	Wed Nov 26 10:24:15 2008 +0900
    38.3 @@ -10,13 +10,19 @@
    38.4  #include <linux/pci.h>
    38.5  #include <xen/xenbus.h>
    38.6  #include <xen/interface/io/pciif.h>
    38.7 +#include <linux/interrupt.h>
    38.8  #include <xen/pcifront.h>
    38.9 +#include <asm/atomic.h>
   38.10 +#include <linux/workqueue.h>
   38.11  
   38.12  struct pci_bus_entry {
   38.13  	struct list_head list;
   38.14  	struct pci_bus *bus;
   38.15  };
   38.16  
   38.17 +#define _PDEVB_op_active		(0)
   38.18 +#define PDEVB_op_active 		(1 << (_PDEVB_op_active))
   38.19 +
   38.20  struct pcifront_device {
   38.21  	struct xenbus_device *xdev;
   38.22  	struct list_head root_buses;
   38.23 @@ -28,6 +34,9 @@ struct pcifront_device {
   38.24  	/* Lock this when doing any operations in sh_info */
   38.25  	spinlock_t sh_info_lock;
   38.26  	struct xen_pci_sharedinfo *sh_info;
   38.27 +	struct work_struct op_work;
   38.28 +	unsigned long flags;
   38.29 +
   38.30  };
   38.31  
   38.32  int pcifront_connect(struct pcifront_device *pdev);
   38.33 @@ -39,4 +48,8 @@ int pcifront_rescan_root(struct pcifront
   38.34  			 unsigned int domain, unsigned int bus);
   38.35  void pcifront_free_roots(struct pcifront_device *pdev);
   38.36  
   38.37 +void pcifront_do_aer( void *data);
   38.38 +
   38.39 +irqreturn_t pcifront_handler_aer(int irq, void *dev, struct pt_regs *regs);
   38.40 +
   38.41  #endif	/* __XEN_PCIFRONT_H__ */
    39.1 --- a/drivers/xen/pcifront/xenbus.c	Tue Nov 04 12:43:37 2008 +0900
    39.2 +++ b/drivers/xen/pcifront/xenbus.c	Wed Nov 26 10:24:15 2008 +0900
    39.3 @@ -7,6 +7,7 @@
    39.4  #include <linux/init.h>
    39.5  #include <linux/mm.h>
    39.6  #include <xen/xenbus.h>
    39.7 +#include <xen/evtchn.h>
    39.8  #include <xen/gnttab.h>
    39.9  #include "pcifront.h"
   39.10  
   39.11 @@ -34,6 +35,9 @@ static struct pcifront_device *alloc_pde
   39.12  	}
   39.13  	pdev->sh_info->flags = 0;
   39.14  
   39.15 +	/*Flag for registering PV AER handler*/
   39.16 +	set_bit(_XEN_PCIB_AERHANDLER, (void*)&pdev->sh_info->flags);
   39.17 +
   39.18  	xdev->dev.driver_data = pdev;
   39.19  	pdev->xdev = xdev;
   39.20  
   39.21 @@ -45,6 +49,8 @@ static struct pcifront_device *alloc_pde
   39.22  	pdev->evtchn = INVALID_EVTCHN;
   39.23  	pdev->gnt_ref = INVALID_GRANT_REF;
   39.24  
   39.25 +	INIT_WORK(&pdev->op_work, pcifront_do_aer, pdev);
   39.26 +
   39.27  	dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n",
   39.28  		pdev, pdev->sh_info);
   39.29        out:
   39.30 @@ -57,6 +63,11 @@ static void free_pdev(struct pcifront_de
   39.31  
   39.32  	pcifront_free_roots(pdev);
   39.33  
   39.34 +	/*For PCIE_AER error handling job*/
   39.35 +	cancel_delayed_work(&pdev->op_work);
   39.36 +	flush_scheduled_work();
   39.37 +	unbind_from_irqhandler(pdev->evtchn, pdev);
   39.38 +
   39.39  	if (pdev->evtchn != INVALID_EVTCHN)
   39.40  		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
   39.41  
   39.42 @@ -84,6 +95,9 @@ static int pcifront_publish_info(struct 
   39.43  	if (err)
   39.44  		goto out;
   39.45  
   39.46 +	bind_caller_port_to_irqhandler(pdev->evtchn, pcifront_handler_aer, 
   39.47 +		SA_SAMPLE_RANDOM, "pcifront", pdev); 
   39.48 +
   39.49        do_publish:
   39.50  	err = xenbus_transaction_start(&trans);
   39.51  	if (err) {
    40.1 --- a/include/asm-i386/mach-xen/asm/hypercall.h	Tue Nov 04 12:43:37 2008 +0900
    40.2 +++ b/include/asm-i386/mach-xen/asm/hypercall.h	Wed Nov 26 10:24:15 2008 +0900
    40.3 @@ -280,13 +280,6 @@ HYPERVISOR_event_channel_op(
    40.4  }
    40.5  
    40.6  static inline int __must_check
    40.7 -HYPERVISOR_acm_op(
    40.8 -	int cmd, void *arg)
    40.9 -{
   40.10 -	return _hypercall2(int, acm_op, cmd, arg);
   40.11 -}
   40.12 -
   40.13 -static inline int __must_check
   40.14  HYPERVISOR_xen_version(
   40.15  	int cmd, void *arg)
   40.16  {
    41.1 --- a/include/asm-x86_64/mach-xen/asm/hypercall.h	Tue Nov 04 12:43:37 2008 +0900
    41.2 +++ b/include/asm-x86_64/mach-xen/asm/hypercall.h	Wed Nov 26 10:24:15 2008 +0900
    41.3 @@ -278,13 +278,6 @@ HYPERVISOR_event_channel_op(
    41.4  }
    41.5  
    41.6  static inline int __must_check
    41.7 -HYPERVISOR_acm_op(
    41.8 -	int cmd, void *arg)
    41.9 -{
   41.10 -	return _hypercall2(int, acm_op, cmd, arg);
   41.11 -}
   41.12 -
   41.13 -static inline int __must_check
   41.14  HYPERVISOR_xen_version(
   41.15  	int cmd, void *arg)
   41.16  {
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/include/linux/aer.h	Wed Nov 26 10:24:15 2008 +0900
    42.3 @@ -0,0 +1,24 @@
    42.4 +/*
    42.5 + * Copyright (C) 2006 Intel Corp.
    42.6 + *     Tom Long Nguyen (tom.l.nguyen@intel.com)
    42.7 + *     Zhang Yanmin (yanmin.zhang@intel.com)
    42.8 + */
    42.9 +
   42.10 +#ifndef _AER_H_
   42.11 +#define _AER_H_
   42.12 +
   42.13 +#if defined(CONFIG_PCIEAER)
   42.14 +/* pci-e port driver needs this function to enable aer */
   42.15 +extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
   42.16 +extern int pci_find_aer_capability(struct pci_dev *dev);
   42.17 +extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
   42.18 +extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
   42.19 +#else
   42.20 +#define pci_enable_pcie_error_reporting(dev)		do { } while (0)
   42.21 +#define pci_find_aer_capability(dev)			do { } while (0)
   42.22 +#define pci_disable_pcie_error_reporting(dev)		do { } while (0)
   42.23 +#define pci_cleanup_aer_uncorrect_error_status(dev)	do { } while (0)
   42.24 +#endif
   42.25 +
   42.26 +#endif //_AER_H_
   42.27 +
    43.1 --- a/include/linux/pci.h	Tue Nov 04 12:43:37 2008 +0900
    43.2 +++ b/include/linux/pci.h	Wed Nov 26 10:24:15 2008 +0900
    43.3 @@ -456,6 +456,7 @@ struct pci_dev *pci_get_subsys (unsigned
    43.4  				unsigned int ss_vendor, unsigned int ss_device,
    43.5  				struct pci_dev *from);
    43.6  struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
    43.7 +struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
    43.8  struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
    43.9  int pci_dev_present(const struct pci_device_id *ids);
   43.10  
   43.11 @@ -655,6 +656,11 @@ static inline struct pci_dev *pci_find_d
   43.12  static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
   43.13  { return NULL; }
   43.14  
   43.15 +
   43.16 +static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
   43.17 +{
   43.18 +	return NULL;
   43.19 +}
   43.20  static inline struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from)
   43.21  { return NULL; }
   43.22  
    44.1 --- a/include/linux/pci_ids.h	Tue Nov 04 12:43:37 2008 +0900
    44.2 +++ b/include/linux/pci_ids.h	Wed Nov 26 10:24:15 2008 +0900
    44.3 @@ -2219,6 +2219,9 @@
    44.4  #define PCI_DEVICE_ID_INTEL_ICH10_3	0x3a1a
    44.5  #define PCI_DEVICE_ID_INTEL_ICH10_4	0x3a30
    44.6  #define PCI_DEVICE_ID_INTEL_ICH10_5	0x3a60
    44.7 +#define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN	0x3b00
    44.8 +#define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX	0x3b1f
    44.9 +#define PCI_DEVICE_ID_INTEL_PCH_SMBUS	0x3b30
   44.10  #define PCI_DEVICE_ID_INTEL_82371SB_0	0x7000
   44.11  #define PCI_DEVICE_ID_INTEL_82371SB_1	0x7010
   44.12  #define PCI_DEVICE_ID_INTEL_82371SB_2	0x7020
    45.1 --- a/include/linux/pcieport_if.h	Tue Nov 04 12:43:37 2008 +0900
    45.2 +++ b/include/linux/pcieport_if.h	Wed Nov 26 10:24:15 2008 +0900
    45.3 @@ -62,6 +62,12 @@ struct pcie_port_service_driver {
    45.4  	int (*suspend) (struct pcie_device *dev, pm_message_t state);
    45.5  	int (*resume) (struct pcie_device *dev);
    45.6  
    45.7 +	/* Service Error Recovery Handler */
    45.8 +	struct pci_error_handlers *err_handler;
    45.9 +
   45.10 +	/* Link Reset Capability - AER service driver specific */
   45.11 +	pci_ers_result_t (*reset_link) (struct pci_dev *dev);
   45.12 +
   45.13  	const struct pcie_port_service_id *id_table;
   45.14  	struct device_driver driver;
   45.15  };
    46.1 --- a/include/xen/interface/features.h	Tue Nov 04 12:43:37 2008 +0900
    46.2 +++ b/include/xen/interface/features.h	Wed Nov 26 10:24:15 2008 +0900
    46.3 @@ -62,6 +62,12 @@
    46.4  /* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */
    46.5  #define XENFEAT_highmem_assist             6
    46.6  
    46.7 +/*
    46.8 + * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel
    46.9 + * available pte bits.
   46.10 + */
   46.11 +#define XENFEAT_gnttab_map_avail_bits      7
   46.12 +
   46.13  #define XENFEAT_NR_SUBMAPS 1
   46.14  
   46.15  #endif /* __XEN_PUBLIC_FEATURES_H__ */
    47.1 --- a/include/xen/interface/grant_table.h	Tue Nov 04 12:43:37 2008 +0900
    47.2 +++ b/include/xen/interface/grant_table.h	Wed Nov 26 10:24:15 2008 +0900
    47.3 @@ -360,7 +360,7 @@ DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and
    47.4  
    47.5  
    47.6  /*
    47.7 - * Bitfield values for update_pin_status.flags.
    47.8 + * Bitfield values for gnttab_map_grant_ref.flags.
    47.9   */
   47.10   /* Map the grant entry for access by I/O devices. */
   47.11  #define _GNTMAP_device_map      (0)
   47.12 @@ -388,6 +388,13 @@ DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and
   47.13  #define GNTMAP_contains_pte     (1<<_GNTMAP_contains_pte)
   47.14  
   47.15  /*
   47.16 + * Bits to be placed in guest kernel available PTE bits (architecture
   47.17 + * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
   47.18 + */
   47.19 +#define _GNTMAP_guest_avail0    (16)
   47.20 +#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0)
   47.21 +
   47.22 +/*
   47.23   * Values for error status returns. All errors are -ve.
   47.24   */
   47.25  #define GNTST_okay             (0)  /* Normal return.                        */
    48.1 --- a/include/xen/interface/io/pciif.h	Tue Nov 04 12:43:37 2008 +0900
    48.2 +++ b/include/xen/interface/io/pciif.h	Wed Nov 26 10:24:15 2008 +0900
    48.3 @@ -30,14 +30,22 @@
    48.4  /* xen_pci_sharedinfo flags */
    48.5  #define _XEN_PCIF_active     (0)
    48.6  #define XEN_PCIF_active      (1<<_XEN_PCI_active)
    48.7 +#define _XEN_PCIB_AERHANDLER (1)
    48.8 +#define XEN_PCIB_AERHANDLER  (1<<_XEN_PCIB_AERHANDLER)
    48.9 +#define _XEN_PCIB_active     (2)
   48.10 +#define XEN_PCIB_active      (1<<_XEN_PCIB_active)
   48.11  
   48.12  /* xen_pci_op commands */
   48.13 -#define XEN_PCI_OP_conf_read    (0)
   48.14 -#define XEN_PCI_OP_conf_write   (1)
   48.15 -#define XEN_PCI_OP_enable_msi   (2)
   48.16 -#define XEN_PCI_OP_disable_msi  (3)
   48.17 -#define XEN_PCI_OP_enable_msix  (4)
   48.18 -#define XEN_PCI_OP_disable_msix (5)
   48.19 +#define XEN_PCI_OP_conf_read    	(0)
   48.20 +#define XEN_PCI_OP_conf_write   	(1)
   48.21 +#define XEN_PCI_OP_enable_msi   	(2)
   48.22 +#define XEN_PCI_OP_disable_msi  	(3)
   48.23 +#define XEN_PCI_OP_enable_msix  	(4)
   48.24 +#define XEN_PCI_OP_disable_msix 	(5)
   48.25 +#define XEN_PCI_OP_aer_detected 	(6)
   48.26 +#define XEN_PCI_OP_aer_resume		(7)
   48.27 +#define XEN_PCI_OP_aer_mmio		(8)
   48.28 +#define XEN_PCI_OP_aer_slotreset	(9)
   48.29  
   48.30  /* xen_pci_op error numbers */
   48.31  #define XEN_PCI_ERR_success          (0)
   48.32 @@ -82,10 +90,25 @@ struct xen_pci_op {
   48.33      struct xen_msix_entry msix_entries[SH_INFO_MAX_VEC];
   48.34  };
   48.35  
   48.36 +/*used for pcie aer handling*/
   48.37 +struct xen_pcie_aer_op
   48.38 +{
   48.39 +
   48.40 +    /* IN: what action to perform: XEN_PCI_OP_* */
   48.41 +    uint32_t cmd;
   48.42 +    /*IN/OUT: return aer_op result or carry error_detected state as input*/
   48.43 +    int32_t err;
   48.44 +
   48.45 +    /* IN: which device to touch */
   48.46 +    uint32_t domain; /* PCI Domain/Segment*/
   48.47 +    uint32_t bus;
   48.48 +    uint32_t devfn;
   48.49 +};
   48.50  struct xen_pci_sharedinfo {
   48.51      /* flags - XEN_PCIF_* */
   48.52      uint32_t flags;
   48.53      struct xen_pci_op op;
   48.54 +    struct xen_pcie_aer_op aer_op;
   48.55  };
   48.56  
   48.57  #endif /* __XEN_PCI_COMMON_H__ */
    49.1 --- a/include/xen/interface/kexec.h	Tue Nov 04 12:43:37 2008 +0900
    49.2 +++ b/include/xen/interface/kexec.h	Wed Nov 26 10:24:15 2008 +0900
    49.3 @@ -155,27 +155,6 @@ typedef struct xen_kexec_range {
    49.4      unsigned long start;
    49.5  } xen_kexec_range_t;
    49.6  
    49.7 -/* vmcoreinfo stuff */
    49.8 -#define VMCOREINFO_BYTES           (4096)
    49.9 -#define VMCOREINFO_NOTE_NAME       "VMCOREINFO_XEN"
   49.10 -void arch_crash_save_vmcoreinfo(void);
   49.11 -void vmcoreinfo_append_str(const char *fmt, ...)
   49.12 -       __attribute__ ((format (printf, 1, 2)));
   49.13 -#define VMCOREINFO_PAGESIZE(value) \
   49.14 -       vmcoreinfo_append_str("PAGESIZE=%ld\n", value)
   49.15 -#define VMCOREINFO_SYMBOL(name) \
   49.16 -       vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
   49.17 -#define VMCOREINFO_SYMBOL_ALIAS(alias, name) \
   49.18 -       vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #alias, (unsigned long)&name)
   49.19 -#define VMCOREINFO_STRUCT_SIZE(name) \
   49.20 -       vmcoreinfo_append_str("SIZE(%s)=%zu\n", #name, sizeof(struct name))
   49.21 -#define VMCOREINFO_OFFSET(name, field) \
   49.22 -       vmcoreinfo_append_str("OFFSET(%s.%s)=%lu\n", #name, #field, \
   49.23 -                             (unsigned long)offsetof(struct name, field))
   49.24 -#define VMCOREINFO_OFFSET_ALIAS(name, field, alias) \
   49.25 -       vmcoreinfo_append_str("OFFSET(%s.%s)=%lu\n", #name, #alias, \
   49.26 -                             (unsigned long)offsetof(struct name, field))
   49.27 -
   49.28  #endif /* _XEN_PUBLIC_KEXEC_H */
   49.29  
   49.30  /*
    50.1 --- a/include/xen/interface/trace.h	Tue Nov 04 12:43:37 2008 +0900
    50.2 +++ b/include/xen/interface/trace.h	Wed Nov 26 10:24:15 2008 +0900
    50.3 @@ -142,7 +142,9 @@
    50.4  #define TRC_HVM_INVLPG64        (TRC_HVM_HANDLER + TRC_64_FLAG + 0x14)
    50.5  #define TRC_HVM_MCE             (TRC_HVM_HANDLER + 0x15)
    50.6  #define TRC_HVM_IO_ASSIST       (TRC_HVM_HANDLER + 0x16)
    50.7 +#define TRC_HVM_IO_ASSIST64     (TRC_HVM_HANDLER + TRC_64_FLAG + 0x16)
    50.8  #define TRC_HVM_MMIO_ASSIST     (TRC_HVM_HANDLER + 0x17)
    50.9 +#define TRC_HVM_MMIO_ASSIST64   (TRC_HVM_HANDLER + TRC_64_FLAG + 0x17)
   50.10  #define TRC_HVM_CLTS            (TRC_HVM_HANDLER + 0x18)
   50.11  #define TRC_HVM_LMSW            (TRC_HVM_HANDLER + 0x19)
   50.12  #define TRC_HVM_LMSW64          (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19)
    51.1 --- a/kernel/kexec.c	Tue Nov 04 12:43:37 2008 +0900
    51.2 +++ b/kernel/kexec.c	Wed Nov 26 10:24:15 2008 +0900
    51.3 @@ -368,9 +368,6 @@ static void kimage_free_pages(struct pag
    51.4  	count = 1 << order;
    51.5  	for (i = 0; i < count; i++)
    51.6  		ClearPageReserved(page + i);
    51.7 -#ifdef CONFIG_XEN
    51.8 -	xen_destroy_contiguous_region((unsigned long)page_address(page), order);
    51.9 -#endif
   51.10  	__free_pages(page, order);
   51.11  }
   51.12  
    52.1 --- a/sound/pci/hda/hda_intel.c	Tue Nov 04 12:43:37 2008 +0900
    52.2 +++ b/sound/pci/hda/hda_intel.c	Wed Nov 26 10:24:15 2008 +0900
    52.3 @@ -82,6 +82,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},
    52.4  			 "{Intel, ICH8},"
    52.5  			 "{Intel, ICH9},"
    52.6  			 "{Intel, ICH10},"
    52.7 +			 "{Intel, PCH},"
    52.8  			 "{ATI, SB450},"
    52.9  			 "{ATI, SB600},"
   52.10  			 "{ATI, RS600},"
   52.11 @@ -1640,6 +1641,7 @@ static struct pci_device_id azx_ids[] = 
   52.12  	{ 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
   52.13  	{ 0x8086, 0x3a3e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
   52.14  	{ 0x8086, 0x3a6e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
   52.15 +	{ 0x8086, 0x3b56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* PCH */
   52.16  	{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
   52.17  	{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
   52.18  	{ 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */