diff options
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 125 |
1 files changed, 57 insertions, 68 deletions
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 5135ceb404d8..e0f8c1bbaf12 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -91,6 +91,12 @@ | |||
91 | #define ATTN_BUTTON 0x80000000 | 91 | #define ATTN_BUTTON 0x80000000 |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Interrupt Locator Register definitions | ||
95 | */ | ||
96 | #define CMD_INTR_PENDING (1 << 0) | ||
97 | #define SLOT_INTR_PENDING(i) (1 << (i + 1)) | ||
98 | |||
99 | /* | ||
94 | * Controller SERR-INT Register | 100 | * Controller SERR-INT Register |
95 | */ | 101 | */ |
96 | #define GLOBAL_INTR_MASK (1 << 0) | 102 | #define GLOBAL_INTR_MASK (1 << 0) |
@@ -218,7 +224,7 @@ static spinlock_t list_lock; | |||
218 | 224 | ||
219 | static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); | 225 | static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); |
220 | 226 | ||
221 | static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); | 227 | static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs); |
222 | 228 | ||
223 | static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); | 229 | static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); |
224 | static int hpc_check_cmd_status(struct controller *ctrl); | 230 | static int hpc_check_cmd_status(struct controller *ctrl); |
@@ -279,7 +285,7 @@ static void int_poll_timeout(unsigned long lphp_ctlr) | |||
279 | } | 285 | } |
280 | 286 | ||
281 | /* Poll for interrupt events. regs == NULL => polling */ | 287 | /* Poll for interrupt events. regs == NULL => polling */ |
282 | shpc_isr( 0, (void *)php_ctlr, NULL ); | 288 | shpc_isr(0, php_ctlr->callback_instance_id, NULL ); |
283 | 289 | ||
284 | init_timer(&php_ctlr->int_poll_timer); | 290 | init_timer(&php_ctlr->int_poll_timer); |
285 | if (!shpchp_poll_time) | 291 | if (!shpchp_poll_time) |
@@ -875,103 +881,86 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) | |||
875 | return retval; | 881 | return retval; |
876 | } | 882 | } |
877 | 883 | ||
878 | static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) | 884 | static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) |
879 | { | 885 | { |
880 | struct controller *ctrl = NULL; | 886 | struct controller *ctrl = (struct controller *)dev_id; |
881 | struct php_ctlr_state_s *php_ctlr; | 887 | struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; |
882 | u8 schedule_flag = 0; | 888 | u32 serr_int, slot_reg, intr_loc, intr_loc2; |
883 | u32 temp_dword, intr_loc, intr_loc2; | ||
884 | int hp_slot; | 889 | int hp_slot; |
885 | 890 | ||
886 | if (!dev_id) | ||
887 | return IRQ_NONE; | ||
888 | |||
889 | if (!shpchp_poll_mode) { | ||
890 | ctrl = (struct controller *)dev_id; | ||
891 | php_ctlr = ctrl->hpc_ctlr_handle; | ||
892 | } else { | ||
893 | php_ctlr = (struct php_ctlr_state_s *) dev_id; | ||
894 | ctrl = (struct controller *)php_ctlr->callback_instance_id; | ||
895 | } | ||
896 | |||
897 | if (!ctrl) | ||
898 | return IRQ_NONE; | ||
899 | |||
900 | if (!php_ctlr || !php_ctlr->creg) | ||
901 | return IRQ_NONE; | ||
902 | |||
903 | /* Check to see if it was our interrupt */ | 891 | /* Check to see if it was our interrupt */ |
904 | intr_loc = shpc_readl(ctrl, INTR_LOC); | 892 | intr_loc = shpc_readl(ctrl, INTR_LOC); |
905 | |||
906 | if (!intr_loc) | 893 | if (!intr_loc) |
907 | return IRQ_NONE; | 894 | return IRQ_NONE; |
895 | |||
908 | dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); | 896 | dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); |
909 | 897 | ||
910 | if(!shpchp_poll_mode) { | 898 | if(!shpchp_poll_mode) { |
911 | /* Mask Global Interrupt Mask - see implementation note on p. 139 */ | 899 | /* |
912 | /* of SHPC spec rev 1.0*/ | 900 | * Mask Global Interrupt Mask - see implementation |
913 | temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); | 901 | * note on p. 139 of SHPC spec rev 1.0 |
914 | temp_dword |= GLOBAL_INTR_MASK; | 902 | */ |
915 | temp_dword &= ~SERR_INTR_RSVDZ_MASK; | 903 | serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); |
916 | shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); | 904 | serr_int |= GLOBAL_INTR_MASK; |
905 | serr_int &= ~SERR_INTR_RSVDZ_MASK; | ||
906 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); | ||
917 | 907 | ||
918 | intr_loc2 = shpc_readl(ctrl, INTR_LOC); | 908 | intr_loc2 = shpc_readl(ctrl, INTR_LOC); |
919 | dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); | 909 | dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); |
920 | } | 910 | } |
921 | 911 | ||
922 | if (intr_loc & 0x0001) { | 912 | if (intr_loc & CMD_INTR_PENDING) { |
923 | /* | 913 | /* |
924 | * Command Complete Interrupt Pending | 914 | * Command Complete Interrupt Pending |
925 | * RO only - clear by writing 1 to the Command Completion | 915 | * RO only - clear by writing 1 to the Command Completion |
926 | * Detect bit in Controller SERR-INT register | 916 | * Detect bit in Controller SERR-INT register |
927 | */ | 917 | */ |
928 | temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); | 918 | serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); |
929 | temp_dword &= ~SERR_INTR_RSVDZ_MASK; | 919 | serr_int &= ~SERR_INTR_RSVDZ_MASK; |
930 | shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); | 920 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); |
921 | |||
931 | ctrl->cmd_busy = 0; | 922 | ctrl->cmd_busy = 0; |
932 | wake_up_interruptible(&ctrl->queue); | 923 | wake_up_interruptible(&ctrl->queue); |
933 | } | 924 | } |
934 | 925 | ||
935 | if ((intr_loc = (intr_loc >> 1)) == 0) | 926 | if (!(intr_loc & ~CMD_INTR_PENDING)) |
936 | goto out; | 927 | goto out; |
937 | 928 | ||
938 | for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { | 929 | for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { |
939 | /* To find out which slot has interrupt pending */ | 930 | /* To find out which slot has interrupt pending */ |
940 | if ((intr_loc >> hp_slot) & 0x01) { | 931 | if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) |
941 | temp_dword = shpc_readl(ctrl, SLOT_REG(hp_slot)); | 932 | continue; |
942 | dbg("%s: Slot %x with intr, slot register = %x\n", | 933 | |
943 | __FUNCTION__, hp_slot, temp_dword); | 934 | slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); |
944 | if ((php_ctlr->switch_change_callback) && | 935 | dbg("%s: Slot %x with intr, slot register = %x\n", |
945 | (temp_dword & MRL_CHANGE_DETECTED)) | 936 | __FUNCTION__, hp_slot, slot_reg); |
946 | schedule_flag += php_ctlr->switch_change_callback( | 937 | |
947 | hp_slot, php_ctlr->callback_instance_id); | 938 | if (slot_reg & MRL_CHANGE_DETECTED) |
948 | if ((php_ctlr->attention_button_callback) && | 939 | php_ctlr->switch_change_callback( |
949 | (temp_dword & BUTTON_PRESS_DETECTED)) | 940 | hp_slot, php_ctlr->callback_instance_id); |
950 | schedule_flag += php_ctlr->attention_button_callback( | 941 | |
951 | hp_slot, php_ctlr->callback_instance_id); | 942 | if (slot_reg & BUTTON_PRESS_DETECTED) |
952 | if ((php_ctlr->presence_change_callback) && | 943 | php_ctlr->attention_button_callback( |
953 | (temp_dword & PRSNT_CHANGE_DETECTED)) | 944 | hp_slot, php_ctlr->callback_instance_id); |
954 | schedule_flag += php_ctlr->presence_change_callback( | 945 | |
955 | hp_slot , php_ctlr->callback_instance_id); | 946 | if (slot_reg & PRSNT_CHANGE_DETECTED) |
956 | if ((php_ctlr->power_fault_callback) && | 947 | php_ctlr->presence_change_callback( |
957 | (temp_dword & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))) | 948 | hp_slot , php_ctlr->callback_instance_id); |
958 | schedule_flag += php_ctlr->power_fault_callback( | 949 | |
959 | hp_slot, php_ctlr->callback_instance_id); | 950 | if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED)) |
960 | 951 | php_ctlr->power_fault_callback( | |
961 | /* Clear all slot events */ | 952 | hp_slot, php_ctlr->callback_instance_id); |
962 | temp_dword &= ~SLOT_REG_RSVDZ_MASK; | 953 | |
963 | shpc_writel(ctrl, SLOT_REG(hp_slot), temp_dword); | 954 | /* Clear all slot events */ |
964 | 955 | slot_reg &= ~SLOT_REG_RSVDZ_MASK; | |
965 | intr_loc2 = shpc_readl(ctrl, INTR_LOC); | 956 | shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); |
966 | dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); | ||
967 | } | ||
968 | } | 957 | } |
969 | out: | 958 | out: |
970 | if (!shpchp_poll_mode) { | 959 | if (!shpchp_poll_mode) { |
971 | /* Unmask Global Interrupt Mask */ | 960 | /* Unmask Global Interrupt Mask */ |
972 | temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); | 961 | serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); |
973 | temp_dword &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); | 962 | serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); |
974 | shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); | 963 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); |
975 | } | 964 | } |
976 | 965 | ||
977 | return IRQ_HANDLED; | 966 | return IRQ_HANDLED; |