diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index de821c1..a8dd983 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -211,7 +211,9 @@ void eeh_dev_phb_init_dynamic(struct pci_controller *phb);
 int __init eeh_init(void);
 int __init eeh_ops_register(struct eeh_ops *ops);
 int __exit eeh_ops_unregister(const char *name);
-unsigned long eeh_check_failure(const volatile void __iomem *token,
+int eeh_check_blocked_io(const volatile void __iomem *token,
+			 void **pedev);
+unsigned long eeh_check_failure(struct eeh_dev *edev,
 				unsigned long val);
 int eeh_dev_check_failure(struct eeh_dev *edev);
 void __init eeh_addr_cache_build(void);
@@ -249,7 +251,13 @@ static inline void *eeh_dev_init(struct device_node *dn, void *data)
 
 static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { }
 
-static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
+int eeh_check_blocked_io(const volatile void __iomem *token,
+			 void **pedev)
+{
+	return 0;
+}
+
+static inline unsigned long eeh_check_failure(void *data, unsigned long val)
 {
 	return val;
 }
@@ -276,57 +284,99 @@ static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
  */
 static inline u8 eeh_readb(const volatile void __iomem *addr)
 {
-	u8 val = in_8(addr);
-	if (EEH_POSSIBLE_ERROR(val, u8))
-		return eeh_check_failure(addr, val);
+	u8 val = 0xFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_8(addr);
+		if (EEH_POSSIBLE_ERROR(val, u8))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u16 eeh_readw(const volatile void __iomem *addr)
 {
-	u16 val = in_le16(addr);
-	if (EEH_POSSIBLE_ERROR(val, u16))
-		return eeh_check_failure(addr, val);
+	u16 val = 0xFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_le16(addr);
+		if (EEH_POSSIBLE_ERROR(val, u16))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u32 eeh_readl(const volatile void __iomem *addr)
 {
-	u32 val = in_le32(addr);
-	if (EEH_POSSIBLE_ERROR(val, u32))
-		return eeh_check_failure(addr, val);
+	u32 val = 0xFFFFFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_le32(addr);
+		if (EEH_POSSIBLE_ERROR(val, u32))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u64 eeh_readq(const volatile void __iomem *addr)
 {
-	u64 val = in_le64(addr);
-	if (EEH_POSSIBLE_ERROR(val, u64))
-		return eeh_check_failure(addr, val);
+	u64 val = 0xFFFFFFFFFFFFFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_le64(addr);
+		if (EEH_POSSIBLE_ERROR(val, u64))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u16 eeh_readw_be(const volatile void __iomem *addr)
 {
-	u16 val = in_be16(addr);
-	if (EEH_POSSIBLE_ERROR(val, u16))
-		return eeh_check_failure(addr, val);
+	u16 val = 0xFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_be16(addr);
+		if (EEH_POSSIBLE_ERROR(val, u16))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u32 eeh_readl_be(const volatile void __iomem *addr)
 {
-	u32 val = in_be32(addr);
-	if (EEH_POSSIBLE_ERROR(val, u32))
-		return eeh_check_failure(addr, val);
+	u32 val = 0xFFFFFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_be32(addr);
+		if (EEH_POSSIBLE_ERROR(val, u32))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u64 eeh_readq_be(const volatile void __iomem *addr)
 {
-	u64 val = in_be64(addr);
-	if (EEH_POSSIBLE_ERROR(val, u64))
-		return eeh_check_failure(addr, val);
+	u64 val = 0xFFFFFFFFFFFFFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_be64(addr);
+		if (EEH_POSSIBLE_ERROR(val, u64))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
@@ -334,40 +384,145 @@ static inline void eeh_memcpy_fromio(void *dest, const
 				     volatile void __iomem *src,
 				     unsigned long n)
 {
-	_memcpy_fromio(dest, src, n);
+	void *edev;
+
+	memset(dest, 0xFF, n);
+
+	if (!eeh_check_blocked_io(src, &edev)) {
+		_memcpy_fromio(dest, src, n);
 
-	/* Look for ffff's here at dest[n].  Assume that at least 4 bytes
-	 * were copied. Check all four bytes.
-	 */
-	if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32))
-		eeh_check_failure(src, *((u32 *)(dest + n - 4)));
+		/*
+		 * Look for ffff's here at dest[n]. Assume that at
+		 * least 4 bytes were copied. Check all four bytes.
+		 */
+		if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32))
+			eeh_check_failure(edev, *((u32 *)(dest + n - 4)));
+	}
 }
 
 /* in-string eeh macros */
 static inline void eeh_readsb(const volatile void __iomem *addr, void * buf,
 			      int ns)
 {
-	_insb(addr, buf, ns);
-	if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
-		eeh_check_failure(addr, *(u8*)buf);
+	void *edev;
+
+	memset(buf, 0xFF, ns);
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		_insb(addr, buf, ns);
+		if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
+			eeh_check_failure(edev, *(u8*)buf);
+	}
 }
 
 static inline void eeh_readsw(const volatile void __iomem *addr, void * buf,
 			      int ns)
 {
-	_insw(addr, buf, ns);
-	if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
-		eeh_check_failure(addr, *(u16*)buf);
+	void *edev;
+
+	memset(buf, 0xFF, ns * sizeof(u16));
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		_insw(addr, buf, ns);
+		if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
+			eeh_check_failure(edev, *(u16*)buf);
+	}
 }
 
 static inline void eeh_readsl(const volatile void __iomem *addr, void * buf,
 			      int nl)
 {
-	_insl(addr, buf, nl);
-	if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
-		eeh_check_failure(addr, *(u32*)buf);
+	void *edev;
+
+	memset(buf, 0xFF, nl * sizeof(u32));
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		_insl(addr, buf, nl);
+		if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
+			eeh_check_failure(edev, *(u32*)buf);
+	}
+}
+
+/* MMIO write */
+static inline void eeh_writeb(volatile u8 __iomem *addr, u8 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_8(addr, val);
+}
+
+static inline void eeh_writew(volatile u16 __iomem *addr, u16 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_le16(addr, val);
 }
 
+static inline void eeh_writel(volatile u32 __iomem *addr, u32 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_le32(addr, val);
+}
+
+static inline void eeh_writeq(volatile u64 __iomem *addr, u64 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_le64(addr, val);
+}
+
+static inline void eeh_writew_be(volatile u16 __iomem *addr, u16 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_be16(addr, val);
+}
+
+static inline void eeh_writel_be(volatile u32 __iomem *addr, u32 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_be32(addr, val);
+}
+
+static inline void eeh_writeq_be(volatile u64 __iomem *addr, u64 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_be64(addr, val);
+}
+
+static inline void eeh_writesb(volatile u8 __iomem *addr,
+			       const void *buf, long count)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		_outsb(addr, buf, count);
+}
+
+static inline void eeh_writesw(volatile u16 __iomem *addr,
+			       const void *buf, long count)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		_outsw(addr, buf, count);
+}
+
+static inline void eeh_writesl(volatile u32 __iomem *addr,
+			       const void *buf, long count)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		_outsl(addr, buf, count);
+}
+
+static inline void eeh_memset_io(volatile void __iomem *addr,
+				 int c, unsigned long n)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		_memset_io(addr, c, n);
+}
+
+static inline void eeh_memcpy_toio(volatile void __iomem *dest,
+				   const void *src, unsigned long n)
+{
+	if (!eeh_check_blocked_io(dest, NULL))
+		_memcpy_toio(dest, src, n);
+}
+
+
+
 #endif /* CONFIG_PPC64 */
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_EEH_H */
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index dd15e5e..fa58c45 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -412,30 +412,37 @@ __do_out_asm(_rec_outl, "stwbrx")
  * possible to hook directly at the toplevel PIO operation if they have to
  * be handled differently
  */
-#define __do_writeb(val, addr)	out_8(PCI_FIX_ADDR(addr), val)
-#define __do_writew(val, addr)	out_le16(PCI_FIX_ADDR(addr), val)
-#define __do_writel(val, addr)	out_le32(PCI_FIX_ADDR(addr), val)
-#define __do_writeq(val, addr)	out_le64(PCI_FIX_ADDR(addr), val)
-#define __do_writew_be(val, addr) out_be16(PCI_FIX_ADDR(addr), val)
-#define __do_writel_be(val, addr) out_be32(PCI_FIX_ADDR(addr), val)
-#define __do_writeq_be(val, addr) out_be64(PCI_FIX_ADDR(addr), val)
 
 #ifdef CONFIG_EEH
-#define __do_readb(addr)	eeh_readb(PCI_FIX_ADDR(addr))
-#define __do_readw(addr)	eeh_readw(PCI_FIX_ADDR(addr))
-#define __do_readl(addr)	eeh_readl(PCI_FIX_ADDR(addr))
-#define __do_readq(addr)	eeh_readq(PCI_FIX_ADDR(addr))
-#define __do_readw_be(addr)	eeh_readw_be(PCI_FIX_ADDR(addr))
-#define __do_readl_be(addr)	eeh_readl_be(PCI_FIX_ADDR(addr))
-#define __do_readq_be(addr)	eeh_readq_be(PCI_FIX_ADDR(addr))
+#define __do_readb(addr)		eeh_readb(PCI_FIX_ADDR(addr))
+#define __do_readw(addr)		eeh_readw(PCI_FIX_ADDR(addr))
+#define __do_readl(addr)		eeh_readl(PCI_FIX_ADDR(addr))
+#define __do_readq(addr)		eeh_readq(PCI_FIX_ADDR(addr))
+#define __do_readw_be(addr)		eeh_readw_be(PCI_FIX_ADDR(addr))
+#define __do_readl_be(addr)		eeh_readl_be(PCI_FIX_ADDR(addr))
+#define __do_readq_be(addr)		eeh_readq_be(PCI_FIX_ADDR(addr))
+#define __do_writeb(val, addr)		eeh_writeb(PCI_FIX_ADDR(addr), val)
+#define __do_writew(val, addr)          eeh_writew(PCI_FIX_ADDR(addr), val)
+#define __do_writel(val, addr)          eeh_writel(PCI_FIX_ADDR(addr), val)
+#define __do_writeq(val, addr)          eeh_writeq(PCI_FIX_ADDR(addr), val)
+#define __do_writew_be(val, addr)       eeh_writew_be(PCI_FIX_ADDR(addr), val)
+#define __do_writel_be(val, addr)       eeh_writel_be(PCI_FIX_ADDR(addr), val)
+#define __do_writeq_be(val, addr)       eeh_writeq_be(PCI_FIX_ADDR(addr), val)
 #else /* CONFIG_EEH */
-#define __do_readb(addr)	in_8(PCI_FIX_ADDR(addr))
-#define __do_readw(addr)	in_le16(PCI_FIX_ADDR(addr))
-#define __do_readl(addr)	in_le32(PCI_FIX_ADDR(addr))
-#define __do_readq(addr)	in_le64(PCI_FIX_ADDR(addr))
-#define __do_readw_be(addr)	in_be16(PCI_FIX_ADDR(addr))
-#define __do_readl_be(addr)	in_be32(PCI_FIX_ADDR(addr))
-#define __do_readq_be(addr)	in_be64(PCI_FIX_ADDR(addr))
+#define __do_readb(addr)		in_8(PCI_FIX_ADDR(addr))
+#define __do_readw(addr)		in_le16(PCI_FIX_ADDR(addr))
+#define __do_readl(addr)		in_le32(PCI_FIX_ADDR(addr))
+#define __do_readq(addr)		in_le64(PCI_FIX_ADDR(addr))
+#define __do_readw_be(addr)		in_be16(PCI_FIX_ADDR(addr))
+#define __do_readl_be(addr)		in_be32(PCI_FIX_ADDR(addr))
+#define __do_readq_be(addr)		in_be64(PCI_FIX_ADDR(addr))
+#define __do_writeb(val, addr)		out_8(PCI_FIX_ADDR(addr), val)
+#define __do_writew(val, addr)		out_le16(PCI_FIX_ADDR(addr), val)
+#define __do_writel(val, addr)		out_le32(PCI_FIX_ADDR(addr), val)
+#define __do_writeq(val, addr)		out_le64(PCI_FIX_ADDR(addr), val)
+#define __do_writew_be(val, addr)	out_be16(PCI_FIX_ADDR(addr), val)
+#define __do_writel_be(val, addr)	out_be32(PCI_FIX_ADDR(addr), val)
+#define __do_writeq_be(val, addr)	out_be64(PCI_FIX_ADDR(addr), val)
 #endif /* !defined(CONFIG_EEH) */
 
 #ifdef CONFIG_PPC32
@@ -458,14 +465,17 @@ __do_out_asm(_rec_outl, "stwbrx")
 #define __do_readsb(a, b, n)	eeh_readsb(PCI_FIX_ADDR(a), (b), (n))
 #define __do_readsw(a, b, n)	eeh_readsw(PCI_FIX_ADDR(a), (b), (n))
 #define __do_readsl(a, b, n)	eeh_readsl(PCI_FIX_ADDR(a), (b), (n))
+#define __do_writesb(a, b, n)   eeh_writesb(PCI_FIX_ADDR(a),(b),(n))
+#define __do_writesw(a, b, n)   eeh_writesw(PCI_FIX_ADDR(a),(b),(n))
+#define __do_writesl(a, b, n)   eeh_writesl(PCI_FIX_ADDR(a),(b),(n))
 #else /* CONFIG_EEH */
 #define __do_readsb(a, b, n)	_insb(PCI_FIX_ADDR(a), (b), (n))
 #define __do_readsw(a, b, n)	_insw(PCI_FIX_ADDR(a), (b), (n))
 #define __do_readsl(a, b, n)	_insl(PCI_FIX_ADDR(a), (b), (n))
-#endif /* !CONFIG_EEH */
 #define __do_writesb(a, b, n)	_outsb(PCI_FIX_ADDR(a),(b),(n))
 #define __do_writesw(a, b, n)	_outsw(PCI_FIX_ADDR(a),(b),(n))
 #define __do_writesl(a, b, n)	_outsl(PCI_FIX_ADDR(a),(b),(n))
+#endif /* !CONFIG_EEH */
 
 #define __do_insb(p, b, n)	readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
 #define __do_insw(p, b, n)	readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
@@ -474,17 +484,20 @@ __do_out_asm(_rec_outl, "stwbrx")
 #define __do_outsw(p, b, n)	writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
 #define __do_outsl(p, b, n)	writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
 
-#define __do_memset_io(addr, c, n)	\
-				_memset_io(PCI_FIX_ADDR(addr), c, n)
-#define __do_memcpy_toio(dst, src, n)	\
-				_memcpy_toio(PCI_FIX_ADDR(dst), src, n)
-
 #ifdef CONFIG_EEH
 #define __do_memcpy_fromio(dst, src, n)	\
 				eeh_memcpy_fromio(dst, PCI_FIX_ADDR(src), n)
+#define __do_memset_io(addr, c, n)	\
+				eeh_memset_io(PCI_FIX_ADDR(addr), c, n)
+#define __do_memcpy_toio(dst, src, n)	\
+				eeh_memcpy_toio(PCI_FIX_ADDR(dst), src, n)
 #else /* CONFIG_EEH */
 #define __do_memcpy_fromio(dst, src, n)	\
 				_memcpy_fromio(dst,PCI_FIX_ADDR(src),n)
+#define __do_memset_io(addr, c, n)	\
+				_memset_io(PCI_FIX_ADDR(addr), c, n)
+#define __do_memcpy_toio(dst, src, n)	\
+				_memcpy_toio(PCI_FIX_ADDR(dst), src, n)
 #endif /* !CONFIG_EEH */
 
 #ifdef CONFIG_PPC_INDIRECT_PIO
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 65320fd..b46f1ca 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -464,39 +464,57 @@ dn_unlock:
 EXPORT_SYMBOL_GPL(eeh_dev_check_failure);
 
 /**
- * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
- * @token: I/O token, should be address in the form 0xA....
- * @val: value, should be all 1's (XXX why do we need this arg??)
- *
- * Check for an EEH failure at the given token address.  Call this
- * routine if the result of a read was all 0xff's and you want to
- * find out if this is due to an EEH slot freeze event.  This routine
- * will query firmware for the EEH status.
+ * eeh_check_blocked_io - Check if the I/O access has been blocked
+ * @token: I/O token
+ * @pedev: EEH device
  *
- * Note this routine is safe to call in an interrupt context.
+ * Check if the I/O access has been blocked. If that's the case, we
+ * should return 0xFF's on read, or sliently drop the write.
  */
-unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
+int eeh_check_blocked_io(const volatile void __iomem *token,
+			 void **pedev)
 {
-	unsigned long addr;
 	struct eeh_dev *edev;
+	unsigned long addr;
+	int rc;
 
-	/* Finding the phys addr + pci device; this is pretty quick. */
+	/* Don't block I/O ranges which aren't traced by cache */
 	addr = eeh_token_to_phys((unsigned long __force) token);
 	edev = eeh_addr_cache_get_dev(addr);
 	if (!edev) {
+		if (pedev) *pedev = NULL;
 		eeh_stats.no_device++;
-		return val;
+		return 0;
 	}
 
-	eeh_dev_check_failure(edev);
+	if (pedev) *pedev = edev;
+	eeh_ops->get_setting(EEH_SETTING_BLOCK_IO, &rc, edev->phb);
+	return rc;
+}
+
+EXPORT_SYMBOL(eeh_check_blocked_io);
+
+/**
+ * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
+ * @edev: EEH device
+ * @val: value
+ *
+ * Check if the EEH device has been frozen.
+ *
+ * Note this routine is safe to call in an interrupt context.
+ */
+unsigned long eeh_check_failure(struct eeh_dev *edev, unsigned long val)
+{
+	if (edev) {
+		eeh_dev_check_failure(edev);
+		pci_dev_put(eeh_dev_to_pci_dev(edev));
+	}
 
-	pci_dev_put(eeh_dev_to_pci_dev(edev));
 	return val;
 }
 
 EXPORT_SYMBOL(eeh_check_failure);
 
-
 /**
  * eeh_pci_enable - Enable MMIO or DMA transfers for this slot
  * @pe: EEH PE
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index cac5e18..20a7865 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -367,7 +367,7 @@ static int powernv_eeh_set_setting(int option, int value, void *data)
 	struct pci_controller *hose = data;
 	struct pnv_phb *phb = hose->private_data;
 
-	return phb->set_setting(option, value, data);
+	return phb->eeh_ops->set_setting(option, value, data);
 }
 
 /**
@@ -383,7 +383,7 @@ static int powernv_eeh_get_setting(int option, int *value, void *data)
 	struct pci_controller *hose = data;
 	struct pnv_phb *phb = hose->private_data;
 
-	return phb->get_setting(option, value, data);
+	return phb->eeh_ops->get_setting(option, value, data);
 }
 
 /**
