Commit e81995bb1c0077a312cb621abc406a36f65a986a
Committed by
Jesse Barnes
1 parent
11876e52e9
Exists in
master
and in
39 other branches
PCI hotplug: acpiphp: use generic pci_configure_slot()
Use the generic pci_configure_slot() rather than the acpiphp-specific decode_hpp() and program_hpp(). Unlike the previous acpiphp-specific code, pci_configure_slot() programs PCIe settings when an _HPX method provides them, so acpiphp-managed PCIe devices can now be configured. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Acked-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Showing 3 changed files with 7 additions and 87 deletions Inline Diff
drivers/pci/hotplug/acpi_pcihp.c
1 | /* | 1 | /* |
2 | * Common ACPI functions for hot plug platforms | 2 | * Common ACPI functions for hot plug platforms |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Intel Corporation | 4 | * Copyright (C) 2006 Intel Corporation |
5 | * | 5 | * |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or (at | 10 | * the Free Software Foundation; either version 2 of the License, or (at |
11 | * your option) any later version. | 11 | * your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, but | 13 | * This program is distributed in the hope that it will be useful, but |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 15 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
16 | * NON INFRINGEMENT. See the GNU General Public License for more | 16 | * NON INFRINGEMENT. See the GNU General Public License for more |
17 | * details. | 17 | * details. |
18 | * | 18 | * |
19 | * You should have received a copy of the GNU General Public License | 19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software | 20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
22 | * | 22 | * |
23 | * Send feedback to <kristen.c.accardi@intel.com> | 23 | * Send feedback to <kristen.c.accardi@intel.com> |
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <linux/pci_hotplug.h> | 32 | #include <linux/pci_hotplug.h> |
33 | #include <linux/acpi.h> | 33 | #include <linux/acpi.h> |
34 | #include <linux/pci-acpi.h> | 34 | #include <linux/pci-acpi.h> |
35 | 35 | ||
36 | #define MY_NAME "acpi_pcihp" | 36 | #define MY_NAME "acpi_pcihp" |
37 | 37 | ||
38 | #define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0) | 38 | #define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0) |
39 | #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) | 39 | #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) |
40 | #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) | 40 | #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) |
41 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) | 41 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) |
42 | 42 | ||
43 | #define METHOD_NAME__SUN "_SUN" | 43 | #define METHOD_NAME__SUN "_SUN" |
44 | #define METHOD_NAME__HPP "_HPP" | 44 | #define METHOD_NAME__HPP "_HPP" |
45 | #define METHOD_NAME_OSHP "OSHP" | 45 | #define METHOD_NAME_OSHP "OSHP" |
46 | 46 | ||
47 | static int debug_acpi; | 47 | static int debug_acpi; |
48 | 48 | ||
49 | static acpi_status | 49 | static acpi_status |
50 | decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx) | 50 | decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx) |
51 | { | 51 | { |
52 | int i; | 52 | int i; |
53 | union acpi_object *fields = record->package.elements; | 53 | union acpi_object *fields = record->package.elements; |
54 | u32 revision = fields[1].integer.value; | 54 | u32 revision = fields[1].integer.value; |
55 | 55 | ||
56 | switch (revision) { | 56 | switch (revision) { |
57 | case 1: | 57 | case 1: |
58 | if (record->package.count != 6) | 58 | if (record->package.count != 6) |
59 | return AE_ERROR; | 59 | return AE_ERROR; |
60 | for (i = 2; i < 6; i++) | 60 | for (i = 2; i < 6; i++) |
61 | if (fields[i].type != ACPI_TYPE_INTEGER) | 61 | if (fields[i].type != ACPI_TYPE_INTEGER) |
62 | return AE_ERROR; | 62 | return AE_ERROR; |
63 | hpx->t0 = &hpx->type0_data; | 63 | hpx->t0 = &hpx->type0_data; |
64 | hpx->t0->revision = revision; | 64 | hpx->t0->revision = revision; |
65 | hpx->t0->cache_line_size = fields[2].integer.value; | 65 | hpx->t0->cache_line_size = fields[2].integer.value; |
66 | hpx->t0->latency_timer = fields[3].integer.value; | 66 | hpx->t0->latency_timer = fields[3].integer.value; |
67 | hpx->t0->enable_serr = fields[4].integer.value; | 67 | hpx->t0->enable_serr = fields[4].integer.value; |
68 | hpx->t0->enable_perr = fields[5].integer.value; | 68 | hpx->t0->enable_perr = fields[5].integer.value; |
69 | break; | 69 | break; |
70 | default: | 70 | default: |
71 | printk(KERN_WARNING | 71 | printk(KERN_WARNING |
72 | "%s: Type 0 Revision %d record not supported\n", | 72 | "%s: Type 0 Revision %d record not supported\n", |
73 | __func__, revision); | 73 | __func__, revision); |
74 | return AE_ERROR; | 74 | return AE_ERROR; |
75 | } | 75 | } |
76 | return AE_OK; | 76 | return AE_OK; |
77 | } | 77 | } |
78 | 78 | ||
79 | static acpi_status | 79 | static acpi_status |
80 | decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx) | 80 | decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx) |
81 | { | 81 | { |
82 | int i; | 82 | int i; |
83 | union acpi_object *fields = record->package.elements; | 83 | union acpi_object *fields = record->package.elements; |
84 | u32 revision = fields[1].integer.value; | 84 | u32 revision = fields[1].integer.value; |
85 | 85 | ||
86 | switch (revision) { | 86 | switch (revision) { |
87 | case 1: | 87 | case 1: |
88 | if (record->package.count != 5) | 88 | if (record->package.count != 5) |
89 | return AE_ERROR; | 89 | return AE_ERROR; |
90 | for (i = 2; i < 5; i++) | 90 | for (i = 2; i < 5; i++) |
91 | if (fields[i].type != ACPI_TYPE_INTEGER) | 91 | if (fields[i].type != ACPI_TYPE_INTEGER) |
92 | return AE_ERROR; | 92 | return AE_ERROR; |
93 | hpx->t1 = &hpx->type1_data; | 93 | hpx->t1 = &hpx->type1_data; |
94 | hpx->t1->revision = revision; | 94 | hpx->t1->revision = revision; |
95 | hpx->t1->max_mem_read = fields[2].integer.value; | 95 | hpx->t1->max_mem_read = fields[2].integer.value; |
96 | hpx->t1->avg_max_split = fields[3].integer.value; | 96 | hpx->t1->avg_max_split = fields[3].integer.value; |
97 | hpx->t1->tot_max_split = fields[4].integer.value; | 97 | hpx->t1->tot_max_split = fields[4].integer.value; |
98 | break; | 98 | break; |
99 | default: | 99 | default: |
100 | printk(KERN_WARNING | 100 | printk(KERN_WARNING |
101 | "%s: Type 1 Revision %d record not supported\n", | 101 | "%s: Type 1 Revision %d record not supported\n", |
102 | __func__, revision); | 102 | __func__, revision); |
103 | return AE_ERROR; | 103 | return AE_ERROR; |
104 | } | 104 | } |
105 | return AE_OK; | 105 | return AE_OK; |
106 | } | 106 | } |
107 | 107 | ||
108 | static acpi_status | 108 | static acpi_status |
109 | decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx) | 109 | decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx) |
110 | { | 110 | { |
111 | int i; | 111 | int i; |
112 | union acpi_object *fields = record->package.elements; | 112 | union acpi_object *fields = record->package.elements; |
113 | u32 revision = fields[1].integer.value; | 113 | u32 revision = fields[1].integer.value; |
114 | 114 | ||
115 | switch (revision) { | 115 | switch (revision) { |
116 | case 1: | 116 | case 1: |
117 | if (record->package.count != 18) | 117 | if (record->package.count != 18) |
118 | return AE_ERROR; | 118 | return AE_ERROR; |
119 | for (i = 2; i < 18; i++) | 119 | for (i = 2; i < 18; i++) |
120 | if (fields[i].type != ACPI_TYPE_INTEGER) | 120 | if (fields[i].type != ACPI_TYPE_INTEGER) |
121 | return AE_ERROR; | 121 | return AE_ERROR; |
122 | hpx->t2 = &hpx->type2_data; | 122 | hpx->t2 = &hpx->type2_data; |
123 | hpx->t2->revision = revision; | 123 | hpx->t2->revision = revision; |
124 | hpx->t2->unc_err_mask_and = fields[2].integer.value; | 124 | hpx->t2->unc_err_mask_and = fields[2].integer.value; |
125 | hpx->t2->unc_err_mask_or = fields[3].integer.value; | 125 | hpx->t2->unc_err_mask_or = fields[3].integer.value; |
126 | hpx->t2->unc_err_sever_and = fields[4].integer.value; | 126 | hpx->t2->unc_err_sever_and = fields[4].integer.value; |
127 | hpx->t2->unc_err_sever_or = fields[5].integer.value; | 127 | hpx->t2->unc_err_sever_or = fields[5].integer.value; |
128 | hpx->t2->cor_err_mask_and = fields[6].integer.value; | 128 | hpx->t2->cor_err_mask_and = fields[6].integer.value; |
129 | hpx->t2->cor_err_mask_or = fields[7].integer.value; | 129 | hpx->t2->cor_err_mask_or = fields[7].integer.value; |
130 | hpx->t2->adv_err_cap_and = fields[8].integer.value; | 130 | hpx->t2->adv_err_cap_and = fields[8].integer.value; |
131 | hpx->t2->adv_err_cap_or = fields[9].integer.value; | 131 | hpx->t2->adv_err_cap_or = fields[9].integer.value; |
132 | hpx->t2->pci_exp_devctl_and = fields[10].integer.value; | 132 | hpx->t2->pci_exp_devctl_and = fields[10].integer.value; |
133 | hpx->t2->pci_exp_devctl_or = fields[11].integer.value; | 133 | hpx->t2->pci_exp_devctl_or = fields[11].integer.value; |
134 | hpx->t2->pci_exp_lnkctl_and = fields[12].integer.value; | 134 | hpx->t2->pci_exp_lnkctl_and = fields[12].integer.value; |
135 | hpx->t2->pci_exp_lnkctl_or = fields[13].integer.value; | 135 | hpx->t2->pci_exp_lnkctl_or = fields[13].integer.value; |
136 | hpx->t2->sec_unc_err_sever_and = fields[14].integer.value; | 136 | hpx->t2->sec_unc_err_sever_and = fields[14].integer.value; |
137 | hpx->t2->sec_unc_err_sever_or = fields[15].integer.value; | 137 | hpx->t2->sec_unc_err_sever_or = fields[15].integer.value; |
138 | hpx->t2->sec_unc_err_mask_and = fields[16].integer.value; | 138 | hpx->t2->sec_unc_err_mask_and = fields[16].integer.value; |
139 | hpx->t2->sec_unc_err_mask_or = fields[17].integer.value; | 139 | hpx->t2->sec_unc_err_mask_or = fields[17].integer.value; |
140 | break; | 140 | break; |
141 | default: | 141 | default: |
142 | printk(KERN_WARNING | 142 | printk(KERN_WARNING |
143 | "%s: Type 2 Revision %d record not supported\n", | 143 | "%s: Type 2 Revision %d record not supported\n", |
144 | __func__, revision); | 144 | __func__, revision); |
145 | return AE_ERROR; | 145 | return AE_ERROR; |
146 | } | 146 | } |
147 | return AE_OK; | 147 | return AE_OK; |
148 | } | 148 | } |
149 | 149 | ||
150 | static acpi_status | 150 | static acpi_status |
151 | acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) | 151 | acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) |
152 | { | 152 | { |
153 | acpi_status status; | 153 | acpi_status status; |
154 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 154 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
155 | union acpi_object *package, *record, *fields; | 155 | union acpi_object *package, *record, *fields; |
156 | u32 type; | 156 | u32 type; |
157 | int i; | 157 | int i; |
158 | 158 | ||
159 | /* Clear the return buffer with zeros */ | 159 | /* Clear the return buffer with zeros */ |
160 | memset(hpx, 0, sizeof(struct hotplug_params)); | 160 | memset(hpx, 0, sizeof(struct hotplug_params)); |
161 | 161 | ||
162 | status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer); | 162 | status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer); |
163 | if (ACPI_FAILURE(status)) | 163 | if (ACPI_FAILURE(status)) |
164 | return status; | 164 | return status; |
165 | 165 | ||
166 | package = (union acpi_object *)buffer.pointer; | 166 | package = (union acpi_object *)buffer.pointer; |
167 | if (package->type != ACPI_TYPE_PACKAGE) { | 167 | if (package->type != ACPI_TYPE_PACKAGE) { |
168 | status = AE_ERROR; | 168 | status = AE_ERROR; |
169 | goto exit; | 169 | goto exit; |
170 | } | 170 | } |
171 | 171 | ||
172 | for (i = 0; i < package->package.count; i++) { | 172 | for (i = 0; i < package->package.count; i++) { |
173 | record = &package->package.elements[i]; | 173 | record = &package->package.elements[i]; |
174 | if (record->type != ACPI_TYPE_PACKAGE) { | 174 | if (record->type != ACPI_TYPE_PACKAGE) { |
175 | status = AE_ERROR; | 175 | status = AE_ERROR; |
176 | goto exit; | 176 | goto exit; |
177 | } | 177 | } |
178 | 178 | ||
179 | fields = record->package.elements; | 179 | fields = record->package.elements; |
180 | if (fields[0].type != ACPI_TYPE_INTEGER || | 180 | if (fields[0].type != ACPI_TYPE_INTEGER || |
181 | fields[1].type != ACPI_TYPE_INTEGER) { | 181 | fields[1].type != ACPI_TYPE_INTEGER) { |
182 | status = AE_ERROR; | 182 | status = AE_ERROR; |
183 | goto exit; | 183 | goto exit; |
184 | } | 184 | } |
185 | 185 | ||
186 | type = fields[0].integer.value; | 186 | type = fields[0].integer.value; |
187 | switch (type) { | 187 | switch (type) { |
188 | case 0: | 188 | case 0: |
189 | status = decode_type0_hpx_record(record, hpx); | 189 | status = decode_type0_hpx_record(record, hpx); |
190 | if (ACPI_FAILURE(status)) | 190 | if (ACPI_FAILURE(status)) |
191 | goto exit; | 191 | goto exit; |
192 | break; | 192 | break; |
193 | case 1: | 193 | case 1: |
194 | status = decode_type1_hpx_record(record, hpx); | 194 | status = decode_type1_hpx_record(record, hpx); |
195 | if (ACPI_FAILURE(status)) | 195 | if (ACPI_FAILURE(status)) |
196 | goto exit; | 196 | goto exit; |
197 | break; | 197 | break; |
198 | case 2: | 198 | case 2: |
199 | status = decode_type2_hpx_record(record, hpx); | 199 | status = decode_type2_hpx_record(record, hpx); |
200 | if (ACPI_FAILURE(status)) | 200 | if (ACPI_FAILURE(status)) |
201 | goto exit; | 201 | goto exit; |
202 | break; | 202 | break; |
203 | default: | 203 | default: |
204 | printk(KERN_ERR "%s: Type %d record not supported\n", | 204 | printk(KERN_ERR "%s: Type %d record not supported\n", |
205 | __func__, type); | 205 | __func__, type); |
206 | status = AE_ERROR; | 206 | status = AE_ERROR; |
207 | goto exit; | 207 | goto exit; |
208 | } | 208 | } |
209 | } | 209 | } |
210 | exit: | 210 | exit: |
211 | kfree(buffer.pointer); | 211 | kfree(buffer.pointer); |
212 | return status; | 212 | return status; |
213 | } | 213 | } |
214 | 214 | ||
215 | static acpi_status | 215 | static acpi_status |
216 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | 216 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) |
217 | { | 217 | { |
218 | acpi_status status; | 218 | acpi_status status; |
219 | u8 nui[4]; | 219 | u8 nui[4]; |
220 | struct acpi_buffer ret_buf = { 0, NULL}; | 220 | struct acpi_buffer ret_buf = { 0, NULL}; |
221 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 221 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
222 | union acpi_object *ext_obj, *package; | 222 | union acpi_object *ext_obj, *package; |
223 | int i, len = 0; | 223 | int i, len = 0; |
224 | 224 | ||
225 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 225 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
226 | 226 | ||
227 | /* Clear the return buffer with zeros */ | 227 | /* Clear the return buffer with zeros */ |
228 | memset(hpp, 0, sizeof(struct hotplug_params)); | 228 | memset(hpp, 0, sizeof(struct hotplug_params)); |
229 | 229 | ||
230 | /* get _hpp */ | 230 | /* get _hpp */ |
231 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); | 231 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); |
232 | switch (status) { | 232 | switch (status) { |
233 | case AE_BUFFER_OVERFLOW: | 233 | case AE_BUFFER_OVERFLOW: |
234 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); | 234 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); |
235 | if (!ret_buf.pointer) { | 235 | if (!ret_buf.pointer) { |
236 | printk(KERN_ERR "%s:%s alloc for _HPP fail\n", | 236 | printk(KERN_ERR "%s:%s alloc for _HPP fail\n", |
237 | __func__, (char *)string.pointer); | 237 | __func__, (char *)string.pointer); |
238 | kfree(string.pointer); | 238 | kfree(string.pointer); |
239 | return AE_NO_MEMORY; | 239 | return AE_NO_MEMORY; |
240 | } | 240 | } |
241 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, | 241 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, |
242 | NULL, &ret_buf); | 242 | NULL, &ret_buf); |
243 | if (ACPI_SUCCESS(status)) | 243 | if (ACPI_SUCCESS(status)) |
244 | break; | 244 | break; |
245 | default: | 245 | default: |
246 | if (ACPI_FAILURE(status)) { | 246 | if (ACPI_FAILURE(status)) { |
247 | pr_debug("%s:%s _HPP fail=0x%x\n", __func__, | 247 | pr_debug("%s:%s _HPP fail=0x%x\n", __func__, |
248 | (char *)string.pointer, status); | 248 | (char *)string.pointer, status); |
249 | kfree(string.pointer); | 249 | kfree(string.pointer); |
250 | return status; | 250 | return status; |
251 | } | 251 | } |
252 | } | 252 | } |
253 | 253 | ||
254 | ext_obj = (union acpi_object *) ret_buf.pointer; | 254 | ext_obj = (union acpi_object *) ret_buf.pointer; |
255 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { | 255 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { |
256 | printk(KERN_ERR "%s:%s _HPP obj not a package\n", __func__, | 256 | printk(KERN_ERR "%s:%s _HPP obj not a package\n", __func__, |
257 | (char *)string.pointer); | 257 | (char *)string.pointer); |
258 | status = AE_ERROR; | 258 | status = AE_ERROR; |
259 | goto free_and_return; | 259 | goto free_and_return; |
260 | } | 260 | } |
261 | 261 | ||
262 | len = ext_obj->package.count; | 262 | len = ext_obj->package.count; |
263 | package = (union acpi_object *) ret_buf.pointer; | 263 | package = (union acpi_object *) ret_buf.pointer; |
264 | for ( i = 0; (i < len) || (i < 4); i++) { | 264 | for ( i = 0; (i < len) || (i < 4); i++) { |
265 | ext_obj = (union acpi_object *) &package->package.elements[i]; | 265 | ext_obj = (union acpi_object *) &package->package.elements[i]; |
266 | switch (ext_obj->type) { | 266 | switch (ext_obj->type) { |
267 | case ACPI_TYPE_INTEGER: | 267 | case ACPI_TYPE_INTEGER: |
268 | nui[i] = (u8)ext_obj->integer.value; | 268 | nui[i] = (u8)ext_obj->integer.value; |
269 | break; | 269 | break; |
270 | default: | 270 | default: |
271 | printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", | 271 | printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", |
272 | __func__, (char *)string.pointer); | 272 | __func__, (char *)string.pointer); |
273 | status = AE_ERROR; | 273 | status = AE_ERROR; |
274 | goto free_and_return; | 274 | goto free_and_return; |
275 | } | 275 | } |
276 | } | 276 | } |
277 | 277 | ||
278 | hpp->t0 = &hpp->type0_data; | 278 | hpp->t0 = &hpp->type0_data; |
279 | hpp->t0->cache_line_size = nui[0]; | 279 | hpp->t0->cache_line_size = nui[0]; |
280 | hpp->t0->latency_timer = nui[1]; | 280 | hpp->t0->latency_timer = nui[1]; |
281 | hpp->t0->enable_serr = nui[2]; | 281 | hpp->t0->enable_serr = nui[2]; |
282 | hpp->t0->enable_perr = nui[3]; | 282 | hpp->t0->enable_perr = nui[3]; |
283 | 283 | ||
284 | pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); | 284 | pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); |
285 | pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); | 285 | pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); |
286 | pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); | 286 | pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); |
287 | pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); | 287 | pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); |
288 | 288 | ||
289 | free_and_return: | 289 | free_and_return: |
290 | kfree(string.pointer); | 290 | kfree(string.pointer); |
291 | kfree(ret_buf.pointer); | 291 | kfree(ret_buf.pointer); |
292 | return status; | 292 | return status; |
293 | } | 293 | } |
294 | 294 | ||
295 | 295 | ||
296 | 296 | ||
297 | /* acpi_run_oshp - get control of hotplug from the firmware | 297 | /* acpi_run_oshp - get control of hotplug from the firmware |
298 | * | 298 | * |
299 | * @handle - the handle of the hotplug controller. | 299 | * @handle - the handle of the hotplug controller. |
300 | */ | 300 | */ |
301 | static acpi_status acpi_run_oshp(acpi_handle handle) | 301 | static acpi_status acpi_run_oshp(acpi_handle handle) |
302 | { | 302 | { |
303 | acpi_status status; | 303 | acpi_status status; |
304 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 304 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
305 | 305 | ||
306 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 306 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
307 | 307 | ||
308 | /* run OSHP */ | 308 | /* run OSHP */ |
309 | status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); | 309 | status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); |
310 | if (ACPI_FAILURE(status)) | 310 | if (ACPI_FAILURE(status)) |
311 | if (status != AE_NOT_FOUND) | 311 | if (status != AE_NOT_FOUND) |
312 | printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", | 312 | printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", |
313 | __func__, (char *)string.pointer, status); | 313 | __func__, (char *)string.pointer, status); |
314 | else | 314 | else |
315 | dbg("%s:%s OSHP not found\n", | 315 | dbg("%s:%s OSHP not found\n", |
316 | __func__, (char *)string.pointer); | 316 | __func__, (char *)string.pointer); |
317 | else | 317 | else |
318 | pr_debug("%s:%s OSHP passes\n", __func__, | 318 | pr_debug("%s:%s OSHP passes\n", __func__, |
319 | (char *)string.pointer); | 319 | (char *)string.pointer); |
320 | 320 | ||
321 | kfree(string.pointer); | 321 | kfree(string.pointer); |
322 | return status; | 322 | return status; |
323 | } | 323 | } |
324 | 324 | ||
325 | /* acpi_get_hp_params_from_firmware | 325 | /* pci_get_hp_params |
326 | * | 326 | * |
327 | * @dev - the pci_dev for which we want parameters | 327 | * @dev - the pci_dev for which we want parameters |
328 | * @hpp - allocated by the caller | 328 | * @hpp - allocated by the caller |
329 | */ | 329 | */ |
330 | int acpi_get_hp_params_from_firmware(struct pci_dev *dev, | 330 | int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp) |
331 | struct hotplug_params *hpp) | ||
332 | { | 331 | { |
333 | acpi_status status; | 332 | acpi_status status; |
334 | acpi_handle handle, phandle; | 333 | acpi_handle handle, phandle; |
335 | struct pci_bus *pbus; | 334 | struct pci_bus *pbus; |
336 | 335 | ||
337 | handle = NULL; | 336 | handle = NULL; |
338 | for (pbus = dev->bus; pbus; pbus = pbus->parent) { | 337 | for (pbus = dev->bus; pbus; pbus = pbus->parent) { |
339 | handle = acpi_pci_get_bridge_handle(pbus); | 338 | handle = acpi_pci_get_bridge_handle(pbus); |
340 | if (handle) | 339 | if (handle) |
341 | break; | 340 | break; |
342 | } | 341 | } |
343 | 342 | ||
344 | /* | 343 | /* |
345 | * _HPP settings apply to all child buses, until another _HPP is | 344 | * _HPP settings apply to all child buses, until another _HPP is |
346 | * encountered. If we don't find an _HPP for the input pci dev, | 345 | * encountered. If we don't find an _HPP for the input pci dev, |
347 | * look for it in the parent device scope since that would apply to | 346 | * look for it in the parent device scope since that would apply to |
348 | * this pci dev. If we don't find any _HPP, use hardcoded defaults | 347 | * this pci dev. |
349 | */ | 348 | */ |
350 | while (handle) { | 349 | while (handle) { |
351 | status = acpi_run_hpx(handle, hpp); | 350 | status = acpi_run_hpx(handle, hpp); |
352 | if (ACPI_SUCCESS(status)) | 351 | if (ACPI_SUCCESS(status)) |
353 | return 0; | 352 | return 0; |
354 | status = acpi_run_hpp(handle, hpp); | 353 | status = acpi_run_hpp(handle, hpp); |
355 | if (ACPI_SUCCESS(status)) | 354 | if (ACPI_SUCCESS(status)) |
356 | return 0; | 355 | return 0; |
357 | if (acpi_is_root_bridge(handle)) | 356 | if (acpi_is_root_bridge(handle)) |
358 | break; | 357 | break; |
359 | status = acpi_get_parent(handle, &phandle); | 358 | status = acpi_get_parent(handle, &phandle); |
360 | if (ACPI_FAILURE(status)) | 359 | if (ACPI_FAILURE(status)) |
361 | break; | 360 | break; |
362 | handle = phandle; | 361 | handle = phandle; |
363 | } | 362 | } |
364 | return -ENODEV; | 363 | return -ENODEV; |
365 | } | 364 | } |
366 | EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); | 365 | EXPORT_SYMBOL_GPL(pci_get_hp_params); |
367 | 366 | ||
368 | /** | 367 | /** |
369 | * acpi_get_hp_hw_control_from_firmware | 368 | * acpi_get_hp_hw_control_from_firmware |
370 | * @dev: the pci_dev of the bridge that has a hotplug controller | 369 | * @dev: the pci_dev of the bridge that has a hotplug controller |
371 | * @flags: requested control bits for _OSC | 370 | * @flags: requested control bits for _OSC |
372 | * | 371 | * |
373 | * Attempt to take hotplug control from firmware. | 372 | * Attempt to take hotplug control from firmware. |
374 | */ | 373 | */ |
375 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | 374 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) |
376 | { | 375 | { |
377 | acpi_status status; | 376 | acpi_status status; |
378 | acpi_handle chandle, handle; | 377 | acpi_handle chandle, handle; |
379 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 378 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
380 | 379 | ||
381 | flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | | 380 | flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | |
382 | OSC_SHPC_NATIVE_HP_CONTROL | | 381 | OSC_SHPC_NATIVE_HP_CONTROL | |
383 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 382 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); |
384 | if (!flags) { | 383 | if (!flags) { |
385 | err("Invalid flags %u specified!\n", flags); | 384 | err("Invalid flags %u specified!\n", flags); |
386 | return -EINVAL; | 385 | return -EINVAL; |
387 | } | 386 | } |
388 | 387 | ||
389 | /* | 388 | /* |
390 | * Per PCI firmware specification, we should run the ACPI _OSC | 389 | * Per PCI firmware specification, we should run the ACPI _OSC |
391 | * method to get control of hotplug hardware before using it. If | 390 | * method to get control of hotplug hardware before using it. If |
392 | * an _OSC is missing, we look for an OSHP to do the same thing. | 391 | * an _OSC is missing, we look for an OSHP to do the same thing. |
393 | * To handle different BIOS behavior, we look for _OSC on a root | 392 | * To handle different BIOS behavior, we look for _OSC on a root |
394 | * bridge preferentially (according to PCI fw spec). Later for | 393 | * bridge preferentially (according to PCI fw spec). Later for |
395 | * OSHP within the scope of the hotplug controller and its parents, | 394 | * OSHP within the scope of the hotplug controller and its parents, |
396 | * upto the host bridge under which this controller exists. | 395 | * upto the host bridge under which this controller exists. |
397 | */ | 396 | */ |
398 | handle = acpi_find_root_bridge_handle(pdev); | 397 | handle = acpi_find_root_bridge_handle(pdev); |
399 | if (handle) { | 398 | if (handle) { |
400 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 399 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
401 | dbg("Trying to get hotplug control for %s\n", | 400 | dbg("Trying to get hotplug control for %s\n", |
402 | (char *)string.pointer); | 401 | (char *)string.pointer); |
403 | status = acpi_pci_osc_control_set(handle, flags); | 402 | status = acpi_pci_osc_control_set(handle, flags); |
404 | if (ACPI_SUCCESS(status)) | 403 | if (ACPI_SUCCESS(status)) |
405 | goto got_one; | 404 | goto got_one; |
406 | kfree(string.pointer); | 405 | kfree(string.pointer); |
407 | string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; | 406 | string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; |
408 | } | 407 | } |
409 | 408 | ||
410 | handle = DEVICE_ACPI_HANDLE(&pdev->dev); | 409 | handle = DEVICE_ACPI_HANDLE(&pdev->dev); |
411 | if (!handle) { | 410 | if (!handle) { |
412 | /* | 411 | /* |
413 | * This hotplug controller was not listed in the ACPI name | 412 | * This hotplug controller was not listed in the ACPI name |
414 | * space at all. Try to get acpi handle of parent pci bus. | 413 | * space at all. Try to get acpi handle of parent pci bus. |
415 | */ | 414 | */ |
416 | struct pci_bus *pbus; | 415 | struct pci_bus *pbus; |
417 | for (pbus = pdev->bus; pbus; pbus = pbus->parent) { | 416 | for (pbus = pdev->bus; pbus; pbus = pbus->parent) { |
418 | handle = acpi_pci_get_bridge_handle(pbus); | 417 | handle = acpi_pci_get_bridge_handle(pbus); |
419 | if (handle) | 418 | if (handle) |
420 | break; | 419 | break; |
421 | } | 420 | } |
422 | } | 421 | } |
423 | 422 | ||
424 | while (handle) { | 423 | while (handle) { |
425 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 424 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
426 | dbg("Trying to get hotplug control for %s \n", | 425 | dbg("Trying to get hotplug control for %s \n", |
427 | (char *)string.pointer); | 426 | (char *)string.pointer); |
428 | status = acpi_run_oshp(handle); | 427 | status = acpi_run_oshp(handle); |
429 | if (ACPI_SUCCESS(status)) | 428 | if (ACPI_SUCCESS(status)) |
430 | goto got_one; | 429 | goto got_one; |
431 | if (acpi_is_root_bridge(handle)) | 430 | if (acpi_is_root_bridge(handle)) |
432 | break; | 431 | break; |
433 | chandle = handle; | 432 | chandle = handle; |
434 | status = acpi_get_parent(chandle, &handle); | 433 | status = acpi_get_parent(chandle, &handle); |
435 | if (ACPI_FAILURE(status)) | 434 | if (ACPI_FAILURE(status)) |
436 | break; | 435 | break; |
437 | } | 436 | } |
438 | 437 | ||
439 | dbg("Cannot get control of hotplug hardware for pci %s\n", | 438 | dbg("Cannot get control of hotplug hardware for pci %s\n", |
440 | pci_name(pdev)); | 439 | pci_name(pdev)); |
441 | 440 | ||
442 | kfree(string.pointer); | 441 | kfree(string.pointer); |
443 | return -ENODEV; | 442 | return -ENODEV; |
444 | got_one: | 443 | got_one: |
445 | dbg("Gained control for hotplug HW for pci %s (%s)\n", | 444 | dbg("Gained control for hotplug HW for pci %s (%s)\n", |
446 | pci_name(pdev), (char *)string.pointer); | 445 | pci_name(pdev), (char *)string.pointer); |
447 | kfree(string.pointer); | 446 | kfree(string.pointer); |
448 | return 0; | 447 | return 0; |
449 | } | 448 | } |
450 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); | 449 | EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); |
451 | 450 | ||
452 | static int is_ejectable(acpi_handle handle) | 451 | static int is_ejectable(acpi_handle handle) |
453 | { | 452 | { |
454 | acpi_status status; | 453 | acpi_status status; |
455 | acpi_handle tmp; | 454 | acpi_handle tmp; |
456 | unsigned long long removable; | 455 | unsigned long long removable; |
457 | status = acpi_get_handle(handle, "_ADR", &tmp); | 456 | status = acpi_get_handle(handle, "_ADR", &tmp); |
458 | if (ACPI_FAILURE(status)) | 457 | if (ACPI_FAILURE(status)) |
459 | return 0; | 458 | return 0; |
460 | status = acpi_get_handle(handle, "_EJ0", &tmp); | 459 | status = acpi_get_handle(handle, "_EJ0", &tmp); |
461 | if (ACPI_SUCCESS(status)) | 460 | if (ACPI_SUCCESS(status)) |
462 | return 1; | 461 | return 1; |
463 | status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable); | 462 | status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable); |
464 | if (ACPI_SUCCESS(status) && removable) | 463 | if (ACPI_SUCCESS(status) && removable) |
465 | return 1; | 464 | return 1; |
466 | return 0; | 465 | return 0; |
467 | } | 466 | } |
468 | 467 | ||
469 | /** | 468 | /** |
470 | * acpi_pcihp_check_ejectable - check if handle is ejectable ACPI PCI slot | 469 | * acpi_pcihp_check_ejectable - check if handle is ejectable ACPI PCI slot |
471 | * @pbus: the PCI bus of the PCI slot corresponding to 'handle' | 470 | * @pbus: the PCI bus of the PCI slot corresponding to 'handle' |
472 | * @handle: ACPI handle to check | 471 | * @handle: ACPI handle to check |
473 | * | 472 | * |
474 | * Return 1 if handle is ejectable PCI slot, 0 otherwise. | 473 | * Return 1 if handle is ejectable PCI slot, 0 otherwise. |
475 | */ | 474 | */ |
476 | int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle) | 475 | int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle) |
477 | { | 476 | { |
478 | acpi_handle bridge_handle, parent_handle; | 477 | acpi_handle bridge_handle, parent_handle; |
479 | 478 | ||
480 | if (!(bridge_handle = acpi_pci_get_bridge_handle(pbus))) | 479 | if (!(bridge_handle = acpi_pci_get_bridge_handle(pbus))) |
481 | return 0; | 480 | return 0; |
482 | if ((ACPI_FAILURE(acpi_get_parent(handle, &parent_handle)))) | 481 | if ((ACPI_FAILURE(acpi_get_parent(handle, &parent_handle)))) |
483 | return 0; | 482 | return 0; |
484 | if (bridge_handle != parent_handle) | 483 | if (bridge_handle != parent_handle) |
485 | return 0; | 484 | return 0; |
486 | return is_ejectable(handle); | 485 | return is_ejectable(handle); |
487 | } | 486 | } |
488 | EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable); | 487 | EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable); |
489 | 488 | ||
490 | static acpi_status | 489 | static acpi_status |
491 | check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv) | 490 | check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv) |
492 | { | 491 | { |
493 | int *found = (int *)context; | 492 | int *found = (int *)context; |
494 | if (is_ejectable(handle)) { | 493 | if (is_ejectable(handle)) { |
495 | *found = 1; | 494 | *found = 1; |
496 | return AE_CTRL_TERMINATE; | 495 | return AE_CTRL_TERMINATE; |
497 | } | 496 | } |
498 | return AE_OK; | 497 | return AE_OK; |
499 | } | 498 | } |
500 | 499 | ||
501 | /** | 500 | /** |
502 | * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots | 501 | * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots |
503 | * @handle - handle of the PCI bus to scan | 502 | * @handle - handle of the PCI bus to scan |
504 | * | 503 | * |
505 | * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise. | 504 | * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise. |
506 | */ | 505 | */ |
507 | int acpi_pci_detect_ejectable(acpi_handle handle) | 506 | int acpi_pci_detect_ejectable(acpi_handle handle) |
508 | { | 507 | { |
509 | int found = 0; | 508 | int found = 0; |
510 | 509 | ||
511 | if (!handle) | 510 | if (!handle) |
512 | return found; | 511 | return found; |
513 | 512 | ||
514 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | 513 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, |
515 | check_hotplug, (void *)&found, NULL); | 514 | check_hotplug, (void *)&found, NULL); |
516 | return found; | 515 | return found; |
517 | } | 516 | } |
518 | EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable); | 517 | EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable); |
519 | 518 | ||
520 | module_param(debug_acpi, bool, 0644); | 519 | module_param(debug_acpi, bool, 0644); |
521 | MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not"); | 520 | MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not"); |
522 | 521 |
drivers/pci/hotplug/acpiphp_glue.c
1 | /* | 1 | /* |
2 | * ACPI PCI HotPlug glue functions to ACPI CA subsystem | 2 | * ACPI PCI HotPlug glue functions to ACPI CA subsystem |
3 | * | 3 | * |
4 | * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) | 4 | * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) |
5 | * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) | 5 | * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) |
6 | * Copyright (C) 2002,2003 NEC Corporation | 6 | * Copyright (C) 2002,2003 NEC Corporation |
7 | * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com) | 7 | * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com) |
8 | * Copyright (C) 2003-2005 Hewlett Packard | 8 | * Copyright (C) 2003-2005 Hewlett Packard |
9 | * Copyright (C) 2005 Rajesh Shah (rajesh.shah@intel.com) | 9 | * Copyright (C) 2005 Rajesh Shah (rajesh.shah@intel.com) |
10 | * Copyright (C) 2005 Intel Corporation | 10 | * Copyright (C) 2005 Intel Corporation |
11 | * | 11 | * |
12 | * All rights reserved. | 12 | * All rights reserved. |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
16 | * the Free Software Foundation; either version 2 of the License, or (at | 16 | * the Free Software Foundation; either version 2 of the License, or (at |
17 | * your option) any later version. | 17 | * your option) any later version. |
18 | * | 18 | * |
19 | * This program is distributed in the hope that it will be useful, but | 19 | * This program is distributed in the hope that it will be useful, but |
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 20 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 21 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
22 | * NON INFRINGEMENT. See the GNU General Public License for more | 22 | * NON INFRINGEMENT. See the GNU General Public License for more |
23 | * details. | 23 | * details. |
24 | * | 24 | * |
25 | * You should have received a copy of the GNU General Public License | 25 | * You should have received a copy of the GNU General Public License |
26 | * along with this program; if not, write to the Free Software | 26 | * along with this program; if not, write to the Free Software |
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
28 | * | 28 | * |
29 | * Send feedback to <kristen.c.accardi@intel.com> | 29 | * Send feedback to <kristen.c.accardi@intel.com> |
30 | * | 30 | * |
31 | */ | 31 | */ |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Lifetime rules for pci_dev: | 34 | * Lifetime rules for pci_dev: |
35 | * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() | 35 | * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() |
36 | * when the bridge is scanned and it loses a refcount when the bridge | 36 | * when the bridge is scanned and it loses a refcount when the bridge |
37 | * is removed. | 37 | * is removed. |
38 | * - When a P2P bridge is present, we elevate the refcount on the subordinate | 38 | * - When a P2P bridge is present, we elevate the refcount on the subordinate |
39 | * bus. It loses the refcount when the the driver unloads. | 39 | * bus. It loses the refcount when the the driver unloads. |
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | 44 | ||
45 | #include <linux/kernel.h> | 45 | #include <linux/kernel.h> |
46 | #include <linux/pci.h> | 46 | #include <linux/pci.h> |
47 | #include <linux/pci_hotplug.h> | 47 | #include <linux/pci_hotplug.h> |
48 | #include <linux/pci-acpi.h> | 48 | #include <linux/pci-acpi.h> |
49 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
50 | 50 | ||
51 | #include "../pci.h" | 51 | #include "../pci.h" |
52 | #include "acpiphp.h" | 52 | #include "acpiphp.h" |
53 | 53 | ||
54 | static LIST_HEAD(bridge_list); | 54 | static LIST_HEAD(bridge_list); |
55 | static LIST_HEAD(ioapic_list); | 55 | static LIST_HEAD(ioapic_list); |
56 | static DEFINE_SPINLOCK(ioapic_list_lock); | 56 | static DEFINE_SPINLOCK(ioapic_list_lock); |
57 | 57 | ||
58 | #define MY_NAME "acpiphp_glue" | 58 | #define MY_NAME "acpiphp_glue" |
59 | 59 | ||
60 | static void handle_hotplug_event_bridge (acpi_handle, u32, void *); | 60 | static void handle_hotplug_event_bridge (acpi_handle, u32, void *); |
61 | static void acpiphp_sanitize_bus(struct pci_bus *bus); | 61 | static void acpiphp_sanitize_bus(struct pci_bus *bus); |
62 | static void acpiphp_set_hpp_values(struct pci_bus *bus); | 62 | static void acpiphp_set_hpp_values(struct pci_bus *bus); |
63 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); | 63 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); |
64 | 64 | ||
65 | /* callback routine to check for the existence of a pci dock device */ | 65 | /* callback routine to check for the existence of a pci dock device */ |
66 | static acpi_status | 66 | static acpi_status |
67 | is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) | 67 | is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) |
68 | { | 68 | { |
69 | int *count = (int *)context; | 69 | int *count = (int *)context; |
70 | 70 | ||
71 | if (is_dock_device(handle)) { | 71 | if (is_dock_device(handle)) { |
72 | (*count)++; | 72 | (*count)++; |
73 | return AE_CTRL_TERMINATE; | 73 | return AE_CTRL_TERMINATE; |
74 | } else { | 74 | } else { |
75 | return AE_OK; | 75 | return AE_OK; |
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * the _DCK method can do funny things... and sometimes not | 80 | * the _DCK method can do funny things... and sometimes not |
81 | * hah-hah funny. | 81 | * hah-hah funny. |
82 | * | 82 | * |
83 | * TBD - figure out a way to only call fixups for | 83 | * TBD - figure out a way to only call fixups for |
84 | * systems that require them. | 84 | * systems that require them. |
85 | */ | 85 | */ |
86 | static int post_dock_fixups(struct notifier_block *nb, unsigned long val, | 86 | static int post_dock_fixups(struct notifier_block *nb, unsigned long val, |
87 | void *v) | 87 | void *v) |
88 | { | 88 | { |
89 | struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb); | 89 | struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb); |
90 | struct pci_bus *bus = func->slot->bridge->pci_bus; | 90 | struct pci_bus *bus = func->slot->bridge->pci_bus; |
91 | u32 buses; | 91 | u32 buses; |
92 | 92 | ||
93 | if (!bus->self) | 93 | if (!bus->self) |
94 | return NOTIFY_OK; | 94 | return NOTIFY_OK; |
95 | 95 | ||
96 | /* fixup bad _DCK function that rewrites | 96 | /* fixup bad _DCK function that rewrites |
97 | * secondary bridge on slot | 97 | * secondary bridge on slot |
98 | */ | 98 | */ |
99 | pci_read_config_dword(bus->self, | 99 | pci_read_config_dword(bus->self, |
100 | PCI_PRIMARY_BUS, | 100 | PCI_PRIMARY_BUS, |
101 | &buses); | 101 | &buses); |
102 | 102 | ||
103 | if (((buses >> 8) & 0xff) != bus->secondary) { | 103 | if (((buses >> 8) & 0xff) != bus->secondary) { |
104 | buses = (buses & 0xff000000) | 104 | buses = (buses & 0xff000000) |
105 | | ((unsigned int)(bus->primary) << 0) | 105 | | ((unsigned int)(bus->primary) << 0) |
106 | | ((unsigned int)(bus->secondary) << 8) | 106 | | ((unsigned int)(bus->secondary) << 8) |
107 | | ((unsigned int)(bus->subordinate) << 16); | 107 | | ((unsigned int)(bus->subordinate) << 16); |
108 | pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); | 108 | pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); |
109 | } | 109 | } |
110 | return NOTIFY_OK; | 110 | return NOTIFY_OK; |
111 | } | 111 | } |
112 | 112 | ||
113 | 113 | ||
114 | static struct acpi_dock_ops acpiphp_dock_ops = { | 114 | static struct acpi_dock_ops acpiphp_dock_ops = { |
115 | .handler = handle_hotplug_event_func, | 115 | .handler = handle_hotplug_event_func, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | /* callback routine to register each ACPI PCI slot object */ | 118 | /* callback routine to register each ACPI PCI slot object */ |
119 | static acpi_status | 119 | static acpi_status |
120 | register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | 120 | register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) |
121 | { | 121 | { |
122 | struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; | 122 | struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; |
123 | struct acpiphp_slot *slot; | 123 | struct acpiphp_slot *slot; |
124 | struct acpiphp_func *newfunc; | 124 | struct acpiphp_func *newfunc; |
125 | acpi_handle tmp; | 125 | acpi_handle tmp; |
126 | acpi_status status = AE_OK; | 126 | acpi_status status = AE_OK; |
127 | unsigned long long adr, sun; | 127 | unsigned long long adr, sun; |
128 | int device, function, retval; | 128 | int device, function, retval; |
129 | struct pci_bus *pbus = bridge->pci_bus; | 129 | struct pci_bus *pbus = bridge->pci_bus; |
130 | struct pci_dev *pdev; | 130 | struct pci_dev *pdev; |
131 | 131 | ||
132 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) | 132 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) |
133 | return AE_OK; | 133 | return AE_OK; |
134 | 134 | ||
135 | acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 135 | acpi_evaluate_integer(handle, "_ADR", NULL, &adr); |
136 | device = (adr >> 16) & 0xffff; | 136 | device = (adr >> 16) & 0xffff; |
137 | function = adr & 0xffff; | 137 | function = adr & 0xffff; |
138 | 138 | ||
139 | newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); | 139 | newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); |
140 | if (!newfunc) | 140 | if (!newfunc) |
141 | return AE_NO_MEMORY; | 141 | return AE_NO_MEMORY; |
142 | 142 | ||
143 | INIT_LIST_HEAD(&newfunc->sibling); | 143 | INIT_LIST_HEAD(&newfunc->sibling); |
144 | newfunc->handle = handle; | 144 | newfunc->handle = handle; |
145 | newfunc->function = function; | 145 | newfunc->function = function; |
146 | 146 | ||
147 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) | 147 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) |
148 | newfunc->flags = FUNC_HAS_EJ0; | 148 | newfunc->flags = FUNC_HAS_EJ0; |
149 | 149 | ||
150 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) | 150 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) |
151 | newfunc->flags |= FUNC_HAS_STA; | 151 | newfunc->flags |= FUNC_HAS_STA; |
152 | 152 | ||
153 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp))) | 153 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp))) |
154 | newfunc->flags |= FUNC_HAS_PS0; | 154 | newfunc->flags |= FUNC_HAS_PS0; |
155 | 155 | ||
156 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) | 156 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) |
157 | newfunc->flags |= FUNC_HAS_PS3; | 157 | newfunc->flags |= FUNC_HAS_PS3; |
158 | 158 | ||
159 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) | 159 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) |
160 | newfunc->flags |= FUNC_HAS_DCK; | 160 | newfunc->flags |= FUNC_HAS_DCK; |
161 | 161 | ||
162 | status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); | 162 | status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); |
163 | if (ACPI_FAILURE(status)) { | 163 | if (ACPI_FAILURE(status)) { |
164 | /* | 164 | /* |
165 | * use the count of the number of slots we've found | 165 | * use the count of the number of slots we've found |
166 | * for the number of the slot | 166 | * for the number of the slot |
167 | */ | 167 | */ |
168 | sun = bridge->nr_slots+1; | 168 | sun = bridge->nr_slots+1; |
169 | } | 169 | } |
170 | 170 | ||
171 | /* search for objects that share the same slot */ | 171 | /* search for objects that share the same slot */ |
172 | for (slot = bridge->slots; slot; slot = slot->next) | 172 | for (slot = bridge->slots; slot; slot = slot->next) |
173 | if (slot->device == device) { | 173 | if (slot->device == device) { |
174 | if (slot->sun != sun) | 174 | if (slot->sun != sun) |
175 | warn("sibling found, but _SUN doesn't match!\n"); | 175 | warn("sibling found, but _SUN doesn't match!\n"); |
176 | break; | 176 | break; |
177 | } | 177 | } |
178 | 178 | ||
179 | if (!slot) { | 179 | if (!slot) { |
180 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); | 180 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); |
181 | if (!slot) { | 181 | if (!slot) { |
182 | kfree(newfunc); | 182 | kfree(newfunc); |
183 | return AE_NO_MEMORY; | 183 | return AE_NO_MEMORY; |
184 | } | 184 | } |
185 | 185 | ||
186 | slot->bridge = bridge; | 186 | slot->bridge = bridge; |
187 | slot->device = device; | 187 | slot->device = device; |
188 | slot->sun = sun; | 188 | slot->sun = sun; |
189 | INIT_LIST_HEAD(&slot->funcs); | 189 | INIT_LIST_HEAD(&slot->funcs); |
190 | mutex_init(&slot->crit_sect); | 190 | mutex_init(&slot->crit_sect); |
191 | 191 | ||
192 | slot->next = bridge->slots; | 192 | slot->next = bridge->slots; |
193 | bridge->slots = slot; | 193 | bridge->slots = slot; |
194 | 194 | ||
195 | bridge->nr_slots++; | 195 | bridge->nr_slots++; |
196 | 196 | ||
197 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", | 197 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", |
198 | slot->sun, pci_domain_nr(pbus), pbus->number, device); | 198 | slot->sun, pci_domain_nr(pbus), pbus->number, device); |
199 | retval = acpiphp_register_hotplug_slot(slot); | 199 | retval = acpiphp_register_hotplug_slot(slot); |
200 | if (retval) { | 200 | if (retval) { |
201 | if (retval == -EBUSY) | 201 | if (retval == -EBUSY) |
202 | warn("Slot %llu already registered by another " | 202 | warn("Slot %llu already registered by another " |
203 | "hotplug driver\n", slot->sun); | 203 | "hotplug driver\n", slot->sun); |
204 | else | 204 | else |
205 | warn("acpiphp_register_hotplug_slot failed " | 205 | warn("acpiphp_register_hotplug_slot failed " |
206 | "(err code = 0x%x)\n", retval); | 206 | "(err code = 0x%x)\n", retval); |
207 | goto err_exit; | 207 | goto err_exit; |
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | newfunc->slot = slot; | 211 | newfunc->slot = slot; |
212 | list_add_tail(&newfunc->sibling, &slot->funcs); | 212 | list_add_tail(&newfunc->sibling, &slot->funcs); |
213 | 213 | ||
214 | pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); | 214 | pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); |
215 | if (pdev) { | 215 | if (pdev) { |
216 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); | 216 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); |
217 | pci_dev_put(pdev); | 217 | pci_dev_put(pdev); |
218 | } | 218 | } |
219 | 219 | ||
220 | if (is_dock_device(handle)) { | 220 | if (is_dock_device(handle)) { |
221 | /* we don't want to call this device's _EJ0 | 221 | /* we don't want to call this device's _EJ0 |
222 | * because we want the dock notify handler | 222 | * because we want the dock notify handler |
223 | * to call it after it calls _DCK | 223 | * to call it after it calls _DCK |
224 | */ | 224 | */ |
225 | newfunc->flags &= ~FUNC_HAS_EJ0; | 225 | newfunc->flags &= ~FUNC_HAS_EJ0; |
226 | if (register_hotplug_dock_device(handle, | 226 | if (register_hotplug_dock_device(handle, |
227 | &acpiphp_dock_ops, newfunc)) | 227 | &acpiphp_dock_ops, newfunc)) |
228 | dbg("failed to register dock device\n"); | 228 | dbg("failed to register dock device\n"); |
229 | 229 | ||
230 | /* we need to be notified when dock events happen | 230 | /* we need to be notified when dock events happen |
231 | * outside of the hotplug operation, since we may | 231 | * outside of the hotplug operation, since we may |
232 | * need to do fixups before we can hotplug. | 232 | * need to do fixups before we can hotplug. |
233 | */ | 233 | */ |
234 | newfunc->nb.notifier_call = post_dock_fixups; | 234 | newfunc->nb.notifier_call = post_dock_fixups; |
235 | if (register_dock_notifier(&newfunc->nb)) | 235 | if (register_dock_notifier(&newfunc->nb)) |
236 | dbg("failed to register a dock notifier"); | 236 | dbg("failed to register a dock notifier"); |
237 | } | 237 | } |
238 | 238 | ||
239 | /* install notify handler */ | 239 | /* install notify handler */ |
240 | if (!(newfunc->flags & FUNC_HAS_DCK)) { | 240 | if (!(newfunc->flags & FUNC_HAS_DCK)) { |
241 | status = acpi_install_notify_handler(handle, | 241 | status = acpi_install_notify_handler(handle, |
242 | ACPI_SYSTEM_NOTIFY, | 242 | ACPI_SYSTEM_NOTIFY, |
243 | handle_hotplug_event_func, | 243 | handle_hotplug_event_func, |
244 | newfunc); | 244 | newfunc); |
245 | 245 | ||
246 | if (ACPI_FAILURE(status)) | 246 | if (ACPI_FAILURE(status)) |
247 | err("failed to register interrupt notify handler\n"); | 247 | err("failed to register interrupt notify handler\n"); |
248 | } else | 248 | } else |
249 | status = AE_OK; | 249 | status = AE_OK; |
250 | 250 | ||
251 | return status; | 251 | return status; |
252 | 252 | ||
253 | err_exit: | 253 | err_exit: |
254 | bridge->nr_slots--; | 254 | bridge->nr_slots--; |
255 | bridge->slots = slot->next; | 255 | bridge->slots = slot->next; |
256 | kfree(slot); | 256 | kfree(slot); |
257 | kfree(newfunc); | 257 | kfree(newfunc); |
258 | 258 | ||
259 | return AE_OK; | 259 | return AE_OK; |
260 | } | 260 | } |
261 | 261 | ||
262 | 262 | ||
263 | /* see if it's worth looking at this bridge */ | 263 | /* see if it's worth looking at this bridge */ |
264 | static int detect_ejectable_slots(acpi_handle handle) | 264 | static int detect_ejectable_slots(acpi_handle handle) |
265 | { | 265 | { |
266 | int found = acpi_pci_detect_ejectable(handle); | 266 | int found = acpi_pci_detect_ejectable(handle); |
267 | if (!found) { | 267 | if (!found) { |
268 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 268 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
269 | is_pci_dock_device, (void *)&found, NULL); | 269 | is_pci_dock_device, (void *)&found, NULL); |
270 | } | 270 | } |
271 | return found; | 271 | return found; |
272 | } | 272 | } |
273 | 273 | ||
274 | |||
275 | /* decode ACPI 2.0 _HPP hot plug parameters */ | ||
276 | static void decode_hpp(struct pci_dev *dev, struct hotplug_params *hpp) | ||
277 | { | ||
278 | int ret; | ||
279 | |||
280 | ret = acpi_get_hp_params_from_firmware(dev, hpp); | ||
281 | if (ret || !hpp->t0 || (hpp->t0->revision > 1)) { | ||
282 | /* use default numbers */ | ||
283 | printk(KERN_WARNING | ||
284 | "%s: Could not get hotplug parameters. Use defaults\n", | ||
285 | __func__); | ||
286 | hpp->t0 = &hpp->type0_data; | ||
287 | hpp->t0->revision = 0; | ||
288 | hpp->t0->cache_line_size = 0x10; | ||
289 | hpp->t0->latency_timer = 0x40; | ||
290 | hpp->t0->enable_serr = 0; | ||
291 | hpp->t0->enable_perr = 0; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | |||
296 | |||
297 | /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ | 274 | /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ |
298 | static void init_bridge_misc(struct acpiphp_bridge *bridge) | 275 | static void init_bridge_misc(struct acpiphp_bridge *bridge) |
299 | { | 276 | { |
300 | acpi_status status; | 277 | acpi_status status; |
301 | 278 | ||
302 | /* must be added to the list prior to calling register_slot */ | 279 | /* must be added to the list prior to calling register_slot */ |
303 | list_add(&bridge->list, &bridge_list); | 280 | list_add(&bridge->list, &bridge_list); |
304 | 281 | ||
305 | /* register all slot objects under this bridge */ | 282 | /* register all slot objects under this bridge */ |
306 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, | 283 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, |
307 | register_slot, bridge, NULL); | 284 | register_slot, bridge, NULL); |
308 | if (ACPI_FAILURE(status)) { | 285 | if (ACPI_FAILURE(status)) { |
309 | list_del(&bridge->list); | 286 | list_del(&bridge->list); |
310 | return; | 287 | return; |
311 | } | 288 | } |
312 | 289 | ||
313 | /* install notify handler */ | 290 | /* install notify handler */ |
314 | if (bridge->type != BRIDGE_TYPE_HOST) { | 291 | if (bridge->type != BRIDGE_TYPE_HOST) { |
315 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { | 292 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { |
316 | status = acpi_remove_notify_handler(bridge->func->handle, | 293 | status = acpi_remove_notify_handler(bridge->func->handle, |
317 | ACPI_SYSTEM_NOTIFY, | 294 | ACPI_SYSTEM_NOTIFY, |
318 | handle_hotplug_event_func); | 295 | handle_hotplug_event_func); |
319 | if (ACPI_FAILURE(status)) | 296 | if (ACPI_FAILURE(status)) |
320 | err("failed to remove notify handler\n"); | 297 | err("failed to remove notify handler\n"); |
321 | } | 298 | } |
322 | status = acpi_install_notify_handler(bridge->handle, | 299 | status = acpi_install_notify_handler(bridge->handle, |
323 | ACPI_SYSTEM_NOTIFY, | 300 | ACPI_SYSTEM_NOTIFY, |
324 | handle_hotplug_event_bridge, | 301 | handle_hotplug_event_bridge, |
325 | bridge); | 302 | bridge); |
326 | 303 | ||
327 | if (ACPI_FAILURE(status)) { | 304 | if (ACPI_FAILURE(status)) { |
328 | err("failed to register interrupt notify handler\n"); | 305 | err("failed to register interrupt notify handler\n"); |
329 | } | 306 | } |
330 | } | 307 | } |
331 | } | 308 | } |
332 | 309 | ||
333 | 310 | ||
334 | /* find acpiphp_func from acpiphp_bridge */ | 311 | /* find acpiphp_func from acpiphp_bridge */ |
335 | static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) | 312 | static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) |
336 | { | 313 | { |
337 | struct list_head *node, *l; | 314 | struct list_head *node, *l; |
338 | struct acpiphp_bridge *bridge; | 315 | struct acpiphp_bridge *bridge; |
339 | struct acpiphp_slot *slot; | 316 | struct acpiphp_slot *slot; |
340 | struct acpiphp_func *func; | 317 | struct acpiphp_func *func; |
341 | 318 | ||
342 | list_for_each(node, &bridge_list) { | 319 | list_for_each(node, &bridge_list) { |
343 | bridge = list_entry(node, struct acpiphp_bridge, list); | 320 | bridge = list_entry(node, struct acpiphp_bridge, list); |
344 | for (slot = bridge->slots; slot; slot = slot->next) { | 321 | for (slot = bridge->slots; slot; slot = slot->next) { |
345 | list_for_each(l, &slot->funcs) { | 322 | list_for_each(l, &slot->funcs) { |
346 | func = list_entry(l, struct acpiphp_func, | 323 | func = list_entry(l, struct acpiphp_func, |
347 | sibling); | 324 | sibling); |
348 | if (func->handle == handle) | 325 | if (func->handle == handle) |
349 | return func; | 326 | return func; |
350 | } | 327 | } |
351 | } | 328 | } |
352 | } | 329 | } |
353 | 330 | ||
354 | return NULL; | 331 | return NULL; |
355 | } | 332 | } |
356 | 333 | ||
357 | 334 | ||
358 | static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) | 335 | static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) |
359 | { | 336 | { |
360 | acpi_handle dummy_handle; | 337 | acpi_handle dummy_handle; |
361 | 338 | ||
362 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | 339 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, |
363 | "_STA", &dummy_handle))) | 340 | "_STA", &dummy_handle))) |
364 | bridge->flags |= BRIDGE_HAS_STA; | 341 | bridge->flags |= BRIDGE_HAS_STA; |
365 | 342 | ||
366 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | 343 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, |
367 | "_EJ0", &dummy_handle))) | 344 | "_EJ0", &dummy_handle))) |
368 | bridge->flags |= BRIDGE_HAS_EJ0; | 345 | bridge->flags |= BRIDGE_HAS_EJ0; |
369 | 346 | ||
370 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | 347 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, |
371 | "_PS0", &dummy_handle))) | 348 | "_PS0", &dummy_handle))) |
372 | bridge->flags |= BRIDGE_HAS_PS0; | 349 | bridge->flags |= BRIDGE_HAS_PS0; |
373 | 350 | ||
374 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | 351 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, |
375 | "_PS3", &dummy_handle))) | 352 | "_PS3", &dummy_handle))) |
376 | bridge->flags |= BRIDGE_HAS_PS3; | 353 | bridge->flags |= BRIDGE_HAS_PS3; |
377 | 354 | ||
378 | /* is this ejectable p2p bridge? */ | 355 | /* is this ejectable p2p bridge? */ |
379 | if (bridge->flags & BRIDGE_HAS_EJ0) { | 356 | if (bridge->flags & BRIDGE_HAS_EJ0) { |
380 | struct acpiphp_func *func; | 357 | struct acpiphp_func *func; |
381 | 358 | ||
382 | dbg("found ejectable p2p bridge\n"); | 359 | dbg("found ejectable p2p bridge\n"); |
383 | 360 | ||
384 | /* make link between PCI bridge and PCI function */ | 361 | /* make link between PCI bridge and PCI function */ |
385 | func = acpiphp_bridge_handle_to_function(bridge->handle); | 362 | func = acpiphp_bridge_handle_to_function(bridge->handle); |
386 | if (!func) | 363 | if (!func) |
387 | return; | 364 | return; |
388 | bridge->func = func; | 365 | bridge->func = func; |
389 | func->bridge = bridge; | 366 | func->bridge = bridge; |
390 | } | 367 | } |
391 | } | 368 | } |
392 | 369 | ||
393 | 370 | ||
394 | /* allocate and initialize host bridge data structure */ | 371 | /* allocate and initialize host bridge data structure */ |
395 | static void add_host_bridge(acpi_handle *handle) | 372 | static void add_host_bridge(acpi_handle *handle) |
396 | { | 373 | { |
397 | struct acpiphp_bridge *bridge; | 374 | struct acpiphp_bridge *bridge; |
398 | struct acpi_pci_root *root = acpi_pci_find_root(handle); | 375 | struct acpi_pci_root *root = acpi_pci_find_root(handle); |
399 | 376 | ||
400 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | 377 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
401 | if (bridge == NULL) | 378 | if (bridge == NULL) |
402 | return; | 379 | return; |
403 | 380 | ||
404 | bridge->type = BRIDGE_TYPE_HOST; | 381 | bridge->type = BRIDGE_TYPE_HOST; |
405 | bridge->handle = handle; | 382 | bridge->handle = handle; |
406 | 383 | ||
407 | bridge->pci_bus = root->bus; | 384 | bridge->pci_bus = root->bus; |
408 | 385 | ||
409 | spin_lock_init(&bridge->res_lock); | 386 | spin_lock_init(&bridge->res_lock); |
410 | 387 | ||
411 | init_bridge_misc(bridge); | 388 | init_bridge_misc(bridge); |
412 | } | 389 | } |
413 | 390 | ||
414 | 391 | ||
415 | /* allocate and initialize PCI-to-PCI bridge data structure */ | 392 | /* allocate and initialize PCI-to-PCI bridge data structure */ |
416 | static void add_p2p_bridge(acpi_handle *handle) | 393 | static void add_p2p_bridge(acpi_handle *handle) |
417 | { | 394 | { |
418 | struct acpiphp_bridge *bridge; | 395 | struct acpiphp_bridge *bridge; |
419 | 396 | ||
420 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | 397 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
421 | if (bridge == NULL) { | 398 | if (bridge == NULL) { |
422 | err("out of memory\n"); | 399 | err("out of memory\n"); |
423 | return; | 400 | return; |
424 | } | 401 | } |
425 | 402 | ||
426 | bridge->type = BRIDGE_TYPE_P2P; | 403 | bridge->type = BRIDGE_TYPE_P2P; |
427 | bridge->handle = handle; | 404 | bridge->handle = handle; |
428 | config_p2p_bridge_flags(bridge); | 405 | config_p2p_bridge_flags(bridge); |
429 | 406 | ||
430 | bridge->pci_dev = acpi_get_pci_dev(handle); | 407 | bridge->pci_dev = acpi_get_pci_dev(handle); |
431 | bridge->pci_bus = bridge->pci_dev->subordinate; | 408 | bridge->pci_bus = bridge->pci_dev->subordinate; |
432 | if (!bridge->pci_bus) { | 409 | if (!bridge->pci_bus) { |
433 | err("This is not a PCI-to-PCI bridge!\n"); | 410 | err("This is not a PCI-to-PCI bridge!\n"); |
434 | goto err; | 411 | goto err; |
435 | } | 412 | } |
436 | 413 | ||
437 | /* | 414 | /* |
438 | * Grab a ref to the subordinate PCI bus in case the bus is | 415 | * Grab a ref to the subordinate PCI bus in case the bus is |
439 | * removed via PCI core logical hotplug. The ref pins the bus | 416 | * removed via PCI core logical hotplug. The ref pins the bus |
440 | * (which we access during module unload). | 417 | * (which we access during module unload). |
441 | */ | 418 | */ |
442 | get_device(&bridge->pci_bus->dev); | 419 | get_device(&bridge->pci_bus->dev); |
443 | spin_lock_init(&bridge->res_lock); | 420 | spin_lock_init(&bridge->res_lock); |
444 | 421 | ||
445 | init_bridge_misc(bridge); | 422 | init_bridge_misc(bridge); |
446 | return; | 423 | return; |
447 | err: | 424 | err: |
448 | pci_dev_put(bridge->pci_dev); | 425 | pci_dev_put(bridge->pci_dev); |
449 | kfree(bridge); | 426 | kfree(bridge); |
450 | return; | 427 | return; |
451 | } | 428 | } |
452 | 429 | ||
453 | 430 | ||
454 | /* callback routine to find P2P bridges */ | 431 | /* callback routine to find P2P bridges */ |
455 | static acpi_status | 432 | static acpi_status |
456 | find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | 433 | find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) |
457 | { | 434 | { |
458 | acpi_status status; | 435 | acpi_status status; |
459 | struct pci_dev *dev; | 436 | struct pci_dev *dev; |
460 | 437 | ||
461 | dev = acpi_get_pci_dev(handle); | 438 | dev = acpi_get_pci_dev(handle); |
462 | if (!dev || !dev->subordinate) | 439 | if (!dev || !dev->subordinate) |
463 | goto out; | 440 | goto out; |
464 | 441 | ||
465 | /* check if this bridge has ejectable slots */ | 442 | /* check if this bridge has ejectable slots */ |
466 | if ((detect_ejectable_slots(handle) > 0)) { | 443 | if ((detect_ejectable_slots(handle) > 0)) { |
467 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); | 444 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); |
468 | add_p2p_bridge(handle); | 445 | add_p2p_bridge(handle); |
469 | } | 446 | } |
470 | 447 | ||
471 | /* search P2P bridges under this p2p bridge */ | 448 | /* search P2P bridges under this p2p bridge */ |
472 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 449 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
473 | find_p2p_bridge, NULL, NULL); | 450 | find_p2p_bridge, NULL, NULL); |
474 | if (ACPI_FAILURE(status)) | 451 | if (ACPI_FAILURE(status)) |
475 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | 452 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); |
476 | 453 | ||
477 | out: | 454 | out: |
478 | pci_dev_put(dev); | 455 | pci_dev_put(dev); |
479 | return AE_OK; | 456 | return AE_OK; |
480 | } | 457 | } |
481 | 458 | ||
482 | 459 | ||
483 | /* find hot-pluggable slots, and then find P2P bridge */ | 460 | /* find hot-pluggable slots, and then find P2P bridge */ |
484 | static int add_bridge(acpi_handle handle) | 461 | static int add_bridge(acpi_handle handle) |
485 | { | 462 | { |
486 | acpi_status status; | 463 | acpi_status status; |
487 | unsigned long long tmp; | 464 | unsigned long long tmp; |
488 | acpi_handle dummy_handle; | 465 | acpi_handle dummy_handle; |
489 | 466 | ||
490 | /* if the bridge doesn't have _STA, we assume it is always there */ | 467 | /* if the bridge doesn't have _STA, we assume it is always there */ |
491 | status = acpi_get_handle(handle, "_STA", &dummy_handle); | 468 | status = acpi_get_handle(handle, "_STA", &dummy_handle); |
492 | if (ACPI_SUCCESS(status)) { | 469 | if (ACPI_SUCCESS(status)) { |
493 | status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); | 470 | status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); |
494 | if (ACPI_FAILURE(status)) { | 471 | if (ACPI_FAILURE(status)) { |
495 | dbg("%s: _STA evaluation failure\n", __func__); | 472 | dbg("%s: _STA evaluation failure\n", __func__); |
496 | return 0; | 473 | return 0; |
497 | } | 474 | } |
498 | if ((tmp & ACPI_STA_FUNCTIONING) == 0) | 475 | if ((tmp & ACPI_STA_FUNCTIONING) == 0) |
499 | /* don't register this object */ | 476 | /* don't register this object */ |
500 | return 0; | 477 | return 0; |
501 | } | 478 | } |
502 | 479 | ||
503 | /* check if this bridge has ejectable slots */ | 480 | /* check if this bridge has ejectable slots */ |
504 | if (detect_ejectable_slots(handle) > 0) { | 481 | if (detect_ejectable_slots(handle) > 0) { |
505 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); | 482 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); |
506 | add_host_bridge(handle); | 483 | add_host_bridge(handle); |
507 | } | 484 | } |
508 | 485 | ||
509 | /* search P2P bridges under this host bridge */ | 486 | /* search P2P bridges under this host bridge */ |
510 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 487 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
511 | find_p2p_bridge, NULL, NULL); | 488 | find_p2p_bridge, NULL, NULL); |
512 | 489 | ||
513 | if (ACPI_FAILURE(status)) | 490 | if (ACPI_FAILURE(status)) |
514 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | 491 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); |
515 | 492 | ||
516 | return 0; | 493 | return 0; |
517 | } | 494 | } |
518 | 495 | ||
519 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) | 496 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) |
520 | { | 497 | { |
521 | struct list_head *head; | 498 | struct list_head *head; |
522 | list_for_each(head, &bridge_list) { | 499 | list_for_each(head, &bridge_list) { |
523 | struct acpiphp_bridge *bridge = list_entry(head, | 500 | struct acpiphp_bridge *bridge = list_entry(head, |
524 | struct acpiphp_bridge, list); | 501 | struct acpiphp_bridge, list); |
525 | if (bridge->handle == handle) | 502 | if (bridge->handle == handle) |
526 | return bridge; | 503 | return bridge; |
527 | } | 504 | } |
528 | 505 | ||
529 | return NULL; | 506 | return NULL; |
530 | } | 507 | } |
531 | 508 | ||
532 | static void cleanup_bridge(struct acpiphp_bridge *bridge) | 509 | static void cleanup_bridge(struct acpiphp_bridge *bridge) |
533 | { | 510 | { |
534 | struct list_head *list, *tmp; | 511 | struct list_head *list, *tmp; |
535 | struct acpiphp_slot *slot; | 512 | struct acpiphp_slot *slot; |
536 | acpi_status status; | 513 | acpi_status status; |
537 | acpi_handle handle = bridge->handle; | 514 | acpi_handle handle = bridge->handle; |
538 | 515 | ||
539 | status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 516 | status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
540 | handle_hotplug_event_bridge); | 517 | handle_hotplug_event_bridge); |
541 | if (ACPI_FAILURE(status)) | 518 | if (ACPI_FAILURE(status)) |
542 | err("failed to remove notify handler\n"); | 519 | err("failed to remove notify handler\n"); |
543 | 520 | ||
544 | if ((bridge->type != BRIDGE_TYPE_HOST) && | 521 | if ((bridge->type != BRIDGE_TYPE_HOST) && |
545 | ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) { | 522 | ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) { |
546 | status = acpi_install_notify_handler(bridge->func->handle, | 523 | status = acpi_install_notify_handler(bridge->func->handle, |
547 | ACPI_SYSTEM_NOTIFY, | 524 | ACPI_SYSTEM_NOTIFY, |
548 | handle_hotplug_event_func, | 525 | handle_hotplug_event_func, |
549 | bridge->func); | 526 | bridge->func); |
550 | if (ACPI_FAILURE(status)) | 527 | if (ACPI_FAILURE(status)) |
551 | err("failed to install interrupt notify handler\n"); | 528 | err("failed to install interrupt notify handler\n"); |
552 | } | 529 | } |
553 | 530 | ||
554 | slot = bridge->slots; | 531 | slot = bridge->slots; |
555 | while (slot) { | 532 | while (slot) { |
556 | struct acpiphp_slot *next = slot->next; | 533 | struct acpiphp_slot *next = slot->next; |
557 | list_for_each_safe (list, tmp, &slot->funcs) { | 534 | list_for_each_safe (list, tmp, &slot->funcs) { |
558 | struct acpiphp_func *func; | 535 | struct acpiphp_func *func; |
559 | func = list_entry(list, struct acpiphp_func, sibling); | 536 | func = list_entry(list, struct acpiphp_func, sibling); |
560 | if (is_dock_device(func->handle)) { | 537 | if (is_dock_device(func->handle)) { |
561 | unregister_hotplug_dock_device(func->handle); | 538 | unregister_hotplug_dock_device(func->handle); |
562 | unregister_dock_notifier(&func->nb); | 539 | unregister_dock_notifier(&func->nb); |
563 | } | 540 | } |
564 | if (!(func->flags & FUNC_HAS_DCK)) { | 541 | if (!(func->flags & FUNC_HAS_DCK)) { |
565 | status = acpi_remove_notify_handler(func->handle, | 542 | status = acpi_remove_notify_handler(func->handle, |
566 | ACPI_SYSTEM_NOTIFY, | 543 | ACPI_SYSTEM_NOTIFY, |
567 | handle_hotplug_event_func); | 544 | handle_hotplug_event_func); |
568 | if (ACPI_FAILURE(status)) | 545 | if (ACPI_FAILURE(status)) |
569 | err("failed to remove notify handler\n"); | 546 | err("failed to remove notify handler\n"); |
570 | } | 547 | } |
571 | list_del(list); | 548 | list_del(list); |
572 | kfree(func); | 549 | kfree(func); |
573 | } | 550 | } |
574 | acpiphp_unregister_hotplug_slot(slot); | 551 | acpiphp_unregister_hotplug_slot(slot); |
575 | list_del(&slot->funcs); | 552 | list_del(&slot->funcs); |
576 | kfree(slot); | 553 | kfree(slot); |
577 | slot = next; | 554 | slot = next; |
578 | } | 555 | } |
579 | 556 | ||
580 | /* | 557 | /* |
581 | * Only P2P bridges have a pci_dev | 558 | * Only P2P bridges have a pci_dev |
582 | */ | 559 | */ |
583 | if (bridge->pci_dev) | 560 | if (bridge->pci_dev) |
584 | put_device(&bridge->pci_bus->dev); | 561 | put_device(&bridge->pci_bus->dev); |
585 | 562 | ||
586 | pci_dev_put(bridge->pci_dev); | 563 | pci_dev_put(bridge->pci_dev); |
587 | list_del(&bridge->list); | 564 | list_del(&bridge->list); |
588 | kfree(bridge); | 565 | kfree(bridge); |
589 | } | 566 | } |
590 | 567 | ||
591 | static acpi_status | 568 | static acpi_status |
592 | cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | 569 | cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) |
593 | { | 570 | { |
594 | struct acpiphp_bridge *bridge; | 571 | struct acpiphp_bridge *bridge; |
595 | 572 | ||
596 | /* cleanup p2p bridges under this P2P bridge | 573 | /* cleanup p2p bridges under this P2P bridge |
597 | in a depth-first manner */ | 574 | in a depth-first manner */ |
598 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 575 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
599 | cleanup_p2p_bridge, NULL, NULL); | 576 | cleanup_p2p_bridge, NULL, NULL); |
600 | 577 | ||
601 | bridge = acpiphp_handle_to_bridge(handle); | 578 | bridge = acpiphp_handle_to_bridge(handle); |
602 | if (bridge) | 579 | if (bridge) |
603 | cleanup_bridge(bridge); | 580 | cleanup_bridge(bridge); |
604 | 581 | ||
605 | return AE_OK; | 582 | return AE_OK; |
606 | } | 583 | } |
607 | 584 | ||
608 | static void remove_bridge(acpi_handle handle) | 585 | static void remove_bridge(acpi_handle handle) |
609 | { | 586 | { |
610 | struct acpiphp_bridge *bridge; | 587 | struct acpiphp_bridge *bridge; |
611 | 588 | ||
612 | /* cleanup p2p bridges under this host bridge | 589 | /* cleanup p2p bridges under this host bridge |
613 | in a depth-first manner */ | 590 | in a depth-first manner */ |
614 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 591 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
615 | (u32)1, cleanup_p2p_bridge, NULL, NULL); | 592 | (u32)1, cleanup_p2p_bridge, NULL, NULL); |
616 | 593 | ||
617 | /* | 594 | /* |
618 | * On root bridges with hotplug slots directly underneath (ie, | 595 | * On root bridges with hotplug slots directly underneath (ie, |
619 | * no p2p bridge inbetween), we call cleanup_bridge(). | 596 | * no p2p bridge inbetween), we call cleanup_bridge(). |
620 | * | 597 | * |
621 | * The else clause cleans up root bridges that either had no | 598 | * The else clause cleans up root bridges that either had no |
622 | * hotplug slots at all, or had a p2p bridge underneath. | 599 | * hotplug slots at all, or had a p2p bridge underneath. |
623 | */ | 600 | */ |
624 | bridge = acpiphp_handle_to_bridge(handle); | 601 | bridge = acpiphp_handle_to_bridge(handle); |
625 | if (bridge) | 602 | if (bridge) |
626 | cleanup_bridge(bridge); | 603 | cleanup_bridge(bridge); |
627 | else | 604 | else |
628 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 605 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
629 | handle_hotplug_event_bridge); | 606 | handle_hotplug_event_bridge); |
630 | } | 607 | } |
631 | 608 | ||
632 | static struct pci_dev * get_apic_pci_info(acpi_handle handle) | 609 | static struct pci_dev * get_apic_pci_info(acpi_handle handle) |
633 | { | 610 | { |
634 | struct pci_dev *dev; | 611 | struct pci_dev *dev; |
635 | 612 | ||
636 | dev = acpi_get_pci_dev(handle); | 613 | dev = acpi_get_pci_dev(handle); |
637 | if (!dev) | 614 | if (!dev) |
638 | return NULL; | 615 | return NULL; |
639 | 616 | ||
640 | if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) && | 617 | if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) && |
641 | (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC)) | 618 | (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC)) |
642 | { | 619 | { |
643 | pci_dev_put(dev); | 620 | pci_dev_put(dev); |
644 | return NULL; | 621 | return NULL; |
645 | } | 622 | } |
646 | 623 | ||
647 | return dev; | 624 | return dev; |
648 | } | 625 | } |
649 | 626 | ||
650 | static int get_gsi_base(acpi_handle handle, u32 *gsi_base) | 627 | static int get_gsi_base(acpi_handle handle, u32 *gsi_base) |
651 | { | 628 | { |
652 | acpi_status status; | 629 | acpi_status status; |
653 | int result = -1; | 630 | int result = -1; |
654 | unsigned long long gsb; | 631 | unsigned long long gsb; |
655 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 632 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
656 | union acpi_object *obj; | 633 | union acpi_object *obj; |
657 | void *table; | 634 | void *table; |
658 | 635 | ||
659 | status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb); | 636 | status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb); |
660 | if (ACPI_SUCCESS(status)) { | 637 | if (ACPI_SUCCESS(status)) { |
661 | *gsi_base = (u32)gsb; | 638 | *gsi_base = (u32)gsb; |
662 | return 0; | 639 | return 0; |
663 | } | 640 | } |
664 | 641 | ||
665 | status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer); | 642 | status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer); |
666 | if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer) | 643 | if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer) |
667 | return -1; | 644 | return -1; |
668 | 645 | ||
669 | obj = buffer.pointer; | 646 | obj = buffer.pointer; |
670 | if (obj->type != ACPI_TYPE_BUFFER) | 647 | if (obj->type != ACPI_TYPE_BUFFER) |
671 | goto out; | 648 | goto out; |
672 | 649 | ||
673 | table = obj->buffer.pointer; | 650 | table = obj->buffer.pointer; |
674 | switch (((struct acpi_subtable_header *)table)->type) { | 651 | switch (((struct acpi_subtable_header *)table)->type) { |
675 | case ACPI_MADT_TYPE_IO_SAPIC: | 652 | case ACPI_MADT_TYPE_IO_SAPIC: |
676 | *gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base; | 653 | *gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base; |
677 | result = 0; | 654 | result = 0; |
678 | break; | 655 | break; |
679 | case ACPI_MADT_TYPE_IO_APIC: | 656 | case ACPI_MADT_TYPE_IO_APIC: |
680 | *gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base; | 657 | *gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base; |
681 | result = 0; | 658 | result = 0; |
682 | break; | 659 | break; |
683 | default: | 660 | default: |
684 | break; | 661 | break; |
685 | } | 662 | } |
686 | out: | 663 | out: |
687 | kfree(buffer.pointer); | 664 | kfree(buffer.pointer); |
688 | return result; | 665 | return result; |
689 | } | 666 | } |
690 | 667 | ||
691 | static acpi_status | 668 | static acpi_status |
692 | ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) | 669 | ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv) |
693 | { | 670 | { |
694 | acpi_status status; | 671 | acpi_status status; |
695 | unsigned long long sta; | 672 | unsigned long long sta; |
696 | acpi_handle tmp; | 673 | acpi_handle tmp; |
697 | struct pci_dev *pdev; | 674 | struct pci_dev *pdev; |
698 | u32 gsi_base; | 675 | u32 gsi_base; |
699 | u64 phys_addr; | 676 | u64 phys_addr; |
700 | struct acpiphp_ioapic *ioapic; | 677 | struct acpiphp_ioapic *ioapic; |
701 | 678 | ||
702 | /* Evaluate _STA if present */ | 679 | /* Evaluate _STA if present */ |
703 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 680 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
704 | if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) | 681 | if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) |
705 | return AE_CTRL_DEPTH; | 682 | return AE_CTRL_DEPTH; |
706 | 683 | ||
707 | /* Scan only PCI bus scope */ | 684 | /* Scan only PCI bus scope */ |
708 | status = acpi_get_handle(handle, "_HID", &tmp); | 685 | status = acpi_get_handle(handle, "_HID", &tmp); |
709 | if (ACPI_SUCCESS(status)) | 686 | if (ACPI_SUCCESS(status)) |
710 | return AE_CTRL_DEPTH; | 687 | return AE_CTRL_DEPTH; |
711 | 688 | ||
712 | if (get_gsi_base(handle, &gsi_base)) | 689 | if (get_gsi_base(handle, &gsi_base)) |
713 | return AE_OK; | 690 | return AE_OK; |
714 | 691 | ||
715 | ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL); | 692 | ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL); |
716 | if (!ioapic) | 693 | if (!ioapic) |
717 | return AE_NO_MEMORY; | 694 | return AE_NO_MEMORY; |
718 | 695 | ||
719 | pdev = get_apic_pci_info(handle); | 696 | pdev = get_apic_pci_info(handle); |
720 | if (!pdev) | 697 | if (!pdev) |
721 | goto exit_kfree; | 698 | goto exit_kfree; |
722 | 699 | ||
723 | if (pci_enable_device(pdev)) | 700 | if (pci_enable_device(pdev)) |
724 | goto exit_pci_dev_put; | 701 | goto exit_pci_dev_put; |
725 | 702 | ||
726 | pci_set_master(pdev); | 703 | pci_set_master(pdev); |
727 | 704 | ||
728 | if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) | 705 | if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) |
729 | goto exit_pci_disable_device; | 706 | goto exit_pci_disable_device; |
730 | 707 | ||
731 | phys_addr = pci_resource_start(pdev, 0); | 708 | phys_addr = pci_resource_start(pdev, 0); |
732 | if (acpi_register_ioapic(handle, phys_addr, gsi_base)) | 709 | if (acpi_register_ioapic(handle, phys_addr, gsi_base)) |
733 | goto exit_pci_release_region; | 710 | goto exit_pci_release_region; |
734 | 711 | ||
735 | ioapic->gsi_base = gsi_base; | 712 | ioapic->gsi_base = gsi_base; |
736 | ioapic->dev = pdev; | 713 | ioapic->dev = pdev; |
737 | spin_lock(&ioapic_list_lock); | 714 | spin_lock(&ioapic_list_lock); |
738 | list_add_tail(&ioapic->list, &ioapic_list); | 715 | list_add_tail(&ioapic->list, &ioapic_list); |
739 | spin_unlock(&ioapic_list_lock); | 716 | spin_unlock(&ioapic_list_lock); |
740 | 717 | ||
741 | return AE_OK; | 718 | return AE_OK; |
742 | 719 | ||
743 | exit_pci_release_region: | 720 | exit_pci_release_region: |
744 | pci_release_region(pdev, 0); | 721 | pci_release_region(pdev, 0); |
745 | exit_pci_disable_device: | 722 | exit_pci_disable_device: |
746 | pci_disable_device(pdev); | 723 | pci_disable_device(pdev); |
747 | exit_pci_dev_put: | 724 | exit_pci_dev_put: |
748 | pci_dev_put(pdev); | 725 | pci_dev_put(pdev); |
749 | exit_kfree: | 726 | exit_kfree: |
750 | kfree(ioapic); | 727 | kfree(ioapic); |
751 | 728 | ||
752 | return AE_OK; | 729 | return AE_OK; |
753 | } | 730 | } |
754 | 731 | ||
755 | static acpi_status | 732 | static acpi_status |
756 | ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv) | 733 | ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv) |
757 | { | 734 | { |
758 | acpi_status status; | 735 | acpi_status status; |
759 | unsigned long long sta; | 736 | unsigned long long sta; |
760 | acpi_handle tmp; | 737 | acpi_handle tmp; |
761 | u32 gsi_base; | 738 | u32 gsi_base; |
762 | struct acpiphp_ioapic *pos, *n, *ioapic = NULL; | 739 | struct acpiphp_ioapic *pos, *n, *ioapic = NULL; |
763 | 740 | ||
764 | /* Evaluate _STA if present */ | 741 | /* Evaluate _STA if present */ |
765 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 742 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
766 | if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) | 743 | if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL) |
767 | return AE_CTRL_DEPTH; | 744 | return AE_CTRL_DEPTH; |
768 | 745 | ||
769 | /* Scan only PCI bus scope */ | 746 | /* Scan only PCI bus scope */ |
770 | status = acpi_get_handle(handle, "_HID", &tmp); | 747 | status = acpi_get_handle(handle, "_HID", &tmp); |
771 | if (ACPI_SUCCESS(status)) | 748 | if (ACPI_SUCCESS(status)) |
772 | return AE_CTRL_DEPTH; | 749 | return AE_CTRL_DEPTH; |
773 | 750 | ||
774 | if (get_gsi_base(handle, &gsi_base)) | 751 | if (get_gsi_base(handle, &gsi_base)) |
775 | return AE_OK; | 752 | return AE_OK; |
776 | 753 | ||
777 | acpi_unregister_ioapic(handle, gsi_base); | 754 | acpi_unregister_ioapic(handle, gsi_base); |
778 | 755 | ||
779 | spin_lock(&ioapic_list_lock); | 756 | spin_lock(&ioapic_list_lock); |
780 | list_for_each_entry_safe(pos, n, &ioapic_list, list) { | 757 | list_for_each_entry_safe(pos, n, &ioapic_list, list) { |
781 | if (pos->gsi_base != gsi_base) | 758 | if (pos->gsi_base != gsi_base) |
782 | continue; | 759 | continue; |
783 | ioapic = pos; | 760 | ioapic = pos; |
784 | list_del(&ioapic->list); | 761 | list_del(&ioapic->list); |
785 | break; | 762 | break; |
786 | } | 763 | } |
787 | spin_unlock(&ioapic_list_lock); | 764 | spin_unlock(&ioapic_list_lock); |
788 | 765 | ||
789 | if (!ioapic) | 766 | if (!ioapic) |
790 | return AE_OK; | 767 | return AE_OK; |
791 | 768 | ||
792 | pci_release_region(ioapic->dev, 0); | 769 | pci_release_region(ioapic->dev, 0); |
793 | pci_disable_device(ioapic->dev); | 770 | pci_disable_device(ioapic->dev); |
794 | pci_dev_put(ioapic->dev); | 771 | pci_dev_put(ioapic->dev); |
795 | kfree(ioapic); | 772 | kfree(ioapic); |
796 | 773 | ||
797 | return AE_OK; | 774 | return AE_OK; |
798 | } | 775 | } |
799 | 776 | ||
800 | static int acpiphp_configure_ioapics(acpi_handle handle) | 777 | static int acpiphp_configure_ioapics(acpi_handle handle) |
801 | { | 778 | { |
802 | ioapic_add(handle, 0, NULL, NULL); | 779 | ioapic_add(handle, 0, NULL, NULL); |
803 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 780 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
804 | ACPI_UINT32_MAX, ioapic_add, NULL, NULL); | 781 | ACPI_UINT32_MAX, ioapic_add, NULL, NULL); |
805 | return 0; | 782 | return 0; |
806 | } | 783 | } |
807 | 784 | ||
808 | static int acpiphp_unconfigure_ioapics(acpi_handle handle) | 785 | static int acpiphp_unconfigure_ioapics(acpi_handle handle) |
809 | { | 786 | { |
810 | ioapic_remove(handle, 0, NULL, NULL); | 787 | ioapic_remove(handle, 0, NULL, NULL); |
811 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 788 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
812 | ACPI_UINT32_MAX, ioapic_remove, NULL, NULL); | 789 | ACPI_UINT32_MAX, ioapic_remove, NULL, NULL); |
813 | return 0; | 790 | return 0; |
814 | } | 791 | } |
815 | 792 | ||
816 | static int power_on_slot(struct acpiphp_slot *slot) | 793 | static int power_on_slot(struct acpiphp_slot *slot) |
817 | { | 794 | { |
818 | acpi_status status; | 795 | acpi_status status; |
819 | struct acpiphp_func *func; | 796 | struct acpiphp_func *func; |
820 | struct list_head *l; | 797 | struct list_head *l; |
821 | int retval = 0; | 798 | int retval = 0; |
822 | 799 | ||
823 | /* if already enabled, just skip */ | 800 | /* if already enabled, just skip */ |
824 | if (slot->flags & SLOT_POWEREDON) | 801 | if (slot->flags & SLOT_POWEREDON) |
825 | goto err_exit; | 802 | goto err_exit; |
826 | 803 | ||
827 | list_for_each (l, &slot->funcs) { | 804 | list_for_each (l, &slot->funcs) { |
828 | func = list_entry(l, struct acpiphp_func, sibling); | 805 | func = list_entry(l, struct acpiphp_func, sibling); |
829 | 806 | ||
830 | if (func->flags & FUNC_HAS_PS0) { | 807 | if (func->flags & FUNC_HAS_PS0) { |
831 | dbg("%s: executing _PS0\n", __func__); | 808 | dbg("%s: executing _PS0\n", __func__); |
832 | status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); | 809 | status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); |
833 | if (ACPI_FAILURE(status)) { | 810 | if (ACPI_FAILURE(status)) { |
834 | warn("%s: _PS0 failed\n", __func__); | 811 | warn("%s: _PS0 failed\n", __func__); |
835 | retval = -1; | 812 | retval = -1; |
836 | goto err_exit; | 813 | goto err_exit; |
837 | } else | 814 | } else |
838 | break; | 815 | break; |
839 | } | 816 | } |
840 | } | 817 | } |
841 | 818 | ||
842 | /* TBD: evaluate _STA to check if the slot is enabled */ | 819 | /* TBD: evaluate _STA to check if the slot is enabled */ |
843 | 820 | ||
844 | slot->flags |= SLOT_POWEREDON; | 821 | slot->flags |= SLOT_POWEREDON; |
845 | 822 | ||
846 | err_exit: | 823 | err_exit: |
847 | return retval; | 824 | return retval; |
848 | } | 825 | } |
849 | 826 | ||
850 | 827 | ||
851 | static int power_off_slot(struct acpiphp_slot *slot) | 828 | static int power_off_slot(struct acpiphp_slot *slot) |
852 | { | 829 | { |
853 | acpi_status status; | 830 | acpi_status status; |
854 | struct acpiphp_func *func; | 831 | struct acpiphp_func *func; |
855 | struct list_head *l; | 832 | struct list_head *l; |
856 | 833 | ||
857 | int retval = 0; | 834 | int retval = 0; |
858 | 835 | ||
859 | /* if already disabled, just skip */ | 836 | /* if already disabled, just skip */ |
860 | if ((slot->flags & SLOT_POWEREDON) == 0) | 837 | if ((slot->flags & SLOT_POWEREDON) == 0) |
861 | goto err_exit; | 838 | goto err_exit; |
862 | 839 | ||
863 | list_for_each (l, &slot->funcs) { | 840 | list_for_each (l, &slot->funcs) { |
864 | func = list_entry(l, struct acpiphp_func, sibling); | 841 | func = list_entry(l, struct acpiphp_func, sibling); |
865 | 842 | ||
866 | if (func->flags & FUNC_HAS_PS3) { | 843 | if (func->flags & FUNC_HAS_PS3) { |
867 | status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); | 844 | status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); |
868 | if (ACPI_FAILURE(status)) { | 845 | if (ACPI_FAILURE(status)) { |
869 | warn("%s: _PS3 failed\n", __func__); | 846 | warn("%s: _PS3 failed\n", __func__); |
870 | retval = -1; | 847 | retval = -1; |
871 | goto err_exit; | 848 | goto err_exit; |
872 | } else | 849 | } else |
873 | break; | 850 | break; |
874 | } | 851 | } |
875 | } | 852 | } |
876 | 853 | ||
877 | /* TBD: evaluate _STA to check if the slot is disabled */ | 854 | /* TBD: evaluate _STA to check if the slot is disabled */ |
878 | 855 | ||
879 | slot->flags &= (~SLOT_POWEREDON); | 856 | slot->flags &= (~SLOT_POWEREDON); |
880 | 857 | ||
881 | err_exit: | 858 | err_exit: |
882 | return retval; | 859 | return retval; |
883 | } | 860 | } |
884 | 861 | ||
885 | 862 | ||
886 | 863 | ||
887 | /** | 864 | /** |
888 | * acpiphp_max_busnr - return the highest reserved bus number under the given bus. | 865 | * acpiphp_max_busnr - return the highest reserved bus number under the given bus. |
889 | * @bus: bus to start search with | 866 | * @bus: bus to start search with |
890 | */ | 867 | */ |
891 | static unsigned char acpiphp_max_busnr(struct pci_bus *bus) | 868 | static unsigned char acpiphp_max_busnr(struct pci_bus *bus) |
892 | { | 869 | { |
893 | struct list_head *tmp; | 870 | struct list_head *tmp; |
894 | unsigned char max, n; | 871 | unsigned char max, n; |
895 | 872 | ||
896 | /* | 873 | /* |
897 | * pci_bus_max_busnr will return the highest | 874 | * pci_bus_max_busnr will return the highest |
898 | * reserved busnr for all these children. | 875 | * reserved busnr for all these children. |
899 | * that is equivalent to the bus->subordinate | 876 | * that is equivalent to the bus->subordinate |
900 | * value. We don't want to use the parent's | 877 | * value. We don't want to use the parent's |
901 | * bus->subordinate value because it could have | 878 | * bus->subordinate value because it could have |
902 | * padding in it. | 879 | * padding in it. |
903 | */ | 880 | */ |
904 | max = bus->secondary; | 881 | max = bus->secondary; |
905 | 882 | ||
906 | list_for_each(tmp, &bus->children) { | 883 | list_for_each(tmp, &bus->children) { |
907 | n = pci_bus_max_busnr(pci_bus_b(tmp)); | 884 | n = pci_bus_max_busnr(pci_bus_b(tmp)); |
908 | if (n > max) | 885 | if (n > max) |
909 | max = n; | 886 | max = n; |
910 | } | 887 | } |
911 | return max; | 888 | return max; |
912 | } | 889 | } |
913 | 890 | ||
914 | 891 | ||
915 | /** | 892 | /** |
916 | * acpiphp_bus_add - add a new bus to acpi subsystem | 893 | * acpiphp_bus_add - add a new bus to acpi subsystem |
917 | * @func: acpiphp_func of the bridge | 894 | * @func: acpiphp_func of the bridge |
918 | */ | 895 | */ |
919 | static int acpiphp_bus_add(struct acpiphp_func *func) | 896 | static int acpiphp_bus_add(struct acpiphp_func *func) |
920 | { | 897 | { |
921 | acpi_handle phandle; | 898 | acpi_handle phandle; |
922 | struct acpi_device *device, *pdevice; | 899 | struct acpi_device *device, *pdevice; |
923 | int ret_val; | 900 | int ret_val; |
924 | 901 | ||
925 | acpi_get_parent(func->handle, &phandle); | 902 | acpi_get_parent(func->handle, &phandle); |
926 | if (acpi_bus_get_device(phandle, &pdevice)) { | 903 | if (acpi_bus_get_device(phandle, &pdevice)) { |
927 | dbg("no parent device, assuming NULL\n"); | 904 | dbg("no parent device, assuming NULL\n"); |
928 | pdevice = NULL; | 905 | pdevice = NULL; |
929 | } | 906 | } |
930 | if (!acpi_bus_get_device(func->handle, &device)) { | 907 | if (!acpi_bus_get_device(func->handle, &device)) { |
931 | dbg("bus exists... trim\n"); | 908 | dbg("bus exists... trim\n"); |
932 | /* this shouldn't be in here, so remove | 909 | /* this shouldn't be in here, so remove |
933 | * the bus then re-add it... | 910 | * the bus then re-add it... |
934 | */ | 911 | */ |
935 | ret_val = acpi_bus_trim(device, 1); | 912 | ret_val = acpi_bus_trim(device, 1); |
936 | dbg("acpi_bus_trim return %x\n", ret_val); | 913 | dbg("acpi_bus_trim return %x\n", ret_val); |
937 | } | 914 | } |
938 | 915 | ||
939 | ret_val = acpi_bus_add(&device, pdevice, func->handle, | 916 | ret_val = acpi_bus_add(&device, pdevice, func->handle, |
940 | ACPI_BUS_TYPE_DEVICE); | 917 | ACPI_BUS_TYPE_DEVICE); |
941 | if (ret_val) { | 918 | if (ret_val) { |
942 | dbg("error adding bus, %x\n", | 919 | dbg("error adding bus, %x\n", |
943 | -ret_val); | 920 | -ret_val); |
944 | goto acpiphp_bus_add_out; | 921 | goto acpiphp_bus_add_out; |
945 | } | 922 | } |
946 | /* | 923 | /* |
947 | * try to start anyway. We could have failed to add | 924 | * try to start anyway. We could have failed to add |
948 | * simply because this bus had previously been added | 925 | * simply because this bus had previously been added |
949 | * on another add. Don't bother with the return value | 926 | * on another add. Don't bother with the return value |
950 | * we just keep going. | 927 | * we just keep going. |
951 | */ | 928 | */ |
952 | ret_val = acpi_bus_start(device); | 929 | ret_val = acpi_bus_start(device); |
953 | 930 | ||
954 | acpiphp_bus_add_out: | 931 | acpiphp_bus_add_out: |
955 | return ret_val; | 932 | return ret_val; |
956 | } | 933 | } |
957 | 934 | ||
958 | 935 | ||
959 | /** | 936 | /** |
960 | * acpiphp_bus_trim - trim a bus from acpi subsystem | 937 | * acpiphp_bus_trim - trim a bus from acpi subsystem |
961 | * @handle: handle to acpi namespace | 938 | * @handle: handle to acpi namespace |
962 | */ | 939 | */ |
963 | static int acpiphp_bus_trim(acpi_handle handle) | 940 | static int acpiphp_bus_trim(acpi_handle handle) |
964 | { | 941 | { |
965 | struct acpi_device *device; | 942 | struct acpi_device *device; |
966 | int retval; | 943 | int retval; |
967 | 944 | ||
968 | retval = acpi_bus_get_device(handle, &device); | 945 | retval = acpi_bus_get_device(handle, &device); |
969 | if (retval) { | 946 | if (retval) { |
970 | dbg("acpi_device not found\n"); | 947 | dbg("acpi_device not found\n"); |
971 | return retval; | 948 | return retval; |
972 | } | 949 | } |
973 | 950 | ||
974 | retval = acpi_bus_trim(device, 1); | 951 | retval = acpi_bus_trim(device, 1); |
975 | if (retval) | 952 | if (retval) |
976 | err("cannot remove from acpi list\n"); | 953 | err("cannot remove from acpi list\n"); |
977 | 954 | ||
978 | return retval; | 955 | return retval; |
979 | } | 956 | } |
980 | 957 | ||
981 | /** | 958 | /** |
982 | * enable_device - enable, configure a slot | 959 | * enable_device - enable, configure a slot |
983 | * @slot: slot to be enabled | 960 | * @slot: slot to be enabled |
984 | * | 961 | * |
985 | * This function should be called per *physical slot*, | 962 | * This function should be called per *physical slot*, |
986 | * not per each slot object in ACPI namespace. | 963 | * not per each slot object in ACPI namespace. |
987 | */ | 964 | */ |
988 | static int __ref enable_device(struct acpiphp_slot *slot) | 965 | static int __ref enable_device(struct acpiphp_slot *slot) |
989 | { | 966 | { |
990 | struct pci_dev *dev; | 967 | struct pci_dev *dev; |
991 | struct pci_bus *bus = slot->bridge->pci_bus; | 968 | struct pci_bus *bus = slot->bridge->pci_bus; |
992 | struct list_head *l; | 969 | struct list_head *l; |
993 | struct acpiphp_func *func; | 970 | struct acpiphp_func *func; |
994 | int retval = 0; | 971 | int retval = 0; |
995 | int num, max, pass; | 972 | int num, max, pass; |
996 | acpi_status status; | 973 | acpi_status status; |
997 | 974 | ||
998 | if (slot->flags & SLOT_ENABLED) | 975 | if (slot->flags & SLOT_ENABLED) |
999 | goto err_exit; | 976 | goto err_exit; |
1000 | 977 | ||
1001 | /* sanity check: dev should be NULL when hot-plugged in */ | 978 | /* sanity check: dev should be NULL when hot-plugged in */ |
1002 | dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); | 979 | dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); |
1003 | if (dev) { | 980 | if (dev) { |
1004 | /* This case shouldn't happen */ | 981 | /* This case shouldn't happen */ |
1005 | err("pci_dev structure already exists.\n"); | 982 | err("pci_dev structure already exists.\n"); |
1006 | pci_dev_put(dev); | 983 | pci_dev_put(dev); |
1007 | retval = -1; | 984 | retval = -1; |
1008 | goto err_exit; | 985 | goto err_exit; |
1009 | } | 986 | } |
1010 | 987 | ||
1011 | num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); | 988 | num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); |
1012 | if (num == 0) { | 989 | if (num == 0) { |
1013 | err("No new device found\n"); | 990 | err("No new device found\n"); |
1014 | retval = -1; | 991 | retval = -1; |
1015 | goto err_exit; | 992 | goto err_exit; |
1016 | } | 993 | } |
1017 | 994 | ||
1018 | max = acpiphp_max_busnr(bus); | 995 | max = acpiphp_max_busnr(bus); |
1019 | for (pass = 0; pass < 2; pass++) { | 996 | for (pass = 0; pass < 2; pass++) { |
1020 | list_for_each_entry(dev, &bus->devices, bus_list) { | 997 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1021 | if (PCI_SLOT(dev->devfn) != slot->device) | 998 | if (PCI_SLOT(dev->devfn) != slot->device) |
1022 | continue; | 999 | continue; |
1023 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 1000 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
1024 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { | 1001 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { |
1025 | max = pci_scan_bridge(bus, dev, max, pass); | 1002 | max = pci_scan_bridge(bus, dev, max, pass); |
1026 | if (pass && dev->subordinate) | 1003 | if (pass && dev->subordinate) |
1027 | pci_bus_size_bridges(dev->subordinate); | 1004 | pci_bus_size_bridges(dev->subordinate); |
1028 | } | 1005 | } |
1029 | } | 1006 | } |
1030 | } | 1007 | } |
1031 | 1008 | ||
1032 | list_for_each (l, &slot->funcs) { | 1009 | list_for_each (l, &slot->funcs) { |
1033 | func = list_entry(l, struct acpiphp_func, sibling); | 1010 | func = list_entry(l, struct acpiphp_func, sibling); |
1034 | acpiphp_bus_add(func); | 1011 | acpiphp_bus_add(func); |
1035 | } | 1012 | } |
1036 | 1013 | ||
1037 | pci_bus_assign_resources(bus); | 1014 | pci_bus_assign_resources(bus); |
1038 | acpiphp_sanitize_bus(bus); | 1015 | acpiphp_sanitize_bus(bus); |
1039 | acpiphp_set_hpp_values(bus); | 1016 | acpiphp_set_hpp_values(bus); |
1040 | list_for_each_entry(func, &slot->funcs, sibling) | 1017 | list_for_each_entry(func, &slot->funcs, sibling) |
1041 | acpiphp_configure_ioapics(func->handle); | 1018 | acpiphp_configure_ioapics(func->handle); |
1042 | pci_enable_bridges(bus); | 1019 | pci_enable_bridges(bus); |
1043 | pci_bus_add_devices(bus); | 1020 | pci_bus_add_devices(bus); |
1044 | 1021 | ||
1045 | list_for_each (l, &slot->funcs) { | 1022 | list_for_each (l, &slot->funcs) { |
1046 | func = list_entry(l, struct acpiphp_func, sibling); | 1023 | func = list_entry(l, struct acpiphp_func, sibling); |
1047 | dev = pci_get_slot(bus, PCI_DEVFN(slot->device, | 1024 | dev = pci_get_slot(bus, PCI_DEVFN(slot->device, |
1048 | func->function)); | 1025 | func->function)); |
1049 | if (!dev) | 1026 | if (!dev) |
1050 | continue; | 1027 | continue; |
1051 | 1028 | ||
1052 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && | 1029 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && |
1053 | dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { | 1030 | dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { |
1054 | pci_dev_put(dev); | 1031 | pci_dev_put(dev); |
1055 | continue; | 1032 | continue; |
1056 | } | 1033 | } |
1057 | 1034 | ||
1058 | status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); | 1035 | status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); |
1059 | if (ACPI_FAILURE(status)) | 1036 | if (ACPI_FAILURE(status)) |
1060 | warn("find_p2p_bridge failed (error code = 0x%x)\n", | 1037 | warn("find_p2p_bridge failed (error code = 0x%x)\n", |
1061 | status); | 1038 | status); |
1062 | pci_dev_put(dev); | 1039 | pci_dev_put(dev); |
1063 | } | 1040 | } |
1064 | 1041 | ||
1065 | slot->flags |= SLOT_ENABLED; | 1042 | slot->flags |= SLOT_ENABLED; |
1066 | 1043 | ||
1067 | err_exit: | 1044 | err_exit: |
1068 | return retval; | 1045 | return retval; |
1069 | } | 1046 | } |
1070 | 1047 | ||
1071 | static void disable_bridges(struct pci_bus *bus) | 1048 | static void disable_bridges(struct pci_bus *bus) |
1072 | { | 1049 | { |
1073 | struct pci_dev *dev; | 1050 | struct pci_dev *dev; |
1074 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1051 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1075 | if (dev->subordinate) { | 1052 | if (dev->subordinate) { |
1076 | disable_bridges(dev->subordinate); | 1053 | disable_bridges(dev->subordinate); |
1077 | pci_disable_device(dev); | 1054 | pci_disable_device(dev); |
1078 | } | 1055 | } |
1079 | } | 1056 | } |
1080 | } | 1057 | } |
1081 | 1058 | ||
1082 | /** | 1059 | /** |
1083 | * disable_device - disable a slot | 1060 | * disable_device - disable a slot |
1084 | * @slot: ACPI PHP slot | 1061 | * @slot: ACPI PHP slot |
1085 | */ | 1062 | */ |
1086 | static int disable_device(struct acpiphp_slot *slot) | 1063 | static int disable_device(struct acpiphp_slot *slot) |
1087 | { | 1064 | { |
1088 | struct acpiphp_func *func; | 1065 | struct acpiphp_func *func; |
1089 | struct pci_dev *pdev; | 1066 | struct pci_dev *pdev; |
1090 | 1067 | ||
1091 | /* is this slot already disabled? */ | 1068 | /* is this slot already disabled? */ |
1092 | if (!(slot->flags & SLOT_ENABLED)) | 1069 | if (!(slot->flags & SLOT_ENABLED)) |
1093 | goto err_exit; | 1070 | goto err_exit; |
1094 | 1071 | ||
1095 | list_for_each_entry(func, &slot->funcs, sibling) { | 1072 | list_for_each_entry(func, &slot->funcs, sibling) { |
1096 | if (func->bridge) { | 1073 | if (func->bridge) { |
1097 | /* cleanup p2p bridges under this P2P bridge */ | 1074 | /* cleanup p2p bridges under this P2P bridge */ |
1098 | cleanup_p2p_bridge(func->bridge->handle, | 1075 | cleanup_p2p_bridge(func->bridge->handle, |
1099 | (u32)1, NULL, NULL); | 1076 | (u32)1, NULL, NULL); |
1100 | func->bridge = NULL; | 1077 | func->bridge = NULL; |
1101 | } | 1078 | } |
1102 | 1079 | ||
1103 | pdev = pci_get_slot(slot->bridge->pci_bus, | 1080 | pdev = pci_get_slot(slot->bridge->pci_bus, |
1104 | PCI_DEVFN(slot->device, func->function)); | 1081 | PCI_DEVFN(slot->device, func->function)); |
1105 | if (pdev) { | 1082 | if (pdev) { |
1106 | pci_stop_bus_device(pdev); | 1083 | pci_stop_bus_device(pdev); |
1107 | if (pdev->subordinate) { | 1084 | if (pdev->subordinate) { |
1108 | disable_bridges(pdev->subordinate); | 1085 | disable_bridges(pdev->subordinate); |
1109 | pci_disable_device(pdev); | 1086 | pci_disable_device(pdev); |
1110 | } | 1087 | } |
1111 | pci_remove_bus_device(pdev); | 1088 | pci_remove_bus_device(pdev); |
1112 | pci_dev_put(pdev); | 1089 | pci_dev_put(pdev); |
1113 | } | 1090 | } |
1114 | } | 1091 | } |
1115 | 1092 | ||
1116 | list_for_each_entry(func, &slot->funcs, sibling) { | 1093 | list_for_each_entry(func, &slot->funcs, sibling) { |
1117 | acpiphp_unconfigure_ioapics(func->handle); | 1094 | acpiphp_unconfigure_ioapics(func->handle); |
1118 | acpiphp_bus_trim(func->handle); | 1095 | acpiphp_bus_trim(func->handle); |
1119 | } | 1096 | } |
1120 | 1097 | ||
1121 | slot->flags &= (~SLOT_ENABLED); | 1098 | slot->flags &= (~SLOT_ENABLED); |
1122 | 1099 | ||
1123 | err_exit: | 1100 | err_exit: |
1124 | return 0; | 1101 | return 0; |
1125 | } | 1102 | } |
1126 | 1103 | ||
1127 | 1104 | ||
1128 | /** | 1105 | /** |
1129 | * get_slot_status - get ACPI slot status | 1106 | * get_slot_status - get ACPI slot status |
1130 | * @slot: ACPI PHP slot | 1107 | * @slot: ACPI PHP slot |
1131 | * | 1108 | * |
1132 | * If a slot has _STA for each function and if any one of them | 1109 | * If a slot has _STA for each function and if any one of them |
1133 | * returned non-zero status, return it. | 1110 | * returned non-zero status, return it. |
1134 | * | 1111 | * |
1135 | * If a slot doesn't have _STA and if any one of its functions' | 1112 | * If a slot doesn't have _STA and if any one of its functions' |
1136 | * configuration space is configured, return 0x0f as a _STA. | 1113 | * configuration space is configured, return 0x0f as a _STA. |
1137 | * | 1114 | * |
1138 | * Otherwise return 0. | 1115 | * Otherwise return 0. |
1139 | */ | 1116 | */ |
1140 | static unsigned int get_slot_status(struct acpiphp_slot *slot) | 1117 | static unsigned int get_slot_status(struct acpiphp_slot *slot) |
1141 | { | 1118 | { |
1142 | acpi_status status; | 1119 | acpi_status status; |
1143 | unsigned long long sta = 0; | 1120 | unsigned long long sta = 0; |
1144 | u32 dvid; | 1121 | u32 dvid; |
1145 | struct list_head *l; | 1122 | struct list_head *l; |
1146 | struct acpiphp_func *func; | 1123 | struct acpiphp_func *func; |
1147 | 1124 | ||
1148 | list_for_each (l, &slot->funcs) { | 1125 | list_for_each (l, &slot->funcs) { |
1149 | func = list_entry(l, struct acpiphp_func, sibling); | 1126 | func = list_entry(l, struct acpiphp_func, sibling); |
1150 | 1127 | ||
1151 | if (func->flags & FUNC_HAS_STA) { | 1128 | if (func->flags & FUNC_HAS_STA) { |
1152 | status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta); | 1129 | status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta); |
1153 | if (ACPI_SUCCESS(status) && sta) | 1130 | if (ACPI_SUCCESS(status) && sta) |
1154 | break; | 1131 | break; |
1155 | } else { | 1132 | } else { |
1156 | pci_bus_read_config_dword(slot->bridge->pci_bus, | 1133 | pci_bus_read_config_dword(slot->bridge->pci_bus, |
1157 | PCI_DEVFN(slot->device, | 1134 | PCI_DEVFN(slot->device, |
1158 | func->function), | 1135 | func->function), |
1159 | PCI_VENDOR_ID, &dvid); | 1136 | PCI_VENDOR_ID, &dvid); |
1160 | if (dvid != 0xffffffff) { | 1137 | if (dvid != 0xffffffff) { |
1161 | sta = ACPI_STA_ALL; | 1138 | sta = ACPI_STA_ALL; |
1162 | break; | 1139 | break; |
1163 | } | 1140 | } |
1164 | } | 1141 | } |
1165 | } | 1142 | } |
1166 | 1143 | ||
1167 | return (unsigned int)sta; | 1144 | return (unsigned int)sta; |
1168 | } | 1145 | } |
1169 | 1146 | ||
1170 | /** | 1147 | /** |
1171 | * acpiphp_eject_slot - physically eject the slot | 1148 | * acpiphp_eject_slot - physically eject the slot |
1172 | * @slot: ACPI PHP slot | 1149 | * @slot: ACPI PHP slot |
1173 | */ | 1150 | */ |
1174 | int acpiphp_eject_slot(struct acpiphp_slot *slot) | 1151 | int acpiphp_eject_slot(struct acpiphp_slot *slot) |
1175 | { | 1152 | { |
1176 | acpi_status status; | 1153 | acpi_status status; |
1177 | struct acpiphp_func *func; | 1154 | struct acpiphp_func *func; |
1178 | struct list_head *l; | 1155 | struct list_head *l; |
1179 | struct acpi_object_list arg_list; | 1156 | struct acpi_object_list arg_list; |
1180 | union acpi_object arg; | 1157 | union acpi_object arg; |
1181 | 1158 | ||
1182 | list_for_each (l, &slot->funcs) { | 1159 | list_for_each (l, &slot->funcs) { |
1183 | func = list_entry(l, struct acpiphp_func, sibling); | 1160 | func = list_entry(l, struct acpiphp_func, sibling); |
1184 | 1161 | ||
1185 | /* We don't want to call _EJ0 on non-existing functions. */ | 1162 | /* We don't want to call _EJ0 on non-existing functions. */ |
1186 | if ((func->flags & FUNC_HAS_EJ0)) { | 1163 | if ((func->flags & FUNC_HAS_EJ0)) { |
1187 | /* _EJ0 method take one argument */ | 1164 | /* _EJ0 method take one argument */ |
1188 | arg_list.count = 1; | 1165 | arg_list.count = 1; |
1189 | arg_list.pointer = &arg; | 1166 | arg_list.pointer = &arg; |
1190 | arg.type = ACPI_TYPE_INTEGER; | 1167 | arg.type = ACPI_TYPE_INTEGER; |
1191 | arg.integer.value = 1; | 1168 | arg.integer.value = 1; |
1192 | 1169 | ||
1193 | status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); | 1170 | status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); |
1194 | if (ACPI_FAILURE(status)) { | 1171 | if (ACPI_FAILURE(status)) { |
1195 | warn("%s: _EJ0 failed\n", __func__); | 1172 | warn("%s: _EJ0 failed\n", __func__); |
1196 | return -1; | 1173 | return -1; |
1197 | } else | 1174 | } else |
1198 | break; | 1175 | break; |
1199 | } | 1176 | } |
1200 | } | 1177 | } |
1201 | return 0; | 1178 | return 0; |
1202 | } | 1179 | } |
1203 | 1180 | ||
1204 | /** | 1181 | /** |
1205 | * acpiphp_check_bridge - re-enumerate devices | 1182 | * acpiphp_check_bridge - re-enumerate devices |
1206 | * @bridge: where to begin re-enumeration | 1183 | * @bridge: where to begin re-enumeration |
1207 | * | 1184 | * |
1208 | * Iterate over all slots under this bridge and make sure that if a | 1185 | * Iterate over all slots under this bridge and make sure that if a |
1209 | * card is present they are enabled, and if not they are disabled. | 1186 | * card is present they are enabled, and if not they are disabled. |
1210 | */ | 1187 | */ |
1211 | static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) | 1188 | static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) |
1212 | { | 1189 | { |
1213 | struct acpiphp_slot *slot; | 1190 | struct acpiphp_slot *slot; |
1214 | int retval = 0; | 1191 | int retval = 0; |
1215 | int enabled, disabled; | 1192 | int enabled, disabled; |
1216 | 1193 | ||
1217 | enabled = disabled = 0; | 1194 | enabled = disabled = 0; |
1218 | 1195 | ||
1219 | for (slot = bridge->slots; slot; slot = slot->next) { | 1196 | for (slot = bridge->slots; slot; slot = slot->next) { |
1220 | unsigned int status = get_slot_status(slot); | 1197 | unsigned int status = get_slot_status(slot); |
1221 | if (slot->flags & SLOT_ENABLED) { | 1198 | if (slot->flags & SLOT_ENABLED) { |
1222 | if (status == ACPI_STA_ALL) | 1199 | if (status == ACPI_STA_ALL) |
1223 | continue; | 1200 | continue; |
1224 | retval = acpiphp_disable_slot(slot); | 1201 | retval = acpiphp_disable_slot(slot); |
1225 | if (retval) { | 1202 | if (retval) { |
1226 | err("Error occurred in disabling\n"); | 1203 | err("Error occurred in disabling\n"); |
1227 | goto err_exit; | 1204 | goto err_exit; |
1228 | } else { | 1205 | } else { |
1229 | acpiphp_eject_slot(slot); | 1206 | acpiphp_eject_slot(slot); |
1230 | } | 1207 | } |
1231 | disabled++; | 1208 | disabled++; |
1232 | } else { | 1209 | } else { |
1233 | if (status != ACPI_STA_ALL) | 1210 | if (status != ACPI_STA_ALL) |
1234 | continue; | 1211 | continue; |
1235 | retval = acpiphp_enable_slot(slot); | 1212 | retval = acpiphp_enable_slot(slot); |
1236 | if (retval) { | 1213 | if (retval) { |
1237 | err("Error occurred in enabling\n"); | 1214 | err("Error occurred in enabling\n"); |
1238 | goto err_exit; | 1215 | goto err_exit; |
1239 | } | 1216 | } |
1240 | enabled++; | 1217 | enabled++; |
1241 | } | 1218 | } |
1242 | } | 1219 | } |
1243 | 1220 | ||
1244 | dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled); | 1221 | dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled); |
1245 | 1222 | ||
1246 | err_exit: | 1223 | err_exit: |
1247 | return retval; | 1224 | return retval; |
1248 | } | 1225 | } |
1249 | 1226 | ||
1250 | static void program_hpp(struct pci_dev *dev, struct hotplug_params *hpp) | ||
1251 | { | ||
1252 | u16 pci_cmd, pci_bctl; | ||
1253 | struct pci_dev *cdev; | ||
1254 | |||
1255 | /* Program hpp values for this device */ | ||
1256 | if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || | ||
1257 | (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && | ||
1258 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | ||
1259 | return; | ||
1260 | |||
1261 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) | ||
1262 | return; | ||
1263 | |||
1264 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, | ||
1265 | hpp->t0->cache_line_size); | ||
1266 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, | ||
1267 | hpp->t0->latency_timer); | ||
1268 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
1269 | if (hpp->t0->enable_serr) | ||
1270 | pci_cmd |= PCI_COMMAND_SERR; | ||
1271 | else | ||
1272 | pci_cmd &= ~PCI_COMMAND_SERR; | ||
1273 | if (hpp->t0->enable_perr) | ||
1274 | pci_cmd |= PCI_COMMAND_PARITY; | ||
1275 | else | ||
1276 | pci_cmd &= ~PCI_COMMAND_PARITY; | ||
1277 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
1278 | |||
1279 | /* Program bridge control value and child devices */ | ||
1280 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
1281 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, | ||
1282 | hpp->t0->latency_timer); | ||
1283 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); | ||
1284 | if (hpp->t0->enable_serr) | ||
1285 | pci_bctl |= PCI_BRIDGE_CTL_SERR; | ||
1286 | else | ||
1287 | pci_bctl &= ~PCI_BRIDGE_CTL_SERR; | ||
1288 | if (hpp->t0->enable_perr) | ||
1289 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; | ||
1290 | else | ||
1291 | pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; | ||
1292 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); | ||
1293 | if (dev->subordinate) { | ||
1294 | list_for_each_entry(cdev, &dev->subordinate->devices, | ||
1295 | bus_list) | ||
1296 | program_hpp(cdev, hpp); | ||
1297 | } | ||
1298 | } | ||
1299 | } | ||
1300 | |||
1301 | static void acpiphp_set_hpp_values(struct pci_bus *bus) | 1227 | static void acpiphp_set_hpp_values(struct pci_bus *bus) |
1302 | { | 1228 | { |
1303 | struct pci_dev *dev; | 1229 | struct pci_dev *dev; |
1304 | struct hotplug_params hpp; | ||
1305 | 1230 | ||
1306 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1231 | list_for_each_entry(dev, &bus->devices, bus_list) |
1307 | decode_hpp(dev, &hpp); | 1232 | pci_configure_slot(dev); |
1308 | program_hpp(dev, &hpp); | ||
1309 | } | ||
1310 | } | 1233 | } |
1311 | 1234 | ||
1312 | /* | 1235 | /* |
1313 | * Remove devices for which we could not assign resources, call | 1236 | * Remove devices for which we could not assign resources, call |
1314 | * arch specific code to fix-up the bus | 1237 | * arch specific code to fix-up the bus |
1315 | */ | 1238 | */ |
1316 | static void acpiphp_sanitize_bus(struct pci_bus *bus) | 1239 | static void acpiphp_sanitize_bus(struct pci_bus *bus) |
1317 | { | 1240 | { |
1318 | struct pci_dev *dev; | 1241 | struct pci_dev *dev; |
1319 | int i; | 1242 | int i; |
1320 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; | 1243 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; |
1321 | 1244 | ||
1322 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1245 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1323 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { | 1246 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { |
1324 | struct resource *res = &dev->resource[i]; | 1247 | struct resource *res = &dev->resource[i]; |
1325 | if ((res->flags & type_mask) && !res->start && | 1248 | if ((res->flags & type_mask) && !res->start && |
1326 | res->end) { | 1249 | res->end) { |
1327 | /* Could not assign a required resources | 1250 | /* Could not assign a required resources |
1328 | * for this device, remove it */ | 1251 | * for this device, remove it */ |
1329 | pci_remove_bus_device(dev); | 1252 | pci_remove_bus_device(dev); |
1330 | break; | 1253 | break; |
1331 | } | 1254 | } |
1332 | } | 1255 | } |
1333 | } | 1256 | } |
1334 | } | 1257 | } |
1335 | 1258 | ||
1336 | /* Program resources in newly inserted bridge */ | 1259 | /* Program resources in newly inserted bridge */ |
1337 | static int acpiphp_configure_bridge (acpi_handle handle) | 1260 | static int acpiphp_configure_bridge (acpi_handle handle) |
1338 | { | 1261 | { |
1339 | struct pci_bus *bus; | 1262 | struct pci_bus *bus; |
1340 | 1263 | ||
1341 | if (acpi_is_root_bridge(handle)) { | 1264 | if (acpi_is_root_bridge(handle)) { |
1342 | struct acpi_pci_root *root = acpi_pci_find_root(handle); | 1265 | struct acpi_pci_root *root = acpi_pci_find_root(handle); |
1343 | bus = root->bus; | 1266 | bus = root->bus; |
1344 | } else { | 1267 | } else { |
1345 | struct pci_dev *pdev = acpi_get_pci_dev(handle); | 1268 | struct pci_dev *pdev = acpi_get_pci_dev(handle); |
1346 | bus = pdev->subordinate; | 1269 | bus = pdev->subordinate; |
1347 | pci_dev_put(pdev); | 1270 | pci_dev_put(pdev); |
1348 | } | 1271 | } |
1349 | 1272 | ||
1350 | pci_bus_size_bridges(bus); | 1273 | pci_bus_size_bridges(bus); |
1351 | pci_bus_assign_resources(bus); | 1274 | pci_bus_assign_resources(bus); |
1352 | acpiphp_sanitize_bus(bus); | 1275 | acpiphp_sanitize_bus(bus); |
1353 | acpiphp_set_hpp_values(bus); | 1276 | acpiphp_set_hpp_values(bus); |
1354 | pci_enable_bridges(bus); | 1277 | pci_enable_bridges(bus); |
1355 | acpiphp_configure_ioapics(handle); | 1278 | acpiphp_configure_ioapics(handle); |
1356 | return 0; | 1279 | return 0; |
1357 | } | 1280 | } |
1358 | 1281 | ||
1359 | static void handle_bridge_insertion(acpi_handle handle, u32 type) | 1282 | static void handle_bridge_insertion(acpi_handle handle, u32 type) |
1360 | { | 1283 | { |
1361 | struct acpi_device *device, *pdevice; | 1284 | struct acpi_device *device, *pdevice; |
1362 | acpi_handle phandle; | 1285 | acpi_handle phandle; |
1363 | 1286 | ||
1364 | if ((type != ACPI_NOTIFY_BUS_CHECK) && | 1287 | if ((type != ACPI_NOTIFY_BUS_CHECK) && |
1365 | (type != ACPI_NOTIFY_DEVICE_CHECK)) { | 1288 | (type != ACPI_NOTIFY_DEVICE_CHECK)) { |
1366 | err("unexpected notification type %d\n", type); | 1289 | err("unexpected notification type %d\n", type); |
1367 | return; | 1290 | return; |
1368 | } | 1291 | } |
1369 | 1292 | ||
1370 | acpi_get_parent(handle, &phandle); | 1293 | acpi_get_parent(handle, &phandle); |
1371 | if (acpi_bus_get_device(phandle, &pdevice)) { | 1294 | if (acpi_bus_get_device(phandle, &pdevice)) { |
1372 | dbg("no parent device, assuming NULL\n"); | 1295 | dbg("no parent device, assuming NULL\n"); |
1373 | pdevice = NULL; | 1296 | pdevice = NULL; |
1374 | } | 1297 | } |
1375 | if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) { | 1298 | if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) { |
1376 | err("cannot add bridge to acpi list\n"); | 1299 | err("cannot add bridge to acpi list\n"); |
1377 | return; | 1300 | return; |
1378 | } | 1301 | } |
1379 | if (!acpiphp_configure_bridge(handle) && | 1302 | if (!acpiphp_configure_bridge(handle) && |
1380 | !acpi_bus_start(device)) | 1303 | !acpi_bus_start(device)) |
1381 | add_bridge(handle); | 1304 | add_bridge(handle); |
1382 | else | 1305 | else |
1383 | err("cannot configure and start bridge\n"); | 1306 | err("cannot configure and start bridge\n"); |
1384 | 1307 | ||
1385 | } | 1308 | } |
1386 | 1309 | ||
1387 | /* | 1310 | /* |
1388 | * ACPI event handlers | 1311 | * ACPI event handlers |
1389 | */ | 1312 | */ |
1390 | 1313 | ||
1391 | static acpi_status | 1314 | static acpi_status |
1392 | count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | 1315 | count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) |
1393 | { | 1316 | { |
1394 | int *count = (int *)context; | 1317 | int *count = (int *)context; |
1395 | struct acpiphp_bridge *bridge; | 1318 | struct acpiphp_bridge *bridge; |
1396 | 1319 | ||
1397 | bridge = acpiphp_handle_to_bridge(handle); | 1320 | bridge = acpiphp_handle_to_bridge(handle); |
1398 | if (bridge) | 1321 | if (bridge) |
1399 | (*count)++; | 1322 | (*count)++; |
1400 | return AE_OK ; | 1323 | return AE_OK ; |
1401 | } | 1324 | } |
1402 | 1325 | ||
1403 | static acpi_status | 1326 | static acpi_status |
1404 | check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | 1327 | check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) |
1405 | { | 1328 | { |
1406 | struct acpiphp_bridge *bridge; | 1329 | struct acpiphp_bridge *bridge; |
1407 | char objname[64]; | 1330 | char objname[64]; |
1408 | struct acpi_buffer buffer = { .length = sizeof(objname), | 1331 | struct acpi_buffer buffer = { .length = sizeof(objname), |
1409 | .pointer = objname }; | 1332 | .pointer = objname }; |
1410 | 1333 | ||
1411 | bridge = acpiphp_handle_to_bridge(handle); | 1334 | bridge = acpiphp_handle_to_bridge(handle); |
1412 | if (bridge) { | 1335 | if (bridge) { |
1413 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 1336 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
1414 | dbg("%s: re-enumerating slots under %s\n", | 1337 | dbg("%s: re-enumerating slots under %s\n", |
1415 | __func__, objname); | 1338 | __func__, objname); |
1416 | acpiphp_check_bridge(bridge); | 1339 | acpiphp_check_bridge(bridge); |
1417 | } | 1340 | } |
1418 | return AE_OK ; | 1341 | return AE_OK ; |
1419 | } | 1342 | } |
1420 | 1343 | ||
1421 | /** | 1344 | /** |
1422 | * handle_hotplug_event_bridge - handle ACPI event on bridges | 1345 | * handle_hotplug_event_bridge - handle ACPI event on bridges |
1423 | * @handle: Notify()'ed acpi_handle | 1346 | * @handle: Notify()'ed acpi_handle |
1424 | * @type: Notify code | 1347 | * @type: Notify code |
1425 | * @context: pointer to acpiphp_bridge structure | 1348 | * @context: pointer to acpiphp_bridge structure |
1426 | * | 1349 | * |
1427 | * Handles ACPI event notification on {host,p2p} bridges. | 1350 | * Handles ACPI event notification on {host,p2p} bridges. |
1428 | */ | 1351 | */ |
1429 | static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context) | 1352 | static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context) |
1430 | { | 1353 | { |
1431 | struct acpiphp_bridge *bridge; | 1354 | struct acpiphp_bridge *bridge; |
1432 | char objname[64]; | 1355 | char objname[64]; |
1433 | struct acpi_buffer buffer = { .length = sizeof(objname), | 1356 | struct acpi_buffer buffer = { .length = sizeof(objname), |
1434 | .pointer = objname }; | 1357 | .pointer = objname }; |
1435 | struct acpi_device *device; | 1358 | struct acpi_device *device; |
1436 | int num_sub_bridges = 0; | 1359 | int num_sub_bridges = 0; |
1437 | 1360 | ||
1438 | if (acpi_bus_get_device(handle, &device)) { | 1361 | if (acpi_bus_get_device(handle, &device)) { |
1439 | /* This bridge must have just been physically inserted */ | 1362 | /* This bridge must have just been physically inserted */ |
1440 | handle_bridge_insertion(handle, type); | 1363 | handle_bridge_insertion(handle, type); |
1441 | return; | 1364 | return; |
1442 | } | 1365 | } |
1443 | 1366 | ||
1444 | bridge = acpiphp_handle_to_bridge(handle); | 1367 | bridge = acpiphp_handle_to_bridge(handle); |
1445 | if (type == ACPI_NOTIFY_BUS_CHECK) { | 1368 | if (type == ACPI_NOTIFY_BUS_CHECK) { |
1446 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX, | 1369 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX, |
1447 | count_sub_bridges, &num_sub_bridges, NULL); | 1370 | count_sub_bridges, &num_sub_bridges, NULL); |
1448 | } | 1371 | } |
1449 | 1372 | ||
1450 | if (!bridge && !num_sub_bridges) { | 1373 | if (!bridge && !num_sub_bridges) { |
1451 | err("cannot get bridge info\n"); | 1374 | err("cannot get bridge info\n"); |
1452 | return; | 1375 | return; |
1453 | } | 1376 | } |
1454 | 1377 | ||
1455 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 1378 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
1456 | 1379 | ||
1457 | switch (type) { | 1380 | switch (type) { |
1458 | case ACPI_NOTIFY_BUS_CHECK: | 1381 | case ACPI_NOTIFY_BUS_CHECK: |
1459 | /* bus re-enumerate */ | 1382 | /* bus re-enumerate */ |
1460 | dbg("%s: Bus check notify on %s\n", __func__, objname); | 1383 | dbg("%s: Bus check notify on %s\n", __func__, objname); |
1461 | if (bridge) { | 1384 | if (bridge) { |
1462 | dbg("%s: re-enumerating slots under %s\n", | 1385 | dbg("%s: re-enumerating slots under %s\n", |
1463 | __func__, objname); | 1386 | __func__, objname); |
1464 | acpiphp_check_bridge(bridge); | 1387 | acpiphp_check_bridge(bridge); |
1465 | } | 1388 | } |
1466 | if (num_sub_bridges) | 1389 | if (num_sub_bridges) |
1467 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | 1390 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
1468 | ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL); | 1391 | ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL); |
1469 | break; | 1392 | break; |
1470 | 1393 | ||
1471 | case ACPI_NOTIFY_DEVICE_CHECK: | 1394 | case ACPI_NOTIFY_DEVICE_CHECK: |
1472 | /* device check */ | 1395 | /* device check */ |
1473 | dbg("%s: Device check notify on %s\n", __func__, objname); | 1396 | dbg("%s: Device check notify on %s\n", __func__, objname); |
1474 | acpiphp_check_bridge(bridge); | 1397 | acpiphp_check_bridge(bridge); |
1475 | break; | 1398 | break; |
1476 | 1399 | ||
1477 | case ACPI_NOTIFY_DEVICE_WAKE: | 1400 | case ACPI_NOTIFY_DEVICE_WAKE: |
1478 | /* wake event */ | 1401 | /* wake event */ |
1479 | dbg("%s: Device wake notify on %s\n", __func__, objname); | 1402 | dbg("%s: Device wake notify on %s\n", __func__, objname); |
1480 | break; | 1403 | break; |
1481 | 1404 | ||
1482 | case ACPI_NOTIFY_EJECT_REQUEST: | 1405 | case ACPI_NOTIFY_EJECT_REQUEST: |
1483 | /* request device eject */ | 1406 | /* request device eject */ |
1484 | dbg("%s: Device eject notify on %s\n", __func__, objname); | 1407 | dbg("%s: Device eject notify on %s\n", __func__, objname); |
1485 | if ((bridge->type != BRIDGE_TYPE_HOST) && | 1408 | if ((bridge->type != BRIDGE_TYPE_HOST) && |
1486 | (bridge->flags & BRIDGE_HAS_EJ0)) { | 1409 | (bridge->flags & BRIDGE_HAS_EJ0)) { |
1487 | struct acpiphp_slot *slot; | 1410 | struct acpiphp_slot *slot; |
1488 | slot = bridge->func->slot; | 1411 | slot = bridge->func->slot; |
1489 | if (!acpiphp_disable_slot(slot)) | 1412 | if (!acpiphp_disable_slot(slot)) |
1490 | acpiphp_eject_slot(slot); | 1413 | acpiphp_eject_slot(slot); |
1491 | } | 1414 | } |
1492 | break; | 1415 | break; |
1493 | 1416 | ||
1494 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | 1417 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: |
1495 | printk(KERN_ERR "Device %s cannot be configured due" | 1418 | printk(KERN_ERR "Device %s cannot be configured due" |
1496 | " to a frequency mismatch\n", objname); | 1419 | " to a frequency mismatch\n", objname); |
1497 | break; | 1420 | break; |
1498 | 1421 | ||
1499 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | 1422 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: |
1500 | printk(KERN_ERR "Device %s cannot be configured due" | 1423 | printk(KERN_ERR "Device %s cannot be configured due" |
1501 | " to a bus mode mismatch\n", objname); | 1424 | " to a bus mode mismatch\n", objname); |
1502 | break; | 1425 | break; |
1503 | 1426 | ||
1504 | case ACPI_NOTIFY_POWER_FAULT: | 1427 | case ACPI_NOTIFY_POWER_FAULT: |
1505 | printk(KERN_ERR "Device %s has suffered a power fault\n", | 1428 | printk(KERN_ERR "Device %s has suffered a power fault\n", |
1506 | objname); | 1429 | objname); |
1507 | break; | 1430 | break; |
1508 | 1431 | ||
1509 | default: | 1432 | default: |
1510 | warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); | 1433 | warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); |
1511 | break; | 1434 | break; |
1512 | } | 1435 | } |
1513 | } | 1436 | } |
1514 | 1437 | ||
1515 | /** | 1438 | /** |
1516 | * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) | 1439 | * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) |
1517 | * @handle: Notify()'ed acpi_handle | 1440 | * @handle: Notify()'ed acpi_handle |
1518 | * @type: Notify code | 1441 | * @type: Notify code |
1519 | * @context: pointer to acpiphp_func structure | 1442 | * @context: pointer to acpiphp_func structure |
1520 | * | 1443 | * |
1521 | * Handles ACPI event notification on slots. | 1444 | * Handles ACPI event notification on slots. |
1522 | */ | 1445 | */ |
1523 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) | 1446 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) |
1524 | { | 1447 | { |
1525 | struct acpiphp_func *func; | 1448 | struct acpiphp_func *func; |
1526 | char objname[64]; | 1449 | char objname[64]; |
1527 | struct acpi_buffer buffer = { .length = sizeof(objname), | 1450 | struct acpi_buffer buffer = { .length = sizeof(objname), |
1528 | .pointer = objname }; | 1451 | .pointer = objname }; |
1529 | 1452 | ||
1530 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 1453 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
1531 | 1454 | ||
1532 | func = (struct acpiphp_func *)context; | 1455 | func = (struct acpiphp_func *)context; |
1533 | 1456 | ||
1534 | switch (type) { | 1457 | switch (type) { |
1535 | case ACPI_NOTIFY_BUS_CHECK: | 1458 | case ACPI_NOTIFY_BUS_CHECK: |
1536 | /* bus re-enumerate */ | 1459 | /* bus re-enumerate */ |
1537 | dbg("%s: Bus check notify on %s\n", __func__, objname); | 1460 | dbg("%s: Bus check notify on %s\n", __func__, objname); |
1538 | acpiphp_enable_slot(func->slot); | 1461 | acpiphp_enable_slot(func->slot); |
1539 | break; | 1462 | break; |
1540 | 1463 | ||
1541 | case ACPI_NOTIFY_DEVICE_CHECK: | 1464 | case ACPI_NOTIFY_DEVICE_CHECK: |
1542 | /* device check : re-enumerate from parent bus */ | 1465 | /* device check : re-enumerate from parent bus */ |
1543 | dbg("%s: Device check notify on %s\n", __func__, objname); | 1466 | dbg("%s: Device check notify on %s\n", __func__, objname); |
1544 | acpiphp_check_bridge(func->slot->bridge); | 1467 | acpiphp_check_bridge(func->slot->bridge); |
1545 | break; | 1468 | break; |
1546 | 1469 | ||
1547 | case ACPI_NOTIFY_DEVICE_WAKE: | 1470 | case ACPI_NOTIFY_DEVICE_WAKE: |
1548 | /* wake event */ | 1471 | /* wake event */ |
1549 | dbg("%s: Device wake notify on %s\n", __func__, objname); | 1472 | dbg("%s: Device wake notify on %s\n", __func__, objname); |
1550 | break; | 1473 | break; |
1551 | 1474 | ||
1552 | case ACPI_NOTIFY_EJECT_REQUEST: | 1475 | case ACPI_NOTIFY_EJECT_REQUEST: |
1553 | /* request device eject */ | 1476 | /* request device eject */ |
1554 | dbg("%s: Device eject notify on %s\n", __func__, objname); | 1477 | dbg("%s: Device eject notify on %s\n", __func__, objname); |
1555 | if (!(acpiphp_disable_slot(func->slot))) | 1478 | if (!(acpiphp_disable_slot(func->slot))) |
1556 | acpiphp_eject_slot(func->slot); | 1479 | acpiphp_eject_slot(func->slot); |
1557 | break; | 1480 | break; |
1558 | 1481 | ||
1559 | default: | 1482 | default: |
1560 | warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); | 1483 | warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); |
1561 | break; | 1484 | break; |
1562 | } | 1485 | } |
1563 | } | 1486 | } |
1564 | 1487 | ||
1565 | 1488 | ||
1566 | static acpi_status | 1489 | static acpi_status |
1567 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | 1490 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) |
1568 | { | 1491 | { |
1569 | int *count = (int *)context; | 1492 | int *count = (int *)context; |
1570 | 1493 | ||
1571 | if (acpi_is_root_bridge(handle)) { | 1494 | if (acpi_is_root_bridge(handle)) { |
1572 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1495 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1573 | handle_hotplug_event_bridge, NULL); | 1496 | handle_hotplug_event_bridge, NULL); |
1574 | (*count)++; | 1497 | (*count)++; |
1575 | } | 1498 | } |
1576 | return AE_OK ; | 1499 | return AE_OK ; |
1577 | } | 1500 | } |
1578 | 1501 | ||
1579 | static struct acpi_pci_driver acpi_pci_hp_driver = { | 1502 | static struct acpi_pci_driver acpi_pci_hp_driver = { |
1580 | .add = add_bridge, | 1503 | .add = add_bridge, |
1581 | .remove = remove_bridge, | 1504 | .remove = remove_bridge, |
1582 | }; | 1505 | }; |
1583 | 1506 | ||
1584 | /** | 1507 | /** |
1585 | * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures | 1508 | * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures |
1586 | */ | 1509 | */ |
1587 | int __init acpiphp_glue_init(void) | 1510 | int __init acpiphp_glue_init(void) |
1588 | { | 1511 | { |
1589 | int num = 0; | 1512 | int num = 0; |
1590 | 1513 | ||
1591 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 1514 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
1592 | ACPI_UINT32_MAX, find_root_bridges, &num, NULL); | 1515 | ACPI_UINT32_MAX, find_root_bridges, &num, NULL); |
1593 | 1516 | ||
1594 | if (num <= 0) | 1517 | if (num <= 0) |
1595 | return -1; | 1518 | return -1; |
1596 | else | 1519 | else |
1597 | acpi_pci_register_driver(&acpi_pci_hp_driver); | 1520 | acpi_pci_register_driver(&acpi_pci_hp_driver); |
1598 | 1521 | ||
1599 | return 0; | 1522 | return 0; |
1600 | } | 1523 | } |
1601 | 1524 | ||
1602 | 1525 | ||
1603 | /** | 1526 | /** |
1604 | * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures | 1527 | * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures |
1605 | * | 1528 | * |
1606 | * This function frees all data allocated in acpiphp_glue_init(). | 1529 | * This function frees all data allocated in acpiphp_glue_init(). |
1607 | */ | 1530 | */ |
1608 | void acpiphp_glue_exit(void) | 1531 | void acpiphp_glue_exit(void) |
1609 | { | 1532 | { |
1610 | acpi_pci_unregister_driver(&acpi_pci_hp_driver); | 1533 | acpi_pci_unregister_driver(&acpi_pci_hp_driver); |
1611 | } | 1534 | } |
1612 | 1535 | ||
1613 | 1536 | ||
1614 | /** | 1537 | /** |
1615 | * acpiphp_get_num_slots - count number of slots in a system | 1538 | * acpiphp_get_num_slots - count number of slots in a system |
1616 | */ | 1539 | */ |
1617 | int __init acpiphp_get_num_slots(void) | 1540 | int __init acpiphp_get_num_slots(void) |
1618 | { | 1541 | { |
1619 | struct acpiphp_bridge *bridge; | 1542 | struct acpiphp_bridge *bridge; |
1620 | int num_slots = 0; | 1543 | int num_slots = 0; |
1621 | 1544 | ||
1622 | list_for_each_entry (bridge, &bridge_list, list) { | 1545 | list_for_each_entry (bridge, &bridge_list, list) { |
1623 | dbg("Bus %04x:%02x has %d slot%s\n", | 1546 | dbg("Bus %04x:%02x has %d slot%s\n", |
1624 | pci_domain_nr(bridge->pci_bus), | 1547 | pci_domain_nr(bridge->pci_bus), |
1625 | bridge->pci_bus->number, bridge->nr_slots, | 1548 | bridge->pci_bus->number, bridge->nr_slots, |
1626 | bridge->nr_slots == 1 ? "" : "s"); | 1549 | bridge->nr_slots == 1 ? "" : "s"); |
1627 | num_slots += bridge->nr_slots; | 1550 | num_slots += bridge->nr_slots; |
1628 | } | 1551 | } |
1629 | 1552 | ||
1630 | dbg("Total %d slots\n", num_slots); | 1553 | dbg("Total %d slots\n", num_slots); |
1631 | return num_slots; | 1554 | return num_slots; |
1632 | } | 1555 | } |
1633 | 1556 | ||
1634 | 1557 | ||
1635 | #if 0 | 1558 | #if 0 |
1636 | /** | 1559 | /** |
1637 | * acpiphp_for_each_slot - call function for each slot | 1560 | * acpiphp_for_each_slot - call function for each slot |
1638 | * @fn: callback function | 1561 | * @fn: callback function |
1639 | * @data: context to be passed to callback function | 1562 | * @data: context to be passed to callback function |
1640 | */ | 1563 | */ |
1641 | static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) | 1564 | static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) |
1642 | { | 1565 | { |
1643 | struct list_head *node; | 1566 | struct list_head *node; |
1644 | struct acpiphp_bridge *bridge; | 1567 | struct acpiphp_bridge *bridge; |
1645 | struct acpiphp_slot *slot; | 1568 | struct acpiphp_slot *slot; |
1646 | int retval = 0; | 1569 | int retval = 0; |
1647 | 1570 | ||
1648 | list_for_each (node, &bridge_list) { | 1571 | list_for_each (node, &bridge_list) { |
1649 | bridge = (struct acpiphp_bridge *)node; | 1572 | bridge = (struct acpiphp_bridge *)node; |
1650 | for (slot = bridge->slots; slot; slot = slot->next) { | 1573 | for (slot = bridge->slots; slot; slot = slot->next) { |
1651 | retval = fn(slot, data); | 1574 | retval = fn(slot, data); |
1652 | if (!retval) | 1575 | if (!retval) |
1653 | goto err_exit; | 1576 | goto err_exit; |
1654 | } | 1577 | } |
1655 | } | 1578 | } |
1656 | 1579 | ||
1657 | err_exit: | 1580 | err_exit: |
1658 | return retval; | 1581 | return retval; |
1659 | } | 1582 | } |
1660 | #endif | 1583 | #endif |
1661 | 1584 | ||
1662 | 1585 | ||
1663 | /** | 1586 | /** |
1664 | * acpiphp_enable_slot - power on slot | 1587 | * acpiphp_enable_slot - power on slot |
1665 | * @slot: ACPI PHP slot | 1588 | * @slot: ACPI PHP slot |
1666 | */ | 1589 | */ |
1667 | int acpiphp_enable_slot(struct acpiphp_slot *slot) | 1590 | int acpiphp_enable_slot(struct acpiphp_slot *slot) |
1668 | { | 1591 | { |
1669 | int retval; | 1592 | int retval; |
1670 | 1593 | ||
1671 | mutex_lock(&slot->crit_sect); | 1594 | mutex_lock(&slot->crit_sect); |
1672 | 1595 | ||
1673 | /* wake up all functions */ | 1596 | /* wake up all functions */ |
1674 | retval = power_on_slot(slot); | 1597 | retval = power_on_slot(slot); |
1675 | if (retval) | 1598 | if (retval) |
1676 | goto err_exit; | 1599 | goto err_exit; |
1677 | 1600 | ||
1678 | if (get_slot_status(slot) == ACPI_STA_ALL) { | 1601 | if (get_slot_status(slot) == ACPI_STA_ALL) { |
1679 | /* configure all functions */ | 1602 | /* configure all functions */ |
1680 | retval = enable_device(slot); | 1603 | retval = enable_device(slot); |
1681 | if (retval) | 1604 | if (retval) |
1682 | power_off_slot(slot); | 1605 | power_off_slot(slot); |
1683 | } else { | 1606 | } else { |
1684 | dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__); | 1607 | dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__); |
1685 | power_off_slot(slot); | 1608 | power_off_slot(slot); |
1686 | } | 1609 | } |
1687 | 1610 | ||
1688 | err_exit: | 1611 | err_exit: |
1689 | mutex_unlock(&slot->crit_sect); | 1612 | mutex_unlock(&slot->crit_sect); |
1690 | return retval; | 1613 | return retval; |
1691 | } | 1614 | } |
1692 | 1615 | ||
1693 | /** | 1616 | /** |
1694 | * acpiphp_disable_slot - power off slot | 1617 | * acpiphp_disable_slot - power off slot |
1695 | * @slot: ACPI PHP slot | 1618 | * @slot: ACPI PHP slot |
1696 | */ | 1619 | */ |
1697 | int acpiphp_disable_slot(struct acpiphp_slot *slot) | 1620 | int acpiphp_disable_slot(struct acpiphp_slot *slot) |
1698 | { | 1621 | { |
1699 | int retval = 0; | 1622 | int retval = 0; |
1700 | 1623 | ||
1701 | mutex_lock(&slot->crit_sect); | 1624 | mutex_lock(&slot->crit_sect); |
1702 | 1625 | ||
1703 | /* unconfigure all functions */ | 1626 | /* unconfigure all functions */ |
1704 | retval = disable_device(slot); | 1627 | retval = disable_device(slot); |
1705 | if (retval) | 1628 | if (retval) |
1706 | goto err_exit; | 1629 | goto err_exit; |
1707 | 1630 | ||
1708 | /* power off all functions */ | 1631 | /* power off all functions */ |
1709 | retval = power_off_slot(slot); | 1632 | retval = power_off_slot(slot); |
1710 | if (retval) | 1633 | if (retval) |
1711 | goto err_exit; | 1634 | goto err_exit; |
1712 | 1635 | ||
1713 | err_exit: | 1636 | err_exit: |
1714 | mutex_unlock(&slot->crit_sect); | 1637 | mutex_unlock(&slot->crit_sect); |
1715 | return retval; | 1638 | return retval; |
1716 | } | 1639 | } |
1717 | 1640 | ||
1718 | 1641 | ||
1719 | /* | 1642 | /* |
1720 | * slot enabled: 1 | 1643 | * slot enabled: 1 |
1721 | * slot disabled: 0 | 1644 | * slot disabled: 0 |
1722 | */ | 1645 | */ |
1723 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot) | 1646 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot) |
1724 | { | 1647 | { |
1725 | return (slot->flags & SLOT_POWEREDON); | 1648 | return (slot->flags & SLOT_POWEREDON); |
1726 | } | 1649 | } |
1727 | 1650 | ||
1728 | 1651 | ||
1729 | /* | 1652 | /* |
1730 | * latch open: 1 | 1653 | * latch open: 1 |
1731 | * latch closed: 0 | 1654 | * latch closed: 0 |
1732 | */ | 1655 | */ |
1733 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | 1656 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) |
1734 | { | 1657 | { |
1735 | unsigned int sta; | 1658 | unsigned int sta; |
1736 | 1659 | ||
1737 | sta = get_slot_status(slot); | 1660 | sta = get_slot_status(slot); |
1738 | 1661 | ||
1739 | return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1; | 1662 | return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1; |
1740 | } | 1663 | } |
1741 | 1664 | ||
1742 | 1665 | ||
1743 | /* | 1666 | /* |
1744 | * adapter presence : 1 | 1667 | * adapter presence : 1 |
1745 | * absence : 0 | 1668 | * absence : 0 |
1746 | */ | 1669 | */ |
1747 | u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot) | 1670 | u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot) |
1748 | { | 1671 | { |
1749 | unsigned int sta; | 1672 | unsigned int sta; |
1750 | 1673 | ||
1751 | sta = get_slot_status(slot); | 1674 | sta = get_slot_status(slot); |
1752 | 1675 | ||
1753 | return (sta == 0) ? 0 : 1; | 1676 | return (sta == 0) ? 0 : 1; |
1754 | } | 1677 | } |
1755 | 1678 |
include/linux/pci_hotplug.h
1 | /* | 1 | /* |
2 | * PCI HotPlug Core Functions | 2 | * PCI HotPlug Core Functions |
3 | * | 3 | * |
4 | * Copyright (C) 1995,2001 Compaq Computer Corporation | 4 | * Copyright (C) 1995,2001 Compaq Computer Corporation |
5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | 5 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) |
6 | * Copyright (C) 2001 IBM Corp. | 6 | * Copyright (C) 2001 IBM Corp. |
7 | * | 7 | * |
8 | * All rights reserved. | 8 | * All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or (at | 12 | * the Free Software Foundation; either version 2 of the License, or (at |
13 | * your option) any later version. | 13 | * your option) any later version. |
14 | * | 14 | * |
15 | * This program is distributed in the hope that it will be useful, but | 15 | * This program is distributed in the hope that it will be useful, but |
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
18 | * NON INFRINGEMENT. See the GNU General Public License for more | 18 | * NON INFRINGEMENT. See the GNU General Public License for more |
19 | * details. | 19 | * details. |
20 | * | 20 | * |
21 | * You should have received a copy of the GNU General Public License | 21 | * You should have received a copy of the GNU General Public License |
22 | * along with this program; if not, write to the Free Software | 22 | * along with this program; if not, write to the Free Software |
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
24 | * | 24 | * |
25 | * Send feedback to <kristen.c.accardi@intel.com> | 25 | * Send feedback to <kristen.c.accardi@intel.com> |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | #ifndef _PCI_HOTPLUG_H | 28 | #ifndef _PCI_HOTPLUG_H |
29 | #define _PCI_HOTPLUG_H | 29 | #define _PCI_HOTPLUG_H |
30 | 30 | ||
31 | 31 | ||
32 | /* These values come from the PCI Hotplug Spec */ | 32 | /* These values come from the PCI Hotplug Spec */ |
33 | enum pci_bus_speed { | 33 | enum pci_bus_speed { |
34 | PCI_SPEED_33MHz = 0x00, | 34 | PCI_SPEED_33MHz = 0x00, |
35 | PCI_SPEED_66MHz = 0x01, | 35 | PCI_SPEED_66MHz = 0x01, |
36 | PCI_SPEED_66MHz_PCIX = 0x02, | 36 | PCI_SPEED_66MHz_PCIX = 0x02, |
37 | PCI_SPEED_100MHz_PCIX = 0x03, | 37 | PCI_SPEED_100MHz_PCIX = 0x03, |
38 | PCI_SPEED_133MHz_PCIX = 0x04, | 38 | PCI_SPEED_133MHz_PCIX = 0x04, |
39 | PCI_SPEED_66MHz_PCIX_ECC = 0x05, | 39 | PCI_SPEED_66MHz_PCIX_ECC = 0x05, |
40 | PCI_SPEED_100MHz_PCIX_ECC = 0x06, | 40 | PCI_SPEED_100MHz_PCIX_ECC = 0x06, |
41 | PCI_SPEED_133MHz_PCIX_ECC = 0x07, | 41 | PCI_SPEED_133MHz_PCIX_ECC = 0x07, |
42 | PCI_SPEED_66MHz_PCIX_266 = 0x09, | 42 | PCI_SPEED_66MHz_PCIX_266 = 0x09, |
43 | PCI_SPEED_100MHz_PCIX_266 = 0x0a, | 43 | PCI_SPEED_100MHz_PCIX_266 = 0x0a, |
44 | PCI_SPEED_133MHz_PCIX_266 = 0x0b, | 44 | PCI_SPEED_133MHz_PCIX_266 = 0x0b, |
45 | PCI_SPEED_66MHz_PCIX_533 = 0x11, | 45 | PCI_SPEED_66MHz_PCIX_533 = 0x11, |
46 | PCI_SPEED_100MHz_PCIX_533 = 0x12, | 46 | PCI_SPEED_100MHz_PCIX_533 = 0x12, |
47 | PCI_SPEED_133MHz_PCIX_533 = 0x13, | 47 | PCI_SPEED_133MHz_PCIX_533 = 0x13, |
48 | PCI_SPEED_UNKNOWN = 0xff, | 48 | PCI_SPEED_UNKNOWN = 0xff, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | /* These values come from the PCI Express Spec */ | 51 | /* These values come from the PCI Express Spec */ |
52 | enum pcie_link_width { | 52 | enum pcie_link_width { |
53 | PCIE_LNK_WIDTH_RESRV = 0x00, | 53 | PCIE_LNK_WIDTH_RESRV = 0x00, |
54 | PCIE_LNK_X1 = 0x01, | 54 | PCIE_LNK_X1 = 0x01, |
55 | PCIE_LNK_X2 = 0x02, | 55 | PCIE_LNK_X2 = 0x02, |
56 | PCIE_LNK_X4 = 0x04, | 56 | PCIE_LNK_X4 = 0x04, |
57 | PCIE_LNK_X8 = 0x08, | 57 | PCIE_LNK_X8 = 0x08, |
58 | PCIE_LNK_X12 = 0x0C, | 58 | PCIE_LNK_X12 = 0x0C, |
59 | PCIE_LNK_X16 = 0x10, | 59 | PCIE_LNK_X16 = 0x10, |
60 | PCIE_LNK_X32 = 0x20, | 60 | PCIE_LNK_X32 = 0x20, |
61 | PCIE_LNK_WIDTH_UNKNOWN = 0xFF, | 61 | PCIE_LNK_WIDTH_UNKNOWN = 0xFF, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | enum pcie_link_speed { | 64 | enum pcie_link_speed { |
65 | PCIE_2_5GB = 0x14, | 65 | PCIE_2_5GB = 0x14, |
66 | PCIE_5_0GB = 0x15, | 66 | PCIE_5_0GB = 0x15, |
67 | PCIE_LNK_SPEED_UNKNOWN = 0xFF, | 67 | PCIE_LNK_SPEED_UNKNOWN = 0xFF, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use | 71 | * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use |
72 | * @owner: The module owner of this structure | 72 | * @owner: The module owner of this structure |
73 | * @mod_name: The module name (KBUILD_MODNAME) of this structure | 73 | * @mod_name: The module name (KBUILD_MODNAME) of this structure |
74 | * @enable_slot: Called when the user wants to enable a specific pci slot | 74 | * @enable_slot: Called when the user wants to enable a specific pci slot |
75 | * @disable_slot: Called when the user wants to disable a specific pci slot | 75 | * @disable_slot: Called when the user wants to disable a specific pci slot |
76 | * @set_attention_status: Called to set the specific slot's attention LED to | 76 | * @set_attention_status: Called to set the specific slot's attention LED to |
77 | * the specified value | 77 | * the specified value |
78 | * @hardware_test: Called to run a specified hardware test on the specified | 78 | * @hardware_test: Called to run a specified hardware test on the specified |
79 | * slot. | 79 | * slot. |
80 | * @get_power_status: Called to get the current power status of a slot. | 80 | * @get_power_status: Called to get the current power status of a slot. |
81 | * If this field is NULL, the value passed in the struct hotplug_slot_info | 81 | * If this field is NULL, the value passed in the struct hotplug_slot_info |
82 | * will be used when this value is requested by a user. | 82 | * will be used when this value is requested by a user. |
83 | * @get_attention_status: Called to get the current attention status of a slot. | 83 | * @get_attention_status: Called to get the current attention status of a slot. |
84 | * If this field is NULL, the value passed in the struct hotplug_slot_info | 84 | * If this field is NULL, the value passed in the struct hotplug_slot_info |
85 | * will be used when this value is requested by a user. | 85 | * will be used when this value is requested by a user. |
86 | * @get_latch_status: Called to get the current latch status of a slot. | 86 | * @get_latch_status: Called to get the current latch status of a slot. |
87 | * If this field is NULL, the value passed in the struct hotplug_slot_info | 87 | * If this field is NULL, the value passed in the struct hotplug_slot_info |
88 | * will be used when this value is requested by a user. | 88 | * will be used when this value is requested by a user. |
89 | * @get_adapter_status: Called to get see if an adapter is present in the slot or not. | 89 | * @get_adapter_status: Called to get see if an adapter is present in the slot or not. |
90 | * If this field is NULL, the value passed in the struct hotplug_slot_info | 90 | * If this field is NULL, the value passed in the struct hotplug_slot_info |
91 | * will be used when this value is requested by a user. | 91 | * will be used when this value is requested by a user. |
92 | * @get_max_bus_speed: Called to get the max bus speed for a slot. | 92 | * @get_max_bus_speed: Called to get the max bus speed for a slot. |
93 | * If this field is NULL, the value passed in the struct hotplug_slot_info | 93 | * If this field is NULL, the value passed in the struct hotplug_slot_info |
94 | * will be used when this value is requested by a user. | 94 | * will be used when this value is requested by a user. |
95 | * @get_cur_bus_speed: Called to get the current bus speed for a slot. | 95 | * @get_cur_bus_speed: Called to get the current bus speed for a slot. |
96 | * If this field is NULL, the value passed in the struct hotplug_slot_info | 96 | * If this field is NULL, the value passed in the struct hotplug_slot_info |
97 | * will be used when this value is requested by a user. | 97 | * will be used when this value is requested by a user. |
98 | * | 98 | * |
99 | * The table of function pointers that is passed to the hotplug pci core by a | 99 | * The table of function pointers that is passed to the hotplug pci core by a |
100 | * hotplug pci driver. These functions are called by the hotplug pci core when | 100 | * hotplug pci driver. These functions are called by the hotplug pci core when |
101 | * the user wants to do something to a specific slot (query it for information, | 101 | * the user wants to do something to a specific slot (query it for information, |
102 | * set an LED, enable / disable power, etc.) | 102 | * set an LED, enable / disable power, etc.) |
103 | */ | 103 | */ |
104 | struct hotplug_slot_ops { | 104 | struct hotplug_slot_ops { |
105 | struct module *owner; | 105 | struct module *owner; |
106 | const char *mod_name; | 106 | const char *mod_name; |
107 | int (*enable_slot) (struct hotplug_slot *slot); | 107 | int (*enable_slot) (struct hotplug_slot *slot); |
108 | int (*disable_slot) (struct hotplug_slot *slot); | 108 | int (*disable_slot) (struct hotplug_slot *slot); |
109 | int (*set_attention_status) (struct hotplug_slot *slot, u8 value); | 109 | int (*set_attention_status) (struct hotplug_slot *slot, u8 value); |
110 | int (*hardware_test) (struct hotplug_slot *slot, u32 value); | 110 | int (*hardware_test) (struct hotplug_slot *slot, u32 value); |
111 | int (*get_power_status) (struct hotplug_slot *slot, u8 *value); | 111 | int (*get_power_status) (struct hotplug_slot *slot, u8 *value); |
112 | int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); | 112 | int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); |
113 | int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); | 113 | int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); |
114 | int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); | 114 | int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); |
115 | int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); | 115 | int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); |
116 | int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); | 116 | int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); |
117 | }; | 117 | }; |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot | 120 | * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot |
121 | * @power: if power is enabled or not (1/0) | 121 | * @power: if power is enabled or not (1/0) |
122 | * @attention_status: if the attention light is enabled or not (1/0) | 122 | * @attention_status: if the attention light is enabled or not (1/0) |
123 | * @latch_status: if the latch (if any) is open or closed (1/0) | 123 | * @latch_status: if the latch (if any) is open or closed (1/0) |
124 | * @adapter_present: if there is a pci board present in the slot or not (1/0) | 124 | * @adapter_present: if there is a pci board present in the slot or not (1/0) |
125 | * @address: (domain << 16 | bus << 8 | dev) | 125 | * @address: (domain << 16 | bus << 8 | dev) |
126 | * | 126 | * |
127 | * Used to notify the hotplug pci core of the status of a specific slot. | 127 | * Used to notify the hotplug pci core of the status of a specific slot. |
128 | */ | 128 | */ |
129 | struct hotplug_slot_info { | 129 | struct hotplug_slot_info { |
130 | u8 power_status; | 130 | u8 power_status; |
131 | u8 attention_status; | 131 | u8 attention_status; |
132 | u8 latch_status; | 132 | u8 latch_status; |
133 | u8 adapter_status; | 133 | u8 adapter_status; |
134 | enum pci_bus_speed max_bus_speed; | 134 | enum pci_bus_speed max_bus_speed; |
135 | enum pci_bus_speed cur_bus_speed; | 135 | enum pci_bus_speed cur_bus_speed; |
136 | }; | 136 | }; |
137 | 137 | ||
138 | /** | 138 | /** |
139 | * struct hotplug_slot - used to register a physical slot with the hotplug pci core | 139 | * struct hotplug_slot - used to register a physical slot with the hotplug pci core |
140 | * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot | 140 | * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot |
141 | * @info: pointer to the &struct hotplug_slot_info for the initial values for | 141 | * @info: pointer to the &struct hotplug_slot_info for the initial values for |
142 | * this slot. | 142 | * this slot. |
143 | * @release: called during pci_hp_deregister to free memory allocated in a | 143 | * @release: called during pci_hp_deregister to free memory allocated in a |
144 | * hotplug_slot structure. | 144 | * hotplug_slot structure. |
145 | * @private: used by the hotplug pci controller driver to store whatever it | 145 | * @private: used by the hotplug pci controller driver to store whatever it |
146 | * needs. | 146 | * needs. |
147 | */ | 147 | */ |
148 | struct hotplug_slot { | 148 | struct hotplug_slot { |
149 | struct hotplug_slot_ops *ops; | 149 | struct hotplug_slot_ops *ops; |
150 | struct hotplug_slot_info *info; | 150 | struct hotplug_slot_info *info; |
151 | void (*release) (struct hotplug_slot *slot); | 151 | void (*release) (struct hotplug_slot *slot); |
152 | void *private; | 152 | void *private; |
153 | 153 | ||
154 | /* Variables below this are for use only by the hotplug pci core. */ | 154 | /* Variables below this are for use only by the hotplug pci core. */ |
155 | struct list_head slot_list; | 155 | struct list_head slot_list; |
156 | struct pci_slot *pci_slot; | 156 | struct pci_slot *pci_slot; |
157 | }; | 157 | }; |
158 | #define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) | 158 | #define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) |
159 | 159 | ||
160 | static inline const char *hotplug_slot_name(const struct hotplug_slot *slot) | 160 | static inline const char *hotplug_slot_name(const struct hotplug_slot *slot) |
161 | { | 161 | { |
162 | return pci_slot_name(slot->pci_slot); | 162 | return pci_slot_name(slot->pci_slot); |
163 | } | 163 | } |
164 | 164 | ||
165 | extern int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus, | 165 | extern int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus, |
166 | int nr, const char *name, | 166 | int nr, const char *name, |
167 | struct module *owner, const char *mod_name); | 167 | struct module *owner, const char *mod_name); |
168 | extern int pci_hp_deregister(struct hotplug_slot *slot); | 168 | extern int pci_hp_deregister(struct hotplug_slot *slot); |
169 | extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, | 169 | extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, |
170 | struct hotplug_slot_info *info); | 170 | struct hotplug_slot_info *info); |
171 | 171 | ||
172 | static inline int pci_hp_register(struct hotplug_slot *slot, | 172 | static inline int pci_hp_register(struct hotplug_slot *slot, |
173 | struct pci_bus *pbus, | 173 | struct pci_bus *pbus, |
174 | int devnr, const char *name) | 174 | int devnr, const char *name) |
175 | { | 175 | { |
176 | return __pci_hp_register(slot, pbus, devnr, name, | 176 | return __pci_hp_register(slot, pbus, devnr, name, |
177 | THIS_MODULE, KBUILD_MODNAME); | 177 | THIS_MODULE, KBUILD_MODNAME); |
178 | } | 178 | } |
179 | 179 | ||
180 | /* PCI Setting Record (Type 0) */ | 180 | /* PCI Setting Record (Type 0) */ |
181 | struct hpp_type0 { | 181 | struct hpp_type0 { |
182 | u32 revision; | 182 | u32 revision; |
183 | u8 cache_line_size; | 183 | u8 cache_line_size; |
184 | u8 latency_timer; | 184 | u8 latency_timer; |
185 | u8 enable_serr; | 185 | u8 enable_serr; |
186 | u8 enable_perr; | 186 | u8 enable_perr; |
187 | }; | 187 | }; |
188 | 188 | ||
189 | /* PCI-X Setting Record (Type 1) */ | 189 | /* PCI-X Setting Record (Type 1) */ |
190 | struct hpp_type1 { | 190 | struct hpp_type1 { |
191 | u32 revision; | 191 | u32 revision; |
192 | u8 max_mem_read; | 192 | u8 max_mem_read; |
193 | u8 avg_max_split; | 193 | u8 avg_max_split; |
194 | u16 tot_max_split; | 194 | u16 tot_max_split; |
195 | }; | 195 | }; |
196 | 196 | ||
197 | /* PCI Express Setting Record (Type 2) */ | 197 | /* PCI Express Setting Record (Type 2) */ |
198 | struct hpp_type2 { | 198 | struct hpp_type2 { |
199 | u32 revision; | 199 | u32 revision; |
200 | u32 unc_err_mask_and; | 200 | u32 unc_err_mask_and; |
201 | u32 unc_err_mask_or; | 201 | u32 unc_err_mask_or; |
202 | u32 unc_err_sever_and; | 202 | u32 unc_err_sever_and; |
203 | u32 unc_err_sever_or; | 203 | u32 unc_err_sever_or; |
204 | u32 cor_err_mask_and; | 204 | u32 cor_err_mask_and; |
205 | u32 cor_err_mask_or; | 205 | u32 cor_err_mask_or; |
206 | u32 adv_err_cap_and; | 206 | u32 adv_err_cap_and; |
207 | u32 adv_err_cap_or; | 207 | u32 adv_err_cap_or; |
208 | u16 pci_exp_devctl_and; | 208 | u16 pci_exp_devctl_and; |
209 | u16 pci_exp_devctl_or; | 209 | u16 pci_exp_devctl_or; |
210 | u16 pci_exp_lnkctl_and; | 210 | u16 pci_exp_lnkctl_and; |
211 | u16 pci_exp_lnkctl_or; | 211 | u16 pci_exp_lnkctl_or; |
212 | u32 sec_unc_err_sever_and; | 212 | u32 sec_unc_err_sever_and; |
213 | u32 sec_unc_err_sever_or; | 213 | u32 sec_unc_err_sever_or; |
214 | u32 sec_unc_err_mask_and; | 214 | u32 sec_unc_err_mask_and; |
215 | u32 sec_unc_err_mask_or; | 215 | u32 sec_unc_err_mask_or; |
216 | }; | 216 | }; |
217 | 217 | ||
218 | struct hotplug_params { | 218 | struct hotplug_params { |
219 | struct hpp_type0 *t0; /* Type0: NULL if not available */ | 219 | struct hpp_type0 *t0; /* Type0: NULL if not available */ |
220 | struct hpp_type1 *t1; /* Type1: NULL if not available */ | 220 | struct hpp_type1 *t1; /* Type1: NULL if not available */ |
221 | struct hpp_type2 *t2; /* Type2: NULL if not available */ | 221 | struct hpp_type2 *t2; /* Type2: NULL if not available */ |
222 | struct hpp_type0 type0_data; | 222 | struct hpp_type0 type0_data; |
223 | struct hpp_type1 type1_data; | 223 | struct hpp_type1 type1_data; |
224 | struct hpp_type2 type2_data; | 224 | struct hpp_type2 type2_data; |
225 | }; | 225 | }; |
226 | 226 | ||
227 | #ifdef CONFIG_ACPI | 227 | #ifdef CONFIG_ACPI |
228 | #include <acpi/acpi.h> | 228 | #include <acpi/acpi.h> |
229 | #include <acpi/acpi_bus.h> | 229 | #include <acpi/acpi_bus.h> |
230 | int acpi_get_hp_params_from_firmware(struct pci_dev *dev, | 230 | int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp); |
231 | struct hotplug_params *hpp); | ||
232 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags); | 231 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags); |
233 | int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle); | 232 | int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle); |
234 | int acpi_pci_detect_ejectable(acpi_handle handle); | 233 | int acpi_pci_detect_ejectable(acpi_handle handle); |
235 | #define pci_get_hp_params(dev, hpp) acpi_get_hp_params_from_firmware(dev, hpp) | ||
236 | #else | 234 | #else |
237 | static inline int pci_get_hp_params(struct pci_dev *dev, | 235 | static inline int pci_get_hp_params(struct pci_dev *dev, |
238 | struct hotplug_params *hpp) | 236 | struct hotplug_params *hpp) |
239 | { | 237 | { |
240 | return -ENODEV; | 238 | return -ENODEV; |
241 | } | 239 | } |
242 | #endif | 240 | #endif |
243 | 241 | ||
244 | void pci_configure_slot(struct pci_dev *dev); | 242 | void pci_configure_slot(struct pci_dev *dev); |
245 | #endif | 243 | #endif |
246 | 244 | ||
247 | 245 |