aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2006-09-22 13:17:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-10-18 14:36:10 -0400
commitdd5619cb4407e830a8921a93c949be37c81105b5 (patch)
treef726db26b6019e6f741dfb146e3d37eca9198cf4
parent49ed2b4963cd00993eab518b820a6700f94f222d (diff)
pciehp - add missing locking
This patch fixes the problem that system will panic if multiple power on/off operations are issued to the same slot in parallel. This problem can be easily reproduced by commands below. # while true; do echo 1 > power; echo 0 > power; done & # while true; do echo 1 > power; echo 0 > power; done & The cause is lack of locking for enable/disable operations. This patch fixes this problem. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_core.c6
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c54
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c2
4 files changed, 33 insertions, 30 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index b71f774aca16..30f021c55fe5 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -92,6 +92,7 @@ struct php_ctlr_state_s {
92struct controller { 92struct controller {
93 struct controller *next; 93 struct controller *next;
94 struct mutex crit_sect; /* critical section mutex */ 94 struct mutex crit_sect; /* critical section mutex */
95 struct mutex ctrl_lock; /* controller lock */
95 struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ 96 struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
96 int num_slots; /* Number of slots on ctlr */ 97 int num_slots; /* Number of slots on ctlr */
97 int slot_num_inc; /* 1 or -1 */ 98 int slot_num_inc; /* 1 or -1 */
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index c67b7c3f1ddf..f93e81e2d2c7 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -448,7 +448,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
448 } 448 }
449 449
450 /* Wait for exclusive access to hardware */ 450 /* Wait for exclusive access to hardware */
451 mutex_lock(&ctrl->crit_sect); 451 mutex_lock(&ctrl->ctrl_lock);
452 452
453 t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ 453 t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
454 454
@@ -456,7 +456,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
456 rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ 456 rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
457 if (rc) { 457 if (rc) {
458 /* Done with exclusive hardware access */ 458 /* Done with exclusive hardware access */
459 mutex_unlock(&ctrl->crit_sect); 459 mutex_unlock(&ctrl->ctrl_lock);
460 goto err_out_free_ctrl_slot; 460 goto err_out_free_ctrl_slot;
461 } else 461 } else
462 /* Wait for the command to complete */ 462 /* Wait for the command to complete */
@@ -464,7 +464,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
464 } 464 }
465 465
466 /* Done with exclusive hardware access */ 466 /* Done with exclusive hardware access */
467 mutex_unlock(&ctrl->crit_sect); 467 mutex_unlock(&ctrl->ctrl_lock);
468 468
469 return 0; 469 return 0;
470 470
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index f602b042adcf..c206a3d63b63 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -234,13 +234,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
234static void set_slot_off(struct controller *ctrl, struct slot * pslot) 234static void set_slot_off(struct controller *ctrl, struct slot * pslot)
235{ 235{
236 /* Wait for exclusive access to hardware */ 236 /* Wait for exclusive access to hardware */
237 mutex_lock(&ctrl->crit_sect); 237 mutex_lock(&ctrl->ctrl_lock);
238 238
239 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ 239 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
240 if (POWER_CTRL(ctrl->ctrlcap)) { 240 if (POWER_CTRL(ctrl->ctrlcap)) {
241 if (pslot->hpc_ops->power_off_slot(pslot)) { 241 if (pslot->hpc_ops->power_off_slot(pslot)) {
242 err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); 242 err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
243 mutex_unlock(&ctrl->crit_sect); 243 mutex_unlock(&ctrl->ctrl_lock);
244 return; 244 return;
245 } 245 }
246 wait_for_ctrl_irq (ctrl); 246 wait_for_ctrl_irq (ctrl);
@@ -254,14 +254,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
254 if (ATTN_LED(ctrl->ctrlcap)) { 254 if (ATTN_LED(ctrl->ctrlcap)) {
255 if (pslot->hpc_ops->set_attention_status(pslot, 1)) { 255 if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
256 err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); 256 err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
257 mutex_unlock(&ctrl->crit_sect); 257 mutex_unlock(&ctrl->ctrl_lock);
258 return; 258 return;
259 } 259 }
260 wait_for_ctrl_irq (ctrl); 260 wait_for_ctrl_irq (ctrl);
261 } 261 }
262 262
263 /* Done with exclusive hardware access */ 263 /* Done with exclusive hardware access */
264 mutex_unlock(&ctrl->crit_sect); 264 mutex_unlock(&ctrl->ctrl_lock);
265} 265}
266 266
267/** 267/**
@@ -284,13 +284,13 @@ static int board_added(struct slot *p_slot)
284 ctrl->slot_device_offset, hp_slot); 284 ctrl->slot_device_offset, hp_slot);
285 285
286 /* Wait for exclusive access to hardware */ 286 /* Wait for exclusive access to hardware */
287 mutex_lock(&ctrl->crit_sect); 287 mutex_lock(&ctrl->ctrl_lock);
288 288
289 if (POWER_CTRL(ctrl->ctrlcap)) { 289 if (POWER_CTRL(ctrl->ctrlcap)) {
290 /* Power on slot */ 290 /* Power on slot */
291 rc = p_slot->hpc_ops->power_on_slot(p_slot); 291 rc = p_slot->hpc_ops->power_on_slot(p_slot);
292 if (rc) { 292 if (rc) {
293 mutex_unlock(&ctrl->crit_sect); 293 mutex_unlock(&ctrl->ctrl_lock);
294 return -1; 294 return -1;
295 } 295 }
296 296
@@ -306,7 +306,7 @@ static int board_added(struct slot *p_slot)
306 } 306 }
307 307
308 /* Done with exclusive hardware access */ 308 /* Done with exclusive hardware access */
309 mutex_unlock(&ctrl->crit_sect); 309 mutex_unlock(&ctrl->ctrl_lock);
310 310
311 /* Wait for ~1 second */ 311 /* Wait for ~1 second */
312 wait_for_ctrl_irq (ctrl); 312 wait_for_ctrl_irq (ctrl);
@@ -340,7 +340,7 @@ static int board_added(struct slot *p_slot)
340 pci_fixup_device(pci_fixup_final, ctrl->pci_dev); 340 pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
341 if (PWR_LED(ctrl->ctrlcap)) { 341 if (PWR_LED(ctrl->ctrlcap)) {
342 /* Wait for exclusive access to hardware */ 342 /* Wait for exclusive access to hardware */
343 mutex_lock(&ctrl->crit_sect); 343 mutex_lock(&ctrl->ctrl_lock);
344 344
345 p_slot->hpc_ops->green_led_on(p_slot); 345 p_slot->hpc_ops->green_led_on(p_slot);
346 346
@@ -348,7 +348,7 @@ static int board_added(struct slot *p_slot)
348 wait_for_ctrl_irq (ctrl); 348 wait_for_ctrl_irq (ctrl);
349 349
350 /* Done with exclusive hardware access */ 350 /* Done with exclusive hardware access */
351 mutex_unlock(&ctrl->crit_sect); 351 mutex_unlock(&ctrl->ctrl_lock);
352 } 352 }
353 return 0; 353 return 0;
354 354
@@ -380,14 +380,14 @@ static int remove_board(struct slot *p_slot)
380 dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); 380 dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
381 381
382 /* Wait for exclusive access to hardware */ 382 /* Wait for exclusive access to hardware */
383 mutex_lock(&ctrl->crit_sect); 383 mutex_lock(&ctrl->ctrl_lock);
384 384
385 if (POWER_CTRL(ctrl->ctrlcap)) { 385 if (POWER_CTRL(ctrl->ctrlcap)) {
386 /* power off slot */ 386 /* power off slot */
387 rc = p_slot->hpc_ops->power_off_slot(p_slot); 387 rc = p_slot->hpc_ops->power_off_slot(p_slot);
388 if (rc) { 388 if (rc) {
389 err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); 389 err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
390 mutex_unlock(&ctrl->crit_sect); 390 mutex_unlock(&ctrl->ctrl_lock);
391 return rc; 391 return rc;
392 } 392 }
393 /* Wait for the command to complete */ 393 /* Wait for the command to complete */
@@ -403,7 +403,7 @@ static int remove_board(struct slot *p_slot)
403 } 403 }
404 404
405 /* Done with exclusive hardware access */ 405 /* Done with exclusive hardware access */
406 mutex_unlock(&ctrl->crit_sect); 406 mutex_unlock(&ctrl->ctrl_lock);
407 407
408 return 0; 408 return 0;
409} 409}
@@ -450,7 +450,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
450 450
451 if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { 451 if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
452 /* Wait for exclusive access to hardware */ 452 /* Wait for exclusive access to hardware */
453 mutex_lock(&p_slot->ctrl->crit_sect); 453 mutex_lock(&p_slot->ctrl->ctrl_lock);
454 454
455 p_slot->hpc_ops->green_led_off(p_slot); 455 p_slot->hpc_ops->green_led_off(p_slot);
456 456
@@ -458,7 +458,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
458 wait_for_ctrl_irq (p_slot->ctrl); 458 wait_for_ctrl_irq (p_slot->ctrl);
459 459
460 /* Done with exclusive hardware access */ 460 /* Done with exclusive hardware access */
461 mutex_unlock(&p_slot->ctrl->crit_sect); 461 mutex_unlock(&p_slot->ctrl->ctrl_lock);
462 } 462 }
463 p_slot->state = STATIC_STATE; 463 p_slot->state = STATIC_STATE;
464 } 464 }
@@ -500,7 +500,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
500 500
501 if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { 501 if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
502 /* Wait for exclusive access to hardware */ 502 /* Wait for exclusive access to hardware */
503 mutex_lock(&p_slot->ctrl->crit_sect); 503 mutex_lock(&p_slot->ctrl->ctrl_lock);
504 504
505 p_slot->hpc_ops->green_led_off(p_slot); 505 p_slot->hpc_ops->green_led_off(p_slot);
506 506
@@ -508,7 +508,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
508 wait_for_ctrl_irq (p_slot->ctrl); 508 wait_for_ctrl_irq (p_slot->ctrl);
509 509
510 /* Done with exclusive hardware access */ 510 /* Done with exclusive hardware access */
511 mutex_unlock(&p_slot->ctrl->crit_sect); 511 mutex_unlock(&p_slot->ctrl->ctrl_lock);
512 } 512 }
513 p_slot->state = STATIC_STATE; 513 p_slot->state = STATIC_STATE;
514 } 514 }
@@ -621,7 +621,7 @@ static void interrupt_event_handler(struct controller *ctrl)
621 switch (p_slot->state) { 621 switch (p_slot->state) {
622 case BLINKINGOFF_STATE: 622 case BLINKINGOFF_STATE:
623 /* Wait for exclusive access to hardware */ 623 /* Wait for exclusive access to hardware */
624 mutex_lock(&ctrl->crit_sect); 624 mutex_lock(&ctrl->ctrl_lock);
625 625
626 if (PWR_LED(ctrl->ctrlcap)) { 626 if (PWR_LED(ctrl->ctrlcap)) {
627 p_slot->hpc_ops->green_led_on(p_slot); 627 p_slot->hpc_ops->green_led_on(p_slot);
@@ -635,11 +635,11 @@ static void interrupt_event_handler(struct controller *ctrl)
635 wait_for_ctrl_irq (ctrl); 635 wait_for_ctrl_irq (ctrl);
636 } 636 }
637 /* Done with exclusive hardware access */ 637 /* Done with exclusive hardware access */
638 mutex_unlock(&ctrl->crit_sect); 638 mutex_unlock(&ctrl->ctrl_lock);
639 break; 639 break;
640 case BLINKINGON_STATE: 640 case BLINKINGON_STATE:
641 /* Wait for exclusive access to hardware */ 641 /* Wait for exclusive access to hardware */
642 mutex_lock(&ctrl->crit_sect); 642 mutex_lock(&ctrl->ctrl_lock);
643 643
644 if (PWR_LED(ctrl->ctrlcap)) { 644 if (PWR_LED(ctrl->ctrlcap)) {
645 p_slot->hpc_ops->green_led_off(p_slot); 645 p_slot->hpc_ops->green_led_off(p_slot);
@@ -652,7 +652,7 @@ static void interrupt_event_handler(struct controller *ctrl)
652 wait_for_ctrl_irq (ctrl); 652 wait_for_ctrl_irq (ctrl);
653 } 653 }
654 /* Done with exclusive hardware access */ 654 /* Done with exclusive hardware access */
655 mutex_unlock(&ctrl->crit_sect); 655 mutex_unlock(&ctrl->ctrl_lock);
656 656
657 break; 657 break;
658 default: 658 default:
@@ -681,7 +681,7 @@ static void interrupt_event_handler(struct controller *ctrl)
681 } 681 }
682 682
683 /* Wait for exclusive access to hardware */ 683 /* Wait for exclusive access to hardware */
684 mutex_lock(&ctrl->crit_sect); 684 mutex_lock(&ctrl->ctrl_lock);
685 685
686 /* blink green LED and turn off amber */ 686 /* blink green LED and turn off amber */
687 if (PWR_LED(ctrl->ctrlcap)) { 687 if (PWR_LED(ctrl->ctrlcap)) {
@@ -698,7 +698,7 @@ static void interrupt_event_handler(struct controller *ctrl)
698 } 698 }
699 699
700 /* Done with exclusive hardware access */ 700 /* Done with exclusive hardware access */
701 mutex_unlock(&ctrl->crit_sect); 701 mutex_unlock(&ctrl->ctrl_lock);
702 702
703 init_timer(&p_slot->task_event); 703 init_timer(&p_slot->task_event);
704 p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ 704 p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
@@ -713,7 +713,7 @@ static void interrupt_event_handler(struct controller *ctrl)
713 if (POWER_CTRL(ctrl->ctrlcap)) { 713 if (POWER_CTRL(ctrl->ctrlcap)) {
714 dbg("power fault\n"); 714 dbg("power fault\n");
715 /* Wait for exclusive access to hardware */ 715 /* Wait for exclusive access to hardware */
716 mutex_lock(&ctrl->crit_sect); 716 mutex_lock(&ctrl->ctrl_lock);
717 717
718 if (ATTN_LED(ctrl->ctrlcap)) { 718 if (ATTN_LED(ctrl->ctrlcap)) {
719 p_slot->hpc_ops->set_attention_status(p_slot, 1); 719 p_slot->hpc_ops->set_attention_status(p_slot, 1);
@@ -726,7 +726,7 @@ static void interrupt_event_handler(struct controller *ctrl)
726 } 726 }
727 727
728 /* Done with exclusive hardware access */ 728 /* Done with exclusive hardware access */
729 mutex_unlock(&ctrl->crit_sect); 729 mutex_unlock(&ctrl->ctrl_lock);
730 } 730 }
731 } 731 }
732 /***********SURPRISE REMOVAL********************/ 732 /***********SURPRISE REMOVAL********************/
@@ -789,7 +789,6 @@ int pciehp_enable_slot(struct slot *p_slot)
789 return -EINVAL; 789 return -EINVAL;
790 } 790 }
791 } 791 }
792 mutex_unlock(&p_slot->ctrl->crit_sect);
793 792
794 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 793 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
795 794
@@ -801,6 +800,7 @@ int pciehp_enable_slot(struct slot *p_slot)
801 if (p_slot) 800 if (p_slot)
802 update_slot_info(p_slot); 801 update_slot_info(p_slot);
803 802
803 mutex_unlock(&p_slot->ctrl->crit_sect);
804 return rc; 804 return rc;
805} 805}
806 806
@@ -846,10 +846,10 @@ int pciehp_disable_slot(struct slot *p_slot)
846 } 846 }
847 } 847 }
848 848
849 mutex_unlock(&p_slot->ctrl->crit_sect);
850
851 ret = remove_board(p_slot); 849 ret = remove_board(p_slot);
852 update_slot_info(p_slot); 850 update_slot_info(p_slot);
851
852 mutex_unlock(&p_slot->ctrl->crit_sect);
853 return ret; 853 return ret;
854} 854}
855 855
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 703a64a39fe8..1c551c697c35 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -1402,6 +1402,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
1402 pdev->subsystem_vendor, pdev->subsystem_device); 1402 pdev->subsystem_vendor, pdev->subsystem_device);
1403 1403
1404 mutex_init(&ctrl->crit_sect); 1404 mutex_init(&ctrl->crit_sect);
1405 mutex_init(&ctrl->ctrl_lock);
1406
1405 /* setup wait queue */ 1407 /* setup wait queue */
1406 init_waitqueue_head(&ctrl->queue); 1408 init_waitqueue_head(&ctrl->queue);
1407 1409