From 4cfe02fabbb87108d7d06d2335429025ca84e616 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 23 Apr 2008 00:28:47 +0200 Subject: PCI Express ASPM support should default to 'No' Running 'make oldconfig' I just noticed that PCIEASPM defaults to 'y' in Kconfig even though the feature is both experimental and the help text recommends that if you are unsure you say 'n'. It seems to me that this really should default to 'n', not 'y' at the moment. The following patch makes that change. Please consider applying. Signed-off-by: Jesper Juhl Signed-off-by: Jesse Barnes --- drivers/pci/pcie/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 25b04fb2517d..5a0c6ad53f8e 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -33,7 +33,7 @@ source "drivers/pci/pcie/aer/Kconfig" config PCIEASPM bool "PCI Express ASPM support(Experimental)" depends on PCI && EXPERIMENTAL && PCIEPORTBUS - default y + default n help This enables PCI Express ASPM (Active State Power Management) and Clock Power Management. ASPM supports state L0/L0s/L1. -- cgit v1.2.3 From 3800345f723fd130d50434d4717b99d4a9f383c8 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:38:38 -0700 Subject: pciehp: fix slot name Current pciehp uses the combination of bus number and slot number as a slot name. But it is not a good idea because bus number is not a physical identifier but a logical identifier. This is against the PCIE specification. So remove the bus number from the physical identifier. However, there are some platforms with the problem that it provides the same slot number. For those platforms, this patch also introduces new module option 'pciehp_slot_with_bus'. If it is specified, pciehp uses the combination of bus number and slot number as a slot name. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index aee19f013d84..cf36f2355173 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -41,6 +41,7 @@ int pciehp_debug; int pciehp_poll_mode; int pciehp_poll_time; int pciehp_force; +int pciehp_slot_with_bus; struct workqueue_struct *pciehp_wq; #define DRIVER_VERSION "0.4" @@ -55,10 +56,12 @@ module_param(pciehp_debug, bool, 0644); module_param(pciehp_poll_mode, bool, 0644); module_param(pciehp_poll_time, int, 0644); module_param(pciehp_force, bool, 0644); +module_param(pciehp_slot_with_bus, bool, 0644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); +MODULE_PARM_DESC(pciehp_slot_with_bus, "Use bus number in the slot name"); #define PCIE_MODULE_NAME "pciehp" @@ -193,8 +196,12 @@ static void release_slot(struct hotplug_slot *hotplug_slot) static void make_slot_name(struct slot *slot) { - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", - slot->bus, slot->number); + if (pciehp_slot_with_bus) + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", + slot->bus, slot->number); + else + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", + slot->number); } static int init_slots(struct controller *ctrl) -- cgit v1.2.3 From c6b069e94601aea8887afbbd922afe20a3580a7d Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:38:57 -0700 Subject: pciehp: Fix interrupt event handlig Current pciehp implementation disables and re-enables hotplug interrupts in its interrupt handler. This operation might be intend to guarantee that interrupts for the events newly occured during previous events are being handled will be successfully generated. But current implementaion has the following prolems. - Current interrupt service routin clears status changes without waiting command completion. Because of this, events might not be cleared properly. - Current interrupt service routine clears status changes caused by disabling or enabling hotplug interrupts itself. This will lose new events that occurs during previous interrupts are being handled. - Current implementation doesn't have any serialization mechanism between the code to wait for command completion and the interrupt handler that clears the command completion events caused by itself. There is clearly race conditions between them, and it may cause the problem that waiting for command completion doesn't work for example. To fix those problems, this patch stops disabling/re-enabling hotplug interrupts in interrupt service routine. Instead of this, this patch re-inspects Slot Status register after clearing what is presumed to be the last bending interrupt in order to guarantee that all interrupt events are serviced. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp.h | 1 - drivers/pci/hotplug/pciehp_hpc.c | 148 ++++++++------------------------------- 2 files changed, 29 insertions(+), 120 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index f14267e197dd..9dd132925ffa 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -97,7 +97,6 @@ struct controller { u8 cap_base; struct timer_list poll_timer; volatile int cmd_busy; - spinlock_t lock; }; #define INT_BUTTON_IGNORE 0 diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index b4bbd07d1e39..51a5055f6965 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -252,7 +252,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask) int retval = 0; u16 slot_status; u16 slot_ctrl; - unsigned long flags; mutex_lock(&ctrl->ctrl_lock); @@ -270,11 +269,10 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask) __func__); } - spin_lock_irqsave(&ctrl->lock, flags); retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); if (retval) { err("%s: Cannot read SLOTCTRL register\n", __func__); - goto out_spin_unlock; + goto out; } slot_ctrl &= ~mask; @@ -285,9 +283,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask) if (retval) err("%s: Cannot write to SLOTCTRL register\n", __func__); - out_spin_unlock: - spin_unlock_irqrestore(&ctrl->lock, flags); - /* * Wait for command completion. */ @@ -733,139 +728,55 @@ static int hpc_power_off_slot(struct slot * slot) static irqreturn_t pcie_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; - u16 slot_status, intr_detect, intr_loc; - u16 temp_word; - int hp_slot = 0; /* only 1 slot per PCI Express port */ - int rc = 0; - unsigned long flags; - - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (rc) { - err("%s: Cannot read SLOTSTATUS register\n", __func__); - return IRQ_NONE; - } + u16 detected, intr_loc; - intr_detect = (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | - MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED); - - intr_loc = slot_status & intr_detect; - - /* Check to see if it was our interrupt */ - if ( !intr_loc ) - return IRQ_NONE; - - dbg("%s: intr_loc %x\n", __func__, intr_loc); - /* Mask Hot-plug Interrupt Enable */ - if (!pciehp_poll_mode) { - spin_lock_irqsave(&ctrl->lock, flags); - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); - if (rc) { - err("%s: Cannot read SLOT_CTRL register\n", - __func__); - spin_unlock_irqrestore(&ctrl->lock, flags); + /* + * In order to guarantee that all interrupt events are + * serviced, we need to re-inspect Slot Status register after + * clearing what is presumed to be the last pending interrupt. + */ + intr_loc = 0; + do { + if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) { + err("%s: Cannot read SLOTSTATUS\n", __func__); return IRQ_NONE; } - dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n", - __func__, temp_word); - temp_word = (temp_word & ~HP_INTR_ENABLE & - ~CMD_CMPL_INTR_ENABLE) | 0x00; - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); - if (rc) { - err("%s: Cannot write to SLOTCTRL register\n", - __func__); - spin_unlock_irqrestore(&ctrl->lock, flags); + detected &= (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | + MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | + CMD_COMPLETED); + intr_loc |= detected; + if (!intr_loc) return IRQ_NONE; - } - spin_unlock_irqrestore(&ctrl->lock, flags); - - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (rc) { - err("%s: Cannot read SLOT_STATUS register\n", - __func__); + if (pciehp_writew(ctrl, SLOTSTATUS, detected)) { + err("%s: Cannot write to SLOTSTATUS\n", __func__); return IRQ_NONE; } - dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n", - __func__, slot_status); + } while (detected); - /* Clear command complete interrupt caused by this write */ - temp_word = 0x1f; - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); - if (rc) { - err("%s: Cannot write to SLOTSTATUS register\n", - __func__); - return IRQ_NONE; - } - } + dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); + /* Check Command Complete Interrupt Pending */ if (intr_loc & CMD_COMPLETED) { - /* - * Command Complete Interrupt Pending - */ ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } + /* Check MRL Sensor Changed */ if (intr_loc & MRL_SENS_CHANGED) - pciehp_handle_switch_change(hp_slot, ctrl); + pciehp_handle_switch_change(0, ctrl); + /* Check Attention Button Pressed */ if (intr_loc & ATTN_BUTTN_PRESSED) - pciehp_handle_attention_button(hp_slot, ctrl); + pciehp_handle_attention_button(0, ctrl); + /* Check Presence Detect Changed */ if (intr_loc & PRSN_DETECT_CHANGED) - pciehp_handle_presence_change(hp_slot, ctrl); + pciehp_handle_presence_change(0, ctrl); + /* Check Power Fault Detected */ if (intr_loc & PWR_FAULT_DETECTED) - pciehp_handle_power_fault(hp_slot, ctrl); - - /* Clear all events after serving them */ - temp_word = 0x1F; - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); - if (rc) { - err("%s: Cannot write to SLOTSTATUS register\n", __func__); - return IRQ_NONE; - } - /* Unmask Hot-plug Interrupt Enable */ - if (!pciehp_poll_mode) { - spin_lock_irqsave(&ctrl->lock, flags); - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); - if (rc) { - err("%s: Cannot read SLOTCTRL register\n", - __func__); - spin_unlock_irqrestore(&ctrl->lock, flags); - return IRQ_NONE; - } - - dbg("%s: Unmask Hot-plug Interrupt Enable\n", __func__); - temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; - - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); - if (rc) { - err("%s: Cannot write to SLOTCTRL register\n", - __func__); - spin_unlock_irqrestore(&ctrl->lock, flags); - return IRQ_NONE; - } - spin_unlock_irqrestore(&ctrl->lock, flags); - - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (rc) { - err("%s: Cannot read SLOT_STATUS register\n", - __func__); - return IRQ_NONE; - } - - /* Clear command complete interrupt caused by this write */ - temp_word = 0x1F; - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); - if (rc) { - err("%s: Cannot write to SLOTSTATUS failed\n", - __func__); - return IRQ_NONE; - } - dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n", - __func__, temp_word); - } + pciehp_handle_power_fault(0, ctrl); return IRQ_HANDLED; } @@ -1334,7 +1245,6 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev) mutex_init(&ctrl->crit_sect); mutex_init(&ctrl->ctrl_lock); - spin_lock_init(&ctrl->lock); /* setup wait queue */ init_waitqueue_head(&ctrl->queue); -- cgit v1.2.3 From 2d32a9aed2e335d110fbb11985a9545b1f7219ab Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:39:02 -0700 Subject: pciehp: Add missing memory barrier Fix the possible race condition between pcie_isr() and pciehp_write_cmd() because of the lack of memory barrier. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 51a5055f6965..19eba2a2f746 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -279,6 +279,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask) slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE); ctrl->cmd_busy = 1; + smp_mb(); retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl); if (retval) err("%s: Cannot write to SLOTCTRL register\n", __func__); @@ -759,6 +760,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) /* Check Command Complete Interrupt Pending */ if (intr_loc & CMD_COMPLETED) { ctrl->cmd_busy = 0; + smp_mb(); wake_up_interruptible(&ctrl->queue); } -- cgit v1.2.3 From c27fb883dffe11aa4cb35ecea1fa1832ba45d4da Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:39:05 -0700 Subject: pciehp: Fix wrong slot control register access Current pciehp implementaion clears hotplug events without waiting for command completion. Because of this, events might not be cleared properly. To prevent this problem, we must use pciehp_write_cmd() to write to Slot Control register. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 150 ++++++++++----------------------------- 1 file changed, 38 insertions(+), 112 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 19eba2a2f746..7104a15e2661 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -242,13 +242,12 @@ static inline int pcie_wait_cmd(struct controller *ctrl) /** * pcie_write_cmd - Issue controller command - * @slot: slot to which the command is issued + * @ctrl: controller to which the command is issued * @cmd: command value written to slot control register * @mask: bitmask of slot control register to be modified */ -static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask) +static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) { - struct controller *ctrl = slot->ctrl; int retval = 0; u16 slot_status; u16 slot_ctrl; @@ -468,7 +467,7 @@ static int hpc_toggle_emi(struct slot *slot) cmd_mask = cmd_mask | HP_INTR_ENABLE; } - rc = pcie_write_cmd(slot, slot_cmd, cmd_mask); + rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask); slot->last_emi_toggle = get_seconds(); return rc; @@ -500,7 +499,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) cmd_mask = cmd_mask | HP_INTR_ENABLE; } - rc = pcie_write_cmd(slot, slot_cmd, cmd_mask); + rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); @@ -520,7 +519,7 @@ static void hpc_set_green_led_on(struct slot *slot) cmd_mask = cmd_mask | HP_INTR_ENABLE; } - pcie_write_cmd(slot, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); @@ -539,7 +538,7 @@ static void hpc_set_green_led_off(struct slot *slot) cmd_mask = cmd_mask | HP_INTR_ENABLE; } - pcie_write_cmd(slot, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); } @@ -557,7 +556,7 @@ static void hpc_set_green_led_blink(struct slot *slot) cmd_mask = cmd_mask | HP_INTR_ENABLE; } - pcie_write_cmd(slot, slot_cmd, cmd_mask); + pcie_write_cmd(ctrl, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); @@ -620,7 +619,7 @@ static int hpc_power_on_slot(struct slot * slot) HP_INTR_ENABLE; } - retval = pcie_write_cmd(slot, slot_cmd, cmd_mask); + retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { err("%s: Write %x command failed!\n", __func__, slot_cmd); @@ -704,7 +703,7 @@ static int hpc_power_off_slot(struct slot * slot) HP_INTR_ENABLE; } - retval = pcie_write_cmd(slot, slot_cmd, cmd_mask); + retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); if (retval) { err("%s: Write command failed!\n", __func__); retval = -1; @@ -1036,45 +1035,9 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) static int pcie_init_hardware_part1(struct controller *ctrl, struct pcie_device *dev) { - int rc; - u16 temp_word; - u32 slot_cap; - u16 slot_status; - - rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); - if (rc) { - err("%s: Cannot read SLOTCAP register\n", __func__); - return -1; - } - /* Mask Hot-plug Interrupt Enable */ - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); - if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __func__); - return -1; - } - - dbg("%s: SLOTCTRL %x value read %x\n", - __func__, ctrl->cap_base + SLOTCTRL, temp_word); - temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | - 0x00; - - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); - if (rc) { - err("%s: Cannot write to SLOTCTRL register\n", __func__); - return -1; - } - - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (rc) { - err("%s: Cannot read SLOTSTATUS register\n", __func__); - return -1; - } - - temp_word = 0x1F; /* Clear all events */ - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); - if (rc) { - err("%s: Cannot write to SLOTSTATUS register\n", __func__); + if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) { + err("%s: Cannot mask hotplug interrupt enable\n", __func__); return -1; } return 0; @@ -1082,84 +1045,47 @@ static int pcie_init_hardware_part1(struct controller *ctrl, int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) { - int rc; - u16 temp_word; - u16 intr_enable = 0; - u32 slot_cap; - u16 slot_status; - - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); - if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __func__); - goto abort; - } - - intr_enable = intr_enable | PRSN_DETECT_ENABLE; - - rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); - if (rc) { - err("%s: Cannot read SLOTCAP register\n", __func__); - goto abort; - } - - if (ATTN_BUTTN(slot_cap)) - intr_enable = intr_enable | ATTN_BUTTN_ENABLE; - - if (POWER_CTRL(slot_cap)) - intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE; - - if (MRL_SENS(slot_cap)) - intr_enable = intr_enable | MRL_DETECT_ENABLE; - - temp_word = (temp_word & ~intr_enable) | intr_enable; - - if (pciehp_poll_mode) { - temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0; - } else { - temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; - } + u16 cmd, mask; /* - * Unmask Hot-plug Interrupt Enable for the interrupt - * notification mechanism case. + * We need to clear all events before enabling hotplug interrupt + * notification mechanism in order for hotplug controler to + * generate interrupts. */ - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); - if (rc) { - err("%s: Cannot write to SLOTCTRL register\n", __func__); - goto abort; - } - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (rc) { - err("%s: Cannot read SLOTSTATUS register\n", __func__); - goto abort_disable_intr; + if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) { + err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); + return -1; } - temp_word = 0x1F; /* Clear all events */ - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); - if (rc) { - err("%s: Cannot write to SLOTSTATUS register\n", __func__); - goto abort_disable_intr; + cmd = PRSN_DETECT_ENABLE; + if (ATTN_BUTTN(ctrl->ctrlcap)) + cmd |= ATTN_BUTTN_ENABLE; + if (POWER_CTRL(ctrl->ctrlcap)) + cmd |= PWR_FAULT_DETECT_ENABLE; + if (MRL_SENS(ctrl->ctrlcap)) + cmd |= MRL_DETECT_ENABLE; + if (!pciehp_poll_mode) + cmd |= HP_INTR_ENABLE; + + mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | + PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | HP_INTR_ENABLE; + + if (pcie_write_cmd(ctrl, cmd, mask)) { + err("%s: Cannot enable software notification\n", __func__); + goto abort; } - if (pciehp_force) { + if (pciehp_force) dbg("Bypassing BIOS check for pciehp use on %s\n", pci_name(ctrl->pci_dev)); - } else { - rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); - if (rc) - goto abort_disable_intr; - } + else if (pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev)) + goto abort_disable_intr; return 0; /* We end up here for the many possible ways to fail this API. */ abort_disable_intr: - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); - if (!rc) { - temp_word &= ~(intr_enable | HP_INTR_ENABLE); - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); - } - if (rc) + if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE)) err("%s : disabling interrupts failed\n", __func__); abort: return -1; -- cgit v1.2.3 From ae416e6b2936fdb70aeee6eb9066115d4521daa6 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:39:06 -0700 Subject: pciehp: Fix wrong slot capability check Current pciehp saves only 8bits of Slot Capability registers in ctrl->ctrlcap. But it refers more than 8bit for checking EMI capability. It is clearly a bug and EMI would never work. To fix this problem, this patch saves full Slot Capability contens in ctrl->slot_cap. It also reduce the redundant reads of Slot Capability register. And this pach also cleans up the macros to check the slot capabilitys (e.g. MRL_SENS(), and so on). Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp.h | 16 +++++++------- drivers/pci/hotplug/pciehp_core.c | 8 +++---- drivers/pci/hotplug/pciehp_ctrl.c | 46 +++++++++++++++++++-------------------- drivers/pci/hotplug/pciehp_hpc.c | 8 +++---- 4 files changed, 39 insertions(+), 39 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 9dd132925ffa..8264a7680435 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -93,7 +93,7 @@ struct controller { u8 slot_device_offset; u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ u8 slot_bus; /* Bus where the slots handled by this controller sit */ - u8 ctrlcap; + u32 slot_cap; u8 cap_base; struct timer_list poll_timer; volatile int cmd_busy; @@ -136,13 +136,13 @@ struct controller { #define HP_SUPR_RM_SUP 0x00000020 #define EMI_PRSN 0x00020000 -#define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN) -#define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN) -#define MRL_SENS(cap) (cap & MRL_SENS_PRSN) -#define ATTN_LED(cap) (cap & ATTN_LED_PRSN) -#define PWR_LED(cap) (cap & PWR_LED_PRSN) -#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) -#define EMI(cap) (cap & EMI_PRSN) +#define ATTN_BUTTN(ctrl) ((ctrl)->slot_cap & ATTN_BUTTN_PRSN) +#define POWER_CTRL(ctrl) ((ctrl)->slot_cap & PWR_CTRL_PRSN) +#define MRL_SENS(ctrl) ((ctrl)->slot_cap & MRL_SENS_PRSN) +#define ATTN_LED(ctrl) ((ctrl)->slot_cap & ATTN_LED_PRSN) +#define PWR_LED(ctrl) ((ctrl)->slot_cap & PWR_LED_PRSN) +#define HP_SUPR_RM(ctrl) ((ctrl)->slot_cap & HP_SUPR_RM_SUP) +#define EMI(ctrl) ((ctrl)->slot_cap & EMI_PRSN) extern int pciehp_sysfs_enable_slot(struct slot *slot); extern int pciehp_sysfs_disable_slot(struct slot *slot); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index cf36f2355173..43d8ddb2d679 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -258,7 +258,7 @@ static int init_slots(struct controller *ctrl) goto error_info; } /* create additional sysfs entries */ - if (EMI(ctrl->ctrlcap)) { + if (EMI(ctrl)) { retval = sysfs_create_file(&hotplug_slot->kobj, &hotplug_slot_attr_lock.attr); if (retval) { @@ -291,7 +291,7 @@ static void cleanup_slots(struct controller *ctrl) list_for_each_safe(tmp, next, &ctrl->slot_list) { slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); - if (EMI(ctrl->ctrlcap)) + if (EMI(ctrl)) sysfs_remove_file(&slot->hotplug_slot->kobj, &hotplug_slot_attr_lock.attr); cancel_delayed_work(&slot->work); @@ -312,7 +312,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) hotplug_slot->info->attention_status = status; - if (ATTN_LED(slot->ctrl->ctrlcap)) + if (ATTN_LED(slot->ctrl)) slot->hpc_ops->set_attention_status(slot, status); return 0; @@ -479,7 +479,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ if (rc) /* -ENODEV: shouldn't happen, but deal with it */ value = 0; } - if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { + if ((POWER_CTRL(ctrl)) && !value) { rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ if (rc) goto err_out_free_ctrl_slot; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 0c481f7d2ab3..0a7aa628e955 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -178,7 +178,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) static void set_slot_off(struct controller *ctrl, struct slot * pslot) { /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ - if (POWER_CTRL(ctrl->ctrlcap)) { + if (POWER_CTRL(ctrl)) { if (pslot->hpc_ops->power_off_slot(pslot)) { err("%s: Issue of Slot Power Off command failed\n", __func__); @@ -186,10 +186,10 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) } } - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl)) pslot->hpc_ops->green_led_off(pslot); - if (ATTN_LED(ctrl->ctrlcap)) { + if (ATTN_LED(ctrl)) { if (pslot->hpc_ops->set_attention_status(pslot, 1)) { err("%s: Issue of Set Attention Led command failed\n", __func__); @@ -214,14 +214,14 @@ static int board_added(struct slot *p_slot) __func__, p_slot->device, ctrl->slot_device_offset, p_slot->hp_slot); - if (POWER_CTRL(ctrl->ctrlcap)) { + if (POWER_CTRL(ctrl)) { /* Power on slot */ retval = p_slot->hpc_ops->power_on_slot(p_slot); if (retval) return retval; } - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_blink(p_slot); /* Wait for ~1 second */ @@ -254,7 +254,7 @@ static int board_added(struct slot *p_slot) */ if (pcie_mch_quirk) pci_fixup_device(pci_fixup_final, ctrl->pci_dev); - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_on(p_slot); return 0; @@ -279,7 +279,7 @@ static int remove_board(struct slot *p_slot) dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot); - if (POWER_CTRL(ctrl->ctrlcap)) { + if (POWER_CTRL(ctrl)) { /* power off slot */ retval = p_slot->hpc_ops->power_off_slot(p_slot); if (retval) { @@ -289,7 +289,7 @@ static int remove_board(struct slot *p_slot) } } - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl)) /* turn off Green LED */ p_slot->hpc_ops->green_led_off(p_slot); @@ -327,7 +327,7 @@ static void pciehp_power_thread(struct work_struct *work) case POWERON_STATE: mutex_unlock(&p_slot->lock); if (pciehp_enable_slot(p_slot) && - PWR_LED(p_slot->ctrl->ctrlcap)) + PWR_LED(p_slot->ctrl)) p_slot->hpc_ops->green_led_off(p_slot); mutex_lock(&p_slot->lock); p_slot->state = STATIC_STATE; @@ -409,9 +409,9 @@ static void handle_button_press_event(struct slot *p_slot) "press.\n", p_slot->name); } /* blink green LED and turn off amber */ - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_blink(p_slot); - if (ATTN_LED(ctrl->ctrlcap)) + if (ATTN_LED(ctrl)) p_slot->hpc_ops->set_attention_status(p_slot, 0); schedule_delayed_work(&p_slot->work, 5*HZ); @@ -427,13 +427,13 @@ static void handle_button_press_event(struct slot *p_slot) dbg("%s: button cancel\n", __func__); cancel_delayed_work(&p_slot->work); if (p_slot->state == BLINKINGOFF_STATE) { - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_on(p_slot); } else { - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_off(p_slot); } - if (ATTN_LED(ctrl->ctrlcap)) + if (ATTN_LED(ctrl)) p_slot->hpc_ops->set_attention_status(p_slot, 0); info("PCI slot #%s - action canceled due to button press\n", p_slot->name); @@ -492,16 +492,16 @@ static void interrupt_event_handler(struct work_struct *work) handle_button_press_event(p_slot); break; case INT_POWER_FAULT: - if (!POWER_CTRL(ctrl->ctrlcap)) + if (!POWER_CTRL(ctrl)) break; - if (ATTN_LED(ctrl->ctrlcap)) + if (ATTN_LED(ctrl)) p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl)) p_slot->hpc_ops->green_led_off(p_slot); break; case INT_PRESENCE_ON: case INT_PRESENCE_OFF: - if (!HP_SUPR_RM(ctrl->ctrlcap)) + if (!HP_SUPR_RM(ctrl)) break; dbg("Surprise Removal\n"); update_slot_info(p_slot); @@ -531,7 +531,7 @@ int pciehp_enable_slot(struct slot *p_slot) mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } - if (MRL_SENS(p_slot->ctrl->ctrlcap)) { + if (MRL_SENS(p_slot->ctrl)) { rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%s)\n", __func__, @@ -541,7 +541,7 @@ int pciehp_enable_slot(struct slot *p_slot) } } - if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { + if (POWER_CTRL(p_slot->ctrl)) { rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%s)\n", __func__, @@ -576,7 +576,7 @@ int pciehp_disable_slot(struct slot *p_slot) /* Check to see if (latch closed, card present, power on) */ mutex_lock(&p_slot->ctrl->crit_sect); - if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { + if (!HP_SUPR_RM(p_slot->ctrl)) { ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: no adapter on slot(%s)\n", __func__, @@ -586,7 +586,7 @@ int pciehp_disable_slot(struct slot *p_slot) } } - if (MRL_SENS(p_slot->ctrl->ctrlcap)) { + if (MRL_SENS(p_slot->ctrl)) { ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%s)\n", __func__, @@ -596,7 +596,7 @@ int pciehp_disable_slot(struct slot *p_slot) } } - if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { + if (POWER_CTRL(p_slot->ctrl)) { ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%s)\n", __func__, diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7104a15e2661..58f8018970fa 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1058,11 +1058,11 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) } cmd = PRSN_DETECT_ENABLE; - if (ATTN_BUTTN(ctrl->ctrlcap)) + if (ATTN_BUTTN(ctrl)) cmd |= ATTN_BUTTN_ENABLE; - if (POWER_CTRL(ctrl->ctrlcap)) + if (POWER_CTRL(ctrl)) cmd |= PWR_FAULT_DETECT_ENABLE; - if (MRL_SENS(ctrl->ctrlcap)) + if (MRL_SENS(ctrl)) cmd |= MRL_DETECT_ENABLE; if (!pciehp_poll_mode) cmd |= HP_INTR_ENABLE; @@ -1181,7 +1181,7 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev) ctrl->slot_device_offset = 0; ctrl->num_slots = 1; ctrl->first_slot = slot_cap >> 19; - ctrl->ctrlcap = slot_cap & 0x0000007f; + ctrl->slot_cap = slot_cap; rc = pcie_init_hardware_part1(ctrl, dev); if (rc) -- cgit v1.2.3 From cff006543fa3fca2a47dd795ac524237489858d6 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:39:06 -0700 Subject: pciehp: Remove useless hotplug interrupt enabling Hotplug interrupt is enabled at initialization and nobody clears it. So we need to setup it in each command. This patch removes redundant codes about this. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 54 ++++++---------------------------------- 1 file changed, 8 insertions(+), 46 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 58f8018970fa..4317513771d1 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -462,11 +462,6 @@ static int hpc_toggle_emi(struct slot *slot) slot_cmd = EMI_CTRL; cmd_mask = EMI_CTRL; - if (!pciehp_poll_mode) { - slot_cmd = slot_cmd | HP_INTR_ENABLE; - cmd_mask = cmd_mask | HP_INTR_ENABLE; - } - rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask); slot->last_emi_toggle = get_seconds(); @@ -494,11 +489,6 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) default: return -1; } - if (!pciehp_poll_mode) { - slot_cmd = slot_cmd | HP_INTR_ENABLE; - cmd_mask = cmd_mask | HP_INTR_ENABLE; - } - rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); @@ -514,13 +504,7 @@ static void hpc_set_green_led_on(struct slot *slot) slot_cmd = 0x0100; cmd_mask = PWR_LED_CTRL; - if (!pciehp_poll_mode) { - slot_cmd = slot_cmd | HP_INTR_ENABLE; - cmd_mask = cmd_mask | HP_INTR_ENABLE; - } - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); - dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); } @@ -533,11 +517,6 @@ static void hpc_set_green_led_off(struct slot *slot) slot_cmd = 0x0300; cmd_mask = PWR_LED_CTRL; - if (!pciehp_poll_mode) { - slot_cmd = slot_cmd | HP_INTR_ENABLE; - cmd_mask = cmd_mask | HP_INTR_ENABLE; - } - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); @@ -551,13 +530,7 @@ static void hpc_set_green_led_blink(struct slot *slot) slot_cmd = 0x0200; cmd_mask = PWR_LED_CTRL; - if (!pciehp_poll_mode) { - slot_cmd = slot_cmd | HP_INTR_ENABLE; - cmd_mask = cmd_mask | HP_INTR_ENABLE; - } - pcie_write_cmd(ctrl, slot_cmd, cmd_mask); - dbg("%s: SLOTCTRL %x write cmd %x\n", __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); } @@ -607,16 +580,10 @@ static int hpc_power_on_slot(struct slot * slot) cmd_mask = PWR_CTRL; /* Enable detection that we turned off at slot power-off time */ if (!pciehp_poll_mode) { - slot_cmd = slot_cmd | - PWR_FAULT_DETECT_ENABLE | - MRL_DETECT_ENABLE | - PRSN_DETECT_ENABLE | - HP_INTR_ENABLE; - cmd_mask = cmd_mask | - PWR_FAULT_DETECT_ENABLE | - MRL_DETECT_ENABLE | - PRSN_DETECT_ENABLE | - HP_INTR_ENABLE; + slot_cmd |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | + PRSN_DETECT_ENABLE); + cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | + PRSN_DETECT_ENABLE); } retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); @@ -692,15 +659,10 @@ static int hpc_power_off_slot(struct slot * slot) * till the slot is powered on again. */ if (!pciehp_poll_mode) { - slot_cmd = (slot_cmd & - ~PWR_FAULT_DETECT_ENABLE & - ~MRL_DETECT_ENABLE & - ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE; - cmd_mask = cmd_mask | - PWR_FAULT_DETECT_ENABLE | - MRL_DETECT_ENABLE | - PRSN_DETECT_ENABLE | - HP_INTR_ENABLE; + slot_cmd &= ~(PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | + PRSN_DETECT_ENABLE); + cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | + PRSN_DETECT_ENABLE); } retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); -- cgit v1.2.3 From d84be093a81c29e085144c4d483d9fa0a83a1918 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:39:07 -0700 Subject: pciehp: Mask hotplug interrupt at controller release We must disable hotplug interrupt at controller relase time, otherwise spurious interrupts might happen if any slot events occured (e.g. MRL change) after unloading pciehp driver. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 4317513771d1..df1266cd6861 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -537,6 +537,10 @@ static void hpc_set_green_led_blink(struct slot *slot) static void hpc_release_ctlr(struct controller *ctrl) { + /* Mask Hot-plug Interrupt Enable */ + if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) + err("%s: Cannot mask hotplut interrupt enable\n", __func__); + if (pciehp_poll_mode) del_timer(&ctrl->poll_timer); else -- cgit v1.2.3 From 2aeeef11999590d88249fbd086671af8300116f4 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:39:08 -0700 Subject: pciehp: Clean up pcie_init() Clean up pciehp_ini(). This patch is trying to - Remove redundant capablity checks that were already done in PCIe port bus driver. - Separate the code only for debugging and make debug information easier to read. - Make the entire code easier to read and understand what it is doing. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 198 +++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 110 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index df1266cd6861..5cadcd0654cb 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -221,6 +221,32 @@ static void start_int_poll_timer(struct controller *ctrl, int sec) add_timer(&ctrl->poll_timer); } +static inline int pciehp_request_irq(struct controller *ctrl) +{ + int retval, irq = ctrl->pci_dev->irq; + + /* Install interrupt polling timer. Start with 10 sec delay */ + if (pciehp_poll_mode) { + init_timer(&ctrl->poll_timer); + start_int_poll_timer(ctrl, 10); + return 0; + } + + /* Installs the interrupt handler */ + retval = request_irq(irq, pcie_isr, IRQF_SHARED, MY_NAME, ctrl); + if (retval) + err("Cannot get irq %d for the hotplug controller\n", irq); + return retval; +} + +static inline void pciehp_free_irq(struct controller *ctrl) +{ + if (pciehp_poll_mode) + del_timer_sync(&ctrl->poll_timer); + else + free_irq(ctrl->pci_dev->irq, ctrl); +} + static inline int pcie_wait_cmd(struct controller *ctrl) { int retval = 0; @@ -541,10 +567,8 @@ static void hpc_release_ctlr(struct controller *ctrl) if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) err("%s: Cannot mask hotplut interrupt enable\n", __func__); - if (pciehp_poll_mode) - del_timer(&ctrl->poll_timer); - else - free_irq(ctrl->pci_dev->irq, ctrl); + /* Free interrupt handler or interrupt polling timer */ + pciehp_free_irq(ctrl); /* * If this is the last controller to be released, destroy the @@ -1057,121 +1081,79 @@ abort: return -1; } -int pcie_init(struct controller *ctrl, struct pcie_device *dev) +static inline void dbg_ctrl(struct controller *ctrl) { - int rc; - u16 cap_reg; - u32 slot_cap; - int cap_base; - u16 slot_status, slot_ctrl; - struct pci_dev *pdev; - - pdev = dev->port; - ctrl->pci_dev = pdev; /* save pci_dev in context */ + int i; + u16 reg16; + struct pci_dev *pdev = ctrl->pci_dev; - dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", - __func__, pdev->vendor, pdev->device); + if (!pciehp_debug) + return; - cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (cap_base == 0) { - dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __func__); - goto abort; + dbg("Hotplug Controller:\n"); + dbg(" Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n", pci_name(pdev), pdev->irq); + dbg(" Vendor ID : 0x%04x\n", pdev->vendor); + dbg(" Device ID : 0x%04x\n", pdev->device); + dbg(" Subsystem ID : 0x%04x\n", pdev->subsystem_device); + dbg(" Subsystem Vendor ID : 0x%04x\n", pdev->subsystem_vendor); + dbg(" PCIe Cap offset : 0x%02x\n", ctrl->cap_base); + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + if (!pci_resource_len(pdev, i)) + continue; + dbg(" PCI resource [%d] : 0x%llx@0x%llx\n", i, + (unsigned long long)pci_resource_len(pdev, i), + (unsigned long long)pci_resource_start(pdev, i)); } + dbg("Slot Capabilities : 0x%08x\n", ctrl->slot_cap); + dbg(" Physical Slot Number : %d\n", ctrl->first_slot); + dbg(" Attention Button : %3s\n", ATTN_BUTTN(ctrl) ? "yes" : "no"); + dbg(" Power Controller : %3s\n", POWER_CTRL(ctrl) ? "yes" : "no"); + dbg(" MRL Sensor : %3s\n", MRL_SENS(ctrl) ? "yes" : "no"); + dbg(" Attention Indicator : %3s\n", ATTN_LED(ctrl) ? "yes" : "no"); + dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no"); + dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no"); + dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no"); + pciehp_readw(ctrl, SLOTSTATUS, ®16); + dbg("Slot Status : 0x%04x\n", reg16); + pciehp_readw(ctrl, SLOTSTATUS, ®16); + dbg("Slot Control : 0x%04x\n", reg16); +} - ctrl->cap_base = cap_base; - - dbg("%s: pcie_cap_base %x\n", __func__, cap_base); +int pcie_init(struct controller *ctrl, struct pcie_device *dev) +{ + u32 slot_cap; + struct pci_dev *pdev = dev->port; - rc = pciehp_readw(ctrl, CAPREG, &cap_reg); - if (rc) { - err("%s: Cannot read CAPREG register\n", __func__); - goto abort; - } - dbg("%s: CAPREG offset %x cap_reg %x\n", - __func__, ctrl->cap_base + CAPREG, cap_reg); - - if (((cap_reg & SLOT_IMPL) == 0) || - (((cap_reg & DEV_PORT_TYPE) != 0x0040) - && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) { - dbg("%s : This is not a root port or the port is not " - "connected to a slot\n", __func__); + ctrl->pci_dev = pdev; + ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); + if (!ctrl->cap_base) { + err("%s: Cannot find PCI Express capability\n", __func__); goto abort; } - - rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); - if (rc) { + if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) { err("%s: Cannot read SLOTCAP register\n", __func__); goto abort; } - dbg("%s: SLOTCAP offset %x slot_cap %x\n", - __func__, ctrl->cap_base + SLOTCAP, slot_cap); - - if (!(slot_cap & HP_CAP)) { - dbg("%s : This slot is not hot-plug capable\n", __func__); - goto abort; - } - /* For debugging purpose */ - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (rc) { - err("%s: Cannot read SLOTSTATUS register\n", __func__); - goto abort; - } - dbg("%s: SLOTSTATUS offset %x slot_status %x\n", - __func__, ctrl->cap_base + SLOTSTATUS, slot_status); - - rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); - if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __func__); - goto abort; - } - dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", - __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl); - - for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) - if (pci_resource_len(pdev, rc) > 0) - dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc, - (unsigned long long)pci_resource_start(pdev, rc), - (unsigned long long)pci_resource_len(pdev, rc)); - - info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", - pdev->vendor, pdev->device, - pdev->subsystem_vendor, pdev->subsystem_device); + ctrl->slot_cap = slot_cap; + ctrl->first_slot = slot_cap >> 19; + ctrl->slot_device_offset = 0; + ctrl->num_slots = 1; + ctrl->hpc_ops = &pciehp_hpc_ops; mutex_init(&ctrl->crit_sect); mutex_init(&ctrl->ctrl_lock); - - /* setup wait queue */ init_waitqueue_head(&ctrl->queue); + dbg_ctrl(ctrl); - /* return PCI Controller Info */ - ctrl->slot_device_offset = 0; - ctrl->num_slots = 1; - ctrl->first_slot = slot_cap >> 19; - ctrl->slot_cap = slot_cap; + info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", + pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device); - rc = pcie_init_hardware_part1(ctrl, dev); - if (rc) + if (pcie_init_hardware_part1(ctrl, dev)) goto abort; - if (pciehp_poll_mode) { - /* Install interrupt polling timer. Start with 10 sec delay */ - init_timer(&ctrl->poll_timer); - start_int_poll_timer(ctrl, 10); - } else { - /* Installs the interrupt handler */ - rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED, - MY_NAME, (void *)ctrl); - dbg("%s: request_irq %d for hpc%d (returns %d)\n", - __func__, ctrl->pci_dev->irq, - atomic_read(&pciehp_num_controllers), rc); - if (rc) { - err("Can't get irq %d for the hotplug controller\n", - ctrl->pci_dev->irq); - goto abort; - } - } - dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); + if (pciehp_request_irq(ctrl)) + goto abort; /* * If this is the first controller to be initialized, @@ -1180,21 +1162,17 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev) if (atomic_add_return(1, &pciehp_num_controllers) == 1) { pciehp_wq = create_singlethread_workqueue("pciehpd"); if (!pciehp_wq) { - rc = -ENOMEM; goto abort_free_irq; } } - rc = pcie_init_hardware_part2(ctrl, dev); - if (rc == 0) { - ctrl->hpc_ops = &pciehp_hpc_ops; - return 0; - } + if (pcie_init_hardware_part2(ctrl, dev)) + goto abort_free_irq; + + return 0; + abort_free_irq: - if (pciehp_poll_mode) - del_timer_sync(&ctrl->poll_timer); - else - free_irq(ctrl->pci_dev->irq, ctrl); + pciehp_free_irq(ctrl); abort: return -1; } -- cgit v1.2.3 From 4ea3e58b22b3719af99c567d08136bbe50cb4435 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 25 Apr 2008 14:39:10 -0700 Subject: make pciehp_acpi_get_hp_hw_control_from_firmware() this_patch_makes_the_needlessly_global_pciehp_acpi_get_hp_hw_control_from_firmware_static ;) Signed-off-by: Adrian Bunk Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 5cadcd0654cb..3efb1296290d 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -954,7 +954,7 @@ static struct hpc_ops pciehp_hpc_ops = { }; #ifdef CONFIG_ACPI -int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) +static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) { acpi_status status; acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); -- cgit v1.2.3 From ef0ff95f136f0f2d035667af5d18b824609de320 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:39:12 -0700 Subject: shpchp: fix slot name Current shpchp uses the combination of bus number and slot number as a slot name. But it is not a good idea because bus number is not a physical identifier but a logical identifier. This is against the shpc specification. So remove the bus number from the physical identifier. However, there are some platforms with the problem that it provides the same slot number. For those platforms, this patch also introduces new module option 'shpchp_slot_with_bus'. If it is specified, shpchp uses the combination of bus number and slot number as a slot name. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/shpchp_core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 43816d4b3c43..1648076600fc 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -39,6 +39,7 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; +int shpchp_slot_with_bus; struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" @@ -52,9 +53,11 @@ MODULE_LICENSE("GPL"); module_param(shpchp_debug, bool, 0644); module_param(shpchp_poll_mode, bool, 0644); module_param(shpchp_poll_time, int, 0644); +module_param(shpchp_slot_with_bus, bool, 0644); MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); +MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name"); #define SHPC_MODULE_NAME "shpchp" @@ -100,8 +103,12 @@ static void release_slot(struct hotplug_slot *hotplug_slot) static void make_slot_name(struct slot *slot) { - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", - slot->bus, slot->number); + if (shpchp_slot_with_bus) + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", + slot->bus, slot->number); + else + snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", + slot->number); } static int init_slots(struct controller *ctrl) -- cgit v1.2.3 From b7aa1f1603bea4fdec49a915712dea280cfd07e8 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 25 Apr 2008 14:39:14 -0700 Subject: pciehp: Fix command write Current implementation of pciehp_write_cmd() always enables command completed interrupt. But pciehp_write_cmd() is also used for clearing command completed interrupt enable bit. In this case, we must not set the command completed interrupt enable bit. To fix this bug, this patch add the check to see if caller wants to change command complete interrupt enable bit. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 3efb1296290d..49883c59756e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -301,7 +301,10 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) } slot_ctrl &= ~mask; - slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE); + slot_ctrl |= (cmd & mask); + /* Don't enable command completed if caller is changing it. */ + if (!(mask & CMD_CMPL_INTR_ENABLE)) + slot_ctrl |= CMD_CMPL_INTR_ENABLE; ctrl->cmd_busy = 1; smp_mb(); -- cgit v1.2.3 From 8e149e09f91098fd72bf9ac5b4a77a693abf721e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 23 Apr 2008 14:56:30 -0700 Subject: pci/irq: restore mask_bits in msi shutdown -v3 [PATCH 1/2] pci/irq: restore mask_bits in msi shutdown -v3 Yinghai found that kexec'ing a RHEL 5.1 kernel with 2.6.25-rc3+ kernels prevents his NIC from working. He bisected to | commit 89d694b9dbe769ca1004e01db0ca43964806a611 | Author: Thomas Gleixner | Date: Mon Feb 18 18:25:17 2008 +0100 | | genirq: do not leave interupts enabled on free_irq | | The default_disable() function was changed in commit: | | 76d2160147f43f982dfe881404cfde9fd0a9da21 | genirq: do not mask interrupts by default | For MSI, default_shutdown will call mask_bit for msi device. All mask bits will left disabled after free_irq. Then in the kexec case, the next kernel can only use msi_enable bit, so all device's MSI can not be used. So lets to restore the mask bit to its pci reset defined value (enabled) when we disable the kernels use of msi to be a little friendlier to kexec'd kernels. Extend msi_set_mask_bit to msi_set_mask_bits to take mask, so we can fully restore that to 0x00 instead of 0xfe. Signed-off-by: Yinghai Lu Signed-off-by: Jesse Barnes --- drivers/pci/msi.c | 21 ++++++++++++++------- include/linux/msi.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 26938da8f438..e3a05cc9a595 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -123,7 +123,7 @@ static void msix_flush_writes(unsigned int irq) } } -static void msi_set_mask_bit(unsigned int irq, int flag) +static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) { struct msi_desc *entry; @@ -137,8 +137,8 @@ static void msi_set_mask_bit(unsigned int irq, int flag) pos = (long)entry->mask_base; pci_read_config_dword(entry->dev, pos, &mask_bits); - mask_bits &= ~(1); - mask_bits |= flag; + mask_bits &= ~(mask); + mask_bits |= flag & mask; pci_write_config_dword(entry->dev, pos, mask_bits); } else { msi_set_enable(entry->dev, !flag); @@ -241,13 +241,13 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) void mask_msi_irq(unsigned int irq) { - msi_set_mask_bit(irq, 1); + msi_set_mask_bits(irq, 1, 1); msix_flush_writes(irq); } void unmask_msi_irq(unsigned int irq) { - msi_set_mask_bit(irq, 0); + msi_set_mask_bits(irq, 1, 0); msix_flush_writes(irq); } @@ -291,7 +291,8 @@ static void __pci_restore_msi_state(struct pci_dev *dev) msi_set_enable(dev, 0); write_msi_msg(dev->irq, &entry->msg); if (entry->msi_attrib.maskbit) - msi_set_mask_bit(dev->irq, entry->msi_attrib.masked); + msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask, + entry->msi_attrib.masked); pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE); @@ -315,7 +316,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev) list_for_each_entry(entry, &dev->msi_list, list) { write_msi_msg(entry->irq, &entry->msg); - msi_set_mask_bit(entry->irq, entry->msi_attrib.masked); + msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked); } BUG_ON(list_empty(&dev->msi_list)); @@ -382,6 +383,7 @@ static int msi_capability_init(struct pci_dev *dev) pci_write_config_dword(dev, msi_mask_bits_reg(pos, is_64bit_address(control)), maskbits); + entry->msi_attrib.maskbits_mask = temp; } list_add_tail(&entry->list, &dev->msi_list); @@ -583,6 +585,11 @@ void pci_disable_msi(struct pci_dev* dev) BUG_ON(list_empty(&dev->msi_list)); entry = list_entry(dev->msi_list.next, struct msi_desc, list); + /* Return the the pci reset with msi irqs unmasked */ + if (entry->msi_attrib.maskbit) { + u32 mask = entry->msi_attrib.maskbits_mask; + msi_set_mask_bits(dev->irq, mask, ~mask); + } if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { return; } diff --git a/include/linux/msi.h b/include/linux/msi.h index 94bb46d82efd..8f2939227207 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -22,6 +22,7 @@ struct msi_desc { __u8 masked : 1; __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */ __u8 pos; /* Location of the msi capability */ + __u32 maskbits_mask; /* mask bits mask */ __u16 entry_nr; /* specific enabled entry */ unsigned default_irq; /* default pre-assigned irq */ }msi_attrib; -- cgit v1.2.3 From d52877c7b1afb8c37ebe17e2005040b79cb618b0 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 23 Apr 2008 14:58:09 -0700 Subject: pci/irq: let pci_device_shutdown to call pci_msi_shutdown v2 [PATCH 2/2] pci/irq: let pci_device_shutdown to call pci_msi_shutdown v2 this change | commit 23a274c8a5adafc74a66f16988776fc7dd6f6e51 | Author: Prakash, Sathya | Date: Fri Mar 7 15:53:21 2008 +0530 | | [SCSI] mpt fusion: Enable MSI by default for SAS controllers | | This patch modifies the driver to enable MSI by default for all SAS chips. | | Signed-off-by: Sathya Prakash | Signed-off-by: James Bottomley | Causes the kexec of a RHEL 5.1 kernel to fail. root casue: the rhel 5.1 kernel still uses INTx emulation. and mptscsih_shutdown doesn't call pci_disable_msi to reenable INTx on kexec path So call pci_msi_shutdown in the shutdown path to do the same thing to msix Signed-off-by: Yinghai Lu Signed-off-by: Jesse Barnes --- drivers/pci/msi.c | 35 ++++++++++++++++++++++++++--------- drivers/pci/pci-driver.c | 2 ++ include/linux/pci.h | 6 ++++++ 3 files changed, 34 insertions(+), 9 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index e3a05cc9a595..8c61304cbb37 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -571,10 +571,9 @@ int pci_enable_msi(struct pci_dev* dev) } EXPORT_SYMBOL(pci_enable_msi); -void pci_disable_msi(struct pci_dev* dev) +void pci_msi_shutdown(struct pci_dev* dev) { struct msi_desc *entry; - int default_irq; if (!pci_msi_enable || !dev || !dev->msi_enabled) return; @@ -590,15 +589,26 @@ void pci_disable_msi(struct pci_dev* dev) u32 mask = entry->msi_attrib.maskbits_mask; msi_set_mask_bits(dev->irq, mask, ~mask); } - if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { + if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) return; - } - - default_irq = entry->msi_attrib.default_irq; - msi_free_irqs(dev); /* Restore dev->irq to its default pin-assertion irq */ - dev->irq = default_irq; + dev->irq = entry->msi_attrib.default_irq; +} +void pci_disable_msi(struct pci_dev* dev) +{ + struct msi_desc *entry; + + if (!pci_msi_enable || !dev || !dev->msi_enabled) + return; + + pci_msi_shutdown(dev); + + entry = list_entry(dev->msi_list.next, struct msi_desc, list); + if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) + return; + + msi_free_irqs(dev); } EXPORT_SYMBOL(pci_disable_msi); @@ -691,7 +701,7 @@ static void msix_free_all_irqs(struct pci_dev *dev) msi_free_irqs(dev); } -void pci_disable_msix(struct pci_dev* dev) +void pci_msix_shutdown(struct pci_dev* dev) { if (!pci_msi_enable || !dev || !dev->msix_enabled) return; @@ -699,6 +709,13 @@ void pci_disable_msix(struct pci_dev* dev) msix_set_enable(dev, 0); pci_intx_for_msi(dev, 1); dev->msix_enabled = 0; +} +void pci_disable_msix(struct pci_dev* dev) +{ + if (!pci_msi_enable || !dev || !dev->msix_enabled) + return; + + pci_msix_shutdown(dev); msix_free_all_irqs(dev); } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e8d94fafc280..72cf61ed8f96 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -360,6 +360,8 @@ static void pci_device_shutdown(struct device *dev) if (drv && drv->shutdown) drv->shutdown(pci_dev); + pci_msi_shutdown(pci_dev); + pci_msix_shutdown(pci_dev); } /** diff --git a/include/linux/pci.h b/include/linux/pci.h index 7a0770d4c4e2..e09c57e9c373 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -701,6 +701,8 @@ static inline int pci_enable_msi(struct pci_dev *dev) return -1; } +static inline void pci_msi_shutdown(struct pci_dev *dev) +{ } static inline void pci_disable_msi(struct pci_dev *dev) { } @@ -710,6 +712,8 @@ static inline int pci_enable_msix(struct pci_dev *dev, return -1; } +static inline void pci_msix_shutdown(struct pci_dev *dev) +{ } static inline void pci_disable_msix(struct pci_dev *dev) { } @@ -720,9 +724,11 @@ static inline void pci_restore_msi_state(struct pci_dev *dev) { } #else extern int pci_enable_msi(struct pci_dev *dev); +extern void pci_msi_shutdown(struct pci_dev *dev); extern void pci_disable_msi(struct pci_dev *dev); extern int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec); +extern void pci_msix_shutdown(struct pci_dev *dev); extern void pci_disable_msix(struct pci_dev *dev); extern void msi_remove_pci_irq_vectors(struct pci_dev *dev); extern void pci_restore_msi_state(struct pci_dev *dev); -- cgit v1.2.3 From a53edac131cadee317e7e36a5908bb4c71d874cd Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 29 Apr 2008 09:15:04 -0700 Subject: pciehp: fix error message about getting hotplug control People are confused by the following error message that actually is not for indicating a error. Cannot get control of hotplug hardware for pci %s This patch changes this message to debug message. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp_hpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 49883c59756e..891f81a0400c 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1017,7 +1017,7 @@ static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) break; } - err("Cannot get control of hotplug hardware for pci %s\n", + dbg("Cannot get control of hotplug hardware for pci %s\n", pci_name(dev)); kfree(string.pointer); -- cgit v1.2.3