diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 63e23062e982..b58ed05078b8 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -100,6 +100,9 @@ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; | |||
100 | static DEFINE_SPINLOCK(slot_errbuf_lock); | 100 | static DEFINE_SPINLOCK(slot_errbuf_lock); |
101 | static int eeh_error_buf_size; | 101 | static int eeh_error_buf_size; |
102 | 102 | ||
103 | #define EEH_PCI_REGS_LOG_LEN 4096 | ||
104 | static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN]; | ||
105 | |||
103 | /* System monitoring statistics */ | 106 | /* System monitoring statistics */ |
104 | static unsigned long no_device; | 107 | static unsigned long no_device; |
105 | static unsigned long no_dn; | 108 | static unsigned long no_dn; |
@@ -115,7 +118,8 @@ static unsigned long slot_resets; | |||
115 | /* --------------------------------------------------------------- */ | 118 | /* --------------------------------------------------------------- */ |
116 | /* Below lies the EEH event infrastructure */ | 119 | /* Below lies the EEH event infrastructure */ |
117 | 120 | ||
118 | void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | 121 | static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, |
122 | char *driver_log, size_t loglen) | ||
119 | { | 123 | { |
120 | int config_addr; | 124 | int config_addr; |
121 | unsigned long flags; | 125 | unsigned long flags; |
@@ -133,7 +137,8 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | |||
133 | rc = rtas_call(ibm_slot_error_detail, | 137 | rc = rtas_call(ibm_slot_error_detail, |
134 | 8, 1, NULL, config_addr, | 138 | 8, 1, NULL, config_addr, |
135 | BUID_HI(pdn->phb->buid), | 139 | BUID_HI(pdn->phb->buid), |
136 | BUID_LO(pdn->phb->buid), NULL, 0, | 140 | BUID_LO(pdn->phb->buid), |
141 | virt_to_phys(driver_log), loglen, | ||
137 | virt_to_phys(slot_errbuf), | 142 | virt_to_phys(slot_errbuf), |
138 | eeh_error_buf_size, | 143 | eeh_error_buf_size, |
139 | severity); | 144 | severity); |
@@ -144,6 +149,40 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity) | |||
144 | } | 149 | } |
145 | 150 | ||
146 | /** | 151 | /** |
152 | * gather_pci_data - copy assorted PCI config space registers to buff | ||
153 | * @pdn: device to report data for | ||
154 | * @buf: point to buffer in which to log | ||
155 | * @len: amount of room in buffer | ||
156 | * | ||
157 | * This routine captures assorted PCI configuration space data, | ||
158 | * and puts them into a buffer for RTAS error logging. | ||
159 | */ | ||
160 | static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | ||
161 | { | ||
162 | u32 cfg; | ||
163 | int n = 0; | ||
164 | |||
165 | n += scnprintf(buf+n, len-n, "%s\n", pdn->node->name); | ||
166 | rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg); | ||
167 | n += scnprintf(buf+n, len-n, "dev/vend:%x\n", cfg); | ||
168 | rtas_read_config(pdn, PCI_COMMAND, 4, &cfg); | ||
169 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); | ||
170 | |||
171 | return n; | ||
172 | } | ||
173 | |||
174 | void eeh_slot_error_detail(struct pci_dn *pdn, int severity) | ||
175 | { | ||
176 | size_t loglen = 0; | ||
177 | memset(pci_regs_buf, 0, EEH_PCI_REGS_LOG_LEN); | ||
178 | |||
179 | rtas_pci_enable(pdn, EEH_THAW_MMIO); | ||
180 | loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN); | ||
181 | |||
182 | rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen); | ||
183 | } | ||
184 | |||
185 | /** | ||
147 | * read_slot_reset_state - Read the reset state of a device node's slot | 186 | * read_slot_reset_state - Read the reset state of a device node's slot |
148 | * @dn: device node to read | 187 | * @dn: device node to read |
149 | * @rets: array to return results in | 188 | * @rets: array to return results in |