Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] acpi_pcihp: Add support for _HPX

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>

authored by

Kenji Kaneshige and committed by
Greg Kroah-Hartman
e22b7350 aad20cab

+262 -36
+180 -8
drivers/pci/hotplug/acpi_pcihp.c
··· 47 47 48 48 static int debug_acpi; 49 49 50 + static acpi_status 51 + decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx) 52 + { 53 + int i; 54 + union acpi_object *fields = record->package.elements; 55 + u32 revision = fields[1].integer.value; 56 + 57 + switch (revision) { 58 + case 1: 59 + if (record->package.count != 6) 60 + return AE_ERROR; 61 + for (i = 2; i < 6; i++) 62 + if (fields[i].type != ACPI_TYPE_INTEGER) 63 + return AE_ERROR; 64 + hpx->t0 = &hpx->type0_data; 65 + hpx->t0->revision = revision; 66 + hpx->t0->cache_line_size = fields[2].integer.value; 67 + hpx->t0->latency_timer = fields[3].integer.value; 68 + hpx->t0->enable_serr = fields[4].integer.value; 69 + hpx->t0->enable_perr = fields[5].integer.value; 70 + break; 71 + default: 72 + printk(KERN_WARNING 73 + "%s: Type 0 Revision %d record not supported\n", 74 + __FUNCTION__, revision); 75 + return AE_ERROR; 76 + } 77 + return AE_OK; 78 + } 79 + 80 + static acpi_status 81 + decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx) 82 + { 83 + int i; 84 + union acpi_object *fields = record->package.elements; 85 + u32 revision = fields[1].integer.value; 86 + 87 + switch (revision) { 88 + case 1: 89 + if (record->package.count != 5) 90 + return AE_ERROR; 91 + for (i = 2; i < 5; i++) 92 + if (fields[i].type != ACPI_TYPE_INTEGER) 93 + return AE_ERROR; 94 + hpx->t1 = &hpx->type1_data; 95 + hpx->t1->revision = revision; 96 + hpx->t1->max_mem_read = fields[2].integer.value; 97 + hpx->t1->avg_max_split = fields[3].integer.value; 98 + hpx->t1->tot_max_split = fields[4].integer.value; 99 + break; 100 + default: 101 + printk(KERN_WARNING 102 + "%s: Type 1 Revision %d record not supported\n", 103 + __FUNCTION__, revision); 104 + return AE_ERROR; 105 + } 106 + return AE_OK; 107 + } 108 + 109 + static acpi_status 110 + decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx) 111 + { 112 + int i; 113 + union acpi_object *fields = record->package.elements; 114 + u32 revision = fields[1].integer.value; 115 + 116 + switch (revision) { 117 + case 1: 118 + if (record->package.count != 18) 119 + return AE_ERROR; 120 + for (i = 2; i < 18; i++) 121 + if (fields[i].type != ACPI_TYPE_INTEGER) 122 + return AE_ERROR; 123 + hpx->t2 = &hpx->type2_data; 124 + hpx->t2->revision = revision; 125 + hpx->t2->unc_err_mask_and = fields[2].integer.value; 126 + hpx->t2->unc_err_mask_or = fields[3].integer.value; 127 + hpx->t2->unc_err_sever_and = fields[4].integer.value; 128 + hpx->t2->unc_err_sever_or = fields[5].integer.value; 129 + hpx->t2->cor_err_mask_and = fields[6].integer.value; 130 + hpx->t2->cor_err_mask_or = fields[7].integer.value; 131 + hpx->t2->adv_err_cap_and = fields[8].integer.value; 132 + hpx->t2->adv_err_cap_or = fields[9].integer.value; 133 + hpx->t2->pci_exp_devctl_and = fields[10].integer.value; 134 + hpx->t2->pci_exp_devctl_or = fields[11].integer.value; 135 + hpx->t2->pci_exp_lnkctl_and = fields[12].integer.value; 136 + hpx->t2->pci_exp_lnkctl_or = fields[13].integer.value; 137 + hpx->t2->sec_unc_err_sever_and = fields[14].integer.value; 138 + hpx->t2->sec_unc_err_sever_or = fields[15].integer.value; 139 + hpx->t2->sec_unc_err_mask_and = fields[16].integer.value; 140 + hpx->t2->sec_unc_err_mask_or = fields[17].integer.value; 141 + break; 142 + default: 143 + printk(KERN_WARNING 144 + "%s: Type 2 Revision %d record not supported\n", 145 + __FUNCTION__, revision); 146 + return AE_ERROR; 147 + } 148 + return AE_OK; 149 + } 150 + 151 + static acpi_status 152 + acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) 153 + { 154 + acpi_status status; 155 + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 156 + union acpi_object *package, *record, *fields; 157 + u32 type; 158 + int i; 159 + 160 + /* Clear the return buffer with zeros */ 161 + memset(hpx, 0, sizeof(struct hotplug_params)); 162 + 163 + status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer); 164 + if (ACPI_FAILURE(status)) 165 + return status; 166 + 167 + package = (union acpi_object *)buffer.pointer; 168 + if (package->type != ACPI_TYPE_PACKAGE) { 169 + status = AE_ERROR; 170 + goto exit; 171 + } 172 + 173 + for (i = 0; i < package->package.count; i++) { 174 + record = &package->package.elements[i]; 175 + if (record->type != ACPI_TYPE_PACKAGE) { 176 + status = AE_ERROR; 177 + goto exit; 178 + } 179 + 180 + fields = record->package.elements; 181 + if (fields[0].type != ACPI_TYPE_INTEGER || 182 + fields[1].type != ACPI_TYPE_INTEGER) { 183 + status = AE_ERROR; 184 + goto exit; 185 + } 186 + 187 + type = fields[0].integer.value; 188 + switch (type) { 189 + case 0: 190 + status = decode_type0_hpx_record(record, hpx); 191 + if (ACPI_FAILURE(status)) 192 + goto exit; 193 + break; 194 + case 1: 195 + status = decode_type1_hpx_record(record, hpx); 196 + if (ACPI_FAILURE(status)) 197 + goto exit; 198 + break; 199 + case 2: 200 + status = decode_type2_hpx_record(record, hpx); 201 + if (ACPI_FAILURE(status)) 202 + goto exit; 203 + break; 204 + default: 205 + printk(KERN_ERR "%s: Type %d record not supported\n", 206 + __FUNCTION__, type); 207 + status = AE_ERROR; 208 + goto exit; 209 + } 210 + } 211 + exit: 212 + kfree(buffer.pointer); 213 + return status; 214 + } 50 215 51 216 static acpi_status 52 217 acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) ··· 224 59 int i, len = 0; 225 60 226 61 acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); 62 + 63 + /* Clear the return buffer with zeros */ 64 + memset(hpp, 0, sizeof(struct hotplug_params)); 227 65 228 66 /* get _hpp */ 229 67 status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); ··· 276 108 } 277 109 } 278 110 279 - hpp->cache_line_size = nui[0]; 280 - hpp->latency_timer = nui[1]; 281 - hpp->enable_serr = nui[2]; 282 - hpp->enable_perr = nui[3]; 111 + hpp->t0 = &hpp->type0_data; 112 + hpp->t0->cache_line_size = nui[0]; 113 + hpp->t0->latency_timer = nui[1]; 114 + hpp->t0->enable_serr = nui[2]; 115 + hpp->t0->enable_perr = nui[3]; 283 116 284 - pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); 285 - pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer); 286 - pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); 287 - pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); 117 + pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); 118 + pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); 119 + pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); 120 + pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); 288 121 289 122 free_and_return: 290 123 kfree(string.pointer); ··· 357 188 * this pci dev. If we don't find any _HPP, use hardcoded defaults 358 189 */ 359 190 while (handle) { 191 + status = acpi_run_hpx(handle, hpp); 192 + if (ACPI_SUCCESS(status)) 193 + break; 360 194 status = acpi_run_hpp(handle, hpp); 361 195 if (ACPI_SUCCESS(status)) 362 196 break;
+19 -12
drivers/pci/hotplug/acpiphp_glue.c
··· 287 287 acpi_status status; 288 288 289 289 status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); 290 - if (ACPI_FAILURE(status)) { 290 + if (ACPI_FAILURE(status) || 291 + !bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) { 291 292 /* use default numbers */ 292 - bridge->hpp.cache_line_size = 0x10; 293 - bridge->hpp.latency_timer = 0x40; 294 - bridge->hpp.enable_serr = 0; 295 - bridge->hpp.enable_perr = 0; 293 + printk(KERN_WARNING 294 + "%s: Could not get hotplug parameters. Use defaults\n", 295 + __FUNCTION__); 296 + bridge->hpp.t0 = &bridge->hpp.type0_data; 297 + bridge->hpp.t0->revision = 0; 298 + bridge->hpp.t0->cache_line_size = 0x10; 299 + bridge->hpp.t0->latency_timer = 0x40; 300 + bridge->hpp.t0->enable_serr = 0; 301 + bridge->hpp.t0->enable_perr = 0; 296 302 } 297 303 } 298 304 ··· 1212 1206 (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && 1213 1207 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) 1214 1208 return; 1209 + 1215 1210 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 1216 - bridge->hpp.cache_line_size); 1211 + bridge->hpp.t0->cache_line_size); 1217 1212 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 1218 - bridge->hpp.latency_timer); 1213 + bridge->hpp.t0->latency_timer); 1219 1214 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); 1220 - if (bridge->hpp.enable_serr) 1215 + if (bridge->hpp.t0->enable_serr) 1221 1216 pci_cmd |= PCI_COMMAND_SERR; 1222 1217 else 1223 1218 pci_cmd &= ~PCI_COMMAND_SERR; 1224 - if (bridge->hpp.enable_perr) 1219 + if (bridge->hpp.t0->enable_perr) 1225 1220 pci_cmd |= PCI_COMMAND_PARITY; 1226 1221 else 1227 1222 pci_cmd &= ~PCI_COMMAND_PARITY; ··· 1231 1224 /* Program bridge control value and child devices */ 1232 1225 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 1233 1226 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 1234 - bridge->hpp.latency_timer); 1227 + bridge->hpp.t0->latency_timer); 1235 1228 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); 1236 - if (bridge->hpp.enable_serr) 1229 + if (bridge->hpp.t0->enable_serr) 1237 1230 pci_bctl |= PCI_BRIDGE_CTL_SERR; 1238 1231 else 1239 1232 pci_bctl &= ~PCI_BRIDGE_CTL_SERR; 1240 - if (bridge->hpp.enable_perr) 1233 + if (bridge->hpp.t0->enable_perr) 1241 1234 pci_bctl |= PCI_BRIDGE_CTL_PARITY; 1242 1235 else 1243 1236 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+44 -4
drivers/pci/hotplug/pci_hotplug.h
··· 176 176 struct hotplug_slot_info *info); 177 177 extern struct subsystem pci_hotplug_slots_subsys; 178 178 179 + /* PCI Setting Record (Type 0) */ 180 + struct hpp_type0 { 181 + u32 revision; 182 + u8 cache_line_size; 183 + u8 latency_timer; 184 + u8 enable_serr; 185 + u8 enable_perr; 186 + }; 187 + 188 + /* PCI-X Setting Record (Type 1) */ 189 + struct hpp_type1 { 190 + u32 revision; 191 + u8 max_mem_read; 192 + u8 avg_max_split; 193 + u16 tot_max_split; 194 + }; 195 + 196 + /* PCI Express Setting Record (Type 2) */ 197 + struct hpp_type2 { 198 + u32 revision; 199 + u32 unc_err_mask_and; 200 + u32 unc_err_mask_or; 201 + u32 unc_err_sever_and; 202 + u32 unc_err_sever_or; 203 + u32 cor_err_mask_and; 204 + u32 cor_err_mask_or; 205 + u32 adv_err_cap_and; 206 + u32 adv_err_cap_or; 207 + u16 pci_exp_devctl_and; 208 + u16 pci_exp_devctl_or; 209 + u16 pci_exp_lnkctl_and; 210 + u16 pci_exp_lnkctl_or; 211 + u32 sec_unc_err_sever_and; 212 + u32 sec_unc_err_sever_or; 213 + u32 sec_unc_err_mask_and; 214 + u32 sec_unc_err_mask_or; 215 + }; 216 + 179 217 struct hotplug_params { 180 - u8 cache_line_size; 181 - u8 latency_timer; 182 - u8 enable_serr; 183 - u8 enable_perr; 218 + struct hpp_type0 *t0; /* Type0: NULL if not available */ 219 + struct hpp_type1 *t1; /* Type1: NULL if not available */ 220 + struct hpp_type2 *t2; /* Type2: NULL if not available */ 221 + struct hpp_type0 type0_data; 222 + struct hpp_type1 type1_data; 223 + struct hpp_type2 type2_data; 184 224 }; 185 225 186 226 #ifdef CONFIG_ACPI
+19 -12
drivers/pci/hotplug/shpchp_pci.c
··· 47 47 return; 48 48 49 49 /* use default values if we can't get them from firmware */ 50 - if (get_hp_params_from_firmware(dev, &hpp)) { 51 - hpp.cache_line_size = 8; 52 - hpp.latency_timer = 0x40; 53 - hpp.enable_serr = 0; 54 - hpp.enable_perr = 0; 50 + if (get_hp_params_from_firmware(dev, &hpp) || 51 + !hpp.t0 || (hpp.t0->revision > 1)) { 52 + printk(KERN_WARNING 53 + "%s: Could not get hotplug parameters. Use defaults\n", 54 + __FUNCTION__); 55 + hpp.t0 = &hpp.type0_data; 56 + hpp.t0->revision = 0; 57 + hpp.t0->cache_line_size = 8; 58 + hpp.t0->latency_timer = 0x40; 59 + hpp.t0->enable_serr = 0; 60 + hpp.t0->enable_perr = 0; 55 61 } 56 62 57 - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); 58 - pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); 63 + pci_write_config_byte(dev, 64 + PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size); 65 + pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer); 59 66 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); 60 - if (hpp.enable_serr) 67 + if (hpp.t0->enable_serr) 61 68 pci_cmd |= PCI_COMMAND_SERR; 62 69 else 63 70 pci_cmd &= ~PCI_COMMAND_SERR; 64 - if (hpp.enable_perr) 71 + if (hpp.t0->enable_perr) 65 72 pci_cmd |= PCI_COMMAND_PARITY; 66 73 else 67 74 pci_cmd &= ~PCI_COMMAND_PARITY; ··· 77 70 /* Program bridge control value and child devices */ 78 71 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 79 72 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 80 - hpp.latency_timer); 73 + hpp.t0->latency_timer); 81 74 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); 82 - if (hpp.enable_serr) 75 + if (hpp.t0->enable_serr) 83 76 pci_bctl |= PCI_BRIDGE_CTL_SERR; 84 77 else 85 78 pci_bctl &= ~PCI_BRIDGE_CTL_SERR; 86 - if (hpp.enable_perr) 79 + if (hpp.t0->enable_perr) 87 80 pci_bctl |= PCI_BRIDGE_CTL_PARITY; 88 81 else 89 82 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;