diff options
author | Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> | 2007-05-31 12:43:34 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-11 19:02:08 -0400 |
commit | f477836457730a2b925f625023ec4e5bf11015be (patch) | |
tree | 178c8e7efd7a3f8f0220d3da537d649f4cb1278f /drivers/pci | |
parent | adf809d01043d8808e47db2d35fc07b53062884e (diff) |
PCI: hotplug: pciehp: Fix possible race condition in writing slot
The slot control register is modified as follows:
(1) Read the register value
(2) Change the value
(3) Write the value to the register
Those must be done atomically, otherwise writing to control register
would cause an unexpected result.
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>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 191 |
2 files changed, 102 insertions, 90 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index ccc57627201e..7959c222dc24 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -103,6 +103,7 @@ struct controller { | |||
103 | u8 cap_base; | 103 | u8 cap_base; |
104 | struct timer_list poll_timer; | 104 | struct timer_list poll_timer; |
105 | volatile int cmd_busy; | 105 | volatile int cmd_busy; |
106 | spinlock_t lock; | ||
106 | }; | 107 | }; |
107 | 108 | ||
108 | #define INT_BUTTON_IGNORE 0 | 109 | #define INT_BUTTON_IGNORE 0 |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 9aac6a87eb53..016eea94a8a5 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -275,11 +275,19 @@ static inline int pcie_wait_cmd(struct controller *ctrl) | |||
275 | return retval; | 275 | return retval; |
276 | } | 276 | } |
277 | 277 | ||
278 | static int pcie_write_cmd(struct slot *slot, u16 cmd) | 278 | /** |
279 | * pcie_write_cmd - Issue controller command | ||
280 | * @slot: slot to which the command is issued | ||
281 | * @cmd: command value written to slot control register | ||
282 | * @mask: bitmask of slot control register to be modified | ||
283 | */ | ||
284 | static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask) | ||
279 | { | 285 | { |
280 | struct controller *ctrl = slot->ctrl; | 286 | struct controller *ctrl = slot->ctrl; |
281 | int retval = 0; | 287 | int retval = 0; |
282 | u16 slot_status; | 288 | u16 slot_status; |
289 | u16 slot_ctrl; | ||
290 | unsigned long flags; | ||
283 | 291 | ||
284 | DBG_ENTER_ROUTINE | 292 | DBG_ENTER_ROUTINE |
285 | 293 | ||
@@ -299,17 +307,29 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd) | |||
299 | __FUNCTION__); | 307 | __FUNCTION__); |
300 | } | 308 | } |
301 | 309 | ||
302 | ctrl->cmd_busy = 1; | 310 | spin_lock_irqsave(&ctrl->lock, flags); |
303 | retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE)); | 311 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
304 | if (retval) { | 312 | if (retval) { |
305 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); | 313 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
306 | goto out; | 314 | goto out_spin_unlock; |
307 | } | 315 | } |
308 | 316 | ||
317 | slot_ctrl &= ~mask; | ||
318 | slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE); | ||
319 | |||
320 | ctrl->cmd_busy = 1; | ||
321 | retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl); | ||
322 | if (retval) | ||
323 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); | ||
324 | |||
325 | out_spin_unlock: | ||
326 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
327 | |||
309 | /* | 328 | /* |
310 | * Wait for command completion. | 329 | * Wait for command completion. |
311 | */ | 330 | */ |
312 | retval = pcie_wait_cmd(ctrl); | 331 | if (!retval) |
332 | retval = pcie_wait_cmd(ctrl); | ||
313 | out: | 333 | out: |
314 | mutex_unlock(&ctrl->ctrl_lock); | 334 | mutex_unlock(&ctrl->ctrl_lock); |
315 | DBG_LEAVE_ROUTINE | 335 | DBG_LEAVE_ROUTINE |
@@ -502,25 +522,20 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status) | |||
502 | 522 | ||
503 | static int hpc_toggle_emi(struct slot *slot) | 523 | static int hpc_toggle_emi(struct slot *slot) |
504 | { | 524 | { |
505 | struct controller *ctrl = slot->ctrl; | 525 | u16 slot_cmd; |
506 | u16 slot_cmd = 0; | 526 | u16 cmd_mask; |
507 | u16 slot_ctrl; | 527 | int rc; |
508 | int rc = 0; | ||
509 | 528 | ||
510 | DBG_ENTER_ROUTINE | 529 | DBG_ENTER_ROUTINE |
511 | 530 | ||
512 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 531 | slot_cmd = EMI_CTRL; |
513 | if (rc) { | 532 | cmd_mask = EMI_CTRL; |
514 | err("%s : hp_register_read_word SLOT_CTRL failed\n", | 533 | if (!pciehp_poll_mode) { |
515 | __FUNCTION__); | ||
516 | return rc; | ||
517 | } | ||
518 | |||
519 | slot_cmd = (slot_ctrl | EMI_CTRL); | ||
520 | if (!pciehp_poll_mode) | ||
521 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 534 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
535 | cmd_mask = cmd_mask | HP_INTR_ENABLE; | ||
536 | } | ||
522 | 537 | ||
523 | pcie_write_cmd(slot, slot_cmd); | 538 | rc = pcie_write_cmd(slot, slot_cmd, cmd_mask); |
524 | slot->last_emi_toggle = get_seconds(); | 539 | slot->last_emi_toggle = get_seconds(); |
525 | DBG_LEAVE_ROUTINE | 540 | DBG_LEAVE_ROUTINE |
526 | return rc; | 541 | return rc; |
@@ -529,35 +544,32 @@ static int hpc_toggle_emi(struct slot *slot) | |||
529 | static int hpc_set_attention_status(struct slot *slot, u8 value) | 544 | static int hpc_set_attention_status(struct slot *slot, u8 value) |
530 | { | 545 | { |
531 | struct controller *ctrl = slot->ctrl; | 546 | struct controller *ctrl = slot->ctrl; |
532 | u16 slot_cmd = 0; | 547 | u16 slot_cmd; |
533 | u16 slot_ctrl; | 548 | u16 cmd_mask; |
534 | int rc = 0; | 549 | int rc; |
535 | 550 | ||
536 | DBG_ENTER_ROUTINE | 551 | DBG_ENTER_ROUTINE |
537 | 552 | ||
538 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 553 | cmd_mask = ATTN_LED_CTRL; |
539 | if (rc) { | ||
540 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | ||
541 | return rc; | ||
542 | } | ||
543 | |||
544 | switch (value) { | 554 | switch (value) { |
545 | case 0 : /* turn off */ | 555 | case 0 : /* turn off */ |
546 | slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0; | 556 | slot_cmd = 0x00C0; |
547 | break; | 557 | break; |
548 | case 1: /* turn on */ | 558 | case 1: /* turn on */ |
549 | slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040; | 559 | slot_cmd = 0x0040; |
550 | break; | 560 | break; |
551 | case 2: /* turn blink */ | 561 | case 2: /* turn blink */ |
552 | slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080; | 562 | slot_cmd = 0x0080; |
553 | break; | 563 | break; |
554 | default: | 564 | default: |
555 | return -1; | 565 | return -1; |
556 | } | 566 | } |
557 | if (!pciehp_poll_mode) | 567 | if (!pciehp_poll_mode) { |
558 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | 568 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
569 | cmd_mask = cmd_mask | HP_INTR_ENABLE; | ||
570 | } | ||
559 | 571 | ||
560 | pcie_write_cmd(slot, slot_cmd); | 572 | rc = pcie_write_cmd(slot, slot_cmd, cmd_mask); |
561 | dbg("%s: SLOTCTRL %x write cmd %x\n", | 573 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
562 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 574 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); |
563 | 575 | ||
@@ -570,21 +582,18 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
570 | { | 582 | { |
571 | struct controller *ctrl = slot->ctrl; | 583 | struct controller *ctrl = slot->ctrl; |
572 | u16 slot_cmd; | 584 | u16 slot_cmd; |
573 | u16 slot_ctrl; | 585 | u16 cmd_mask; |
574 | int rc = 0; | ||
575 | 586 | ||
576 | DBG_ENTER_ROUTINE | 587 | DBG_ENTER_ROUTINE |
577 | 588 | ||
578 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 589 | slot_cmd = 0x0100; |
579 | if (rc) { | 590 | cmd_mask = PWR_LED_CTRL; |
580 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | 591 | if (!pciehp_poll_mode) { |
581 | return; | 592 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
593 | cmd_mask = cmd_mask | HP_INTR_ENABLE; | ||
582 | } | 594 | } |
583 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; | ||
584 | if (!pciehp_poll_mode) | ||
585 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | ||
586 | 595 | ||
587 | pcie_write_cmd(slot, slot_cmd); | 596 | pcie_write_cmd(slot, slot_cmd, cmd_mask); |
588 | 597 | ||
589 | dbg("%s: SLOTCTRL %x write cmd %x\n", | 598 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
590 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 599 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); |
@@ -596,22 +605,18 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
596 | { | 605 | { |
597 | struct controller *ctrl = slot->ctrl; | 606 | struct controller *ctrl = slot->ctrl; |
598 | u16 slot_cmd; | 607 | u16 slot_cmd; |
599 | u16 slot_ctrl; | 608 | u16 cmd_mask; |
600 | int rc = 0; | ||
601 | 609 | ||
602 | DBG_ENTER_ROUTINE | 610 | DBG_ENTER_ROUTINE |
603 | 611 | ||
604 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 612 | slot_cmd = 0x0300; |
605 | if (rc) { | 613 | cmd_mask = PWR_LED_CTRL; |
606 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | 614 | if (!pciehp_poll_mode) { |
607 | return; | 615 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
616 | cmd_mask = cmd_mask | HP_INTR_ENABLE; | ||
608 | } | 617 | } |
609 | 618 | ||
610 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; | 619 | pcie_write_cmd(slot, slot_cmd, cmd_mask); |
611 | |||
612 | if (!pciehp_poll_mode) | ||
613 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | ||
614 | pcie_write_cmd(slot, slot_cmd); | ||
615 | dbg("%s: SLOTCTRL %x write cmd %x\n", | 620 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
616 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 621 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); |
617 | 622 | ||
@@ -623,22 +628,18 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
623 | { | 628 | { |
624 | struct controller *ctrl = slot->ctrl; | 629 | struct controller *ctrl = slot->ctrl; |
625 | u16 slot_cmd; | 630 | u16 slot_cmd; |
626 | u16 slot_ctrl; | 631 | u16 cmd_mask; |
627 | int rc = 0; | ||
628 | 632 | ||
629 | DBG_ENTER_ROUTINE | 633 | DBG_ENTER_ROUTINE |
630 | 634 | ||
631 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 635 | slot_cmd = 0x0200; |
632 | if (rc) { | 636 | cmd_mask = PWR_LED_CTRL; |
633 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | 637 | if (!pciehp_poll_mode) { |
634 | return; | 638 | slot_cmd = slot_cmd | HP_INTR_ENABLE; |
639 | cmd_mask = cmd_mask | HP_INTR_ENABLE; | ||
635 | } | 640 | } |
636 | 641 | ||
637 | slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; | 642 | pcie_write_cmd(slot, slot_cmd, cmd_mask); |
638 | |||
639 | if (!pciehp_poll_mode) | ||
640 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | ||
641 | pcie_write_cmd(slot, slot_cmd); | ||
642 | 643 | ||
643 | dbg("%s: SLOTCTRL %x write cmd %x\n", | 644 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
644 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 645 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); |
@@ -669,7 +670,8 @@ static int hpc_power_on_slot(struct slot * slot) | |||
669 | { | 670 | { |
670 | struct controller *ctrl = slot->ctrl; | 671 | struct controller *ctrl = slot->ctrl; |
671 | u16 slot_cmd; | 672 | u16 slot_cmd; |
672 | u16 slot_ctrl, slot_status; | 673 | u16 cmd_mask; |
674 | u16 slot_status; | ||
673 | int retval = 0; | 675 | int retval = 0; |
674 | 676 | ||
675 | DBG_ENTER_ROUTINE | 677 | DBG_ENTER_ROUTINE |
@@ -692,23 +694,23 @@ static int hpc_power_on_slot(struct slot * slot) | |||
692 | } | 694 | } |
693 | } | 695 | } |
694 | 696 | ||
695 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 697 | slot_cmd = POWER_ON; |
696 | if (retval) { | 698 | cmd_mask = PWR_CTRL; |
697 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | ||
698 | return retval; | ||
699 | } | ||
700 | |||
701 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; | ||
702 | |||
703 | /* Enable detection that we turned off at slot power-off time */ | 699 | /* Enable detection that we turned off at slot power-off time */ |
704 | if (!pciehp_poll_mode) | 700 | if (!pciehp_poll_mode) { |
705 | slot_cmd = slot_cmd | | 701 | slot_cmd = slot_cmd | |
706 | PWR_FAULT_DETECT_ENABLE | | 702 | PWR_FAULT_DETECT_ENABLE | |
707 | MRL_DETECT_ENABLE | | 703 | MRL_DETECT_ENABLE | |
708 | PRSN_DETECT_ENABLE | | 704 | PRSN_DETECT_ENABLE | |
709 | HP_INTR_ENABLE; | 705 | HP_INTR_ENABLE; |
706 | cmd_mask = cmd_mask | | ||
707 | PWR_FAULT_DETECT_ENABLE | | ||
708 | MRL_DETECT_ENABLE | | ||
709 | PRSN_DETECT_ENABLE | | ||
710 | HP_INTR_ENABLE; | ||
711 | } | ||
710 | 712 | ||
711 | retval = pcie_write_cmd(slot, slot_cmd); | 713 | retval = pcie_write_cmd(slot, slot_cmd, cmd_mask); |
712 | 714 | ||
713 | if (retval) { | 715 | if (retval) { |
714 | err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); | 716 | err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); |
@@ -726,21 +728,15 @@ static int hpc_power_off_slot(struct slot * slot) | |||
726 | { | 728 | { |
727 | struct controller *ctrl = slot->ctrl; | 729 | struct controller *ctrl = slot->ctrl; |
728 | u16 slot_cmd; | 730 | u16 slot_cmd; |
729 | u16 slot_ctrl; | 731 | u16 cmd_mask; |
730 | int retval = 0; | 732 | int retval = 0; |
731 | 733 | ||
732 | DBG_ENTER_ROUTINE | 734 | DBG_ENTER_ROUTINE |
733 | 735 | ||
734 | dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); | 736 | dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); |
735 | 737 | ||
736 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 738 | slot_cmd = POWER_OFF; |
737 | if (retval) { | 739 | cmd_mask = PWR_CTRL; |
738 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | ||
739 | return retval; | ||
740 | } | ||
741 | |||
742 | slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; | ||
743 | |||
744 | /* | 740 | /* |
745 | * If we get MRL or presence detect interrupts now, the isr | 741 | * If we get MRL or presence detect interrupts now, the isr |
746 | * will notice the sticky power-fault bit too and issue power | 742 | * will notice the sticky power-fault bit too and issue power |
@@ -748,14 +744,19 @@ static int hpc_power_off_slot(struct slot * slot) | |||
748 | * of command completions, since the power-fault bit remains on | 744 | * of command completions, since the power-fault bit remains on |
749 | * till the slot is powered on again. | 745 | * till the slot is powered on again. |
750 | */ | 746 | */ |
751 | if (!pciehp_poll_mode) | 747 | if (!pciehp_poll_mode) { |
752 | slot_cmd = (slot_cmd & | 748 | slot_cmd = (slot_cmd & |
753 | ~PWR_FAULT_DETECT_ENABLE & | 749 | ~PWR_FAULT_DETECT_ENABLE & |
754 | ~MRL_DETECT_ENABLE & | 750 | ~MRL_DETECT_ENABLE & |
755 | ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE; | 751 | ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE; |
752 | cmd_mask = cmd_mask | | ||
753 | PWR_FAULT_DETECT_ENABLE | | ||
754 | MRL_DETECT_ENABLE | | ||
755 | PRSN_DETECT_ENABLE | | ||
756 | HP_INTR_ENABLE; | ||
757 | } | ||
756 | 758 | ||
757 | retval = pcie_write_cmd(slot, slot_cmd); | 759 | retval = pcie_write_cmd(slot, slot_cmd, cmd_mask); |
758 | |||
759 | if (retval) { | 760 | if (retval) { |
760 | err("%s: Write command failed!\n", __FUNCTION__); | 761 | err("%s: Write command failed!\n", __FUNCTION__); |
761 | return -1; | 762 | return -1; |
@@ -775,6 +776,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
775 | u16 temp_word; | 776 | u16 temp_word; |
776 | int hp_slot = 0; /* only 1 slot per PCI Express port */ | 777 | int hp_slot = 0; /* only 1 slot per PCI Express port */ |
777 | int rc = 0; | 778 | int rc = 0; |
779 | unsigned long flags; | ||
778 | 780 | ||
779 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 781 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
780 | if (rc) { | 782 | if (rc) { |
@@ -794,10 +796,12 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
794 | dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); | 796 | dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); |
795 | /* Mask Hot-plug Interrupt Enable */ | 797 | /* Mask Hot-plug Interrupt Enable */ |
796 | if (!pciehp_poll_mode) { | 798 | if (!pciehp_poll_mode) { |
799 | spin_lock_irqsave(&ctrl->lock, flags); | ||
797 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | 800 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); |
798 | if (rc) { | 801 | if (rc) { |
799 | err("%s: Cannot read SLOT_CTRL register\n", | 802 | err("%s: Cannot read SLOT_CTRL register\n", |
800 | __FUNCTION__); | 803 | __FUNCTION__); |
804 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
801 | return IRQ_NONE; | 805 | return IRQ_NONE; |
802 | } | 806 | } |
803 | 807 | ||
@@ -808,8 +812,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
808 | if (rc) { | 812 | if (rc) { |
809 | err("%s: Cannot write to SLOTCTRL register\n", | 813 | err("%s: Cannot write to SLOTCTRL register\n", |
810 | __FUNCTION__); | 814 | __FUNCTION__); |
815 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
811 | return IRQ_NONE; | 816 | return IRQ_NONE; |
812 | } | 817 | } |
818 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
813 | 819 | ||
814 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 820 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
815 | if (rc) { | 821 | if (rc) { |
@@ -859,10 +865,12 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
859 | } | 865 | } |
860 | /* Unmask Hot-plug Interrupt Enable */ | 866 | /* Unmask Hot-plug Interrupt Enable */ |
861 | if (!pciehp_poll_mode) { | 867 | if (!pciehp_poll_mode) { |
868 | spin_lock_irqsave(&ctrl->lock, flags); | ||
862 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | 869 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); |
863 | if (rc) { | 870 | if (rc) { |
864 | err("%s: Cannot read SLOTCTRL register\n", | 871 | err("%s: Cannot read SLOTCTRL register\n", |
865 | __FUNCTION__); | 872 | __FUNCTION__); |
873 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
866 | return IRQ_NONE; | 874 | return IRQ_NONE; |
867 | } | 875 | } |
868 | 876 | ||
@@ -873,8 +881,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
873 | if (rc) { | 881 | if (rc) { |
874 | err("%s: Cannot write to SLOTCTRL register\n", | 882 | err("%s: Cannot write to SLOTCTRL register\n", |
875 | __FUNCTION__); | 883 | __FUNCTION__); |
884 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
876 | return IRQ_NONE; | 885 | return IRQ_NONE; |
877 | } | 886 | } |
887 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
878 | 888 | ||
879 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 889 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
880 | if (rc) { | 890 | if (rc) { |
@@ -1237,6 +1247,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1237 | 1247 | ||
1238 | mutex_init(&ctrl->crit_sect); | 1248 | mutex_init(&ctrl->crit_sect); |
1239 | mutex_init(&ctrl->ctrl_lock); | 1249 | mutex_init(&ctrl->ctrl_lock); |
1250 | spin_lock_init(&ctrl->lock); | ||
1240 | 1251 | ||
1241 | /* setup wait queue */ | 1252 | /* setup wait queue */ |
1242 | init_waitqueue_head(&ctrl->queue); | 1253 | init_waitqueue_head(&ctrl->queue); |