aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c125
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
219static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); 225static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
220 226
221static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); 227static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs);
222 228
223static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); 229static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
224static int hpc_check_cmd_status(struct controller *ctrl); 230static 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
878static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) 884static 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;