aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2006-05-01 21:57:14 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-19 17:13:22 -0400
commite22b73501608901bab7ee9b1f8cb67f15e8efb7a (patch)
tree4edf850a0216b36c184b6abe43e32a600d4f7787 /drivers/pci/hotplug
parentaad20cabaa3d6dfa1e0ebc8fb0537a96d3518b8f (diff)
[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>
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c188
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c31
-rw-r--r--drivers/pci/hotplug/pci_hotplug.h48
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c31
4 files changed, 262 insertions, 36 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index afac5c37325b..51cb9f817c22 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -47,6 +47,171 @@
47 47
48static int debug_acpi; 48static int debug_acpi;
49 49
50static acpi_status
51decode_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
80static acpi_status
81decode_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
109static acpi_status
110decode_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
151static acpi_status
152acpi_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
51static acpi_status 216static acpi_status
52acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) 217acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
@@ -60,6 +225,9 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
60 225
61 acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); 226 acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
62 227
228 /* Clear the return buffer with zeros */
229 memset(hpp, 0, sizeof(struct hotplug_params));
230
63 /* get _hpp */ 231 /* get _hpp */
64 status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); 232 status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
65 switch (status) { 233 switch (status) {
@@ -108,15 +276,16 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
108 } 276 }
109 } 277 }
110 278
111 hpp->cache_line_size = nui[0]; 279 hpp->t0 = &hpp->type0_data;
112 hpp->latency_timer = nui[1]; 280 hpp->t0->cache_line_size = nui[0];
113 hpp->enable_serr = nui[2]; 281 hpp->t0->latency_timer = nui[1];
114 hpp->enable_perr = nui[3]; 282 hpp->t0->enable_serr = nui[2];
283 hpp->t0->enable_perr = nui[3];
115 284
116 pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); 285 pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size);
117 pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer); 286 pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer);
118 pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); 287 pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr);
119 pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); 288 pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr);
120 289
121free_and_return: 290free_and_return:
122 kfree(string.pointer); 291 kfree(string.pointer);
@@ -188,6 +357,9 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
188 * this pci dev. If we don't find any _HPP, use hardcoded defaults 357 * this pci dev. If we don't find any _HPP, use hardcoded defaults
189 */ 358 */
190 while (handle) { 359 while (handle) {
360 status = acpi_run_hpx(handle, hpp);
361 if (ACPI_SUCCESS(status))
362 break;
191 status = acpi_run_hpp(handle, hpp); 363 status = acpi_run_hpp(handle, hpp);
192 if (ACPI_SUCCESS(status)) 364 if (ACPI_SUCCESS(status))
193 break; 365 break;
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 4b0988e93806..d370f999782e 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -287,12 +287,18 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
287 acpi_status status; 287 acpi_status status;
288 288
289 status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); 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 /* use default numbers */ 292 /* use default numbers */
292 bridge->hpp.cache_line_size = 0x10; 293 printk(KERN_WARNING
293 bridge->hpp.latency_timer = 0x40; 294 "%s: Could not get hotplug parameters. Use defaults\n",
294 bridge->hpp.enable_serr = 0; 295 __FUNCTION__);
295 bridge->hpp.enable_perr = 0; 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
@@ -1206,16 +1212,17 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
1206 (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && 1212 (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
1207 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) 1213 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
1208 return; 1214 return;
1215
1209 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 1216 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
1210 bridge->hpp.cache_line_size); 1217 bridge->hpp.t0->cache_line_size);
1211 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 1218 pci_write_config_byte(dev, PCI_LATENCY_TIMER,
1212 bridge->hpp.latency_timer); 1219 bridge->hpp.t0->latency_timer);
1213 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); 1220 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
1214 if (bridge->hpp.enable_serr) 1221 if (bridge->hpp.t0->enable_serr)
1215 pci_cmd |= PCI_COMMAND_SERR; 1222 pci_cmd |= PCI_COMMAND_SERR;
1216 else 1223 else
1217 pci_cmd &= ~PCI_COMMAND_SERR; 1224 pci_cmd &= ~PCI_COMMAND_SERR;
1218 if (bridge->hpp.enable_perr) 1225 if (bridge->hpp.t0->enable_perr)
1219 pci_cmd |= PCI_COMMAND_PARITY; 1226 pci_cmd |= PCI_COMMAND_PARITY;
1220 else 1227 else
1221 pci_cmd &= ~PCI_COMMAND_PARITY; 1228 pci_cmd &= ~PCI_COMMAND_PARITY;
@@ -1224,13 +1231,13 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
1224 /* Program bridge control value and child devices */ 1231 /* Program bridge control value and child devices */
1225 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 1232 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
1226 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 1233 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
1227 bridge->hpp.latency_timer); 1234 bridge->hpp.t0->latency_timer);
1228 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); 1235 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
1229 if (bridge->hpp.enable_serr) 1236 if (bridge->hpp.t0->enable_serr)
1230 pci_bctl |= PCI_BRIDGE_CTL_SERR; 1237 pci_bctl |= PCI_BRIDGE_CTL_SERR;
1231 else 1238 else
1232 pci_bctl &= ~PCI_BRIDGE_CTL_SERR; 1239 pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
1233 if (bridge->hpp.enable_perr) 1240 if (bridge->hpp.t0->enable_perr)
1234 pci_bctl |= PCI_BRIDGE_CTL_PARITY; 1241 pci_bctl |= PCI_BRIDGE_CTL_PARITY;
1235 else 1242 else
1236 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; 1243 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h
index 6913ace70e9b..e929b7c11429 100644
--- a/drivers/pci/hotplug/pci_hotplug.h
+++ b/drivers/pci/hotplug/pci_hotplug.h
@@ -176,11 +176,51 @@ extern int pci_hp_change_slot_info (struct hotplug_slot *slot,
176 struct hotplug_slot_info *info); 176 struct hotplug_slot_info *info);
177extern struct subsystem pci_hotplug_slots_subsys; 177extern struct subsystem pci_hotplug_slots_subsys;
178 178
179/* PCI Setting Record (Type 0) */
180struct 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) */
189struct 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) */
197struct 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
179struct hotplug_params { 217struct hotplug_params {
180 u8 cache_line_size; 218 struct hpp_type0 *t0; /* Type0: NULL if not available */
181 u8 latency_timer; 219 struct hpp_type1 *t1; /* Type1: NULL if not available */
182 u8 enable_serr; 220 struct hpp_type2 *t2; /* Type2: NULL if not available */
183 u8 enable_perr; 221 struct hpp_type0 type0_data;
222 struct hpp_type1 type1_data;
223 struct hpp_type2 type2_data;
184}; 224};
185 225
186#ifdef CONFIG_ACPI 226#ifdef CONFIG_ACPI
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 257adc233996..0a6b25ef194c 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -47,21 +47,28 @@ static void program_fw_provided_values(struct pci_dev *dev)
47 return; 47 return;
48 48
49 /* use default values if we can't get them from firmware */ 49 /* use default values if we can't get them from firmware */
50 if (get_hp_params_from_firmware(dev, &hpp)) { 50 if (get_hp_params_from_firmware(dev, &hpp) ||
51 hpp.cache_line_size = 8; 51 !hpp.t0 || (hpp.t0->revision > 1)) {
52 hpp.latency_timer = 0x40; 52 printk(KERN_WARNING
53 hpp.enable_serr = 0; 53 "%s: Could not get hotplug parameters. Use defaults\n",
54 hpp.enable_perr = 0; 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); 63 pci_write_config_byte(dev,
58 pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); 64 PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size);
65 pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer);
59 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); 66 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
60 if (hpp.enable_serr) 67 if (hpp.t0->enable_serr)
61 pci_cmd |= PCI_COMMAND_SERR; 68 pci_cmd |= PCI_COMMAND_SERR;
62 else 69 else
63 pci_cmd &= ~PCI_COMMAND_SERR; 70 pci_cmd &= ~PCI_COMMAND_SERR;
64 if (hpp.enable_perr) 71 if (hpp.t0->enable_perr)
65 pci_cmd |= PCI_COMMAND_PARITY; 72 pci_cmd |= PCI_COMMAND_PARITY;
66 else 73 else
67 pci_cmd &= ~PCI_COMMAND_PARITY; 74 pci_cmd &= ~PCI_COMMAND_PARITY;
@@ -70,13 +77,13 @@ static void program_fw_provided_values(struct pci_dev *dev)
70 /* Program bridge control value and child devices */ 77 /* Program bridge control value and child devices */
71 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 78 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
72 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 79 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
73 hpp.latency_timer); 80 hpp.t0->latency_timer);
74 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); 81 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
75 if (hpp.enable_serr) 82 if (hpp.t0->enable_serr)
76 pci_bctl |= PCI_BRIDGE_CTL_SERR; 83 pci_bctl |= PCI_BRIDGE_CTL_SERR;
77 else 84 else
78 pci_bctl &= ~PCI_BRIDGE_CTL_SERR; 85 pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
79 if (hpp.enable_perr) 86 if (hpp.t0->enable_perr)
80 pci_bctl |= PCI_BRIDGE_CTL_PARITY; 87 pci_bctl |= PCI_BRIDGE_CTL_PARITY;
81 else 88 else
82 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; 89 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;