Skip to contentSkip to conversation

PCI Error Recovery (readX_check)

PATCH In review Hidetoshi Seto 2 participants 2 messages Aug 24, 2004 – Aug 25, 2004 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 2/2 PCI Error Recovery (readX_check)

The implementation patch, pasted (not attached).

-----

tmp/linux-2.6.8.1/arch/i386/pci/common.c renamed from usr/src/linux-2.6.8.1/arch/i386/pci/common.c +22 -0
diff -Nur /usr/src/linux-2.6.8.1/arch/i386/pci/common.c /tmp/linux-2.6.8.1/arch/i386/pci/common.c
@@ -118,6 +118,19 @@
  	pci_read_bridge_bases(b);
  }
 
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+static void pci_i386_fixup_host_bridge_self(struct pci_bus *bus)
+{
+	struct pci_dev *pdev;
+
+	list_for_each_entry(pdev, &bus->devices, bus_list) {
+		if (pdev->class >> 8 = PCI_CLASS_BRIDGE_HOST) {
+			bus->self = pdev;
+			return;
+		}
+	}
+}
+#endif
 
  struct pci_bus * __devinit pcibios_scan_root(int busnum)
  {
@@ -132,7 +145,16 @@
 
  	printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);
 
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+{
+	struct pci_bus *bus = pci_scan_bus(busnum, &pci_root_ops, NULL);
+	if (bus)
+		pci_i386_fixup_host_bridge_self(bus);
+	return bus;
+}
+#else
  	return pci_scan_bus(busnum, &pci_root_ops, NULL);
+#endif
  }
 
  extern u8 pci_cache_line_size;
tmp/linux-2.6.8.1/drivers/pci/Kconfig renamed from usr/src/linux-2.6.8.1/drivers/pci/Kconfig +7 -0
diff -Nur /usr/src/linux-2.6.8.1/drivers/pci/Kconfig /tmp/linux-2.6.8.1/drivers/pci/Kconfig
@@ -47,3 +47,10 @@
 
  	  When in doubt, say Y.
 
+config PCI_ERROR_RECOVERY
+	bool "PCI device error recovery"
+	depends on PCI
+	---help---
+	By default, the device driver hardly recovers from PCI errors. When
+	this feature is available, the special io interface are provided
+	from the kernel.
tmp/linux-2.6.8.1/drivers/pci/Makefile renamed from usr/src/linux-2.6.8.1/drivers/pci/Makefile +1 -0
diff -Nur /usr/src/linux-2.6.8.1/drivers/pci/Makefile /tmp/linux-2.6.8.1/drivers/pci/Makefile
@@ -5,6 +5,7 @@
  obj-y		+= access.o bus.o probe.o remove.o pci.o quirks.o \
  			names.o pci-driver.o search.o pci-sysfs.o
  obj-$(CONFIG_PROC_FS) += proc.o
+obj-$(CONFIG_PCI_ERROR_RECOVERY) += pci-rec.o
 
  ifndef CONFIG_SPARC64
  obj-y += setup-res.o
tmp/linux-2.6.8.1/drivers/pci/pci-rec.c renamed from usr/src/linux-2.6.8.1/drivers/pci/pci-rec.c +222 -0

222 lines not on this page · raw message

tmp/linux-2.6.8.1/drivers/pci/pci.c renamed from usr/src/linux-2.6.8.1/drivers/pci/pci.c +3 -0
diff -Nur /usr/src/linux-2.6.8.1/drivers/pci/pci.c /tmp/linux-2.6.8.1/drivers/pci/pci.c
@@ -750,6 +750,9 @@
  	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
  		pci_fixup_device(PCI_FIXUP_FINAL, dev);
  	}
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+	pciwhole_lock_init();
+#endif
  	return 0;
  }
 
tmp/linux-2.6.8.1/drivers/pci/probe.c renamed from usr/src/linux-2.6.8.1/drivers/pci/probe.c +6 -0
diff -Nur /usr/src/linux-2.6.8.1/drivers/pci/probe.c /tmp/linux-2.6.8.1/drivers/pci/probe.c
@@ -270,6 +270,9 @@
  		INIT_LIST_HEAD(&b->node);
  		INIT_LIST_HEAD(&b->children);
  		INIT_LIST_HEAD(&b->devices);
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+		pcibus_lock_init(b);
+#endif
  	}
  	return b;
  }
@@ -624,6 +627,9 @@
 
  	dev->dev.dma_mask = &dev->dma_mask;
  	dev->dev.coherent_dma_mask = 0xffffffffull;
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+	pcidev_extra_init(dev);
+#endif
 
  	return dev;
  }
tmp/linux-2.6.8.1/include/asm-i386/io.h renamed from usr/src/linux-2.6.8.1/include/asm-i386/io.h +15 -0
diff -Nur /usr/src/linux-2.6.8.1/include/asm-i386/io.h /tmp/linux-2.6.8.1/include/asm-i386/io.h
@@ -364,4 +364,19 @@
  BUILDIO(w,w,short)
  BUILDIO(l,,int)
 
+static inline unsigned char _readb_check(unsigned char *addr)
+{
+	return readb(addr);
+}
+
+static inline unsigned short _readw_check(unsigned short *addr)
+{
+	return readw(addr);
+}
+
+static inline unsigned int _readl_check(unsigned int *addr)
+{
+	return readl(addr);
+}
+
  #endif
tmp/linux-2.6.8.1/include/asm-i386/pci.h renamed from usr/src/linux-2.6.8.1/include/asm-i386/pci.h +5 -0
diff -Nur /usr/src/linux-2.6.8.1/include/asm-i386/pci.h /tmp/linux-2.6.8.1/include/asm-i386/pci.h
@@ -99,6 +99,11 @@
  {
  }
 
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+u8 readb_check(struct pci_dev *, u8*);
+u16 readw_check(struct pci_dev *, u16*);
+u32 readl_check(struct pci_dev *, u32*);
+#endif
  #endif /* __KERNEL__ */
 
  /* implement the pci_ DMA API in terms of the generic device dma_ one */
tmp/linux-2.6.8.1/include/asm-ia64/io.h renamed from usr/src/linux-2.6.8.1/include/asm-ia64/io.h +35 -0
diff -Nur /usr/src/linux-2.6.8.1/include/asm-ia64/io.h /tmp/linux-2.6.8.1/include/asm-ia64/io.h
@@ -457,4 +457,39 @@
  #define BIO_VMERGE_BOUNDARY	(ia64_max_iommu_merge_mask + 1)
  #endif
 
+static inline unsigned char
+_readb_check(unsignged char *addr)
+{
+	register unsigned long gr8 asm("r8");
+	unsigned char val;
+
+	val = readb(addr);
+	asm volatile ("add %0=%1,r0" : "=r"(gr8) : "r"(val));
+
+	return val;
+}
+
+static inline unsigned short
+_readw_check(unsignged short *addr)
+{
+	register unsigned long gr8 asm("r8");
+	unsigned short val;
+
+	val = readw(addr);
+	asm volatile ("add %0=%1,r0" : "=r"(gr8) : "r"(val));
+
+	return val;
+}
+
+static inline unsigned int
+_readl_check(unsignged int *addr)
+{
+	register unsigned long gr8 asm("r8");
+	unsigned int val;
+
+	val = readl(addr);
+	asm volatile ("add %0=%1,r0" : "=r"(gr8) : "r"(val));
+
+	return val;
+}
  #endif /* _ASM_IA64_IO_H */
tmp/linux-2.6.8.1/include/asm-ia64/pci.h renamed from usr/src/linux-2.6.8.1/include/asm-ia64/pci.h +5 -0
diff -Nur /usr/src/linux-2.6.8.1/include/asm-ia64/pci.h /tmp/linux-2.6.8.1/include/asm-ia64/pci.h
@@ -119,6 +119,11 @@
  {
  }
 
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+u8 readb_check(struct pci_dev *, u8*);
+u16 readw_check(struct pci_dev *, u16*);
+u32 readl_check(struct pci_dev *, u32*);
+#endif
  /* generic pci stuff */
  #include <asm-generic/pci.h>
 
tmp/linux-2.6.8.1/include/linux/pci.h renamed from usr/src/linux-2.6.8.1/include/linux/pci.h +23 -0
diff -Nur /usr/src/linux-2.6.8.1/include/linux/pci.h /tmp/linux-2.6.8.1/include/linux/pci.h
@@ -486,6 +486,10 @@
  struct pci_dev {
  	struct list_head global_list;	/* node in list of all PCI devices */
  	struct list_head bus_list;	/* node in per-bus list */
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+	struct list_head working_device;/* working device */
+	unsigned        err_status;     /* root bridge status and other error */
+#endif
  	struct pci_bus	*bus;		/* bus this device is on */
  	struct pci_bus	*subordinate;	/* bus this device bridges to */
 
@@ -568,6 +572,9 @@
 
  struct pci_bus {
  	struct list_head node;		/* node in list of buses */
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+       struct rw_semaphore bus_lock;   /* for serialized operation under same root bridge */
+#endif
  	struct pci_bus	*parent;	/* parent bus this bridge is on */
  	struct list_head children;	/* list of child buses */
  	struct list_head devices;	/* list of devices on this bus */
@@ -1021,5 +1028,21 @@
  #define PCIPCI_VSFX		16
  #define PCIPCI_ALIMAGIK		32
 
+#ifdef CONFIG_PCI_ERROR_RECOVERY
+void pcidev_extra_init(struct pci_dev *);
+void pcibus_lock_init(struct pci_bus *);
+void pcibus_lock(struct pci_bus *);
+void pcibus_unlock(struct pci_bus *);
+void pciwhole_lock_init(void);
+void pciwhole_read_lock(void);
+void pciwhole_read_unlock(void);
+void pciwhole_write_lock(void);
+void pciwhole_write_unlock(void);
+void clear_pci_errors(struct pci_dev *);
+int read_pci_errors(struct pci_dev *);
+u8  readb_check(struct pci_dev *, u8 *);
+u16 readw_check(struct pci_dev *, u16 *);
+u32 readl_check(struct pci_dev *, u32 *);
+#endif
  #endif /* __KERNEL__ */
  #endif /* LINUX_PCI_H */
#1 lore raw

tmp/linux-2.6.8.1/drivers/pci/Kconfig line 52

Quoted 2 lines · Hidetoshi Seto
tmp/linux-2.6.8.1/drivers/pci/Kconfig renamed from usr/src/linux-2.6.8.1/drivers/pci/Kconfig +2 -0
+	bool "PCI device error recovery"
+	depends on PCI
	depends on PCI && EXPERIMENTAL

tmp/linux-2.6.8.1/drivers/pci/Kconfig line 56

Quoted 4 lines
tmp/linux-2.6.8.1/drivers/pci/Kconfig renamed from usr/src/linux-2.6.8.1/drivers/pci/Kconfig +4 -0
+	---help---
+	By default, the device driver hardly recovers from PCI errors. When
+	this feature is available, the special io interface are provided
+	from the kernel.

May I suggest an alternate text?
Saying Y provides PCI infrastructure to recover from some PCI errors. Currently, very few PCI drivers actually implement this. See Documentation/pci-errors.txt for a description of the infrastructure provided.

I'm still digesting the rest of the patch.

grant