Sun Aug 8 16:26:47 2010 UTC ()
acpi_pcidev_scan: discard invalid PCI addresses.


(gsutre)
diff -r1.12 -r1.13 src/sys/dev/acpi/acpi_pci.c

cvs diff -r1.12 -r1.13 src/sys/dev/acpi/acpi_pci.c (expand / switch to unified diff)

--- src/sys/dev/acpi/acpi_pci.c 2010/06/09 04:20:10 1.12
+++ src/sys/dev/acpi/acpi_pci.c 2010/08/08 16:26:47 1.13
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: acpi_pci.c,v 1.12 2010/06/09 04:20:10 mrg Exp $ */ 1/* $NetBSD: acpi_pci.c,v 1.13 2010/08/08 16:26:47 gsutre Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christoph Egger and Gregoire Sutre. 8 * by Christoph Egger and Gregoire Sutre.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -19,27 +19,27 @@ @@ -19,27 +19,27 @@
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE. 28 * SUCH DAMAGE.
29 */ 29 */
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.12 2010/06/09 04:20:10 mrg Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.13 2010/08/08 16:26:47 gsutre Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/device.h> 35#include <sys/device.h>
36#include <sys/kmem.h> 36#include <sys/kmem.h>
37#include <sys/systm.h> 37#include <sys/systm.h>
38 38
39#include <dev/pci/pcireg.h> 39#include <dev/pci/pcireg.h>
40#include <dev/pci/pcidevs.h> 40#include <dev/pci/pcidevs.h>
41#include <dev/pci/ppbreg.h> 41#include <dev/pci/ppbreg.h>
42 42
43#include <dev/acpi/acpireg.h> 43#include <dev/acpi/acpireg.h>
44#include <dev/acpi/acpivar.h> 44#include <dev/acpi/acpivar.h>
45#include <dev/acpi/acpi_pci.h> 45#include <dev/acpi/acpi_pci.h>
@@ -153,31 +153,31 @@ acpi_pcidev_pciroot_bus_callback(ACPI_RE @@ -153,31 +153,31 @@ acpi_pcidev_pciroot_bus_callback(ACPI_RE
153 * Scan the ACPI device tree for PCI devices. A node is detected as a 153 * Scan the ACPI device tree for PCI devices. A node is detected as a
154 * PCI device if it has an ancestor that is a PCI root bridge and such 154 * PCI device if it has an ancestor that is a PCI root bridge and such
155 * that all intermediate nodes are PCI-to-PCI bridges. Depth-first 155 * that all intermediate nodes are PCI-to-PCI bridges. Depth-first
156 * recursive implementation. 156 * recursive implementation.
157 */ 157 */
158ACPI_STATUS 158ACPI_STATUS
159acpi_pcidev_scan(struct acpi_devnode *ad) 159acpi_pcidev_scan(struct acpi_devnode *ad)
160{ 160{
161 struct acpi_devnode *child; 161 struct acpi_devnode *child;
162 struct acpi_pci_info *ap; 162 struct acpi_pci_info *ap;
163 ACPI_INTEGER val; 163 ACPI_INTEGER val;
164 ACPI_STATUS rv; 164 ACPI_STATUS rv;
165 165
 166 ad->ad_pciinfo = NULL;
 167
166 if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE || 168 if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE ||
167 !(ad->ad_devinfo->Valid & ACPI_VALID_ADR)) { 169 !(ad->ad_devinfo->Valid & ACPI_VALID_ADR))
168 ad->ad_pciinfo = NULL; 
169 goto rec; 170 goto rec;
170 } 
171 171
172 if (ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) { 172 if (ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) {
173 173
174 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP); 174 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
175 175
176 if (ap == NULL) 176 if (ap == NULL)
177 return AE_NO_MEMORY; 177 return AE_NO_MEMORY;
178 178
179 /* 179 /*
180 * If no _SEG exist, all PCI bus segments are assumed 180 * If no _SEG exist, all PCI bus segments are assumed
181 * to be in the PCI segment group 0 (ACPI 4.0, p. 277). 181 * to be in the PCI segment group 0 (ACPI 4.0, p. 277).
182 * The segment group number is conveyed in the lower 182 * The segment group number is conveyed in the lower
183 * 16 bits of _SEG (the other bits are all reserved). 183 * 16 bits of _SEG (the other bits are all reserved).
@@ -190,26 +190,34 @@ acpi_pcidev_scan(struct acpi_devnode *ad @@ -190,26 +190,34 @@ acpi_pcidev_scan(struct acpi_devnode *ad
190 /* Try to get bus number using _CRS first. */ 190 /* Try to get bus number using _CRS first. */
191 rv = acpi_pcidev_pciroot_bus(ad->ad_handle, &ap->ap_bus); 191 rv = acpi_pcidev_pciroot_bus(ad->ad_handle, &ap->ap_bus);
192 192
193 if (ACPI_FAILURE(rv)) { 193 if (ACPI_FAILURE(rv)) {
194 rv = acpi_eval_integer(ad->ad_handle, "_BBN", &val); 194 rv = acpi_eval_integer(ad->ad_handle, "_BBN", &val);
195 195
196 if (ACPI_SUCCESS(rv)) 196 if (ACPI_SUCCESS(rv))
197 ap->ap_bus = ACPI_LOWORD(val); 197 ap->ap_bus = ACPI_LOWORD(val);
198 } 198 }
199 199
200 ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address); 200 ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address);
201 ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address); 201 ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address);
202 202
 203 if (ap->ap_bus > 255 || ap->ap_device > 31 ||
 204 ap->ap_function > 7) {
 205 aprint_error_dev(ad->ad_root,
 206 "invalid PCI address for %s\n", ad->ad_name);
 207 kmem_free(ap, sizeof(*ap));
 208 goto rec;
 209 }
 210
203 ap->ap_bridge = true; 211 ap->ap_bridge = true;
204 ap->ap_downbus = ap->ap_bus; 212 ap->ap_downbus = ap->ap_bus;
205 213
206 ad->ad_pciinfo = ap; 214 ad->ad_pciinfo = ap;
207 215
208 goto rec; 216 goto rec;
209 } 217 }
210 218
211 if ((ad->ad_parent != NULL) && 219 if ((ad->ad_parent != NULL) &&
212 (ad->ad_parent->ad_pciinfo != NULL) && 220 (ad->ad_parent->ad_pciinfo != NULL) &&
213 (ad->ad_parent->ad_pciinfo->ap_bridge)) { 221 (ad->ad_parent->ad_pciinfo->ap_bridge)) {
214 222
215 /* 223 /*
@@ -218,26 +226,33 @@ acpi_pcidev_scan(struct acpi_devnode *ad @@ -218,26 +226,33 @@ acpi_pcidev_scan(struct acpi_devnode *ad
218 * our bus number is its downstream bus number. 226 * our bus number is its downstream bus number.
219 */ 227 */
220 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP); 228 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
221 229
222 if (ap == NULL) 230 if (ap == NULL)
223 return AE_NO_MEMORY; 231 return AE_NO_MEMORY;
224 232
225 ap->ap_segment = ad->ad_parent->ad_pciinfo->ap_segment; 233 ap->ap_segment = ad->ad_parent->ad_pciinfo->ap_segment;
226 ap->ap_bus = ad->ad_parent->ad_pciinfo->ap_downbus; 234 ap->ap_bus = ad->ad_parent->ad_pciinfo->ap_downbus;
227 235
228 ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address); 236 ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address);
229 ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address); 237 ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address);
230 238
 239 if (ap->ap_device > 31 || ap->ap_function > 7) {
 240 aprint_error_dev(ad->ad_root,
 241 "invalid PCI address for %s\n", ad->ad_name);
 242 kmem_free(ap, sizeof(*ap));
 243 goto rec;
 244 }
 245
231 /* 246 /*
232 * Check whether this device is a PCI-to-PCI 247 * Check whether this device is a PCI-to-PCI
233 * bridge and get its secondary bus number. 248 * bridge and get its secondary bus number.
234 */ 249 */
235 rv = acpi_pcidev_ppb_downbus(ap->ap_segment, ap->ap_bus, 250 rv = acpi_pcidev_ppb_downbus(ap->ap_segment, ap->ap_bus,
236 ap->ap_device, ap->ap_function, &ap->ap_downbus); 251 ap->ap_device, ap->ap_function, &ap->ap_downbus);
237 252
238 ap->ap_bridge = (rv != AE_OK) ? false : true; 253 ap->ap_bridge = (rv != AE_OK) ? false : true;
239 ad->ad_pciinfo = ap; 254 ad->ad_pciinfo = ap;
240 255
241 goto rec; 256 goto rec;
242 } 257 }
243 258
@@ -246,28 +261,28 @@ rec: @@ -246,28 +261,28 @@ rec:
246 rv = acpi_pcidev_scan(child); 261 rv = acpi_pcidev_scan(child);
247 262
248 if (ACPI_FAILURE(rv)) 263 if (ACPI_FAILURE(rv))
249 return rv; 264 return rv;
250 } 265 }
251 266
252 return AE_OK; 267 return AE_OK;
253} 268}
254 269
255/* 270/*
256 * acpi_pcidev_ppb_downbus: 271 * acpi_pcidev_ppb_downbus:
257 * 272 *
258 * Retrieve the secondary bus number of the PCI-to-PCI bridge having the 273 * Retrieve the secondary bus number of the PCI-to-PCI bridge having the
259 * given PCI id. If successful, return AE_OK and fill *busp. Otherwise, 274 * given PCI id. If successful, return AE_OK and fill *downbus.
260 * return an exception code and leave *busp unchanged. 275 * Otherwise, return an exception code and leave *downbus unchanged.
261 * 276 *
262 * XXX Need to deal with PCI segment groups (see also acpica/OsdHardware.c). 277 * XXX Need to deal with PCI segment groups (see also acpica/OsdHardware.c).
263 */ 278 */
264ACPI_STATUS 279ACPI_STATUS
265acpi_pcidev_ppb_downbus(uint16_t segment, uint16_t bus, uint16_t device, 280acpi_pcidev_ppb_downbus(uint16_t segment, uint16_t bus, uint16_t device,
266 uint16_t function, uint16_t *downbus) 281 uint16_t function, uint16_t *downbus)
267{ 282{
268 struct acpi_softc *sc = acpi_softc; 283 struct acpi_softc *sc = acpi_softc;
269 pci_chipset_tag_t pc; 284 pci_chipset_tag_t pc;
270 pcitag_t tag; 285 pcitag_t tag;
271 pcireg_t val; 286 pcireg_t val;
272 287
273 if (bus > 255 || device > 31 || function > 7) 288 if (bus > 255 || device > 31 || function > 7)