aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJason Uhlenkott <juhlenko@akamai.com>2007-07-19 04:50:16 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:55 -0400
commit654ede200fe028373852bbca387ab4834ddb7228 (patch)
treed82908a5559e0fc899234220fb4a441bdb103055 /drivers
parentb113a3f7e85d7f97c8383a88a5bc7c2ea8daeb2f (diff)
drivers/edac: mod race fix i82875p
If ERRSTS indicates that there's no error then we don't need to bother reading the other registers. In addition to making the common case faster, this actually fixes a small race where we don't see an error but we clear the error bits anyway, potentially wiping away info on an error that happened in the interim (or where a CE arrives between the first and second read of ERRSTS, causing us to falsely claim "UE overwrote CE"). Signed-off-by: Jason Uhlenkott <juhlenko@akamai.com> Signed-off-by: Douglas Thompson <dougthompson@xmission.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/edac/i82875p_edac.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index c9aed70fec8e..089ec397ca6a 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -198,27 +198,28 @@ static void i82875p_get_error_info(struct mem_ctl_info *mci,
198 * overwritten by UE. 198 * overwritten by UE.
199 */ 199 */
200 pci_read_config_word(pdev, I82875P_ERRSTS, &info->errsts); 200 pci_read_config_word(pdev, I82875P_ERRSTS, &info->errsts);
201
202 if (!(info->errsts & 0x0081))
203 return;
204
201 pci_read_config_dword(pdev, I82875P_EAP, &info->eap); 205 pci_read_config_dword(pdev, I82875P_EAP, &info->eap);
202 pci_read_config_byte(pdev, I82875P_DES, &info->des); 206 pci_read_config_byte(pdev, I82875P_DES, &info->des);
203 pci_read_config_byte(pdev, I82875P_DERRSYN, &info->derrsyn); 207 pci_read_config_byte(pdev, I82875P_DERRSYN, &info->derrsyn);
204 pci_read_config_word(pdev, I82875P_ERRSTS, &info->errsts2); 208 pci_read_config_word(pdev, I82875P_ERRSTS, &info->errsts2);
205 209
206 pci_write_bits16(pdev, I82875P_ERRSTS, 0x0081, 0x0081);
207
208 /* 210 /*
209 * If the error is the same then we can for both reads then 211 * If the error is the same then we can for both reads then
210 * the first set of reads is valid. If there is a change then 212 * the first set of reads is valid. If there is a change then
211 * there is a CE no info and the second set of reads is valid 213 * there is a CE no info and the second set of reads is valid
212 * and should be UE info. 214 * and should be UE info.
213 */ 215 */
214 if (!(info->errsts2 & 0x0081))
215 return;
216
217 if ((info->errsts ^ info->errsts2) & 0x0081) { 216 if ((info->errsts ^ info->errsts2) & 0x0081) {
218 pci_read_config_dword(pdev, I82875P_EAP, &info->eap); 217 pci_read_config_dword(pdev, I82875P_EAP, &info->eap);
219 pci_read_config_byte(pdev, I82875P_DES, &info->des); 218 pci_read_config_byte(pdev, I82875P_DES, &info->des);
220 pci_read_config_byte(pdev, I82875P_DERRSYN, &info->derrsyn); 219 pci_read_config_byte(pdev, I82875P_DERRSYN, &info->derrsyn);
221 } 220 }
221
222 pci_write_bits16(pdev, I82875P_ERRSTS, 0x0081, 0x0081);
222} 223}
223 224
224static int i82875p_process_error_info(struct mem_ctl_info *mci, 225static int i82875p_process_error_info(struct mem_ctl_info *mci,
@@ -229,7 +230,7 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci,
229 230
230 multi_chan = mci->csrows[0].nr_channels - 1; 231 multi_chan = mci->csrows[0].nr_channels - 1;
231 232
232 if (!(info->errsts2 & 0x0081)) 233 if (!(info->errsts & 0x0081))
233 return 0; 234 return 0;
234 235
235 if (!handle_errors) 236 if (!handle_errors)