diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-28 14:03:52 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-28 14:03:52 -0800 |
commit | 6679fbe6bdbce2f3cf532e354bbc8398d9b6672a (patch) | |
tree | ae91179f8be23d188873d8460db4c205f5519009 /pci | |
parent | d38f69ec46298606986c5b2cb9ef9292ca642968 (diff) | |
download | patches-6679fbe6bdbce2f3cf532e354bbc8398d9b6672a.tar.gz |
shpchp patches
Diffstat (limited to 'pci')
6 files changed, 688 insertions, 0 deletions
diff --git a/pci/shpchp-fix-improper-mmio-mapping.patch b/pci/shpchp-fix-improper-mmio-mapping.patch new file mode 100644 index 0000000000000..6ca78e29e1ea2 --- /dev/null +++ b/pci/shpchp-fix-improper-mmio-mapping.patch @@ -0,0 +1,178 @@ +From kaneshige.kenji@jp.fujitsu.com Wed Nov 23 18:42:59 2005 +Message-ID: <4385274B.5010407@jp.fujitsu.com> +Date: Thu, 24 Nov 2005 11:36:59 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com>, <kristen.c.accardi@intel.com> +CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: shpchp: fix improper mmio mapping + +Current SHPCHP driver seems not to map MMIO region properly. This +patch fixes this bug. This patch also cleanup the code. + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/shpchp.h | 3 + + drivers/pci/hotplug/shpchp_core.c | 2 - + drivers/pci/hotplug/shpchp_hpc.c | 73 +++++++++++++++++++++++--------------- + 3 files changed, 49 insertions(+), 29 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h ++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h +@@ -98,6 +98,9 @@ struct controller { + enum pci_bus_speed speed; + u32 first_slot; /* First physical slot number */ + u8 slot_bus; /* Bus where the slots handled by this controller sit */ ++ u32 cap_offset; ++ unsigned long mmio_base; ++ unsigned long mmio_size; + }; + + struct hotplug_params { +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -791,7 +791,7 @@ static void hpc_release_ctlr(struct cont + } + if (php_ctlr->pci_dev) { + iounmap(php_ctlr->creg); +- release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0)); ++ release_mem_region(ctrl->mmio_base, ctrl->mmio_size); + php_ctlr->pci_dev = NULL; + } + +@@ -1320,19 +1320,34 @@ static struct hpc_ops shpchp_hpc_ops = { + .check_cmd_status = hpc_check_cmd_status, + }; + ++inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, ++ u32 *value) ++{ ++ int rc; ++ u32 cap_offset = ctrl->cap_offset; ++ struct pci_dev *pdev = ctrl->pci_dev; ++ ++ rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); ++ if (rc) ++ return rc; ++ return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); ++} ++ + int shpc_init(struct controller * ctrl, struct pci_dev * pdev) + { + struct php_ctlr_state_s *php_ctlr, *p; + void *instance_id = ctrl; +- int rc; ++ int rc, num_slots = 0; + u8 hp_slot; + static int first = 1; +- u32 shpc_cap_offset, shpc_base_offset; ++ u32 shpc_base_offset; + u32 tempdword, slot_reg; + u8 i; + + DBG_ENTER_ROUTINE + ++ ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ ++ + spin_lock_init(&list_lock); + php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); + +@@ -1347,41 +1362,45 @@ int shpc_init(struct controller * ctrl, + + if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == + PCI_DEVICE_ID_AMD_GOLAM_7450)) { +- shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */ ++ /* amd shpc driver doesn't use Base Offset; assume 0 */ ++ ctrl->mmio_base = pci_resource_start(pdev, 0); ++ ctrl->mmio_size = pci_resource_len(pdev, 0); + } else { +- if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) { +- err("%s : shpc_cap_offset == 0\n", __FUNCTION__); ++ ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC); ++ if (!ctrl->cap_offset) { ++ err("%s : cap_offset == 0\n", __FUNCTION__); + goto abort_free_ctlr; + } +- dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset); +- +- rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET); ++ dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); ++ ++ rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset); + if (rc) { +- err("%s : pci_word_config_byte failed\n", __FUNCTION__); ++ err("%s: cannot read base_offset\n", __FUNCTION__); + goto abort_free_ctlr; + } +- +- rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset); ++ ++ rc = shpc_indirect_creg_read(ctrl, 3, &tempdword); + if (rc) { +- err("%s : pci_read_config_dword failed\n", __FUNCTION__); ++ err("%s: cannot read slot config\n", __FUNCTION__); + goto abort_free_ctlr; + } ++ num_slots = tempdword & SLOT_NUM; ++ dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); + +- for (i = 0; i <= 14; i++) { +- rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , i); +- if (rc) { +- err("%s : pci_word_config_byte failed\n", __FUNCTION__); +- goto abort_free_ctlr; +- } +- +- rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword); ++ for (i = 0; i < 9 + num_slots; i++) { ++ rc = shpc_indirect_creg_read(ctrl, i, &tempdword); + if (rc) { +- err("%s : pci_read_config_dword failed\n", __FUNCTION__); ++ err("%s: cannot read creg (index = %d)\n", ++ __FUNCTION__, i); + goto abort_free_ctlr; + } + dbg("%s: offset %d: value %x\n", __FUNCTION__,i, + tempdword); + } ++ ++ ctrl->mmio_base = ++ pci_resource_start(pdev, 0) + shpc_base_offset; ++ ctrl->mmio_size = 0x24 + 0x4 * num_slots; + } + + if (first) { +@@ -1395,16 +1414,16 @@ int shpc_init(struct controller * ctrl, + if (pci_enable_device(pdev)) + goto abort_free_ctlr; + +- if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) { ++ if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { + err("%s: cannot reserve MMIO region\n", __FUNCTION__); + goto abort_free_ctlr; + } + +- php_ctlr->creg = ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); ++ php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); + if (!php_ctlr->creg) { +- err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), +- pci_resource_start(pdev, 0) + shpc_base_offset); +- release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); ++ err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, ++ ctrl->mmio_size, ctrl->mmio_base); ++ release_mem_region(ctrl->mmio_base, ctrl->mmio_size); + goto abort_free_ctlr; + } + dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_core.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_core.c +@@ -377,8 +377,6 @@ static int shpc_probe(struct pci_dev *pd + goto err_out_free_ctrl; + } + +- ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ +- + pci_set_drvdata(pdev, ctrl); + + ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); diff --git a/pci/shpchp-fix-improper-reference-to-mode-1-ecc-capability-bit.patch b/pci/shpchp-fix-improper-reference-to-mode-1-ecc-capability-bit.patch new file mode 100644 index 0000000000000..ac4ccb1a3d360 --- /dev/null +++ b/pci/shpchp-fix-improper-reference-to-mode-1-ecc-capability-bit.patch @@ -0,0 +1,31 @@ +From kaneshige.kenji@jp.fujitsu.com Wed Nov 23 18:37:41 2005 +Message-ID: <438526D9.1020605@jp.fujitsu.com> +Date: Thu, 24 Nov 2005 11:35:05 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com>, <kristen.c.accardi@intel.com> +CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: shpchp: fix improper reference to Mode 1 ECC Capability" bit + +The hpc_get_mode1_ECC_cap() function of SHPCHP driver seems to refer +the wrong bit for refering the "Mode 1 ECC Capability" bit. This bug +seems not to cause any problem so far. But I think this should be +fixed. This patch fixes this bug. + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/shpchp_hpc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -604,7 +604,7 @@ static int hpc_get_mode1_ECC_cap(struct + sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); + + if (pi == 2) { +- *mode = (sec_bus_status & 0x0100) >> 7; ++ *mode = (sec_bus_status & 0x0100) >> 8; + } else { + retval = -1; + } diff --git a/pci/shpchp-fix-improper-reference-to-slot-avail-regsister.patch b/pci/shpchp-fix-improper-reference-to-slot-avail-regsister.patch new file mode 100644 index 0000000000000..bdce2eab7434d --- /dev/null +++ b/pci/shpchp-fix-improper-reference-to-slot-avail-regsister.patch @@ -0,0 +1,87 @@ +From kaneshige.kenji@jp.fujitsu.com Wed Nov 23 20:48:14 2005 +Message-ID: <43854511.9060405@jp.fujitsu.com> +Date: Thu, 24 Nov 2005 13:44:01 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com>, <kristen.c.accardi@intel.com> +CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: shpchp: fix improper reference to Slot Avail Regsister + +The hpc_get_max_bus_speed() function of the SHPCHP driver seems to +refer wrong bits in the "Slot Avail Register I" and "Slot Avail +Register II". This patch fixes this bug. And this also cleanup the +code. + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/pci/hotplug/shpchp_hpc.c | 33 ++++++++++++++++----------------- + 1 file changed, 16 insertions(+), 17 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -1121,7 +1121,6 @@ static int hpc_get_max_bus_speed (struct + int retval = 0; + u8 pi; + u32 slot_avail1, slot_avail2; +- int slot_num; + + DBG_ENTER_ROUTINE + +@@ -1140,39 +1139,39 @@ static int hpc_get_max_bus_speed (struct + slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); + + if (pi == 2) { +- if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_533) >> 27) ) != 0 ) ++ if (slot_avail2 & SLOT_133MHZ_PCIX_533) + bus_speed = PCIX_133MHZ_533; +- else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_533) >> 23) ) != 0 ) ++ else if (slot_avail2 & SLOT_100MHZ_PCIX_533) + bus_speed = PCIX_100MHZ_533; +- else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_533) >> 19) ) != 0 ) ++ else if (slot_avail2 & SLOT_66MHZ_PCIX_533) + bus_speed = PCIX_66MHZ_533; +- else if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_266) >> 15) ) != 0 ) ++ else if (slot_avail2 & SLOT_133MHZ_PCIX_266) + bus_speed = PCIX_133MHZ_266; +- else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_266) >> 11) ) != 0 ) ++ else if (slot_avail2 & SLOT_100MHZ_PCIX_266) + bus_speed = PCIX_100MHZ_266; +- else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_266) >> 7) ) != 0 ) ++ else if (slot_avail2 & SLOT_66MHZ_PCIX_266) + bus_speed = PCIX_66MHZ_266; +- else if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 ) ++ else if (slot_avail1 & SLOT_133MHZ_PCIX) + bus_speed = PCIX_133MHZ; +- else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 ) ++ else if (slot_avail1 & SLOT_100MHZ_PCIX) + bus_speed = PCIX_100MHZ; +- else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 ) ++ else if (slot_avail1 & SLOT_66MHZ_PCIX) + bus_speed = PCIX_66MHZ; +- else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 ) ++ else if (slot_avail2 & SLOT_66MHZ) + bus_speed = PCI_66MHZ; +- else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 ) ++ else if (slot_avail1 & SLOT_33MHZ) + bus_speed = PCI_33MHZ; + else bus_speed = PCI_SPEED_UNKNOWN; + } else { +- if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 ) ++ if (slot_avail1 & SLOT_133MHZ_PCIX) + bus_speed = PCIX_133MHZ; +- else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 ) ++ else if (slot_avail1 & SLOT_100MHZ_PCIX) + bus_speed = PCIX_100MHZ; +- else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 ) ++ else if (slot_avail1 & SLOT_66MHZ_PCIX) + bus_speed = PCIX_66MHZ; +- else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 ) ++ else if (slot_avail2 & SLOT_66MHZ) + bus_speed = PCI_66MHZ; +- else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 ) ++ else if (slot_avail1 & SLOT_33MHZ) + bus_speed = PCI_33MHZ; + else bus_speed = PCI_SPEED_UNKNOWN; + } diff --git a/pci/shpchp-fix-improper-wait-for-command-completion.patch b/pci/shpchp-fix-improper-wait-for-command-completion.patch new file mode 100644 index 0000000000000..61ec54a9fd301 --- /dev/null +++ b/pci/shpchp-fix-improper-wait-for-command-completion.patch @@ -0,0 +1,247 @@ +From kaneshige.kenji@jp.fujitsu.com Thu Nov 24 19:32:27 2005 +Message-ID: <438684F5.4080107@jp.fujitsu.com> +Date: Fri, 25 Nov 2005 12:28:53 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com>, <kristen.c.accardi@intel.com> +CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: shpchp: fix improper wait for command completion + +Current SHPCHP driver uses msleep_interruptible() function to wait for +a command completion event. But I think this would cause an unnecessary +long wait until timeout, if command completion interrupt came before +task state was changed to TASK_INTERRUPTIBLE. This patch fixes this +issue. With this patch, command completion becomes faster as follows: + +o Without this patch + + # time echo 1 > power + + real 0m4.708s + user 0m0.000s + sys 0m0.524s + +o With this patch + + # time echo 1 > power + + real 0m2.221s + user 0m0.000s + sys 0m0.532s + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/shpchp.h | 1 + + drivers/pci/hotplug/shpchp_ctrl.c | 37 ------------------------------------- + drivers/pci/hotplug/shpchp_hpc.c | 26 ++++++++++++++++++++++++++ + 3 files changed, 27 insertions(+), 37 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h ++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h +@@ -101,6 +101,7 @@ struct controller { + u32 cap_offset; + unsigned long mmio_base; + unsigned long mmio_size; ++ volatile int cmd_busy; + }; + + struct hotplug_params { +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -275,6 +275,25 @@ static void start_int_poll_timer(struct + return; + } + ++static inline int shpc_wait_cmd(struct controller *ctrl) ++{ ++ int retval = 0; ++ unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; ++ unsigned long timeout = msecs_to_jiffies(timeout_msec); ++ int rc = wait_event_interruptible_timeout(ctrl->queue, ++ !ctrl->cmd_busy, timeout); ++ if (!rc) { ++ retval = -EIO; ++ err("Command not completed in %d msec\n", timeout_msec); ++ } else if (rc < 0) { ++ retval = -EINTR; ++ info("Command was interrupted by a signal\n"); ++ } ++ ctrl->cmd_busy = 0; ++ ++ return retval; ++} ++ + static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) + { + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; +@@ -314,8 +333,14 @@ static int shpc_write_cmd(struct slot *s + /* To make sure the Controller Busy bit is 0 before we send out the + * command. + */ ++ slot->ctrl->cmd_busy = 1; + writew(temp_word, php_ctlr->creg + CMD); + ++ /* ++ * Wait for command completion. ++ */ ++ retval = shpc_wait_cmd(slot->ctrl); ++ + DBG_LEAVE_ROUTINE + return retval; + } +@@ -1064,6 +1089,7 @@ static irqreturn_t shpc_isr(int IRQ, voi + temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + temp_dword &= 0xfffdffff; + writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); ++ ctrl->cmd_busy = 0; + wake_up_interruptible(&ctrl->queue); + } + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_ctrl.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_ctrl.c +@@ -248,7 +248,6 @@ static int change_bus_speed(struct contr + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } +- wait_for_ctrl_irq (ctrl); + + if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", +@@ -330,9 +329,6 @@ static int board_added(struct slot *p_sl + up(&ctrl->crit_sect); + return -1; + } +- +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { +@@ -352,7 +348,6 @@ static int board_added(struct slot *p_sl + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } +- wait_for_ctrl_irq (ctrl); + + if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", +@@ -367,7 +362,6 @@ static int board_added(struct slot *p_sl + up(&ctrl->crit_sect); + return rc; + } +- wait_for_ctrl_irq (ctrl); + + if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { + err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); +@@ -494,7 +488,6 @@ static int board_added(struct slot *p_sl + up(&ctrl->crit_sect); + return rc; + } +- wait_for_ctrl_irq (ctrl); + + if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { + err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); +@@ -532,9 +525,6 @@ static int board_added(struct slot *p_sl + + p_slot->hpc_ops->green_led_on(p_slot); + +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); +- + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + +@@ -552,8 +542,6 @@ err_exit: + up(&ctrl->crit_sect); + return rc; + } +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { +@@ -603,8 +591,6 @@ static int remove_board(struct slot *p_s + up(&ctrl->crit_sect); + return rc; + } +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { +@@ -621,8 +607,6 @@ static int remove_board(struct slot *p_s + up(&ctrl->crit_sect); + return rc; + } +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); +@@ -676,9 +660,6 @@ static void shpchp_pushbutton_thread (un + + p_slot->hpc_ops->green_led_off(p_slot); + +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (p_slot->ctrl); +- + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + } +@@ -790,14 +771,9 @@ static void interrupt_event_handler(stru + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_on(p_slot); +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); + +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); +- + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + break; +@@ -806,12 +782,8 @@ static void interrupt_event_handler(stru + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_off(p_slot); +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); +@@ -845,14 +817,9 @@ static void interrupt_event_handler(stru + + /* blink green LED and turn off amber */ + p_slot->hpc_ops->green_led_blink(p_slot); +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); + +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); +- + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + +@@ -870,12 +837,8 @@ static void interrupt_event_handler(stru + down(&ctrl->crit_sect); + + p_slot->hpc_ops->set_attention_status(p_slot, 1); +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->green_led_off(p_slot); +- /* Wait for the command to complete */ +- wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); diff --git a/pci/shpchp-fix-improper-write-to-command-completion-detect-bit.patch b/pci/shpchp-fix-improper-write-to-command-completion-detect-bit.patch new file mode 100644 index 0000000000000..76a4b8b5b2637 --- /dev/null +++ b/pci/shpchp-fix-improper-write-to-command-completion-detect-bit.patch @@ -0,0 +1,36 @@ +From kaneshige.kenji@jp.fujitsu.com Wed Nov 23 18:43:14 2005 +Message-ID: <438527E1.20709@jp.fujitsu.com> +Date: Thu, 24 Nov 2005 11:39:29 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com>, <kristen.c.accardi@intel.com> +CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: shpchp: fix improper write to Command Completion Detect bit + +Current SHPCHP driver writes a '0' to the Command Completion Detect +bit to clear the Command Complete Interrupt Pending. But according to +the SHPC spec (See 4.7.3.1 System Interrupts), SHPCHP driver must +write '1'. This patch fixes this bug. + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/pci/hotplug/shpchp_hpc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -1058,11 +1058,11 @@ static irqreturn_t shpc_isr(int IRQ, voi + if (intr_loc & 0x0001) { + /* + * Command Complete Interrupt Pending +- * RO only - clear by writing 0 to the Command Completion ++ * RO only - clear by writing 1 to the Command Completion + * Detect bit in Controller SERR-INT register + */ + temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); +- temp_dword &= 0xfffeffff; ++ temp_dword &= 0xfffdffff; + writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + wake_up_interruptible(&ctrl->queue); + } diff --git a/pci/shpchp-replace-pci_find_slot-with-pci_get_slot.patch b/pci/shpchp-replace-pci_find_slot-with-pci_get_slot.patch new file mode 100644 index 0000000000000..e06288f10443a --- /dev/null +++ b/pci/shpchp-replace-pci_find_slot-with-pci_get_slot.patch @@ -0,0 +1,109 @@ +From kaneshige.kenji@jp.fujitsu.com Thu Nov 24 19:27:04 2005 +Message-ID: <43868335.3080001@jp.fujitsu.com> +Date: Fri, 25 Nov 2005 12:21:25 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <greg@kroah.com> +CC: <kristen.c.accardi@intel.com> +Subject: shpchp: replace pci_find_slot() with pci_get_slot() + + +This patch replaces pci_find_slot() with pci_get_slot() in the SHPCHP +driver. This enables SHPCHP driver to work on multiple PCI segment +systems. + +Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/pci/hotplug/shpchp_pci.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_pci.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_pci.c +@@ -89,10 +89,11 @@ int shpchp_configure_device(struct slot + struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; + int num, fn; + +- dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0)); ++ dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); + if (dev) { + err("Device %s already exists at %x:%x, cannot hot-add\n", + pci_name(dev), p_slot->bus, p_slot->device); ++ pci_dev_put(dev); + return -EINVAL; + } + +@@ -103,12 +104,13 @@ int shpchp_configure_device(struct slot + } + + for (fn = 0; fn < 8; fn++) { +- if (!(dev = pci_find_slot(p_slot->bus, +- PCI_DEVFN(p_slot->device, fn)))) ++ dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); ++ if (!dev) + continue; + if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { + err("Cannot hot-add display device %s\n", + pci_name(dev)); ++ pci_dev_put(dev); + continue; + } + if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || +@@ -124,18 +126,21 @@ int shpchp_configure_device(struct slot + } + if (busnr >= end) { + err("No free bus for hot-added bridge\n"); ++ pci_dev_put(dev); + continue; + } + child = pci_add_new_bus(parent, dev, busnr); + if (!child) { + err("Cannot add new bus for %s\n", + pci_name(dev)); ++ pci_dev_put(dev); + continue; + } + child->subordinate = pci_do_scan_bus(child); + pci_bus_size_bridges(child); + } + program_fw_provided_values(dev); ++ pci_dev_put(dev); + } + + pci_bus_assign_resources(parent); +@@ -149,17 +154,19 @@ int shpchp_unconfigure_device(struct slo + int rc = 0; + int j; + u8 bctl = 0; +- ++ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; ++ + dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device); + + for (j=0; j<8 ; j++) { +- struct pci_dev* temp = pci_find_slot(p_slot->bus, ++ struct pci_dev* temp = pci_get_slot(parent, + (p_slot->device << 3) | j); + if (!temp) + continue; + if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { + err("Cannot remove display device %s\n", + pci_name(temp)); ++ pci_dev_put(temp); + continue; + } + if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { +@@ -167,10 +174,12 @@ int shpchp_unconfigure_device(struct slo + if (bctl & PCI_BRIDGE_CTL_VGA) { + err("Cannot remove display device %s\n", + pci_name(temp)); ++ pci_dev_put(temp); + continue; + } + } + pci_remove_bus_device(temp); ++ pci_dev_put(temp); + } + return rc; + } |