aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2006-01-25 20:00:33 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-23 17:35:11 -0500
commitef3be54777901e570185089f21fbe4498453f67e (patch)
tree6b03aacd9c9c99ec2160014e0d64415893f6f9f7
parentd29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccf (diff)
[PATCH] shpchp - bugfix: add missing serialization
Current shpchp driver might cause system panic because of lack of serialization. It can be reproduced very easily by the following operation. # cd /sys/bus/pci/slots/<slot#> # while true; do echo 0 > power ; echo 1 > power ; done & # while true; do echo 0 > power ; echo 1 > power ; done & This patch fixes this issue by changing shpchp to get appropreate semaphore for hot-plug operation. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c66
1 files changed, 24 insertions, 42 deletions
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 802c4c48d18..1a7003d4ba9 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -307,15 +307,10 @@ static int board_added(struct slot *p_slot)
307 __FUNCTION__, p_slot->device, 307 __FUNCTION__, p_slot->device,
308 ctrl->slot_device_offset, hp_slot); 308 ctrl->slot_device_offset, hp_slot);
309 309
310 /* Wait for exclusive access to hardware */
311 mutex_lock(&ctrl->crit_sect);
312
313 /* Power on slot without connecting to bus */ 310 /* Power on slot without connecting to bus */
314 rc = p_slot->hpc_ops->power_on_slot(p_slot); 311 rc = p_slot->hpc_ops->power_on_slot(p_slot);
315 if (rc) { 312 if (rc) {
316 err("%s: Failed to power on slot\n", __FUNCTION__); 313 err("%s: Failed to power on slot\n", __FUNCTION__);
317 /* Done with exclusive hardware access */
318 mutex_unlock(&ctrl->crit_sect);
319 return -1; 314 return -1;
320 } 315 }
321 316
@@ -325,14 +320,12 @@ static int board_added(struct slot *p_slot)
325 320
326 if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { 321 if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
327 err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); 322 err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
328 mutex_unlock(&ctrl->crit_sect);
329 return WRONG_BUS_FREQUENCY; 323 return WRONG_BUS_FREQUENCY;
330 } 324 }
331 325
332 /* turn on board, blink green LED, turn off Amber LED */ 326 /* turn on board, blink green LED, turn off Amber LED */
333 if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { 327 if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
334 err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); 328 err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
335 mutex_unlock(&ctrl->crit_sect);
336 return rc; 329 return rc;
337 } 330 }
338 } 331 }
@@ -346,16 +339,12 @@ static int board_added(struct slot *p_slot)
346 339
347 if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { 340 if (rc || adapter_speed == PCI_SPEED_UNKNOWN) {
348 err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); 341 err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__);
349 /* Done with exclusive hardware access */
350 mutex_unlock(&ctrl->crit_sect);
351 return WRONG_BUS_FREQUENCY; 342 return WRONG_BUS_FREQUENCY;
352 } 343 }
353 344
354 rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); 345 rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed);
355 if (rc || bus_speed == PCI_SPEED_UNKNOWN) { 346 if (rc || bus_speed == PCI_SPEED_UNKNOWN) {
356 err("%s: Can't get bus operation speed\n", __FUNCTION__); 347 err("%s: Can't get bus operation speed\n", __FUNCTION__);
357 /* Done with exclusive hardware access */
358 mutex_unlock(&ctrl->crit_sect);
359 return WRONG_BUS_FREQUENCY; 348 return WRONG_BUS_FREQUENCY;
360 } 349 }
361 350
@@ -365,9 +354,6 @@ static int board_added(struct slot *p_slot)
365 max_bus_speed = bus_speed; 354 max_bus_speed = bus_speed;
366 } 355 }
367 356
368 /* Done with exclusive hardware access */
369 mutex_unlock(&ctrl->crit_sect);
370
371 if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { 357 if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) {
372 err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); 358 err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__);
373 pi = 1; 359 pi = 1;
@@ -744,29 +730,25 @@ static void interrupt_event_handler(struct controller *ctrl)
744int shpchp_enable_slot (struct slot *p_slot) 730int shpchp_enable_slot (struct slot *p_slot)
745{ 731{
746 u8 getstatus = 0; 732 u8 getstatus = 0;
747 int rc; 733 int rc, retval = -ENODEV;
748 734
749 /* Check to see if (latch closed, card present, power off) */ 735 /* Check to see if (latch closed, card present, power off) */
750 mutex_lock(&p_slot->ctrl->crit_sect); 736 mutex_lock(&p_slot->ctrl->crit_sect);
751 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 737 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
752 if (rc || !getstatus) { 738 if (rc || !getstatus) {
753 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); 739 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
754 mutex_unlock(&p_slot->ctrl->crit_sect); 740 goto out;
755 return -ENODEV;
756 } 741 }
757 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 742 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
758 if (rc || getstatus) { 743 if (rc || getstatus) {
759 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); 744 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
760 mutex_unlock(&p_slot->ctrl->crit_sect); 745 goto out;
761 return -ENODEV;
762 } 746 }
763 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 747 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
764 if (rc || getstatus) { 748 if (rc || getstatus) {
765 info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); 749 info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
766 mutex_unlock(&p_slot->ctrl->crit_sect); 750 goto out;
767 return -ENODEV;
768 } 751 }
769 mutex_unlock(&p_slot->ctrl->crit_sect);
770 752
771 p_slot->is_a_board = 1; 753 p_slot->is_a_board = 1;
772 754
@@ -781,27 +763,29 @@ int shpchp_enable_slot (struct slot *p_slot)
781 && p_slot->ctrl->num_slots == 1) { 763 && p_slot->ctrl->num_slots == 1) {
782 /* handle amd pogo errata; this must be done before enable */ 764 /* handle amd pogo errata; this must be done before enable */
783 amd_pogo_errata_save_misc_reg(p_slot); 765 amd_pogo_errata_save_misc_reg(p_slot);
784 rc = board_added(p_slot); 766 retval = board_added(p_slot);
785 /* handle amd pogo errata; this must be done after enable */ 767 /* handle amd pogo errata; this must be done after enable */
786 amd_pogo_errata_restore_misc_reg(p_slot); 768 amd_pogo_errata_restore_misc_reg(p_slot);
787 } else 769 } else
788 rc = board_added(p_slot); 770 retval = board_added(p_slot);
789 771
790 if (rc) { 772 if (retval) {
791 p_slot->hpc_ops->get_adapter_status(p_slot, 773 p_slot->hpc_ops->get_adapter_status(p_slot,
792 &(p_slot->presence_save)); 774 &(p_slot->presence_save));
793 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 775 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
794 } 776 }
795 777
796 update_slot_info(p_slot); 778 update_slot_info(p_slot);
797 return rc; 779 out:
780 mutex_unlock(&p_slot->ctrl->crit_sect);
781 return retval;
798} 782}
799 783
800 784
801int shpchp_disable_slot (struct slot *p_slot) 785int shpchp_disable_slot (struct slot *p_slot)
802{ 786{
803 u8 getstatus = 0; 787 u8 getstatus = 0;
804 int ret = 0; 788 int rc, retval = -ENODEV;
805 789
806 if (!p_slot->ctrl) 790 if (!p_slot->ctrl)
807 return -ENODEV; 791 return -ENODEV;
@@ -809,28 +793,26 @@ int shpchp_disable_slot (struct slot *p_slot)
809 /* Check to see if (latch closed, card present, power on) */ 793 /* Check to see if (latch closed, card present, power on) */
810 mutex_lock(&p_slot->ctrl->crit_sect); 794 mutex_lock(&p_slot->ctrl->crit_sect);
811 795
812 ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); 796 rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
813 if (ret || !getstatus) { 797 if (rc || !getstatus) {
814 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); 798 info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
815 mutex_unlock(&p_slot->ctrl->crit_sect); 799 goto out;
816 return -ENODEV;
817 } 800 }
818 ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 801 rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
819 if (ret || getstatus) { 802 if (rc || getstatus) {
820 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); 803 info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
821 mutex_unlock(&p_slot->ctrl->crit_sect); 804 goto out;
822 return -ENODEV;
823 } 805 }
824 ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); 806 rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
825 if (ret || !getstatus) { 807 if (rc || !getstatus) {
826 info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); 808 info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
827 mutex_unlock(&p_slot->ctrl->crit_sect); 809 goto out;
828 return -ENODEV;
829 } 810 }
830 mutex_unlock(&p_slot->ctrl->crit_sect);
831 811
832 ret = remove_board(p_slot); 812 retval = remove_board(p_slot);
833 update_slot_info(p_slot); 813 update_slot_info(p_slot);
834 return ret; 814 out:
815 mutex_unlock(&p_slot->ctrl->crit_sect);
816 return retval;
835} 817}
836 818