diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-05-01 22:57:24 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-05-01 22:57:24 -0700 |
commit | 5fe8a0d180166b24d6181657324a460c429939b5 (patch) | |
tree | 10a9cb3c335c76f7325553cdbce3093019d6c405 /pci | |
parent | de68488eebf4191d07dad2802b458a08f73f0e58 (diff) | |
download | patches-5fe8a0d180166b24d6181657324a460c429939b5.tar.gz |
added pci hotplug patches
Diffstat (limited to 'pci')
-rw-r--r-- | pci/acpi_pcihp-add-support-for-_hpx.patch | 424 | ||||
-rw-r--r-- | pci/acpi_pcihp-fix-programming-_hpp-values.patch | 135 | ||||
-rw-r--r-- | pci/acpi_pcihp-remove-improper-error-message-about-oshp.patch | 30 | ||||
-rw-r--r-- | pci/pciehp-fix-programming-hotplug-parameters.patch | 178 | ||||
-rw-r--r-- | pci/shpc-cleanup-shpc-logical-slot-register-access.patch | 142 | ||||
-rw-r--r-- | pci/shpc-cleanup-shpc-logical-slot-register-bits-access.patch | 299 | ||||
-rw-r--r-- | pci/shpc-cleanup-shpc-register-access.patch | 536 | ||||
-rw-r--r-- | pci/shpc-fix-shpc-contoller-serr-int-register-bits-access.patch | 115 | ||||
-rw-r--r-- | pci/shpc-fix-shpc-logical-slot-register-bits-access.patch | 148 |
9 files changed, 2007 insertions, 0 deletions
diff --git a/pci/acpi_pcihp-add-support-for-_hpx.patch b/pci/acpi_pcihp-add-support-for-_hpx.patch new file mode 100644 index 0000000000000..201a6c5b71958 --- /dev/null +++ b/pci/acpi_pcihp-add-support-for-_hpx.patch @@ -0,0 +1,424 @@ +From pcihpd-discuss-admin@lists.sourceforge.net Mon May 1 19:00:10 2006 +Message-ID: <4456BC7A.10908@jp.fujitsu.com> +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: gregkh@suse.de, kristen.c.accardi@intel.com +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: acpi_pcihp: Add support for _HPX +Date: Tue, 02 May 2006 10:57:14 +0900 + +This patch adds support for _HPX (Hot Plug Parameter Extensions) +defined in ACPI3.0a spec. + +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> + +--- + drivers/pci/hotplug/acpi_pcihp.c | 190 +++++++++++++++++++++++++++++++++++-- + drivers/pci/hotplug/acpiphp_glue.c | 31 +++--- + drivers/pci/hotplug/pci_hotplug.h | 48 ++++++++- + drivers/pci/hotplug/shpchp_pci.c | 35 ++++-- + 4 files changed, 265 insertions(+), 39 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/acpi_pcihp.c ++++ gregkh-2.6/drivers/pci/hotplug/acpi_pcihp.c +@@ -37,6 +37,171 @@ + #define METHOD_NAME__HPP "_HPP" + #define METHOD_NAME_OSHP "OSHP" + ++static acpi_status ++decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx) ++{ ++ int i; ++ union acpi_object *fields = record->package.elements; ++ u32 revision = fields[1].integer.value; ++ ++ switch (revision) { ++ case 1: ++ if (record->package.count != 6) ++ return AE_ERROR; ++ for (i = 2; i < 6; i++) ++ if (fields[i].type != ACPI_TYPE_INTEGER) ++ return AE_ERROR; ++ hpx->t0 = &hpx->type0_data; ++ hpx->t0->revision = revision; ++ hpx->t0->cache_line_size = fields[2].integer.value; ++ hpx->t0->latency_timer = fields[3].integer.value; ++ hpx->t0->enable_serr = fields[4].integer.value; ++ hpx->t0->enable_perr = fields[5].integer.value; ++ break; ++ default: ++ printk(KERN_WARNING ++ "%s: Type 0 Revision %d record not supported\n", ++ __FUNCTION__, revision); ++ return AE_ERROR; ++ } ++ return AE_OK; ++} ++ ++static acpi_status ++decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx) ++{ ++ int i; ++ union acpi_object *fields = record->package.elements; ++ u32 revision = fields[1].integer.value; ++ ++ switch (revision) { ++ case 1: ++ if (record->package.count != 5) ++ return AE_ERROR; ++ for (i = 2; i < 5; i++) ++ if (fields[i].type != ACPI_TYPE_INTEGER) ++ return AE_ERROR; ++ hpx->t1 = &hpx->type1_data; ++ hpx->t1->revision = revision; ++ hpx->t1->max_mem_read = fields[2].integer.value; ++ hpx->t1->avg_max_split = fields[3].integer.value; ++ hpx->t1->tot_max_split = fields[4].integer.value; ++ break; ++ default: ++ printk(KERN_WARNING ++ "%s: Type 1 Revision %d record not supported\n", ++ __FUNCTION__, revision); ++ return AE_ERROR; ++ } ++ return AE_OK; ++} ++ ++static acpi_status ++decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx) ++{ ++ int i; ++ union acpi_object *fields = record->package.elements; ++ u32 revision = fields[1].integer.value; ++ ++ switch (revision) { ++ case 1: ++ if (record->package.count != 18) ++ return AE_ERROR; ++ for (i = 2; i < 18; i++) ++ if (fields[i].type != ACPI_TYPE_INTEGER) ++ return AE_ERROR; ++ hpx->t2 = &hpx->type2_data; ++ hpx->t2->revision = revision; ++ hpx->t2->unc_err_mask_and = fields[2].integer.value; ++ hpx->t2->unc_err_mask_or = fields[3].integer.value; ++ hpx->t2->unc_err_sever_and = fields[4].integer.value; ++ hpx->t2->unc_err_sever_or = fields[5].integer.value; ++ hpx->t2->cor_err_mask_and = fields[6].integer.value; ++ hpx->t2->cor_err_mask_or = fields[7].integer.value; ++ hpx->t2->adv_err_cap_and = fields[8].integer.value; ++ hpx->t2->adv_err_cap_or = fields[9].integer.value; ++ hpx->t2->pci_exp_devctl_and = fields[10].integer.value; ++ hpx->t2->pci_exp_devctl_or = fields[11].integer.value; ++ hpx->t2->pci_exp_lnkctl_and = fields[12].integer.value; ++ hpx->t2->pci_exp_lnkctl_or = fields[13].integer.value; ++ hpx->t2->sec_unc_err_sever_and = fields[14].integer.value; ++ hpx->t2->sec_unc_err_sever_or = fields[15].integer.value; ++ hpx->t2->sec_unc_err_mask_and = fields[16].integer.value; ++ hpx->t2->sec_unc_err_mask_or = fields[17].integer.value; ++ break; ++ default: ++ printk(KERN_WARNING ++ "%s: Type 2 Revision %d record not supported\n", ++ __FUNCTION__, revision); ++ return AE_ERROR; ++ } ++ return AE_OK; ++} ++ ++static acpi_status ++acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) ++{ ++ acpi_status status; ++ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; ++ union acpi_object *package, *record, *fields; ++ u32 type; ++ int i; ++ ++ /* Clear the return buffer with zeros */ ++ memset(hpx, 0, sizeof(struct hotplug_params)); ++ ++ status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer); ++ if (ACPI_FAILURE(status)) ++ return status; ++ ++ package = (union acpi_object *)buffer.pointer; ++ if (package->type != ACPI_TYPE_PACKAGE) { ++ status = AE_ERROR; ++ goto exit; ++ } ++ ++ for (i = 0; i < package->package.count; i++) { ++ record = &package->package.elements[i]; ++ if (record->type != ACPI_TYPE_PACKAGE) { ++ status = AE_ERROR; ++ goto exit; ++ } ++ ++ fields = record->package.elements; ++ if (fields[0].type != ACPI_TYPE_INTEGER || ++ fields[1].type != ACPI_TYPE_INTEGER) { ++ status = AE_ERROR; ++ goto exit; ++ } ++ ++ type = fields[0].integer.value; ++ switch (type) { ++ case 0: ++ status = decode_type0_hpx_record(record, hpx); ++ if (ACPI_FAILURE(status)) ++ goto exit; ++ break; ++ case 1: ++ status = decode_type1_hpx_record(record, hpx); ++ if (ACPI_FAILURE(status)) ++ goto exit; ++ break; ++ case 2: ++ status = decode_type2_hpx_record(record, hpx); ++ if (ACPI_FAILURE(status)) ++ goto exit; ++ break; ++ default: ++ printk(KERN_ERR "%s: Type %d record not supported\n", ++ __FUNCTION__, type); ++ status = AE_ERROR; ++ goto exit; ++ } ++ } ++ exit: ++ kfree(buffer.pointer); ++ return status; ++} + + static acpi_status + acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) +@@ -50,6 +215,9 @@ acpi_run_hpp(acpi_handle handle, struct + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + ++ /* Clear the return buffer with zeros */ ++ memset(hpp, 0, sizeof(struct hotplug_params)); ++ + /* get _hpp */ + status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); + switch (status) { +@@ -98,15 +266,16 @@ acpi_run_hpp(acpi_handle handle, struct + } + } + +- hpp->cache_line_size = nui[0]; +- hpp->latency_timer = nui[1]; +- hpp->enable_serr = nui[2]; +- hpp->enable_perr = nui[3]; +- +- pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); +- pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer); +- pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); +- pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); ++ hpp->t0 = &hpp->type0_data; ++ hpp->t0->cache_line_size = nui[0]; ++ hpp->t0->latency_timer = nui[1]; ++ hpp->t0->enable_serr = nui[2]; ++ hpp->t0->enable_perr = nui[3]; ++ ++ pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); ++ pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); ++ pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); ++ pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); + + free_and_return: + kfree(string.pointer); +@@ -174,6 +343,9 @@ acpi_status acpi_get_hp_params_from_firm + * this pci dev. If we don't find any _HPP, use hardcoded defaults + */ + while (handle) { ++ status = acpi_run_hpx(handle, hpp); ++ if (ACPI_SUCCESS(status)) ++ break; + status = acpi_run_hpp(handle, hpp); + if (ACPI_SUCCESS(status)) + break; +--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c ++++ gregkh-2.6/drivers/pci/hotplug/acpiphp_glue.c +@@ -287,12 +287,18 @@ static void decode_hpp(struct acpiphp_br + acpi_status status; + + status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); +- if (ACPI_FAILURE(status)) { ++ if (ACPI_FAILURE(status) || ++ !bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) { + /* use default numbers */ +- bridge->hpp.cache_line_size = 0x10; +- bridge->hpp.latency_timer = 0x40; +- bridge->hpp.enable_serr = 0; +- bridge->hpp.enable_perr = 0; ++ printk(KERN_WARNING ++ "%s: Could not get hotplug parameters. Use defaults\n", ++ __FUNCTION__); ++ bridge->hpp.t0 = &bridge->hpp.type0_data; ++ bridge->hpp.t0->revision = 0; ++ bridge->hpp.t0->cache_line_size = 0x10; ++ bridge->hpp.t0->latency_timer = 0x40; ++ bridge->hpp.t0->enable_serr = 0; ++ bridge->hpp.t0->enable_perr = 0; + } + } + +@@ -1206,16 +1212,17 @@ static void program_hpp(struct pci_dev * + (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && + (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) + return; ++ + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, +- bridge->hpp.cache_line_size); ++ bridge->hpp.t0->cache_line_size); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, +- bridge->hpp.latency_timer); ++ bridge->hpp.t0->latency_timer); + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); +- if (bridge->hpp.enable_serr) ++ if (bridge->hpp.t0->enable_serr) + pci_cmd |= PCI_COMMAND_SERR; + else + pci_cmd &= ~PCI_COMMAND_SERR; +- if (bridge->hpp.enable_perr) ++ if (bridge->hpp.t0->enable_perr) + pci_cmd |= PCI_COMMAND_PARITY; + else + pci_cmd &= ~PCI_COMMAND_PARITY; +@@ -1224,13 +1231,13 @@ static void program_hpp(struct pci_dev * + /* Program bridge control value and child devices */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, +- bridge->hpp.latency_timer); ++ bridge->hpp.t0->latency_timer); + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); +- if (bridge->hpp.enable_serr) ++ if (bridge->hpp.t0->enable_serr) + pci_bctl |= PCI_BRIDGE_CTL_SERR; + else + pci_bctl &= ~PCI_BRIDGE_CTL_SERR; +- if (bridge->hpp.enable_perr) ++ if (bridge->hpp.t0->enable_perr) + pci_bctl |= PCI_BRIDGE_CTL_PARITY; + else + pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; +--- gregkh-2.6.orig/drivers/pci/hotplug/pci_hotplug.h ++++ gregkh-2.6/drivers/pci/hotplug/pci_hotplug.h +@@ -176,11 +176,51 @@ extern int pci_hp_change_slot_info (stru + struct hotplug_slot_info *info); + extern struct subsystem pci_hotplug_slots_subsys; + ++/* PCI Setting Record (Type 0) */ ++struct hpp_type0 { ++ u32 revision; ++ u8 cache_line_size; ++ u8 latency_timer; ++ u8 enable_serr; ++ u8 enable_perr; ++}; ++ ++/* PCI-X Setting Record (Type 1) */ ++struct hpp_type1 { ++ u32 revision; ++ u8 max_mem_read; ++ u8 avg_max_split; ++ u16 tot_max_split; ++}; ++ ++/* PCI Express Setting Record (Type 2) */ ++struct hpp_type2 { ++ u32 revision; ++ u32 unc_err_mask_and; ++ u32 unc_err_mask_or; ++ u32 unc_err_sever_and; ++ u32 unc_err_sever_or; ++ u32 cor_err_mask_and; ++ u32 cor_err_mask_or; ++ u32 adv_err_cap_and; ++ u32 adv_err_cap_or; ++ u16 pci_exp_devctl_and; ++ u16 pci_exp_devctl_or; ++ u16 pci_exp_lnkctl_and; ++ u16 pci_exp_lnkctl_or; ++ u32 sec_unc_err_sever_and; ++ u32 sec_unc_err_sever_or; ++ u32 sec_unc_err_mask_and; ++ u32 sec_unc_err_mask_or; ++}; ++ + struct hotplug_params { +- u8 cache_line_size; +- u8 latency_timer; +- u8 enable_serr; +- u8 enable_perr; ++ struct hpp_type0 *t0; /* Type0: NULL if not available */ ++ struct hpp_type1 *t1; /* Type1: NULL if not available */ ++ struct hpp_type2 *t2; /* Type2: NULL if not available */ ++ struct hpp_type0 type0_data; ++ struct hpp_type1 type1_data; ++ struct hpp_type2 type2_data; + }; + + #ifdef CONFIG_ACPI +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_pci.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_pci.c +@@ -47,21 +47,28 @@ static void program_fw_provided_values(s + return; + + /* use default values if we can't get them from firmware */ +- if (get_hp_params_from_firmware(dev, &hpp)) { +- hpp.cache_line_size = 8; +- hpp.latency_timer = 0x40; +- hpp.enable_serr = 0; +- hpp.enable_perr = 0; +- } +- +- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); +- pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); ++ if (get_hp_params_from_firmware(dev, &hpp) || ++ !hpp.t0 || (hpp.t0->revision > 1)) { ++ printk(KERN_WARNING ++ "%s: Could not get hotplug parameters. Use defaults\n", ++ __FUNCTION__); ++ hpp.t0 = &hpp.type0_data; ++ hpp.t0->revision = 0; ++ hpp.t0->cache_line_size = 8; ++ hpp.t0->latency_timer = 0x40; ++ hpp.t0->enable_serr = 0; ++ hpp.t0->enable_perr = 0; ++ } ++ ++ pci_write_config_byte(dev, ++ PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size); ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer); + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); +- if (hpp.enable_serr) ++ if (hpp.t0->enable_serr) + pci_cmd |= PCI_COMMAND_SERR; + else + pci_cmd &= ~PCI_COMMAND_SERR; +- if (hpp.enable_perr) ++ if (hpp.t0->enable_perr) + pci_cmd |= PCI_COMMAND_PARITY; + else + pci_cmd &= ~PCI_COMMAND_PARITY; +@@ -70,13 +77,13 @@ static void program_fw_provided_values(s + /* Program bridge control value and child devices */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, +- hpp.latency_timer); ++ hpp.t0->latency_timer); + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); +- if (hpp.enable_serr) ++ if (hpp.t0->enable_serr) + pci_bctl |= PCI_BRIDGE_CTL_SERR; + else + pci_bctl &= ~PCI_BRIDGE_CTL_SERR; +- if (hpp.enable_perr) ++ if (hpp.t0->enable_perr) + pci_bctl |= PCI_BRIDGE_CTL_PARITY; + else + pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; diff --git a/pci/acpi_pcihp-fix-programming-_hpp-values.patch b/pci/acpi_pcihp-fix-programming-_hpp-values.patch new file mode 100644 index 0000000000000..ca212453e04bf --- /dev/null +++ b/pci/acpi_pcihp-fix-programming-_hpp-values.patch @@ -0,0 +1,135 @@ +From pcihpd-discuss-admin@lists.sourceforge.net Mon May 1 18:58:14 2006 +Message-ID: <4456BBEA.2000005@jp.fujitsu.com> +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: gregkh@suse.de, kristen.c.accardi@intel.com +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: acpi_pcihp: Fix programming _HPP values +Date: Tue, 02 May 2006 10:54:50 +0900 + +This patch fixes the problem that hotplug parameters are not programed +when PCI cards are hot-added by ACPIPHP, SHPCHP and PCIEHP driver. The +pci_dev structure being hot-added is not bound to ACPI handle, so we +need to trace PCI bus tree to find ACPI handle. + +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> + + +--- + drivers/pci/hotplug/acpi_pcihp.c | 34 ++++++++++++++++++++++++---------- + drivers/pci/hotplug/acpiphp_glue.c | 3 ++- + drivers/pci/hotplug/pci_hotplug.h | 2 +- + drivers/pci/hotplug/pciehp.h | 2 +- + drivers/pci/hotplug/shpchp.h | 2 +- + 5 files changed, 29 insertions(+), 14 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/acpi_pcihp.c ++++ gregkh-2.6/drivers/pci/hotplug/acpi_pcihp.c +@@ -145,14 +145,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp); + + /* acpi_get_hp_params_from_firmware + * +- * @dev - the pci_dev of the newly added device ++ * @bus - the pci_bus of the bus on which the device is newly added + * @hpp - allocated by the caller + */ +-acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, ++acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, + struct hotplug_params *hpp) + { + acpi_status status = AE_NOT_FOUND; +- struct pci_dev *pdev = dev; ++ acpi_handle handle, phandle; ++ struct pci_bus *pbus = bus; ++ struct pci_dev *pdev; ++ ++ do { ++ pdev = pbus->self; ++ if (!pdev) { ++ handle = acpi_get_pci_rootbridge_handle( ++ pci_domain_nr(pbus), pbus->number); ++ break; ++ } ++ handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); ++ pbus = pbus->parent; ++ } while (!handle); + + /* + * _HPP settings apply to all child buses, until another _HPP is +@@ -160,15 +173,16 @@ acpi_status acpi_get_hp_params_from_firm + * look for it in the parent device scope since that would apply to + * this pci dev. If we don't find any _HPP, use hardcoded defaults + */ +- while (pdev && (ACPI_FAILURE(status))) { +- acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); +- if (!handle) +- break; ++ while (handle) { + status = acpi_run_hpp(handle, hpp); +- if (!(pdev->bus->parent)) ++ if (ACPI_SUCCESS(status)) ++ break; ++ if (acpi_root_bridge(handle)) ++ break; ++ status = acpi_get_parent(handle, &phandle); ++ if (ACPI_FAILURE(status)) + break; +- /* Check if a parent object supports _HPP */ +- pdev = pdev->bus->parent->self; ++ handle = phandle; + } + return status; + } +--- gregkh-2.6.orig/drivers/pci/hotplug/acpiphp_glue.c ++++ gregkh-2.6/drivers/pci/hotplug/acpiphp_glue.c +@@ -286,7 +286,7 @@ static void decode_hpp(struct acpiphp_br + { + acpi_status status; + +- status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); ++ status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); + if (ACPI_FAILURE(status)) { + /* use default numbers */ + bridge->hpp.cache_line_size = 0x10; +@@ -1250,6 +1250,7 @@ static void acpiphp_set_hpp_values(acpi_ + + memset(&bridge, 0, sizeof(bridge)); + bridge.handle = handle; ++ bridge.pci_bus = bus; + bridge.pci_dev = bus->self; + decode_hpp(&bridge); + list_for_each_entry(dev, &bus->devices, bus_list) +--- gregkh-2.6.orig/drivers/pci/hotplug/pci_hotplug.h ++++ gregkh-2.6/drivers/pci/hotplug/pci_hotplug.h +@@ -188,7 +188,7 @@ struct hotplug_params { + #include <acpi/acpi_bus.h> + #include <acpi/actypes.h> + extern acpi_status acpi_run_oshp(acpi_handle handle); +-extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, ++extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, + struct hotplug_params *hpp); + int acpi_root_bridge(acpi_handle handle); + #endif +--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp.h ++++ gregkh-2.6/drivers/pci/hotplug/pciehp.h +@@ -284,7 +284,7 @@ struct hpc_ops { + static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) + { +- if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) ++ if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) + return -ENODEV; + return 0; + } +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp.h ++++ gregkh-2.6/drivers/pci/hotplug/shpchp.h +@@ -196,7 +196,7 @@ extern void queue_pushbutton_work(void * + static inline int get_hp_params_from_firmware(struct pci_dev *dev, + struct hotplug_params *hpp) + { +- if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) ++ if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) + return -ENODEV; + return 0; + } diff --git a/pci/acpi_pcihp-remove-improper-error-message-about-oshp.patch b/pci/acpi_pcihp-remove-improper-error-message-about-oshp.patch new file mode 100644 index 0000000000000..2adf2db50eee7 --- /dev/null +++ b/pci/acpi_pcihp-remove-improper-error-message-about-oshp.patch @@ -0,0 +1,30 @@ +From pcihpd-discuss-admin@lists.sourceforge.net Mon May 1 18:59:10 2006 +Message-ID: <4456BC22.8090806@jp.fujitsu.com> +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: gregkh@suse.de, kristen.c.accardi@intel.com +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: acpi_pcihp: Remove improper error message about OSHP +Date: Tue, 02 May 2006 10:55:46 +0900 + +This patch removes improper error messages from the acpi_run_oshp() +function. + +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> + +--- + drivers/pci/hotplug/acpi_pcihp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/acpi_pcihp.c ++++ gregkh-2.6/drivers/pci/hotplug/acpi_pcihp.c +@@ -129,7 +129,7 @@ acpi_status acpi_run_oshp(acpi_handle ha + + /* run OSHP */ + status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); +- if (ACPI_FAILURE(status)) ++ if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) + printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__, + (char *)string.pointer, status); + else diff --git a/pci/pciehp-fix-programming-hotplug-parameters.patch b/pci/pciehp-fix-programming-hotplug-parameters.patch new file mode 100644 index 0000000000000..692e5457d93da --- /dev/null +++ b/pci/pciehp-fix-programming-hotplug-parameters.patch @@ -0,0 +1,178 @@ +From pcihpd-discuss-admin@lists.sourceforge.net Mon May 1 19:01:17 2006 +Message-ID: <4456BCB4.30707@jp.fujitsu.com> +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: gregkh@suse.de, kristen.c.accardi@intel.com +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: pciehp: Fix programming hotplug parameters +Date: Tue, 02 May 2006 10:58:12 +0900 + +Current PCHEHP driver doesn't have any code to program hotplug +parameters from firmware. So hotplug parameters are never programed at +hot-add time. This patch add support for programming hotplug +parameters to PCIEHP driver. + +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> + +--- + drivers/pci/hotplug/pciehp_pci.c | 141 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 139 insertions(+), 2 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/pciehp_pci.c ++++ gregkh-2.6/drivers/pci/hotplug/pciehp_pci.c +@@ -34,6 +34,144 @@ + #include "../pci.h" + #include "pciehp.h" + ++static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) ++{ ++ u16 pci_cmd, pci_bctl; ++ ++ if (hpp->revision > 1) { ++ printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n", ++ __FUNCTION__, hpp->revision); ++ return; ++ } ++ ++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size); ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer); ++ pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); ++ if (hpp->enable_serr) ++ pci_cmd |= PCI_COMMAND_SERR; ++ else ++ pci_cmd &= ~PCI_COMMAND_SERR; ++ if (hpp->enable_perr) ++ pci_cmd |= PCI_COMMAND_PARITY; ++ else ++ pci_cmd &= ~PCI_COMMAND_PARITY; ++ pci_write_config_word(dev, PCI_COMMAND, pci_cmd); ++ ++ /* Program bridge control value */ ++ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { ++ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, ++ hpp->latency_timer); ++ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); ++ if (hpp->enable_serr) ++ pci_bctl |= PCI_BRIDGE_CTL_SERR; ++ else ++ pci_bctl &= ~PCI_BRIDGE_CTL_SERR; ++ if (hpp->enable_perr) ++ pci_bctl |= PCI_BRIDGE_CTL_PARITY; ++ else ++ pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; ++ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); ++ } ++} ++ ++static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) ++{ ++ int pos; ++ u16 reg16; ++ u32 reg32; ++ ++ if (hpp->revision > 1) { ++ printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n", ++ __FUNCTION__, hpp->revision); ++ return; ++ } ++ ++ /* Find PCI Express capability */ ++ pos = pci_find_capability(dev, PCI_CAP_ID_EXP); ++ if (!pos) ++ return; ++ ++ /* Initialize Device Control Register */ ++ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); ++ reg32 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; ++ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); ++ ++ /* Initialize Link Control Register */ ++ if (dev->subordinate) { ++ pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); ++ reg16 = (reg32 & hpp->pci_exp_lnkctl_and) ++ | hpp->pci_exp_lnkctl_or; ++ pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); ++ } ++ ++ /* Find Advanced Error Reporting Enhanced Capability */ ++ pos = 256; ++ do { ++ pci_read_config_dword(dev, pos, ®32); ++ if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR) ++ break; ++ } while ((pos = PCI_EXT_CAP_NEXT(reg32))); ++ if (!pos) ++ return; ++ ++ /* Initialize Uncorrectable Error Mask Register */ ++ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, ®32); ++ reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; ++ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); ++ ++ /* Initialize Uncorrectable Error Severity Register */ ++ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, ®32); ++ reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; ++ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); ++ ++ /* Initialize Correctable Error Mask Register */ ++ pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®32); ++ reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; ++ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); ++ ++ /* Initialize Advanced Error Capabilities and Control Register */ ++ pci_read_config_dword(dev, pos + PCI_ERR_CAP, ®32); ++ reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; ++ pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); ++ ++ /* ++ * FIXME: The following two registers are not supported yet. ++ * ++ * o Secondary Uncorrectable Error Severity Register ++ * o Secondary Uncorrectable Error Mask Register ++ */ ++} ++ ++static void program_fw_provided_values(struct pci_dev *dev) ++{ ++ struct pci_dev *cdev; ++ struct hotplug_params hpp; ++ ++ /* Program hpp values for this device */ ++ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || ++ (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && ++ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) ++ return; ++ ++ if (pciehp_get_hp_params_from_firmware(dev, &hpp)) { ++ printk(KERN_WARNING "%s: Could not get hotplug parameters\n", ++ __FUNCTION__); ++ return; ++ } ++ ++ if (hpp.t2) ++ program_hpp_type2(dev, hpp.t2); ++ if (hpp.t0) ++ program_hpp_type0(dev, hpp.t0); ++ ++ /* Program child devices */ ++ if (dev->subordinate) { ++ list_for_each_entry(cdev, &dev->subordinate->devices, ++ bus_list) ++ program_fw_provided_values(cdev); ++ } ++} ++ + static int pciehp_add_bridge(struct pci_dev *dev) + { + struct pci_bus *parent = dev->bus; +@@ -92,8 +230,7 @@ int pciehp_configure_device(struct slot + (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { + pciehp_add_bridge(dev); + } +- /* TBD: program firmware provided _HPP values */ +- /* program_fw_provided_values(dev); */ ++ program_fw_provided_values(dev); + } + + pci_bus_assign_resources(parent); diff --git a/pci/shpc-cleanup-shpc-logical-slot-register-access.patch b/pci/shpc-cleanup-shpc-logical-slot-register-access.patch new file mode 100644 index 0000000000000..c827331718ff2 --- /dev/null +++ b/pci/shpc-cleanup-shpc-logical-slot-register-access.patch @@ -0,0 +1,142 @@ +From kaneshige.kenji@jp.fujitsu.com Mon May 1 19:12:18 2006 +Message-ID: <4456BF66.6090200@jp.fujitsu.com> +Date: Tue, 02 May 2006 11:09:42 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <gregkh@suse.de>, Kristen Accardi <kristen.c.accardi@intel.com> +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: SHPC: Cleanup SHPC Logical Slot Register access + +This patch cleans up the code to access slot logical registers. This +patch has no functional changes. + +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> + +--- + drivers/pci/hotplug/shpchp_hpc.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -90,6 +90,11 @@ + #define MRLSENSOR 0x40000000 + #define ATTN_BUTTON 0x80000000 + ++/* ++ * Logical Slot Register definitions ++ */ ++#define SLOT_REG(i) (SLOT1 + (4 * i)) ++ + /* Slot Status Field Definitions */ + /* Slot State */ + #define PWR_ONLY 0x0001 +@@ -433,7 +438,7 @@ static int hpc_get_attention_status(stru + return -1; + } + +- slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + slot_status = (u16) slot_reg; + atten_led_state = (slot_status & 0x0030) >> 4; + +@@ -474,7 +479,7 @@ static int hpc_get_power_status(struct s + return -1; + } + +- slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + slot_status = (u16) slot_reg; + slot_state = (slot_status & 0x0003); + +@@ -514,7 +519,7 @@ static int hpc_get_latch_status(struct s + return -1; + } + +- slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + slot_status = (u16)slot_reg; + + *status = ((slot_status & 0x0100) == 0) ? 0 : 1; /* 0 -> close; 1 -> open */ +@@ -538,7 +543,7 @@ static int hpc_get_adapter_status(struct + return -1; + } + +- slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + slot_status = (u16)slot_reg; + card_state = (u8)((slot_status & 0x0C00) >> 10); + *status = (card_state != 0x3) ? 1 : 0; +@@ -568,7 +573,7 @@ static int hpc_get_adapter_speed(struct + { + int retval = 0; + struct controller *ctrl = slot->ctrl; +- u32 slot_reg = shpc_readl(ctrl, SLOT1 + 4 * slot->hp_slot); ++ u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + u8 pcix_cap = (slot_reg >> 12) & 7; + u8 m66_cap = (slot_reg >> 9) & 1; + +@@ -648,7 +653,7 @@ static int hpc_query_power_fault(struct + return -1; + } + +- slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + slot_status = (u16) slot_reg; + pwr_fault_state = (slot_status & 0x0040) >> 7; + status = (pwr_fault_state == 1) ? 0 : 1; +@@ -805,7 +810,7 @@ static void hpc_release_ctlr(struct cont + * Mask all slot event interrupts + */ + for (i = 0; i < ctrl->num_slots; i++) +- shpc_writel(ctrl, SLOT1 + (4 * i), 0xffff3fff); ++ shpc_writel(ctrl, SLOT_REG(i), 0xffff3fff); + + cleanup_slots(ctrl); + +@@ -1072,7 +1077,7 @@ static irqreturn_t shpc_isr(int IRQ, voi + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { + /* To find out which slot has interrupt pending */ + if ((intr_loc >> hp_slot) & 0x01) { +- temp_dword = shpc_readl(ctrl, SLOT1 + (4*hp_slot)); ++ temp_dword = shpc_readl(ctrl, SLOT_REG(hp_slot)); + dbg("%s: Slot %x with intr, slot register = %x\n", + __FUNCTION__, hp_slot, temp_dword); + temp_byte = (temp_dword >> 16) & 0xFF; +@@ -1091,7 +1096,7 @@ static irqreturn_t shpc_isr(int IRQ, voi + + /* Clear all slot events */ + temp_dword = 0xe01f3fff; +- shpc_writel(ctrl, SLOT1 + (4*hp_slot), temp_dword); ++ shpc_writel(ctrl, SLOT_REG(hp_slot), temp_dword); + + intr_loc2 = shpc_readl(ctrl, INTR_LOC); + dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); +@@ -1379,11 +1384,11 @@ int shpc_init(struct controller * ctrl, + * Slot SERR-INT Mask & clear all the existing event if any + */ + for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { +- slot_reg = shpc_readl(ctrl, SLOT1 + 4*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 = 0xffff3fff; +- shpc_writel(ctrl, SLOT1 + (4*hp_slot), tempdword); ++ shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); + } + + if (shpchp_poll_mode) {/* Install interrupt polling code */ +@@ -1430,11 +1435,11 @@ int shpc_init(struct controller * ctrl, + ctlr_seq_num++; + + for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { +- slot_reg = shpc_readl(ctrl, SLOT1 + 4*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, SLOT1 + (4*hp_slot), tempdword); ++ shpc_writel(ctrl, SLOT_REG(hp_slot), tempdword); + } + if (!shpchp_poll_mode) { + /* Unmask all general input interrupts and SERR */ diff --git a/pci/shpc-cleanup-shpc-logical-slot-register-bits-access.patch b/pci/shpc-cleanup-shpc-logical-slot-register-bits-access.patch new file mode 100644 index 0000000000000..36d0a499060f6 --- /dev/null +++ b/pci/shpc-cleanup-shpc-logical-slot-register-bits-access.patch @@ -0,0 +1,299 @@ +From kaneshige.kenji@jp.fujitsu.com Mon May 1 19:13:04 2006 +Message-ID: <4456BF9D.6090608@jp.fujitsu.com> +Date: Tue, 02 May 2006 11:10:37 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <gregkh@suse.de>, Kristen Accardi <kristen.c.accardi@intel.com> +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: SHPC: Cleanup SHPC Logical Slot Register bits access + +This patch cleans up the code to access bits in slot logical +registers. This patch has no functional change. + +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> + +--- + drivers/pci/hotplug/shpchp_hpc.c | 151 ++++++++++++++++----------------------- + 1 file changed, 64 insertions(+), 87 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -95,43 +95,40 @@ + */ + #define SLOT_REG(i) (SLOT1 + (4 * i)) + +-/* Slot Status Field Definitions */ +-/* Slot State */ +-#define PWR_ONLY 0x0001 +-#define ENABLED 0x0002 +-#define DISABLED 0x0003 +- +-/* Power Indicator State */ +-#define PWR_LED_ON 0x0004 +-#define PWR_LED_BLINK 0x0008 +-#define PWR_LED_OFF 0x000c +- +-/* Attention Indicator State */ +-#define ATTEN_LED_ON 0x0010 +-#define ATTEN_LED_BLINK 0x0020 +-#define ATTEN_LED_OFF 0x0030 +- +-/* Power Fault */ +-#define pwr_fault 0x0040 +- +-/* Attention Button */ +-#define ATTEN_BUTTON 0x0080 +- +-/* MRL Sensor */ +-#define MRL_SENSOR 0x0100 +- +-/* 66 MHz Capable */ +-#define IS_66MHZ_CAP 0x0200 +- +-/* PRSNT1#/PRSNT2# */ +-#define SLOT_EMP 0x0c00 +- +-/* PCI-X Capability */ +-#define NON_PCIX 0x0000 +-#define PCIX_66 0x1000 +-#define PCIX_133 0x3000 +-#define PCIX_266 0x4000 /* For PI = 2 only */ +-#define PCIX_533 0x5000 /* For PI = 2 only */ ++#define SLOT_STATE_SHIFT (0) ++#define SLOT_STATE_MASK (3 << 0) ++#define SLOT_STATE_PWRONLY (1) ++#define SLOT_STATE_ENABLED (2) ++#define SLOT_STATE_DISABLED (3) ++#define PWR_LED_STATE_SHIFT (2) ++#define PWR_LED_STATE_MASK (3 << 2) ++#define ATN_LED_STATE_SHIFT (4) ++#define ATN_LED_STATE_MASK (3 << 4) ++#define ATN_LED_STATE_ON (1) ++#define ATN_LED_STATE_BLINK (2) ++#define ATN_LED_STATE_OFF (3) ++#define POWER_FAULT (1 << 6) ++#define ATN_BUTTON (1 << 7) ++#define MRL_SENSOR (1 << 8) ++#define MHZ66_CAP (1 << 9) ++#define PRSNT_SHIFT (10) ++#define PRSNT_MASK (3 << 10) ++#define PCIX_CAP_SHIFT (12) ++#define PCIX_CAP_MASK_PI1 (3 << 12) ++#define PCIX_CAP_MASK_PI2 (7 << 12) ++#define PRSNT_CHANGE_DETECTED (1 << 16) ++#define ISO_PFAULT_DETECTED (1 << 17) ++#define BUTTON_PRESS_DETECTED (1 << 18) ++#define MRL_CHANGE_DETECTED (1 << 19) ++#define CON_PFAULT_DETECTED (1 << 20) ++#define PRSNT_CHANGE_INTR_MASK (1 << 24) ++#define ISO_PFAULT_INTR_MASK (1 << 25) ++#define BUTTON_PRESS_INTR_MASK (1 << 26) ++#define MRL_CHANGE_INTR_MASK (1 << 27) ++#define CON_PFAULT_INTR_MASK (1 << 28) ++#define MRL_CHANGE_SERR_MASK (1 << 29) ++#define CON_PFAULT_SERR_MASK (1 << 30) ++#define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21) + + /* SHPC 'write' operations/commands */ + +@@ -428,8 +425,7 @@ static int hpc_get_attention_status(stru + { + struct controller *ctrl = slot->ctrl; + u32 slot_reg; +- u16 slot_status; +- u8 atten_led_state; ++ u8 state; + + DBG_ENTER_ROUTINE + +@@ -439,24 +435,20 @@ static int hpc_get_attention_status(stru + } + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); +- slot_status = (u16) slot_reg; +- atten_led_state = (slot_status & 0x0030) >> 4; ++ state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; + +- switch (atten_led_state) { +- case 0: +- *status = 0xFF; /* Reserved */ +- break; +- case 1: ++ switch (state) { ++ case ATN_LED_STATE_ON: + *status = 1; /* On */ + break; +- case 2: ++ case ATN_LED_STATE_BLINK: + *status = 2; /* Blink */ + break; +- case 3: ++ case ATN_LED_STATE_OFF: + *status = 0; /* Off */ + break; + default: +- *status = 0xFF; ++ *status = 0xFF; /* Reserved */ + break; + } + +@@ -468,9 +460,7 @@ static int hpc_get_power_status(struct s + { + struct controller *ctrl = slot->ctrl; + u32 slot_reg; +- u16 slot_status; +- u8 slot_state; +- int retval = 0; ++ u8 state; + + DBG_ENTER_ROUTINE + +@@ -480,29 +470,25 @@ static int hpc_get_power_status(struct s + } + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); +- slot_status = (u16) slot_reg; +- slot_state = (slot_status & 0x0003); ++ state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; + +- switch (slot_state) { +- case 0: +- *status = 0xFF; +- break; +- case 1: ++ switch (state) { ++ case SLOT_STATE_PWRONLY: + *status = 2; /* Powered only */ + break; +- case 2: ++ case SLOT_STATE_ENABLED: + *status = 1; /* Enabled */ + break; +- case 3: ++ case SLOT_STATE_DISABLED: + *status = 0; /* Disabled */ + break; + default: +- *status = 0xFF; ++ *status = 0xFF; /* Reserved */ + break; + } + + DBG_LEAVE_ROUTINE +- return retval; ++ return 0; + } + + +@@ -510,7 +496,6 @@ static int hpc_get_latch_status(struct s + { + struct controller *ctrl = slot->ctrl; + u32 slot_reg; +- u16 slot_status; + + DBG_ENTER_ROUTINE + +@@ -520,10 +505,7 @@ static int hpc_get_latch_status(struct s + } + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); +- slot_status = (u16)slot_reg; +- +- *status = ((slot_status & 0x0100) == 0) ? 0 : 1; /* 0 -> close; 1 -> open */ +- ++ *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ + + DBG_LEAVE_ROUTINE + return 0; +@@ -533,8 +515,7 @@ static int hpc_get_adapter_status(struct + { + struct controller *ctrl = slot->ctrl; + u32 slot_reg; +- u16 slot_status; +- u8 card_state; ++ u8 state; + + DBG_ENTER_ROUTINE + +@@ -544,9 +525,8 @@ static int hpc_get_adapter_status(struct + } + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); +- slot_status = (u16)slot_reg; +- card_state = (u8)((slot_status & 0x0C00) >> 10); +- *status = (card_state != 0x3) ? 1 : 0; ++ state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; ++ *status = (state != 0x3) ? 1 : 0; + + DBG_LEAVE_ROUTINE + return 0; +@@ -574,8 +554,8 @@ static int hpc_get_adapter_speed(struct + int retval = 0; + struct controller *ctrl = slot->ctrl; + u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); +- u8 pcix_cap = (slot_reg >> 12) & 7; +- u8 m66_cap = (slot_reg >> 9) & 1; ++ u8 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; ++ u8 m66_cap = !!(slot_reg & MHZ66_CAP); + + DBG_ENTER_ROUTINE + +@@ -643,8 +623,6 @@ static int hpc_query_power_fault(struct + { + struct controller *ctrl = slot->ctrl; + u32 slot_reg; +- u16 slot_status; +- u8 pwr_fault_state, status; + + DBG_ENTER_ROUTINE + +@@ -654,13 +632,10 @@ static int hpc_query_power_fault(struct + } + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); +- slot_status = (u16) slot_reg; +- pwr_fault_state = (slot_status & 0x0040) >> 7; +- status = (pwr_fault_state == 1) ? 0 : 1; + + DBG_LEAVE_ROUTINE + /* Note: Logic 0 => fault */ +- return status; ++ return !(slot_reg & POWER_FAULT); + } + + static int hpc_set_attention_status(struct slot *slot, u8 value) +@@ -1019,7 +994,6 @@ static irqreturn_t shpc_isr(int IRQ, voi + struct controller *ctrl = NULL; + struct php_ctlr_state_s *php_ctlr; + u8 schedule_flag = 0; +- u8 temp_byte; + u32 temp_dword, intr_loc, intr_loc2; + int hp_slot; + +@@ -1080,17 +1054,20 @@ static irqreturn_t shpc_isr(int IRQ, voi + temp_dword = shpc_readl(ctrl, SLOT_REG(hp_slot)); + dbg("%s: Slot %x with intr, slot register = %x\n", + __FUNCTION__, hp_slot, temp_dword); +- temp_byte = (temp_dword >> 16) & 0xFF; +- if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08)) ++ if ((php_ctlr->switch_change_callback) && ++ (temp_dword & MRL_CHANGE_DETECTED)) + schedule_flag += php_ctlr->switch_change_callback( + hp_slot, php_ctlr->callback_instance_id); +- if ((php_ctlr->attention_button_callback) && (temp_byte & 0x04)) ++ if ((php_ctlr->attention_button_callback) && ++ (temp_dword & BUTTON_PRESS_DETECTED)) + schedule_flag += php_ctlr->attention_button_callback( + hp_slot, php_ctlr->callback_instance_id); +- if ((php_ctlr->presence_change_callback) && (temp_byte & 0x01)) ++ if ((php_ctlr->presence_change_callback) && ++ (temp_dword & PRSNT_CHANGE_DETECTED)) + schedule_flag += php_ctlr->presence_change_callback( + hp_slot , php_ctlr->callback_instance_id); +- if ((php_ctlr->power_fault_callback) && (temp_byte & 0x12)) ++ if ((php_ctlr->power_fault_callback) && ++ (temp_dword & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))) + schedule_flag += php_ctlr->power_fault_callback( + hp_slot, php_ctlr->callback_instance_id); + diff --git a/pci/shpc-cleanup-shpc-register-access.patch b/pci/shpc-cleanup-shpc-register-access.patch new file mode 100644 index 0000000000000..e5d200d0c3962 --- /dev/null +++ b/pci/shpc-cleanup-shpc-register-access.patch @@ -0,0 +1,536 @@ +From kaneshige.kenji@jp.fujitsu.com Mon May 1 19:11:17 2006 +Message-ID: <4456BF2A.40304@jp.fujitsu.com> +Date: Tue, 02 May 2006 11:08:42 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <gregkh@suse.de>, Kristen Accardi <kristen.c.accardi@intel.com>, +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: SHPC: Cleanup SHPC register access + +This patch cleans up the code to access SHPC working register +sets. This patch has no functional changes. + +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> + +--- + drivers/pci/hotplug/shpchp_hpc.c | 192 ++++++++++++++++++++++----------------- + 1 file changed, 112 insertions(+), 80 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -208,6 +208,49 @@ static irqreturn_t shpc_isr(int IRQ, voi + static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); + static int hpc_check_cmd_status(struct controller *ctrl); + ++static inline u8 shpc_readb(struct controller *ctrl, int reg) ++{ ++ return readb(ctrl->hpc_ctlr_handle->creg + reg); ++} ++ ++static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val) ++{ ++ writeb(val, ctrl->hpc_ctlr_handle->creg + reg); ++} ++ ++static inline u16 shpc_readw(struct controller *ctrl, int reg) ++{ ++ return readw(ctrl->hpc_ctlr_handle->creg + reg); ++} ++ ++static inline void shpc_writew(struct controller *ctrl, int reg, u16 val) ++{ ++ writew(val, ctrl->hpc_ctlr_handle->creg + reg); ++} ++ ++static inline u32 shpc_readl(struct controller *ctrl, int reg) ++{ ++ return readl(ctrl->hpc_ctlr_handle->creg + reg); ++} ++ ++static inline void shpc_writel(struct controller *ctrl, int reg, u32 val) ++{ ++ writel(val, ctrl->hpc_ctlr_handle->creg + reg); ++} ++ ++static inline int shpc_indirect_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); ++} ++ + /* This is the interrupt polling timeout function. */ + static void int_poll_timeout(unsigned long lphp_ctlr) + { +@@ -273,6 +316,7 @@ static inline int shpc_wait_cmd(struct c + 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; ++ struct controller *ctrl = slot->ctrl; + u16 cmd_status; + int retval = 0; + u16 temp_word; +@@ -289,7 +333,7 @@ static int shpc_write_cmd(struct slot *s + } + + for (i = 0; i < 10; i++) { +- cmd_status = readw(php_ctlr->creg + CMD_STATUS); ++ cmd_status = shpc_readw(ctrl, CMD_STATUS); + + if (!(cmd_status & 0x1)) + break; +@@ -297,7 +341,7 @@ static int shpc_write_cmd(struct slot *s + msleep(100); + } + +- cmd_status = readw(php_ctlr->creg + CMD_STATUS); ++ cmd_status = shpc_readw(ctrl, CMD_STATUS); + + if (cmd_status & 0x1) { + /* After 1 sec and and the controller is still busy */ +@@ -314,7 +358,7 @@ static int shpc_write_cmd(struct slot *s + * command. + */ + slot->ctrl->cmd_busy = 1; +- writew(temp_word, php_ctlr->creg + CMD); ++ shpc_writew(ctrl, CMD, temp_word); + + /* + * Wait for command completion. +@@ -338,7 +382,6 @@ static int shpc_write_cmd(struct slot *s + + static int hpc_check_cmd_status(struct controller *ctrl) + { +- struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; + u16 cmd_status; + int retval = 0; + +@@ -349,7 +392,7 @@ static int hpc_check_cmd_status(struct c + return -1; + } + +- cmd_status = readw(php_ctlr->creg + CMD_STATUS) & 0x000F; ++ cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; + + switch (cmd_status >> 1) { + case 0: +@@ -378,7 +421,7 @@ static int hpc_check_cmd_status(struct c + + static int hpc_get_attention_status(struct slot *slot, u8 *status) + { +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + u32 slot_reg; + u16 slot_status; + u8 atten_led_state; +@@ -390,7 +433,7 @@ static int hpc_get_attention_status(stru + return -1; + } + +- slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16) slot_reg; + atten_led_state = (slot_status & 0x0030) >> 4; + +@@ -418,7 +461,7 @@ static int hpc_get_attention_status(stru + + static int hpc_get_power_status(struct slot * slot, u8 *status) + { +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + u32 slot_reg; + u16 slot_status; + u8 slot_state; +@@ -431,7 +474,7 @@ static int hpc_get_power_status(struct s + return -1; + } + +- slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16) slot_reg; + slot_state = (slot_status & 0x0003); + +@@ -460,7 +503,7 @@ static int hpc_get_power_status(struct s + + static int hpc_get_latch_status(struct slot *slot, u8 *status) + { +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + u32 slot_reg; + u16 slot_status; + +@@ -471,7 +514,7 @@ static int hpc_get_latch_status(struct s + return -1; + } + +- slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16)slot_reg; + + *status = ((slot_status & 0x0100) == 0) ? 0 : 1; /* 0 -> close; 1 -> open */ +@@ -483,7 +526,7 @@ static int hpc_get_latch_status(struct s + + static int hpc_get_adapter_status(struct slot *slot, u8 *status) + { +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + u32 slot_reg; + u16 slot_status; + u8 card_state; +@@ -495,7 +538,7 @@ static int hpc_get_adapter_status(struct + return -1; + } + +- slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16)slot_reg; + card_state = (u8)((slot_status & 0x0C00) >> 10); + *status = (card_state != 0x3) ? 1 : 0; +@@ -506,7 +549,7 @@ static int hpc_get_adapter_status(struct + + static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) + { +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + + DBG_ENTER_ROUTINE + +@@ -515,7 +558,7 @@ static int hpc_get_prog_int(struct slot + return -1; + } + +- *prog_int = readb(php_ctlr->creg + PROG_INTERFACE); ++ *prog_int = shpc_readb(ctrl, PROG_INTERFACE); + + DBG_LEAVE_ROUTINE + return 0; +@@ -524,8 +567,8 @@ static int hpc_get_prog_int(struct slot + static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) + { + int retval = 0; +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; +- u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot); ++ struct controller *ctrl = slot->ctrl; ++ u32 slot_reg = shpc_readl(ctrl, SLOT1 + 4 * slot->hp_slot); + u8 pcix_cap = (slot_reg >> 12) & 7; + u8 m66_cap = (slot_reg >> 9) & 1; + +@@ -564,7 +607,7 @@ static int hpc_get_adapter_speed(struct + + static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) + { +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + u16 sec_bus_status; + u8 pi; + int retval = 0; +@@ -576,8 +619,8 @@ static int hpc_get_mode1_ECC_cap(struct + return -1; + } + +- pi = readb(php_ctlr->creg + PROG_INTERFACE); +- sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); ++ pi = shpc_readb(ctrl, PROG_INTERFACE); ++ sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); + + if (pi == 2) { + *mode = (sec_bus_status & 0x0100) >> 8; +@@ -593,7 +636,7 @@ static int hpc_get_mode1_ECC_cap(struct + + static int hpc_query_power_fault(struct slot * slot) + { +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + u32 slot_reg; + u16 slot_status; + u8 pwr_fault_state, status; +@@ -605,7 +648,7 @@ static int hpc_query_power_fault(struct + return -1; + } + +- slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); ++ slot_reg = shpc_readl(ctrl, SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16) slot_reg; + pwr_fault_state = (slot_status & 0x0040) >> 7; + status = (pwr_fault_state == 1) ? 0 : 1; +@@ -724,7 +767,7 @@ int shpc_get_ctlr_slot_config(struct con + int *updown, /* physical_slot_num increament: 1 or -1 */ + int *flags) + { +- struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; ++ u32 slot_config; + + DBG_ENTER_ROUTINE + +@@ -733,12 +776,13 @@ int shpc_get_ctlr_slot_config(struct con + return -1; + } + +- *first_device_num = php_ctlr->slot_device_offset; /* Obtained in shpc_init() */ +- *num_ctlr_slots = php_ctlr->num_slots; /* Obtained in shpc_init() */ ++ slot_config = shpc_readl(ctrl, SLOT_CONFIG); ++ *first_device_num = (slot_config & FIRST_DEV_NUM) >> 8; ++ *num_ctlr_slots = slot_config & SLOT_NUM; ++ *physical_slot_num = (slot_config & PSN) >> 16; ++ *updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1; + +- *physical_slot_num = (readl(php_ctlr->creg + SLOT_CONFIG) & PSN) >> 16; + dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num); +- *updown = ((readl(php_ctlr->creg + SLOT_CONFIG) & UPDOWN ) >> 29) ? 1 : -1; + + DBG_LEAVE_ROUTINE + return 0; +@@ -761,7 +805,7 @@ static void hpc_release_ctlr(struct cont + * Mask all slot event interrupts + */ + for (i = 0; i < ctrl->num_slots; i++) +- writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i)); ++ shpc_writel(ctrl, SLOT1 + (4 * i), 0xffff3fff); + + cleanup_slots(ctrl); + +@@ -901,12 +945,12 @@ static int hpc_slot_disable(struct slot + static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) + { + int retval; +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + u8 pi, cmd; + + DBG_ENTER_ROUTINE + +- pi = readb(php_ctlr->creg + PROG_INTERFACE); ++ pi = shpc_readb(ctrl, PROG_INTERFACE); + if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) + return -EINVAL; + +@@ -992,7 +1036,7 @@ static irqreturn_t shpc_isr(int IRQ, voi + return IRQ_NONE; + + /* Check to see if it was our interrupt */ +- intr_loc = readl(php_ctlr->creg + INTR_LOC); ++ intr_loc = shpc_readl(ctrl, INTR_LOC); + + if (!intr_loc) + return IRQ_NONE; +@@ -1001,11 +1045,11 @@ static irqreturn_t shpc_isr(int IRQ, voi + if(!shpchp_poll_mode) { + /* Mask Global Interrupt Mask - see implementation note on p. 139 */ + /* of SHPC spec rev 1.0*/ +- temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); ++ temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); + temp_dword |= 0x00000001; +- writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); ++ shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + +- intr_loc2 = readl(php_ctlr->creg + INTR_LOC); ++ intr_loc2 = shpc_readl(ctrl, INTR_LOC); + dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); + } + +@@ -1015,9 +1059,9 @@ static irqreturn_t shpc_isr(int IRQ, voi + * 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 = shpc_readl(ctrl, SERR_INTR_ENABLE); + temp_dword &= 0xfffdffff; +- writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); ++ shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + ctrl->cmd_busy = 0; + wake_up_interruptible(&ctrl->queue); + } +@@ -1028,7 +1072,7 @@ static irqreturn_t shpc_isr(int IRQ, voi + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { + /* To find out which slot has interrupt pending */ + if ((intr_loc >> hp_slot) & 0x01) { +- temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot)); ++ temp_dword = shpc_readl(ctrl, SLOT1 + (4*hp_slot)); + dbg("%s: Slot %x with intr, slot register = %x\n", + __FUNCTION__, hp_slot, temp_dword); + temp_byte = (temp_dword >> 16) & 0xFF; +@@ -1047,18 +1091,18 @@ static irqreturn_t shpc_isr(int IRQ, voi + + /* Clear all slot events */ + temp_dword = 0xe01f3fff; +- writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot)); ++ shpc_writel(ctrl, SLOT1 + (4*hp_slot), temp_dword); + +- intr_loc2 = readl(php_ctlr->creg + INTR_LOC); ++ intr_loc2 = shpc_readl(ctrl, INTR_LOC); + dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); + } + } + out: + if (!shpchp_poll_mode) { + /* Unmask Global Interrupt Mask */ +- temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); ++ temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); + temp_dword &= 0xfffffffe; +- writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); ++ shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + } + + return IRQ_HANDLED; +@@ -1067,11 +1111,11 @@ static irqreturn_t shpc_isr(int IRQ, voi + static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) + { + int retval = 0; +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; +- u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); +- u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); +- u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); ++ u8 pi = shpc_readb(ctrl, PROG_INTERFACE); ++ u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); ++ u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); + + DBG_ENTER_ROUTINE + +@@ -1114,10 +1158,10 @@ static int hpc_get_max_bus_speed (struct + static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) + { + int retval = 0; +- struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; ++ struct controller *ctrl = slot->ctrl; + enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; +- u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG); +- u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); ++ u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); ++ u8 pi = shpc_readb(ctrl, PROG_INTERFACE); + u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); + + DBG_ENTER_ROUTINE +@@ -1206,19 +1250,6 @@ static struct hpc_ops shpchp_hpc_ops = { + .release_ctlr = hpc_release_ctlr, + }; + +-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; +@@ -1227,7 +1258,7 @@ int shpc_init(struct controller * ctrl, + u8 hp_slot; + static int first = 1; + u32 shpc_base_offset; +- u32 tempdword, slot_reg; ++ u32 tempdword, slot_reg, slot_config; + u8 i; + + DBG_ENTER_ROUTINE +@@ -1257,13 +1288,13 @@ int shpc_init(struct controller * ctrl, + } + dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); + +- rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset); ++ rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); + if (rc) { + err("%s: cannot read base_offset\n", __FUNCTION__); + goto abort_free_ctlr; + } + +- rc = shpc_indirect_creg_read(ctrl, 3, &tempdword); ++ rc = shpc_indirect_read(ctrl, 3, &tempdword); + if (rc) { + err("%s: cannot read slot config\n", __FUNCTION__); + goto abort_free_ctlr; +@@ -1272,7 +1303,7 @@ int shpc_init(struct controller * ctrl, + dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); + + for (i = 0; i < 9 + num_slots; i++) { +- rc = shpc_indirect_creg_read(ctrl, i, &tempdword); ++ rc = shpc_indirect_read(ctrl, i, &tempdword); + if (rc) { + err("%s: cannot read creg (index = %d)\n", + __FUNCTION__, i); +@@ -1326,29 +1357,33 @@ int shpc_init(struct controller * ctrl, + php_ctlr->power_fault_callback = shpchp_handle_power_fault; + php_ctlr->callback_instance_id = instance_id; + ++ ctrl->hpc_ctlr_handle = php_ctlr; ++ ctrl->hpc_ops = &shpchp_hpc_ops; ++ + /* Return PCI Controller Info */ +- php_ctlr->slot_device_offset = (readl(php_ctlr->creg + SLOT_CONFIG) & FIRST_DEV_NUM ) >> 8; +- php_ctlr->num_slots = readl(php_ctlr->creg + SLOT_CONFIG) & SLOT_NUM; ++ slot_config = shpc_readl(ctrl, SLOT_CONFIG); ++ php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; ++ php_ctlr->num_slots = slot_config & SLOT_NUM; + dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset); + dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots); + + /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ +- tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); ++ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); + tempdword = 0x0003000f; +- writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); +- tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); ++ shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); ++ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); + + /* Mask the MRL sensor SERR Mask of individual slot in + * Slot SERR-INT Mask & clear all the existing event if any + */ + for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { +- slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); ++ slot_reg = shpc_readl(ctrl, SLOT1 + 4*hp_slot ); + dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, + hp_slot, slot_reg); + tempdword = 0xffff3fff; +- writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); ++ shpc_writel(ctrl, SLOT1 + (4*hp_slot), tempdword); + } + + if (shpchp_poll_mode) {/* Install interrupt polling code */ +@@ -1392,24 +1427,21 @@ int shpc_init(struct controller * ctrl, + } + spin_unlock(&list_lock); + +- + ctlr_seq_num++; +- ctrl->hpc_ctlr_handle = php_ctlr; +- ctrl->hpc_ops = &shpchp_hpc_ops; + + for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { +- slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); ++ slot_reg = shpc_readl(ctrl, SLOT1 + 4*hp_slot ); + dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, + hp_slot, slot_reg); + tempdword = 0xe01f3fff; +- writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); ++ shpc_writel(ctrl, SLOT1 + (4*hp_slot), tempdword); + } + if (!shpchp_poll_mode) { + /* Unmask all general input interrupts and SERR */ +- tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); ++ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); + tempdword = 0x0000000a; +- writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); +- tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); ++ shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); ++ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); + } + diff --git a/pci/shpc-fix-shpc-contoller-serr-int-register-bits-access.patch b/pci/shpc-fix-shpc-contoller-serr-int-register-bits-access.patch new file mode 100644 index 0000000000000..0e17888ae884f --- /dev/null +++ b/pci/shpc-fix-shpc-contoller-serr-int-register-bits-access.patch @@ -0,0 +1,115 @@ +From kaneshige.kenji@jp.fujitsu.com Mon May 1 19:15:35 2006 +Message-ID: <4456C015.7080604@jp.fujitsu.com> +Date: Tue, 02 May 2006 11:12:37 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <gregkh@suse.de>, Kristen Accardi <kristen.c.accardi@intel.com> +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: SHPC: Fix SHPC Contoller SERR-INT Register bits access + +Current SHPCHP driver doesn't take care of RsvdP/RsvdZ[*] bits in +controller SERR-INT register. 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> + +--- + drivers/pci/hotplug/shpchp_hpc.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -91,6 +91,17 @@ + #define ATTN_BUTTON 0x80000000 + + /* ++ * Controller SERR-INT Register ++ */ ++#define GLOBAL_INTR_MASK (1 << 0) ++#define GLOBAL_SERR_MASK (1 << 1) ++#define COMMAND_INTR_MASK (1 << 2) ++#define ARBITER_SERR_MASK (1 << 3) ++#define COMMAND_DETECTED (1 << 16) ++#define ARBITER_DETECTED (1 << 17) ++#define SERR_INTR_RSVDZ_MASK 0xfffc0000 ++ ++/* + * Logical Slot Register definitions + */ + #define SLOT_REG(i) (SLOT1 + (4 * i)) +@@ -1047,7 +1058,8 @@ static irqreturn_t shpc_isr(int IRQ, voi + /* Mask Global Interrupt Mask - see implementation note on p. 139 */ + /* of SHPC spec rev 1.0*/ + temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); +- temp_dword |= 0x00000001; ++ temp_dword |= GLOBAL_INTR_MASK; ++ temp_dword &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + + intr_loc2 = shpc_readl(ctrl, INTR_LOC); +@@ -1061,7 +1073,7 @@ static irqreturn_t shpc_isr(int IRQ, voi + * Detect bit in Controller SERR-INT register + */ + temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); +- temp_dword &= 0xfffdffff; ++ temp_dword &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + ctrl->cmd_busy = 0; + wake_up_interruptible(&ctrl->queue); +@@ -1105,7 +1117,7 @@ static irqreturn_t shpc_isr(int IRQ, voi + if (!shpchp_poll_mode) { + /* Unmask Global Interrupt Mask */ + temp_dword = shpc_readl(ctrl, SERR_INTR_ENABLE); +- temp_dword &= 0xfffffffe; ++ temp_dword &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); + shpc_writel(ctrl, SERR_INTR_ENABLE, temp_dword); + } + +@@ -1374,7 +1386,9 @@ int shpc_init(struct controller * ctrl, + /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); +- tempdword = 0x0003000f; ++ tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | ++ COMMAND_INTR_MASK | ARBITER_SERR_MASK); ++ tempdword &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); +@@ -1452,7 +1466,8 @@ int shpc_init(struct controller * ctrl, + if (!shpchp_poll_mode) { + /* Unmask all general input interrupts and SERR */ + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); +- tempdword = 0x0000000a; ++ tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK | ++ SERR_INTR_RSVDZ_MASK); + shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); diff --git a/pci/shpc-fix-shpc-logical-slot-register-bits-access.patch b/pci/shpc-fix-shpc-logical-slot-register-bits-access.patch new file mode 100644 index 0000000000000..aa00b6717da66 --- /dev/null +++ b/pci/shpc-fix-shpc-logical-slot-register-bits-access.patch @@ -0,0 +1,148 @@ +From kaneshige.kenji@jp.fujitsu.com Mon May 1 19:14:15 2006 +Message-ID: <4456BFEA.4070008@jp.fujitsu.com> +Date: Tue, 02 May 2006 11:11:54 +0900 +From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +To: Greg KH <gregkh@suse.de>, Kristen Accardi <kristen.c.accardi@intel.com> +Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> +Subject: 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> + +--- + drivers/pci/hotplug/shpchp_hpc.c | 49 +++++++++++++++++++++++++++++++-------- + 1 file changed, 40 insertions(+), 9 deletions(-) + +--- gregkh-2.6.orig/drivers/pci/hotplug/shpchp_hpc.c ++++ gregkh-2.6/drivers/pci/hotplug/shpchp_hpc.c +@@ -554,11 +554,25 @@ static int hpc_get_adapter_speed(struct + 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 cont + 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 cont + } + + /* +- * 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, voi + 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, + 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, + + 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 */ |