1172ca9261800bacbbc7d320d9924d9b482dff8deLinas Vepstas/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation. 3cb3bc9d0de1e247268622acd40e0d2f8120f299cGavin Shan * Copyright 2001-2012 IBM Corporation. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 9172ca9261800bacbbc7d320d9924d9b482dff8deLinas Vepstas * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 14172ca9261800bacbbc7d320d9924d9b482dff8deLinas Vepstas * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 208b8da35804bb89eee23f9bcd5638e1f754bd4c91Benjamin Herrenschmidt#ifndef _POWERPC_EEH_H 218b8da35804bb89eee23f9bcd5638e1f754bd4c91Benjamin Herrenschmidt#define _POWERPC_EEH_H 2288ced0314938814e1772b4d0d7ab20c52e4472b6Arnd Bergmann#ifdef __KERNEL__ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/list.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_dev; 29827c1a6c1a5dcb2902fecfb648f9af6a532934ebJohn Rosestruct pci_bus; 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct device_node; 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_EEH 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan/* 35eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan * The struct is used to trace EEH state for the associated 36eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan * PCI device node or PCI device. In future, it might 37eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan * represent PE as well so that the EEH device to form 38eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan * another tree except the currently existing tree of PCI 39eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan * buses and PCI devices 40eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan */ 41eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan#define EEH_MODE_SUPPORTED (1<<0) /* EEH supported on the device */ 42eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan#define EEH_MODE_NOCHECK (1<<1) /* EEH check should be skipped */ 43eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan#define EEH_MODE_ISOLATED (1<<2) /* The device has been isolated */ 44eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan#define EEH_MODE_RECOVERING (1<<3) /* Recovering the device */ 45eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan#define EEH_MODE_IRQ_DISABLED (1<<4) /* Interrupt disabled */ 46eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan 47eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanstruct eeh_dev { 48eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan int mode; /* EEH mode */ 49eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan int class_code; /* Class code of the device */ 50eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan int config_addr; /* Config address */ 51eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan int pe_config_addr; /* PE config address */ 52eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan int check_count; /* Times of ignored error */ 53eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan int freeze_count; /* Times of froze up */ 54eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan int false_positives; /* Times of reported #ff's */ 55eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan u32 config_space[16]; /* Saved PCI config space */ 56eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan struct pci_controller *phb; /* Associated PHB */ 57eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan struct device_node *dn; /* Associated device node */ 58eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan struct pci_dev *pdev; /* Associated PCI device */ 59eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan}; 60eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan 61eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanstatic inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) 62eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan{ 63eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan return edev->dn; 64eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan} 65eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan 66eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanstatic inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev) 67eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan{ 68eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan return edev->pdev; 69eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan} 70eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan 71eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan/* 72aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan * The struct is used to trace the registered EEH operation 73aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan * callback functions. Actually, those operation callback 74aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan * functions are heavily platform dependent. That means the 75aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan * platform should register its own EEH operation callback 76aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan * functions before any EEH further operations. 77aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan */ 788fb8f709025c13ae72968a66a1ade24431a342b2Gavin Shan#define EEH_OPT_DISABLE 0 /* EEH disable */ 798fb8f709025c13ae72968a66a1ade24431a342b2Gavin Shan#define EEH_OPT_ENABLE 1 /* EEH enable */ 808fb8f709025c13ae72968a66a1ade24431a342b2Gavin Shan#define EEH_OPT_THAW_MMIO 2 /* MMIO enable */ 818fb8f709025c13ae72968a66a1ade24431a342b2Gavin Shan#define EEH_OPT_THAW_DMA 3 /* DMA enable */ 82eb594a4754e71e41c048e0f1559bb6f13dab7070Gavin Shan#define EEH_STATE_UNAVAILABLE (1 << 0) /* State unavailable */ 83eb594a4754e71e41c048e0f1559bb6f13dab7070Gavin Shan#define EEH_STATE_NOT_SUPPORT (1 << 1) /* EEH not supported */ 84eb594a4754e71e41c048e0f1559bb6f13dab7070Gavin Shan#define EEH_STATE_RESET_ACTIVE (1 << 2) /* Active reset */ 85eb594a4754e71e41c048e0f1559bb6f13dab7070Gavin Shan#define EEH_STATE_MMIO_ACTIVE (1 << 3) /* Active MMIO */ 86eb594a4754e71e41c048e0f1559bb6f13dab7070Gavin Shan#define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */ 87eb594a4754e71e41c048e0f1559bb6f13dab7070Gavin Shan#define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */ 88eb594a4754e71e41c048e0f1559bb6f13dab7070Gavin Shan#define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */ 892652481f75186940c4608f68c9fd76b32ec9b159Gavin Shan#define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */ 902652481f75186940c4608f68c9fd76b32ec9b159Gavin Shan#define EEH_RESET_HOT 1 /* Hot reset */ 912652481f75186940c4608f68c9fd76b32ec9b159Gavin Shan#define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */ 928d633291b4fc0539ecad31f972447104be6953ecGavin Shan#define EEH_LOG_TEMP 1 /* EEH temporary error log */ 938d633291b4fc0539ecad31f972447104be6953ecGavin Shan#define EEH_LOG_PERM 2 /* EEH permanent error log */ 94eb594a4754e71e41c048e0f1559bb6f13dab7070Gavin Shan 95aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shanstruct eeh_ops { 96aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan char *name; 97aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan int (*init)(void); 98aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan int (*set_option)(struct device_node *dn, int option); 99aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan int (*get_pe_addr)(struct device_node *dn); 100aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan int (*get_state)(struct device_node *dn, int *state); 101aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan int (*reset)(struct device_node *dn, int option); 102aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan int (*wait_state)(struct device_node *dn, int max_wait); 103aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan int (*get_log)(struct device_node *dn, int severity, char *drv_log, unsigned long len); 104aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan int (*configure_bridge)(struct device_node *dn); 1053780444c4fcec28c96ab7002858bb051215a5fc1Gavin Shan int (*read_config)(struct device_node *dn, int where, int size, u32 *val); 1063780444c4fcec28c96ab7002858bb051215a5fc1Gavin Shan int (*write_config)(struct device_node *dn, int where, int size, u32 val); 107aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan}; 108aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan 109aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shanextern struct eeh_ops *eeh_ops; 1101e28a7ddd3e713384e9c6768e7c502031dc205e2David Woodhouseextern int eeh_subsystem_enabled; 1111e28a7ddd3e713384e9c6768e7c502031dc205e2David Woodhouse 112cb3bc9d0de1e247268622acd40e0d2f8120f299cGavin Shan/* 113cb3bc9d0de1e247268622acd40e0d2f8120f299cGavin Shan * Max number of EEH freezes allowed before we consider the device 114cb3bc9d0de1e247268622acd40e0d2f8120f299cGavin Shan * to be permanently disabled. 115cb3bc9d0de1e247268622acd40e0d2f8120f299cGavin Shan */ 116172ca9261800bacbbc7d320d9924d9b482dff8deLinas Vepstas#define EEH_MAX_ALLOWED_FREEZES 5 117172ca9261800bacbbc7d320d9924d9b482dff8deLinas Vepstas 118eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanvoid * __devinit eeh_dev_init(struct device_node *dn, void *data); 119eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanvoid __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb); 120eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanvoid __init eeh_dev_phb_init(void); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init eeh_init(void); 122aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan#ifdef CONFIG_PPC_PSERIES 123aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shanint __init eeh_pseries_init(void); 124aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan#endif 125aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shanint __init eeh_ops_register(struct eeh_ops *ops); 126aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shanint __exit eeh_ops_unregister(const char *name); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long eeh_check_failure(const volatile void __iomem *token, 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init pci_addr_cache_build(void); 131e2a296eeaa344450196e910a136ab14119d7ae48Linas Vepstasvoid eeh_add_device_tree_early(struct device_node *); 132827c1a6c1a5dcb2902fecfb648f9af6a532934ebJohn Rosevoid eeh_add_device_tree_late(struct pci_bus *); 133e2a296eeaa344450196e910a136ab14119d7ae48Linas Vepstasvoid eeh_remove_bus_device(struct pci_dev *); 134e2a296eeaa344450196e910a136ab14119d7ae48Linas Vepstas 135e2a296eeaa344450196e910a136ab14119d7ae48Linas Vepstas/** 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this macro yields TRUE, the caller relays to eeh_check_failure() 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * which does further tests out of line. 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1411e28a7ddd3e713384e9c6768e7c502031dc205e2David Woodhouse#define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0 && eeh_subsystem_enabled) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reads from a device which has been isolated by EEH will return 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all 1s. This macro gives an all-1s value of the given size (in 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bytes: 1, 2, or 4) for comparing with the result of a read. 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EEH_IO_ERROR_VALUE(size) (~0U >> ((4 - (size)) * 8)) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* !CONFIG_EEH */ 151eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan 152eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanstatic inline void *eeh_dev_init(struct device_node *dn, void *data) 153eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan{ 154eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan return NULL; 155eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan} 156eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan 157eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanstatic inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { } 158eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan 159eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shanstatic inline void eeh_dev_phb_init(void) { } 160eb740b5f3e6559a8f1c22e2505914d07f9632881Gavin Shan 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void eeh_init(void) { } 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 163aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan#ifdef CONFIG_PPC_PSERIES 164aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shanstatic inline int eeh_pseries_init(void) 165aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan{ 166aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan return 0; 167aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan} 168aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan#endif /* CONFIG_PPC_PSERIES */ 169aa1e6374ae11788752535ae0c8c6395c9cad1393Gavin Shan 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val) 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void pci_addr_cache_build(void) { } 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 182022930ebea0df878d449b7c74309c1d612441ac5Haren Mynenistatic inline void eeh_add_device_tree_early(struct device_node *dn) { } 183022930ebea0df878d449b7c74309c1d612441ac5Haren Myneni 184827c1a6c1a5dcb2902fecfb648f9af6a532934ebJohn Rosestatic inline void eeh_add_device_tree_late(struct pci_bus *bus) { } 185827c1a6c1a5dcb2902fecfb648f9af6a532934ebJohn Rose 186022930ebea0df878d449b7c74309c1d612441ac5Haren Mynenistatic inline void eeh_remove_bus_device(struct pci_dev *dev) { } 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EEH_POSSIBLE_ERROR(val, type) (0) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EEH_IO_ERROR_VALUE(size) (-1UL) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_EEH */ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1918b8da35804bb89eee23f9bcd5638e1f754bd4c91Benjamin Herrenschmidt#ifdef CONFIG_PPC64 192172ca9261800bacbbc7d320d9924d9b482dff8deLinas Vepstas/* 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MMIO read/write operations with EEH support. 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 eeh_readb(const volatile void __iomem *addr) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 val = in_8(addr); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (EEH_POSSIBLE_ERROR(val, u8)) 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return eeh_check_failure(addr, val); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u16 eeh_readw(const volatile void __iomem *addr) 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 val = in_le16(addr); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (EEH_POSSIBLE_ERROR(val, u16)) 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return eeh_check_failure(addr, val); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u32 eeh_readl(const volatile void __iomem *addr) 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 val = in_le32(addr); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (EEH_POSSIBLE_ERROR(val, u32)) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return eeh_check_failure(addr, val); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2184cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt 2194cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidtstatic inline u64 eeh_readq(const volatile void __iomem *addr) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2214cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt u64 val = in_le64(addr); 2224cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt if (EEH_POSSIBLE_ERROR(val, u64)) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return eeh_check_failure(addr, val); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2274cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidtstatic inline u16 eeh_readw_be(const volatile void __iomem *addr) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2294cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt u16 val = in_be16(addr); 2304cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt if (EEH_POSSIBLE_ERROR(val, u16)) 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return eeh_check_failure(addr, val); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2344cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt 2354cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidtstatic inline u32 eeh_readl_be(const volatile void __iomem *addr) 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2374cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt u32 val = in_be32(addr); 2384cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt if (EEH_POSSIBLE_ERROR(val, u32)) 2394cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt return eeh_check_failure(addr, val); 2404cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt return val; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2424cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt 2434cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidtstatic inline u64 eeh_readq_be(const volatile void __iomem *addr) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 val = in_be64(addr); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (EEH_POSSIBLE_ERROR(val, u64)) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return eeh_check_failure(addr, val); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return val; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25168a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidtstatic inline void eeh_memcpy_fromio(void *dest, const 25268a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidt volatile void __iomem *src, 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long n) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25568a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidt _memcpy_fromio(dest, src, n); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Look for ffff's here at dest[n]. Assume that at least 4 bytes 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * were copied. Check all four bytes. 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26068a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidt if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32)) 26168a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidt eeh_check_failure(src, *((u32 *)(dest + n - 4))); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* in-string eeh macros */ 2654cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidtstatic inline void eeh_readsb(const volatile void __iomem *addr, void * buf, 2664cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt int ns) 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2684cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt _insb(addr, buf, ns); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8)) 2704cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt eeh_check_failure(addr, *(u8*)buf); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2734cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidtstatic inline void eeh_readsw(const volatile void __iomem *addr, void * buf, 2744cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt int ns) 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2764cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt _insw(addr, buf, ns); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16)) 2784cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt eeh_check_failure(addr, *(u16*)buf); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2814cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidtstatic inline void eeh_readsl(const volatile void __iomem *addr, void * buf, 2824cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt int nl) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2844cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt _insl(addr, buf, nl); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32)) 2864cb3cee03d558fd457cb58f56c80a2a09a66110cBenjamin Herrenschmidt eeh_check_failure(addr, *(u32*)buf); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2898b8da35804bb89eee23f9bcd5638e1f754bd4c91Benjamin Herrenschmidt#endif /* CONFIG_PPC64 */ 29088ced0314938814e1772b4d0d7ab20c52e4472b6Arnd Bergmann#endif /* __KERNEL__ */ 2918b8da35804bb89eee23f9bcd5638e1f754bd4c91Benjamin Herrenschmidt#endif /* _POWERPC_EEH_H */ 292