Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2758

kernel-2.6.18-194.11.1.el5.src.rpm

From: Prarit Bhargava <prarit@redhat.com>
Date: Fri, 30 Oct 2009 12:47:22 -0400
Subject: [pci] aer: changes required to compile in RHEL5
Message-id: <20091030124600.6431.7164.sendpatchset@prarit.bos.redhat.com>
Patchwork-id: 21266
O-Subject: [RHEL5 PATCH 2/8]: AER: PCI AER changes required to compile in RHEL5
	[v2]
Bugzilla: 514442 517093
RH-Acked-by: Dean Nelson <dnelson@redhat.com>
RH-Acked-by: Ivan Vecera <ivecera@redhat.com>
RH-Acked-by: Andy Gospodarek <gospo@redhat.com>

All code changes required to compile in RHEL5, including kabi fixes.

Resolves BZ 517093 and 514442.

diff --git a/arch/i386/kernel/acpi/boot-xen.c b/arch/i386/kernel/acpi/boot-xen.c
index 971d940..4cfb374 100644
--- a/arch/i386/kernel/acpi/boot-xen.c
+++ b/arch/i386/kernel/acpi/boot-xen.c
@@ -64,7 +64,7 @@ static inline int gsi_irq_sharing(int gsi) { return gsi; }
 #define PREFIX			"ACPI: "
 
 int acpi_noirq;	/* skip ACPI IRQ initialization */
-int acpi_pci_disabled __initdata;	/* skip ACPI PCI scan and IRQ initialization */
+int acpi_pci_disabled;	/* skip ACPI PCI scan and IRQ initialization */
 int acpi_ht __initdata = 1;	/* enable HT */
 
 int acpi_lapic;
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 34bd312..dfa658b 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -64,7 +64,7 @@ static inline int gsi_irq_sharing(int gsi) { return gsi; }
 #define PREFIX			"ACPI: "
 
 int acpi_noirq;	/* skip ACPI IRQ initialization */
-int acpi_pci_disabled __initdata;	/* skip ACPI PCI scan and IRQ initialization */
+int acpi_pci_disabled;	/* skip ACPI PCI scan and IRQ initialization */
 int acpi_ht __initdata = 1;	/* enable HT */
 
 int acpi_lapic;
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index ea16805..3f71a23 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -63,6 +63,26 @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
 EXPORT_SYMBOL(pci_bus_write_config_word);
 EXPORT_SYMBOL(pci_bus_write_config_dword);
 
+/**
+ * pci_bus_set_ops - Set raw operations of pci bus
+ * @bus:	pci bus struct
+ * @ops:	new raw operations
+ *
+ * Return previous raw operations
+ */
+struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
+{
+	struct pci_ops *old_ops;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_lock, flags);
+	old_ops = bus->ops;
+	bus->ops = ops;
+	spin_unlock_irqrestore(&pci_lock, flags);
+	return old_ops;
+}
+EXPORT_SYMBOL(pci_bus_set_ops);
+
 static u32 pci_user_cached_config(struct pci_dev *dev, int pos)
 {
 	u32 data;
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 5f7db9d..030e822 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -196,6 +196,59 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 }
 EXPORT_SYMBOL_GPL(pci_walk_bus);
 
+/** pci_walk_bus_int - walk devices on/under bus, calling callback.
+ *  @top      bus whose devices should be walked
+ *  @cb       int callback to be called for each device found
+ *  @userdata arbitrary pointer to be passed to callback.
+ *
+ *  Walk the given bus, including any bridged devices
+ *  on buses under this bus.  Call the provided callback
+ *  on each device found.
+ *
+ *  We check the return of @cb each time. If it returns anything
+ *  other than 0, we break out.
+ *
+ *  This is upstream's implementation of pci_walk_bus.
+ */
+void pci_walk_bus_int(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
+		      void *userdata)
+{
+	struct pci_dev *dev;
+	struct pci_bus *bus;
+	struct list_head *next;
+	int retval;
+
+	bus = top;
+	down_read(&pci_bus_sem);
+	next = top->devices.next;
+	for (;;) {
+		if (next == &bus->devices) {
+			/* end of this bus, go up or finish */
+			if (bus == top)
+				break;
+			next = bus->self->bus_list.next;
+			bus = bus->self->bus;
+			continue;
+		}
+		dev = list_entry(next, struct pci_dev, bus_list);
+		if (dev->subordinate) {
+			/* this is a pci-pci bridge, do its devices next */
+			next = dev->subordinate->devices.next;
+			bus = dev->subordinate;
+		} else
+			next = dev->bus_list.next;
+
+		/* Run device routines with the device locked */
+		down(&dev->dev.sem);
+		retval = cb(dev, userdata);
+		up(&dev->dev.sem);
+		if (retval)
+			break;
+	}
+	up_read(&pci_bus_sem);
+}
+EXPORT_SYMBOL_GPL(pci_walk_bus_int);
+
 EXPORT_SYMBOL(pci_bus_alloc_resource);
 EXPORT_SYMBOL_GPL(pci_bus_add_device);
 EXPORT_SYMBOL(pci_bus_add_devices);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 0a497e5..046866d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1264,6 +1264,18 @@ void pci_no_msi(void)
 	pci_msi_enable = 0;
 }
 
+/**
+ * pci_msi_enabled - is MSI enabled?
+ *
+ * Returns true if MSI has not been disabled by the command-line option
+ * pci=nomsi.
+ **/
+int pci_msi_enabled(void)
+{
+	return pci_msi_enable;
+}
+EXPORT_SYMBOL(pci_msi_enabled);
+
 EXPORT_SYMBOL(pci_enable_msi);
 EXPORT_SYMBOL(pci_disable_msi);
 EXPORT_SYMBOL(pci_enable_msix);
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index 984fa87..e00fb99 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -5,3 +5,6 @@
 pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o
 
 obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o
+
+# Build PCI Express AER if needed
+obj-$(CONFIG_PCIEAER)		+= aer/
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 62d15f6..bc3f1b1 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -280,7 +280,7 @@ static int find_aer_device_iter(struct device *device, void *data)
 
 	if (device->bus == &pcie_port_bus_type) {
 		pcie_dev = to_pcie_device(device);
-		if (pcie_dev->service & PCIE_PORT_SERVICE_AER) {
+		if (pcie_dev->id.service_type & PCIE_PORT_SERVICE_AER) {
 			*result = pcie_dev;
 			return 1;
 		}
@@ -393,7 +393,7 @@ static int aer_inject(struct aer_error_inj *einj)
 		goto out_put;
 
 	if (find_aer_device(rpdev, &edev))
-		aer_irq(-1, edev);
+		aer_irq(-1, edev, NULL);
 	else
 		ret = -EINVAL;
 out_put:
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 2ce8f9c..a6fec8a 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -38,7 +38,8 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-static int __devinit aer_probe(struct pcie_device *dev);
+static int __devinit aer_probe(struct pcie_device *dev,
+			       const struct pcie_port_service_id *id);
 static void aer_remove(struct pcie_device *dev);
 static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
 	enum pci_channel_state error);
@@ -50,11 +51,19 @@ static struct pci_error_handlers aer_error_handlers = {
 	.resume		= aer_error_resume,
 };
 
+static struct pcie_port_service_id aer_pci_ids[] = {
+	{
+		.vendor = PCI_ANY_ID,
+		.device = PCI_ANY_ID,
+		.port_type = PCIE_RC_PORT,
+		.service_type = PCIE_PORT_SERVICE_AER,
+		.driver_data =	0,
+	}, { /* end: all zeroes */ }
+};
+
 static struct pcie_port_service_driver aerdriver = {
 	.name		= "aer",
-	.port_type	= PCIE_ANY_PORT,
-	.service	= PCIE_PORT_SERVICE_AER,
-
+	.id_table	= aer_pci_ids,
 	.probe		= aer_probe,
 	.remove		= aer_remove,
 
@@ -74,10 +83,11 @@ void pci_no_aer(void)
  * aer_irq - Root Port's ISR
  * @irq: IRQ assigned to Root Port
  * @context: pointer to Root Port data structure
+ * @regs: pointer to register structure
  *
  * Invoked when Root Port detects AER messages.
  **/
-irqreturn_t aer_irq(int irq, void *context)
+irqreturn_t aer_irq(int irq, void *context, struct pt_regs *regs)
 {
 	unsigned int status, id;
 	struct pcie_device *pdev = (struct pcie_device *)context;
@@ -149,7 +159,8 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
 	spin_lock_init(&rpc->e_lock);
 
 	rpc->rpd = dev;
-	INIT_WORK(&rpc->dpc_handler, aer_isr);
+	INIT_WORK(&rpc->dpc_handler, (void (*)(void *))aer_isr,
+		  &rpc->dpc_handler);
 	rpc->prod_idx = rpc->cons_idx = 0;
 	mutex_init(&rpc->rpc_mutex);
 	init_waitqueue_head(&rpc->wait_release);
@@ -189,7 +200,8 @@ static void aer_remove(struct pcie_device *dev)
  *
  * Invoked when PCI Express bus loads AER service driver.
  **/
-static int __devinit aer_probe(struct pcie_device *dev)
+static int __devinit aer_probe(struct pcie_device *dev,
+			       const struct pcie_port_service_id *id)
 {
 	int status;
 	struct aer_rpc *rpc;
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index bd833ea..d74f035 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -123,7 +123,7 @@ extern int aer_init(struct pcie_device *dev);
 extern void aer_isr(struct work_struct *work);
 extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
 extern void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info);
-extern irqreturn_t aer_irq(int irq, void *context);
+extern irqreturn_t aer_irq(int irq, void *context, struct pt_regs *regs);
 
 #ifdef CONFIG_ACPI
 extern int aer_osc_setup(struct pcie_device *pciedev);
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index 8edb2f3..ebce26c 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -38,7 +38,7 @@ int aer_osc_setup(struct pcie_device *pciedev)
 
 	handle = acpi_find_root_bridge_handle(pdev);
 	if (handle) {
-		status = acpi_pci_osc_control_set(handle,
+		status = pci_osc_control_set(handle,
 					OSC_PCI_EXPRESS_AER_CONTROL |
 					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
 	}
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 9f5ccbe..eabc438 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -144,7 +144,7 @@ static void set_downstream_devices_error_reporting(struct pci_dev *dev,
 
 	if (!dev->subordinate)
 		return;
-	pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
+	pci_walk_bus_int(dev->subordinate, set_device_error_reporting, &enable);
 }
 
 static inline int compare_device_id(struct pci_dev *dev,
@@ -216,7 +216,7 @@ static int find_device_iter(struct pci_dev *dev, void *data)
 	 *      3) There are multiple errors and prior id comparing fails;
 	 * We check AER status registers to find the initial reporter.
 	 */
-	if (atomic_read(&dev->enable_cnt) == 0)
+	if (!dev->is_enabled)
 		return 0;
 	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
 	if (!pos)
@@ -278,7 +278,7 @@ static void find_source_device(struct pci_dev *parent,
 	if (result)
 		return;
 
-	pci_walk_bus(parent->subordinate, find_device_iter, e_info);
+	pci_walk_bus_int(parent->subordinate, find_device_iter, e_info);
 }
 
 static int report_error_detected(struct pci_dev *dev, void *data)
@@ -401,7 +401,7 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
 		 */
 		if (cb == report_error_detected)
 			dev->error_state = state;
-		pci_walk_bus(dev->subordinate, cb, &result_data);
+		pci_walk_bus_int(dev->subordinate, cb, &result_data);
 		if (cb == report_resume) {
 			pci_cleanup_aer_uncorrect_error_status(dev);
 			dev->error_state = pci_channel_io_normal;
@@ -411,7 +411,7 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
 		 * If the error is reported by an end point, we think this
 		 * error is related to the upstream link of the end point.
 		 */
-		pci_walk_bus(dev->bus, cb, &result_data);
+		pci_walk_bus_int(dev->bus, cb, &result_data);
 	}
 
 	return result_data.result;
@@ -431,16 +431,15 @@ static int find_aer_service_iter(struct device *device, void *data)
 	result = (struct find_aer_service_data *) data;
 
 	if (device->bus == &pcie_port_bus_type) {
-		struct pcie_port_data *port_data;
+		struct pcie_device *pciedev = to_pcie_device(device);
 
-		port_data = pci_get_drvdata(to_pcie_device(device)->port);
-		if (port_data->port_type == PCIE_SW_DOWNSTREAM_PORT)
+		if (pciedev->id.port_type == PCIE_SW_DOWNSTREAM_PORT)
 			result->is_downstream = 1;
 
 		driver = device->driver;
 		if (driver) {
 			service_driver = to_service_driver(driver);
-			if (service_driver->service == PCIE_PORT_SERVICE_AER) {
+			if (pciedev->id.service_type == PCIE_PORT_SERVICE_AER) {
 				result->aer_driver = service_driver;
 				return 1;
 			}
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
index 44acde7..18c1424 100644
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ b/drivers/pci/pcie/aer/aerdrv_errprint.c
@@ -57,6 +57,11 @@
 	(e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \
 	AER_TRANSACTION_LAYER_ERROR)
 
+static inline const char *dev_name(const struct device *dev)
+{
+	return kobject_name(&dev->kobj);
+}
+
 #define AER_PR(info, pdev, fmt, args...)				\
 	printk("%s%s %s: " fmt, (info->severity == AER_CORRECTABLE) ?	\
 		KERN_WARNING : KERN_ERR, dev_driver_string(&pdev->dev),	\
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 936ef82..5b0bf39 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -49,6 +49,24 @@
 #ifdef CONFIG_ACPI
 extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
 extern acpi_status pci_osc_support_set(u32 flags);
+
+static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
+{
+	struct pci_bus *pbus = pdev->bus;
+	/* Find a PCI root bus */
+	while (!pci_is_root_bus(pbus))
+		pbus = pbus->parent;
+	return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus),
+					      pbus->number);
+}
+
+static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
+{
+	if (!pci_is_root_bus(pbus))
+		return DEVICE_ACPI_HANDLE(&(pbus->self->dev));
+	return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus),
+					      pbus->number);
+}
 #else
 #if !defined(AE_ERROR)
 typedef u32 		acpi_status;
@@ -57,6 +75,8 @@ typedef u32 		acpi_status;
 static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
 {return AE_ERROR;}
 static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} 
-#endif
 
+static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
+{ return NULL; }
+#endif
 #endif	/* _PCI_ACPI_H_ */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6f981a8..76b934b 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -297,6 +297,15 @@ struct pci_bus {
 #define to_pci_bus(n)	container_of(n, struct pci_bus, class_dev)
 
 /*
+ * Returns true if the pci bus is root (behind host-pci bridge),
+ * false otherwise
+ */
+static inline bool pci_is_root_bus(struct pci_bus *pbus)
+{
+	return !(pbus->parent);
+}
+
+/*
  * Error values that may be returned by PCI functions.
  */
 #define PCIBIOS_SUCCESSFUL		0x00
@@ -535,6 +544,7 @@ int pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int wher
 int pci_bus_write_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 val);
 int pci_bus_write_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 val);
 int pci_bus_write_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 val);
+struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops);
 
 static inline int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
 {
@@ -650,6 +660,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
 
 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 		  void *userdata);
+void pci_walk_bus_int(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
+		      void *userdata);
 int pci_cfg_space_size(struct pci_dev *dev);
 unsigned char pci_bus_max_busnr(struct pci_bus* bus);
 
@@ -691,6 +703,7 @@ static inline int pci_enable_msix(struct pci_dev* dev,
 static inline void pci_disable_msix(struct pci_dev *dev) {}
 static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
 static inline void pci_restore_msi_state(struct pci_dev *dev) {}
+static inline int pci_msi_enabled(void) {return 0;}
 #ifdef CONFIG_XEN
 #define register_msi_get_owner(func) 0
 #define unregister_msi_get_owner(func) 0
@@ -707,6 +720,9 @@ extern void pci_restore_msi_state(struct pci_dev *dev);
 #ifdef CONFIG_XEN
 extern int register_msi_get_owner(int (*func)(struct pci_dev *dev));
 extern int unregister_msi_get_owner(int (*func)(struct pci_dev *dev));
+static inline int pci_msi_enabled(void) { return 0;}
+#else
+extern int pci_msi_enabled(void);
 #endif
 #endif
 
@@ -718,6 +734,17 @@ extern int save_pcie_reg(struct pci_dev *dev);
 extern void restore_pcie_reg(struct pci_dev *dev);
 #endif
 
+#ifndef CONFIG_PCIE_ECRC
+static inline void pcie_set_ecrc_checking(struct pci_dev *dev)
+{
+	return;
+}
+static inline void pcie_ecrc_get_policy(char *str) {};
+#else
+extern void pcie_set_ecrc_checking(struct pci_dev *dev);
+extern void pcie_ecrc_get_policy(char *str);
+#endif
+
 extern void pci_block_user_cfg_access(struct pci_dev *dev);
 extern void pci_unblock_user_cfg_access(struct pci_dev *dev);
 
diff --git a/include/linux/pcieport_if.h b/include/linux/pcieport_if.h
index b44e01a..22e6d2c 100644
--- a/include/linux/pcieport_if.h
+++ b/include/linux/pcieport_if.h
@@ -56,14 +56,22 @@ static inline void* get_service_data(struct pcie_device *dev)
 
 struct pcie_port_service_driver {
 	const char *name;
-	int (*probe) (struct pcie_device *dev, 
-		const struct pcie_port_service_id *id);
+	int (*probe) (struct pcie_device *dev,
+		      const struct pcie_port_service_id *id);
 	void (*remove) (struct pcie_device *dev);
 	int (*suspend) (struct pcie_device *dev, pm_message_t state);
 	int (*resume) (struct pcie_device *dev);
 
 	const struct pcie_port_service_id *id_table;
 	struct device_driver driver;
+
+#ifndef __GENKSYMS__
+	/* Service Error Recovery Handler */
+	struct pci_error_handlers *err_handler;
+
+	/* Link Reset Capability - AER service driver specific */
+	pci_ers_result_t (*reset_link) (struct pci_dev *dev);
+#endif
 };
 #define to_service_driver(d) \
 	container_of(d, struct pcie_port_service_driver, driver)