aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/eeh_pe.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh_pe.c')
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pe.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c
index 30b8d96ed54d..9d35543736ed 100644
--- a/arch/powerpc/platforms/pseries/eeh_pe.c
+++ b/arch/powerpc/platforms/pseries/eeh_pe.c
@@ -99,8 +99,6 @@ static struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb)
99{ 99{
100 struct eeh_pe *pe; 100 struct eeh_pe *pe;
101 101
102 eeh_lock();
103
104 list_for_each_entry(pe, &eeh_phb_pe, child) { 102 list_for_each_entry(pe, &eeh_phb_pe, child) {
105 /* 103 /*
106 * Actually, we needn't check the type since 104 * Actually, we needn't check the type since
@@ -114,8 +112,6 @@ static struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb)
114 } 112 }
115 } 113 }
116 114
117 eeh_unlock();
118
119 return NULL; 115 return NULL;
120} 116}
121 117
@@ -192,14 +188,21 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root,
192 return NULL; 188 return NULL;
193 } 189 }
194 190
191 eeh_lock();
192
195 /* Traverse root PE */ 193 /* Traverse root PE */
196 for (pe = root; pe; pe = eeh_pe_next(pe, root)) { 194 for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
197 eeh_pe_for_each_dev(pe, edev) { 195 eeh_pe_for_each_dev(pe, edev) {
198 ret = fn(edev, flag); 196 ret = fn(edev, flag);
199 if (ret) return ret; 197 if (ret) {
198 eeh_unlock();
199 return ret;
200 }
200 } 201 }
201 } 202 }
202 203
204 eeh_unlock();
205
203 return NULL; 206 return NULL;
204} 207}
205 208
@@ -251,9 +254,7 @@ static struct eeh_pe *eeh_pe_get(struct eeh_dev *edev)
251 struct eeh_pe *root = eeh_phb_pe_get(edev->phb); 254 struct eeh_pe *root = eeh_phb_pe_get(edev->phb);
252 struct eeh_pe *pe; 255 struct eeh_pe *pe;
253 256
254 eeh_lock();
255 pe = eeh_pe_traverse(root, __eeh_pe_get, edev); 257 pe = eeh_pe_traverse(root, __eeh_pe_get, edev);
256 eeh_unlock();
257 258
258 return pe; 259 return pe;
259} 260}
@@ -307,6 +308,8 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
307{ 308{
308 struct eeh_pe *pe, *parent; 309 struct eeh_pe *pe, *parent;
309 310
311 eeh_lock();
312
310 /* 313 /*
311 * Search the PE has been existing or not according 314 * Search the PE has been existing or not according
312 * to the PE address. If that has been existing, the 315 * to the PE address. If that has been existing, the
@@ -316,6 +319,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
316 pe = eeh_pe_get(edev); 319 pe = eeh_pe_get(edev);
317 if (pe && !(pe->type & EEH_PE_INVALID)) { 320 if (pe && !(pe->type & EEH_PE_INVALID)) {
318 if (!edev->pe_config_addr) { 321 if (!edev->pe_config_addr) {
322 eeh_unlock();
319 pr_err("%s: PE with addr 0x%x already exists\n", 323 pr_err("%s: PE with addr 0x%x already exists\n",
320 __func__, edev->config_addr); 324 __func__, edev->config_addr);
321 return -EEXIST; 325 return -EEXIST;
@@ -327,6 +331,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
327 331
328 /* Put the edev to PE */ 332 /* Put the edev to PE */
329 list_add_tail(&edev->list, &pe->edevs); 333 list_add_tail(&edev->list, &pe->edevs);
334 eeh_unlock();
330 pr_debug("EEH: Add %s to Bus PE#%x\n", 335 pr_debug("EEH: Add %s to Bus PE#%x\n",
331 edev->dn->full_name, pe->addr); 336 edev->dn->full_name, pe->addr);
332 337
@@ -345,6 +350,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
345 parent->type &= ~EEH_PE_INVALID; 350 parent->type &= ~EEH_PE_INVALID;
346 parent = parent->parent; 351 parent = parent->parent;
347 } 352 }
353 eeh_unlock();
348 pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n", 354 pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
349 edev->dn->full_name, pe->addr, pe->parent->addr); 355 edev->dn->full_name, pe->addr, pe->parent->addr);
350 356
@@ -354,6 +360,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
354 /* Create a new EEH PE */ 360 /* Create a new EEH PE */
355 pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE); 361 pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
356 if (!pe) { 362 if (!pe) {
363 eeh_unlock();
357 pr_err("%s: out of memory!\n", __func__); 364 pr_err("%s: out of memory!\n", __func__);
358 return -ENOMEM; 365 return -ENOMEM;
359 } 366 }
@@ -370,6 +377,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
370 if (!parent) { 377 if (!parent) {
371 parent = eeh_phb_pe_get(edev->phb); 378 parent = eeh_phb_pe_get(edev->phb);
372 if (!parent) { 379 if (!parent) {
380 eeh_unlock();
373 pr_err("%s: No PHB PE is found (PHB Domain=%d)\n", 381 pr_err("%s: No PHB PE is found (PHB Domain=%d)\n",
374 __func__, edev->phb->global_number); 382 __func__, edev->phb->global_number);
375 edev->pe = NULL; 383 edev->pe = NULL;
@@ -386,6 +394,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
386 list_add_tail(&pe->child, &parent->child_list); 394 list_add_tail(&pe->child, &parent->child_list);
387 list_add_tail(&edev->list, &pe->edevs); 395 list_add_tail(&edev->list, &pe->edevs);
388 edev->pe = pe; 396 edev->pe = pe;
397 eeh_unlock();
389 pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n", 398 pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
390 edev->dn->full_name, pe->addr, pe->parent->addr); 399 edev->dn->full_name, pe->addr, pe->parent->addr);
391 400
@@ -413,6 +422,8 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
413 return -EEXIST; 422 return -EEXIST;
414 } 423 }
415 424
425 eeh_lock();
426
416 /* Remove the EEH device */ 427 /* Remove the EEH device */
417 pe = edev->pe; 428 pe = edev->pe;
418 edev->pe = NULL; 429 edev->pe = NULL;
@@ -457,6 +468,8 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
457 pe = parent; 468 pe = parent;
458 } 469 }
459 470
471 eeh_unlock();
472
460 return 0; 473 return 0;
461} 474}
462 475
@@ -502,7 +515,9 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
502 */ 515 */
503void eeh_pe_state_mark(struct eeh_pe *pe, int state) 516void eeh_pe_state_mark(struct eeh_pe *pe, int state)
504{ 517{
518 eeh_lock();
505 eeh_pe_traverse(pe, __eeh_pe_state_mark, &state); 519 eeh_pe_traverse(pe, __eeh_pe_state_mark, &state);
520 eeh_unlock();
506} 521}
507 522
508/** 523/**
@@ -536,7 +551,9 @@ static void *__eeh_pe_state_clear(void *data, void *flag)
536 */ 551 */
537void eeh_pe_state_clear(struct eeh_pe *pe, int state) 552void eeh_pe_state_clear(struct eeh_pe *pe, int state)
538{ 553{
554 eeh_lock();
539 eeh_pe_traverse(pe, __eeh_pe_state_clear, &state); 555 eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
556 eeh_unlock();
540} 557}
541 558
542/** 559/**
@@ -598,6 +615,10 @@ static void *eeh_restore_one_device_bars(void *data, void *flag)
598 */ 615 */
599void eeh_pe_restore_bars(struct eeh_pe *pe) 616void eeh_pe_restore_bars(struct eeh_pe *pe)
600{ 617{
618 /*
619 * We needn't take the EEH lock since eeh_pe_dev_traverse()
620 * will take that.
621 */
601 eeh_pe_dev_traverse(pe, eeh_restore_one_device_bars, NULL); 622 eeh_pe_dev_traverse(pe, eeh_restore_one_device_bars, NULL);
602} 623}
603 624
@@ -617,6 +638,8 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
617 struct eeh_dev *edev; 638 struct eeh_dev *edev;
618 struct pci_dev *pdev; 639 struct pci_dev *pdev;
619 640
641 eeh_lock();
642
620 if (pe->type & EEH_PE_PHB) { 643 if (pe->type & EEH_PE_PHB) {
621 bus = pe->phb->bus; 644 bus = pe->phb->bus;
622 } else if (pe->type & EEH_PE_BUS) { 645 } else if (pe->type & EEH_PE_BUS) {
@@ -626,5 +649,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
626 bus = pdev->bus; 649 bus = pdev->bus;
627 } 650 }
628 651
652 eeh_unlock();
653
629 return bus; 654 return bus;
630} 655}