diff options
author | Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> | 2006-05-02 11:11:54 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-19 14:13:23 -0700 |
commit | 795eb5c4a73bee30e8c2dbb29174b329da56051c (patch) | |
tree | 2c489f1f647d46cdc29322839d766cbf37d55485 /drivers/pci/hotplug | |
parent | 5858759c2098c6792af1afa6d5ded94044740f9c (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/hotplug')
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 49 |
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) int retval = 0; struct controller *ctrl = slot->ctrl; u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - u8 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; u8 m66_cap = !!(slot_reg & MHZ66_CAP); + u8 pi, pcix_cap; DBG_ENTER_ROUTINE + if ((retval = hpc_get_prog_int(slot, &pi))) + return retval; + + switch (pi) { + case 1: + pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT; + break; + case 2: + pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; + break; + default: + return -ENODEV; + } + dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", __FUNCTION__, slot_reg, pcix_cap, m66_cap); @@ -773,6 +787,7 @@ static void hpc_release_ctlr(struct controller *ctrl) struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *p, *p_prev; int i; + u32 slot_reg; DBG_ENTER_ROUTINE @@ -782,10 +797,17 @@ static void hpc_release_ctlr(struct controller *ctrl) } /* - * Mask all slot event interrupts + * Mask event interrupts and SERRs of all slots */ - for (i = 0; i < ctrl->num_slots; i++) - shpc_writel(ctrl, SLOT_REG(i), 0xffff3fff); + for (i = 0; i < ctrl->num_slots; i++) { + slot_reg = shpc_readl(ctrl, SLOT_REG(i)); + slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | + CON_PFAULT_SERR_MASK); + slot_reg &= ~SLOT_REG_RSVDZ_MASK; + shpc_writel(ctrl, SLOT_REG(i), slot_reg); + } cleanup_slots(ctrl); @@ -1072,7 +1094,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) hp_slot, php_ctlr->callback_instance_id); /* Clear all slot events */ - temp_dword = 0xe01f3fff; + temp_dword &= ~SLOT_REG_RSVDZ_MASK; shpc_writel(ctrl, SLOT_REG(hp_slot), temp_dword); intr_loc2 = shpc_readl(ctrl, INTR_LOC); @@ -1364,8 +1386,12 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); - tempdword = 0xffff3fff; - shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); + slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | + CON_PFAULT_SERR_MASK); + slot_reg &= ~SLOT_REG_RSVDZ_MASK; + shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } if (shpchp_poll_mode) {/* Install interrupt polling code */ @@ -1411,12 +1437,17 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctlr_seq_num++; + /* + * Unmask all event interrupts of all slots + */ for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); - tempdword = 0xe01f3fff; - shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); + slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK); + shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } if (!shpchp_poll_mode) { /* Unmask all general input interrupts and SERR */ |