aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2006-05-01 22:11:54 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-19 17:13:23 -0400
commit795eb5c4a73bee30e8c2dbb29174b329da56051c (patch)
tree2c489f1f647d46cdc29322839d766cbf37d55485 /drivers/pci
parent5858759c2098c6792af1afa6d5ded94044740f9c (diff)
[PATCH] SHPC: Fix SHPC Logical Slot Register bits access
Current SHPCHP driver doesn't take care of RsvdP/RsvdZ[*] bits in logical slot registers. This might cause unpredicable results. This patch fixes this bug. [*] RsvdP and RsvdZ are defined in SHPC spec as follows: RsvdP - Reserved and Preserved. Register bits of this type are reserved for future use as R/W bits. The value read is undefined. Writes are ignored. Software must follow These rules when accessing RsvdP bits: - Software must ignore RsvdP bits when testing values read from these registers. - Software must not depend on RsvdP bit's ability to retain information when written - Software must always write back the value read in the RsvdP bits when writing one of these registers. RsvdZ - Reserved and Zero. Register bits of this type are reserved for future use as R/WC bits. The value read is undefined. Writes are ignored. Software must follow these rules when accessing RsvdZ bits: - Software must ignore RsvdZ bits when testing values read from these registers. - Software must not depends on a RsvdZ bit's ability to retain information when written. - Software must always write 0 to RsvdZ bits when writing one of these register. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Cc: Kristen 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/shpchp_hpc.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 9731ee8224f2..285a21d36524 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -554,11 +554,25 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
554 int retval = 0; 554 int retval = 0;
555 struct controller *ctrl = slot->ctrl; 555 struct controller *ctrl = slot->ctrl;
556 u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 556 u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
557 u8 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT;
558 u8 m66_cap = !!(slot_reg & MHZ66_CAP); 557 u8 m66_cap = !!(slot_reg & MHZ66_CAP);
558 u8 pi, pcix_cap;
559 559
560 DBG_ENTER_ROUTINE 560 DBG_ENTER_ROUTINE
561 561
562 if ((retval = hpc_get_prog_int(slot, &pi)))
563 return retval;
564
565 switch (pi) {
566 case 1:
567 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT;
568 break;
569 case 2:
570 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT;
571 break;
572 default:
573 return -ENODEV;
574 }
575
562 dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", 576 dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
563 __FUNCTION__, slot_reg, pcix_cap, m66_cap); 577 __FUNCTION__, slot_reg, pcix_cap, m66_cap);
564 578
@@ -773,6 +787,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
773 struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; 787 struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
774 struct php_ctlr_state_s *p, *p_prev; 788 struct php_ctlr_state_s *p, *p_prev;
775 int i; 789 int i;
790 u32 slot_reg;
776 791
777 DBG_ENTER_ROUTINE 792 DBG_ENTER_ROUTINE
778 793
@@ -782,10 +797,17 @@ static void hpc_release_ctlr(struct controller *ctrl)
782 } 797 }
783 798
784 /* 799 /*
785 * Mask all slot event interrupts 800 * Mask event interrupts and SERRs of all slots
786 */ 801 */
787 for (i = 0; i < ctrl->num_slots; i++) 802 for (i = 0; i < ctrl->num_slots; i++) {
788 shpc_writel(ctrl, SLOT_REG(i), 0xffff3fff); 803 slot_reg = shpc_readl(ctrl, SLOT_REG(i));
804 slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
805 BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
806 CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK |
807 CON_PFAULT_SERR_MASK);
808 slot_reg &= ~SLOT_REG_RSVDZ_MASK;
809 shpc_writel(ctrl, SLOT_REG(i), slot_reg);
810 }
789 811
790 cleanup_slots(ctrl); 812 cleanup_slots(ctrl);
791 813
@@ -1072,7 +1094,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
1072 hp_slot, php_ctlr->callback_instance_id); 1094 hp_slot, php_ctlr->callback_instance_id);
1073 1095
1074 /* Clear all slot events */ 1096 /* Clear all slot events */
1075 temp_dword = 0xe01f3fff; 1097 temp_dword &= ~SLOT_REG_RSVDZ_MASK;
1076 shpc_writel(ctrl, SLOT_REG(hp_slot), temp_dword); 1098 shpc_writel(ctrl, SLOT_REG(hp_slot), temp_dword);
1077 1099
1078 intr_loc2 = shpc_readl(ctrl, INTR_LOC); 1100 intr_loc2 = shpc_readl(ctrl, INTR_LOC);
@@ -1364,8 +1386,12 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1364 slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); 1386 slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
1365 dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, 1387 dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
1366 hp_slot, slot_reg); 1388 hp_slot, slot_reg);
1367 tempdword = 0xffff3fff; 1389 slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
1368 shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); 1390 BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
1391 CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK |
1392 CON_PFAULT_SERR_MASK);
1393 slot_reg &= ~SLOT_REG_RSVDZ_MASK;
1394 shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
1369 } 1395 }
1370 1396
1371 if (shpchp_poll_mode) {/* Install interrupt polling code */ 1397 if (shpchp_poll_mode) {/* Install interrupt polling code */
@@ -1411,12 +1437,17 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1411 1437
1412 ctlr_seq_num++; 1438 ctlr_seq_num++;
1413 1439
1440 /*
1441 * Unmask all event interrupts of all slots
1442 */
1414 for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { 1443 for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
1415 slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); 1444 slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
1416 dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, 1445 dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
1417 hp_slot, slot_reg); 1446 hp_slot, slot_reg);
1418 tempdword = 0xe01f3fff; 1447 slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
1419 shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); 1448 BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
1449 CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK);
1450 shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
1420 } 1451 }
1421 if (!shpchp_poll_mode) { 1452 if (!shpchp_poll_mode) {
1422 /* Unmask all general input interrupts and SERR */ 1453 /* Unmask all general input interrupts and SERR */