acpipci.c revision 1.10
1/* $OpenBSD: acpipci.c,v 1.10 2019/06/02 18:40:58 kettenis Exp $ */ 2/* 3 * Copyright (c) 2018 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <sys/param.h> 19#include <sys/device.h> 20#include <sys/extent.h> 21#include <sys/malloc.h> 22#include <sys/systm.h> 23 24#include <machine/bus.h> 25 26#include <dev/acpi/acpireg.h> 27#include <dev/acpi/acpivar.h> 28#include <dev/acpi/acpidev.h> 29#include <dev/acpi/amltypes.h> 30#include <dev/acpi/dsdt.h> 31 32#include <dev/pci/pcidevs.h> 33#include <dev/pci/pcireg.h> 34#include <dev/pci/pcivar.h> 35#include <dev/pci/ppbreg.h> 36 37struct acpipci_mcfg { 38 SLIST_ENTRY(acpipci_mcfg) am_list; 39 40 uint16_t am_segment; 41 uint8_t am_min_bus; 42 uint8_t am_max_bus; 43 44 bus_space_tag_t am_iot; 45 bus_space_handle_t am_ioh; 46 47 struct arm64_pci_chipset am_pc; 48}; 49 50struct acpipci_trans { 51 struct acpipci_trans *at_next; 52 bus_space_tag_t at_iot; 53 bus_addr_t at_base; 54 bus_size_t at_size; 55 bus_size_t at_offset; 56}; 57 58struct acpipci_softc { 59 struct device sc_dev; 60 struct acpi_softc *sc_acpi; 61 struct aml_node *sc_node; 62 bus_space_tag_t sc_iot; 63 pci_chipset_tag_t sc_pc; 64 65 struct bus_space sc_bus_iot; 66 struct bus_space sc_bus_memt; 67 struct acpipci_trans *sc_io_trans; 68 struct acpipci_trans *sc_mem_trans; 69 70 struct extent *sc_busex; 71 struct extent *sc_memex; 72 struct extent *sc_ioex; 73 char sc_busex_name[32]; 74 char sc_ioex_name[32]; 75 char sc_memex_name[32]; 76 int sc_bus; 77 uint32_t sc_seg; 78}; 79 80int acpipci_match(struct device *, void *, void *); 81void acpipci_attach(struct device *, struct device *, void *); 82 83struct cfattach acpipci_ca = { 84 sizeof(struct acpipci_softc), acpipci_match, acpipci_attach 85}; 86 87struct cfdriver acpipci_cd = { 88 NULL, "acpipci", DV_DULL 89}; 90 91const char *acpipci_hids[] = { 92 "PNP0A08", 93 NULL 94}; 95 96int acpipci_parse_resources(int, union acpi_resource *, void *); 97int acpipci_bs_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, 98 bus_space_handle_t *); 99 100void acpipci_attach_hook(struct device *, struct device *, 101 struct pcibus_attach_args *); 102int acpipci_bus_maxdevs(void *, int); 103pcitag_t acpipci_make_tag(void *, int, int, int); 104void acpipci_decompose_tag(void *, pcitag_t, int *, int *, int *); 105int acpipci_conf_size(void *, pcitag_t); 106pcireg_t acpipci_conf_read(void *, pcitag_t, int); 107void acpipci_conf_write(void *, pcitag_t, int, pcireg_t); 108 109int acpipci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 110const char *acpipci_intr_string(void *, pci_intr_handle_t); 111void *acpipci_intr_establish(void *, pci_intr_handle_t, int, 112 int (*)(void *), void *, char *); 113void acpipci_intr_disestablish(void *, void *); 114 115uint32_t acpipci_iort_map_msi(pci_chipset_tag_t, pcitag_t); 116 117int 118acpipci_match(struct device *parent, void *match, void *aux) 119{ 120 struct acpi_attach_args *aaa = aux; 121 struct cfdata *cf = match; 122 123 return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name); 124} 125 126void 127acpipci_attach(struct device *parent, struct device *self, void *aux) 128{ 129 struct acpi_attach_args *aaa = aux; 130 struct acpipci_softc *sc = (struct acpipci_softc *)self; 131 struct pcibus_attach_args pba; 132 struct aml_value res; 133 uint64_t bbn = 0; 134 uint64_t seg = 0; 135 136 sc->sc_acpi = (struct acpi_softc *)parent; 137 sc->sc_node = aaa->aaa_node; 138 printf(" %s", sc->sc_node->name); 139 140 if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { 141 printf(": can't find resources\n"); 142 return; 143 } 144 145 aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn); 146 sc->sc_bus = bbn; 147 148 aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg); 149 sc->sc_seg = seg; 150 151 sc->sc_iot = aaa->aaa_memt; 152 153 printf("\n"); 154 155 /* Create extents for our address spaces. */ 156 snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name), 157 "%s pcibus", sc->sc_dev.dv_xname); 158 snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name), 159 "%s pciio", sc->sc_dev.dv_xname); 160 snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name), 161 "%s pcimem", sc->sc_dev.dv_xname); 162 sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255, 163 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 164 sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff, 165 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 166 sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1, 167 M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 168 169 aml_parse_resource(&res, acpipci_parse_resources, sc); 170 171 memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot)); 172 sc->sc_bus_iot.bus_private = sc->sc_io_trans; 173 sc->sc_bus_iot._space_map = acpipci_bs_map; 174 memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt)); 175 sc->sc_bus_memt.bus_private = sc->sc_mem_trans; 176 sc->sc_bus_memt._space_map = acpipci_bs_map; 177 178 sc->sc_pc = pci_lookup_segment(seg); 179 KASSERT(sc->sc_pc->pc_intr_v == NULL); 180 181 sc->sc_pc->pc_intr_v = sc; 182 sc->sc_pc->pc_intr_map = acpipci_intr_map; 183 sc->sc_pc->pc_intr_map_msi = _pci_intr_map_msi; 184 sc->sc_pc->pc_intr_map_msix = _pci_intr_map_msix; 185 sc->sc_pc->pc_intr_string = acpipci_intr_string; 186 sc->sc_pc->pc_intr_establish = acpipci_intr_establish; 187 sc->sc_pc->pc_intr_disestablish = acpipci_intr_disestablish; 188 189 memset(&pba, 0, sizeof(pba)); 190 pba.pba_busname = "pci"; 191 pba.pba_iot = &sc->sc_bus_iot; 192 pba.pba_memt = &sc->sc_bus_memt; 193 pba.pba_dmat = aaa->aaa_dmat; 194 pba.pba_pc = sc->sc_pc; 195 pba.pba_busex = sc->sc_busex; 196 pba.pba_ioex = sc->sc_ioex; 197 pba.pba_memex = sc->sc_memex; 198 pba.pba_pmemex = sc->sc_memex; 199 pba.pba_domain = pci_ndomains++; 200 pba.pba_bus = sc->sc_bus; 201 pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 202 203 config_found(self, &pba, NULL); 204} 205 206int 207acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg) 208{ 209 struct acpipci_softc *sc = arg; 210 struct acpipci_trans *at; 211 int type = AML_CRSTYPE(crs); 212 int restype, tflags; 213 u_long min, len = 0, tra; 214 215 switch (type) { 216 case LR_WORD: 217 restype = crs->lr_word.type; 218 tflags = crs->lr_word.tflags; 219 min = crs->lr_word._min; 220 len = crs->lr_word._len; 221 tra = crs->lr_word._tra; 222 break; 223 case LR_DWORD: 224 restype = crs->lr_dword.type; 225 tflags = crs->lr_dword.tflags; 226 min = crs->lr_dword._min; 227 len = crs->lr_dword._len; 228 tra = crs->lr_dword._tra; 229 break; 230 case LR_QWORD: 231 restype = crs->lr_qword.type; 232 tflags = crs->lr_qword.tflags; 233 min = crs->lr_qword._min; 234 len = crs->lr_qword._len; 235 tra = crs->lr_qword._tra; 236 break; 237 } 238 239 if (len == 0) 240 return 0; 241 242 switch (restype) { 243 case LR_TYPE_MEMORY: 244 if (tflags & LR_MEMORY_TTP) 245 return 0; 246 extent_free(sc->sc_memex, min, len, EX_WAITOK); 247 at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK); 248 at->at_iot = sc->sc_iot; 249 at->at_base = min; 250 at->at_size = len; 251 at->at_offset = tra; 252 at->at_next = sc->sc_mem_trans; 253 sc->sc_mem_trans = at; 254 break; 255 case LR_TYPE_IO: 256 if ((tflags & LR_IO_TTP) == 0) 257 return 0; 258 extent_free(sc->sc_ioex, min, len, EX_WAITOK); 259 at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK); 260 at->at_iot = sc->sc_iot; 261 at->at_base = min; 262 at->at_size = len; 263 at->at_offset = tra; 264 at->at_next = sc->sc_io_trans; 265 sc->sc_io_trans = at; 266 break; 267 case LR_TYPE_BUS: 268 extent_free(sc->sc_busex, min, len, EX_WAITOK); 269 break; 270 } 271 272 return 0; 273} 274 275void 276acpipci_attach_hook(struct device *parent, struct device *self, 277 struct pcibus_attach_args *pba) 278{ 279} 280 281int 282acpipci_bus_maxdevs(void *v, int bus) 283{ 284 return 32; 285} 286 287pcitag_t 288acpipci_make_tag(void *v, int bus, int device, int function) 289{ 290 return ((bus << 20) | (device << 15) | (function << 12)); 291} 292 293void 294acpipci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 295{ 296 if (bp != NULL) 297 *bp = (tag >> 20) & 0xff; 298 if (dp != NULL) 299 *dp = (tag >> 15) & 0x1f; 300 if (fp != NULL) 301 *fp = (tag >> 12) & 0x7; 302} 303 304int 305acpipci_conf_size(void *v, pcitag_t tag) 306{ 307 return PCIE_CONFIG_SPACE_SIZE; 308} 309 310pcireg_t 311acpipci_conf_read(void *v, pcitag_t tag, int reg) 312{ 313 struct acpipci_mcfg *am = v; 314 315 if (tag < (am->am_min_bus << 20) || 316 tag >= ((am->am_max_bus + 1) << 20)) 317 return 0xffffffff; 318 319 return bus_space_read_4(am->am_iot, am->am_ioh, tag | reg); 320} 321 322void 323acpipci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 324{ 325 struct acpipci_mcfg *am = v; 326 327 if (tag < (am->am_min_bus << 20) || 328 tag >= ((am->am_max_bus + 1) << 20)) 329 return; 330 331 bus_space_write_4(am->am_iot, am->am_ioh, tag | reg, data); 332} 333 334int 335acpipci_intr_swizzle(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 336{ 337 int dev, swizpin; 338 339 if (pa->pa_bridgeih == NULL) 340 return -1; 341 342 pci_decompose_tag(pa->pa_pc, pa->pa_tag, NULL, &dev, NULL); 343 swizpin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, dev); 344 if (pa->pa_bridgeih[swizpin - 1].ih_type == PCI_NONE) 345 return -1; 346 347 *ihp = pa->pa_bridgeih[swizpin - 1]; 348 return 0; 349} 350 351int 352acpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 353{ 354 struct acpipci_softc *sc = pa->pa_pc->pc_intr_v; 355 struct aml_node *node = sc->sc_node; 356 struct aml_value res; 357 uint64_t addr, pin, source, index; 358 int i; 359 360 /* 361 * If we're behind a bridge, we need to look for a _PRT for 362 * it. If we don't find a _PRT, we need to swizzle. If we're 363 * not behind a bridge we need to look for a _PRT on the host 364 * bridge node itself. 365 */ 366 if (pa->pa_bridgetag) { 367 node = acpi_find_pci(pa->pa_pc, *pa->pa_bridgetag); 368 if (node == NULL) 369 return acpipci_intr_swizzle(pa, ihp); 370 } 371 372 if (aml_evalname(sc->sc_acpi, node, "_PRT", 0, NULL, &res)) 373 return acpipci_intr_swizzle(pa, ihp); 374 375 if (res.type != AML_OBJTYPE_PACKAGE) 376 return -1; 377 378 for (i = 0; i < res.length; i++) { 379 struct aml_value *val = res.v_package[i]; 380 381 if (val->type != AML_OBJTYPE_PACKAGE) 382 continue; 383 if (val->length != 4) 384 continue; 385 if (val->v_package[0]->type != AML_OBJTYPE_INTEGER || 386 val->v_package[1]->type != AML_OBJTYPE_INTEGER || 387 val->v_package[2]->type != AML_OBJTYPE_INTEGER || 388 val->v_package[3]->type != AML_OBJTYPE_INTEGER) 389 continue; 390 391 addr = val->v_package[0]->v_integer; 392 pin = val->v_package[1]->v_integer; 393 source = val->v_package[2]->v_integer; 394 index = val->v_package[3]->v_integer; 395 if (ACPI_ADR_PCIDEV(addr) != pa->pa_device || 396 ACPI_ADR_PCIFUN(addr) != 0xffff || 397 pin != pa->pa_intrpin - 1 || source != 0) 398 continue; 399 400 ihp->ih_pc = pa->pa_pc; 401 ihp->ih_tag = pa->pa_tag; 402 ihp->ih_intrpin = index; 403 ihp->ih_type = PCI_INTX; 404 405 return 0; 406 } 407 408 return -1; 409} 410 411const char * 412acpipci_intr_string(void *v, pci_intr_handle_t ih) 413{ 414 static char irqstr[32]; 415 416 switch (ih.ih_type) { 417 case PCI_MSI: 418 return "msi"; 419 case PCI_MSIX: 420 return "msix"; 421 } 422 423 snprintf(irqstr, sizeof(irqstr), "irq %d", ih.ih_intrpin); 424 return irqstr; 425} 426 427void * 428acpipci_intr_establish(void *v, pci_intr_handle_t ih, int level, 429 int (*func)(void *), void *arg, char *name) 430{ 431 struct acpipci_softc *sc = v; 432 struct interrupt_controller *ic; 433 void *cookie; 434 435 extern LIST_HEAD(, interrupt_controller) interrupt_controllers; 436 LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 437 if (ic->ic_establish_msi) 438 break; 439 } 440 if (ic == NULL) 441 return NULL; 442 443 KASSERT(ih.ih_type != PCI_NONE); 444 445 if (ih.ih_type != PCI_INTX) { 446 uint64_t addr, data; 447 448 /* Map Requester ID through IORT to get sideband data. */ 449 data = acpipci_iort_map_msi(ih.ih_pc, ih.ih_tag); 450 cookie = ic->ic_establish_msi(ic->ic_cookie, &addr, 451 &data, level, func, arg, name); 452 if (cookie == NULL) 453 return NULL; 454 455 /* TODO: translate address to the PCI device's view */ 456 457 if (ih.ih_type == PCI_MSIX) { 458 pci_msix_enable(ih.ih_pc, ih.ih_tag, 459 &sc->sc_bus_memt, ih.ih_intrpin, addr, data); 460 } else 461 pci_msi_enable(ih.ih_pc, ih.ih_tag, addr, data); 462 } else { 463 cookie = acpi_intr_establish(ih.ih_intrpin, 0, level, 464 func, arg, name); 465 } 466 467 return cookie; 468} 469 470void 471acpipci_intr_disestablish(void *v, void *cookie) 472{ 473 panic("%s", __func__); 474} 475 476/* 477 * Translate memory address if needed. 478 */ 479int 480acpipci_bs_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 481 int flags, bus_space_handle_t *bshp) 482{ 483 struct acpipci_trans *at; 484 485 for (at = t->bus_private; at; at = at->at_next) { 486 if (addr >= at->at_base && addr < at->at_base + at->at_size) { 487 return bus_space_map(at->at_iot, 488 addr + at->at_offset, size, flags, bshp); 489 } 490 } 491 492 return ENXIO; 493} 494 495SLIST_HEAD(,acpipci_mcfg) acpipci_mcfgs = 496 SLIST_HEAD_INITIALIZER(acpipci_mcfgs); 497 498void 499pci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int segment, 500 int min_bus, int max_bus) 501{ 502 struct acpipci_mcfg *am; 503 504 am = malloc(sizeof(struct acpipci_mcfg), M_DEVBUF, M_WAITOK | M_ZERO); 505 am->am_segment = segment; 506 am->am_min_bus = min_bus; 507 am->am_max_bus = max_bus; 508 509 am->am_iot = iot; 510 if (bus_space_map(iot, addr, (max_bus + 1) << 20, 0, &am->am_ioh)) 511 panic("%s: can't map config space", __func__); 512 513 am->am_pc.pc_conf_v = am; 514 am->am_pc.pc_attach_hook = acpipci_attach_hook; 515 am->am_pc.pc_bus_maxdevs = acpipci_bus_maxdevs; 516 am->am_pc.pc_make_tag = acpipci_make_tag; 517 am->am_pc.pc_decompose_tag = acpipci_decompose_tag; 518 am->am_pc.pc_conf_size = acpipci_conf_size; 519 am->am_pc.pc_conf_read = acpipci_conf_read; 520 am->am_pc.pc_conf_write = acpipci_conf_write; 521 SLIST_INSERT_HEAD(&acpipci_mcfgs, am, am_list); 522} 523 524pcireg_t 525acpipci_dummy_conf_read(void *v, pcitag_t tag, int reg) 526{ 527 return 0xffffffff; 528} 529 530void 531acpipci_dummy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 532{ 533} 534 535struct arm64_pci_chipset acpipci_dummy_chipset = { 536 .pc_attach_hook = acpipci_attach_hook, 537 .pc_bus_maxdevs = acpipci_bus_maxdevs, 538 .pc_make_tag = acpipci_make_tag, 539 .pc_decompose_tag = acpipci_decompose_tag, 540 .pc_conf_size = acpipci_conf_size, 541 .pc_conf_read = acpipci_dummy_conf_read, 542 .pc_conf_write = acpipci_dummy_conf_write, 543}; 544 545pci_chipset_tag_t 546pci_lookup_segment(int segment) 547{ 548 struct acpipci_mcfg *am; 549 550 SLIST_FOREACH(am, &acpipci_mcfgs, am_list) { 551 if (am->am_segment == segment) 552 return &am->am_pc; 553 } 554 555 return &acpipci_dummy_chipset; 556} 557 558/* 559 * IORT support. 560 */ 561 562struct acpi_iort { 563 struct acpi_table_header hdr; 564#define IORT_SIG "IORT" 565 uint32_t number_of_nodes; 566 uint32_t offset; 567 uint32_t reserved; 568} __packed; 569 570struct acpi_iort_node { 571 uint8_t type; 572#define ACPI_IORT_ITS 0 573#define ACPI_IORT_ROOT_COMPLEX 2 574 uint16_t length; 575 uint8_t revision; 576 uint32_t reserved1; 577 uint32_t number_of_mappings; 578 uint32_t mapping_offset; 579 uint64_t memory_access_properties; 580 uint32_t atf_attributes; 581 uint32_t segment; 582 uint8_t memory_address_size_limit; 583 uint8_t reserved2[3]; 584} __packed; 585 586struct acpi_iort_mapping { 587 uint32_t input_base; 588 uint32_t length; 589 uint32_t output_base; 590 uint32_t output_reference; 591 uint32_t flags; 592#define ACPI_IORT_MAPPING_SINGLE 0x00000001 593} __packed; 594 595uint32_t 596acpipci_iort_map_node(struct acpi_iort_node *node, uint32_t id, uint32_t reference) 597{ 598 struct acpi_iort_mapping *map = 599 (struct acpi_iort_mapping *)((char *)node + node->mapping_offset); 600 int i; 601 602 for (i = 0; i < node->number_of_mappings; i++) { 603 if (map[i].output_reference != reference) 604 continue; 605 606 if (map[i].flags & ACPI_IORT_MAPPING_SINGLE) 607 return map[i].output_base; 608 609 if (map[i].input_base <= id && 610 id < map[i].input_base + map[i].length) 611 return map[i].output_base + (id - map[i].input_base); 612 } 613 614 return id; 615} 616 617uint32_t 618acpipci_iort_map_msi(pci_chipset_tag_t pc, pcitag_t tag) 619{ 620 struct acpipci_softc *sc = pc->pc_intr_v; 621 struct acpi_table_header *hdr; 622 struct acpi_iort *iort = NULL; 623 struct acpi_iort_node *node; 624 struct acpi_q *entry; 625 uint32_t rid, its = 0; 626 uint32_t offset; 627 int i; 628 629 rid = pci_requester_id(pc, tag); 630 631 /* Look for IORT table. */ 632 SIMPLEQ_FOREACH(entry, &sc->sc_acpi->sc_tables, q_next) { 633 hdr = entry->q_table; 634 if (strncmp(hdr->signature, IORT_SIG, 635 sizeof(hdr->signature)) == 0) { 636 iort = entry->q_table; 637 break; 638 } 639 } 640 if (iort == NULL) 641 return rid; 642 643 /* Find reference to ITS group. */ 644 offset = iort->offset; 645 for (i = 0; i < iort->number_of_nodes; i++) { 646 node = (struct acpi_iort_node *)((char *)iort + offset); 647 switch (node->type) { 648 case ACPI_IORT_ITS: 649 its = offset; 650 break; 651 } 652 offset += node->length; 653 } 654 if (its == 0) 655 return rid; 656 657 /* Find our root complex and map. */ 658 offset = iort->offset; 659 for (i = 0; i < iort->number_of_nodes; i++) { 660 node = (struct acpi_iort_node *)((char *)iort + offset); 661 switch (node->type) { 662 case ACPI_IORT_ROOT_COMPLEX: 663 if (node->segment == sc->sc_seg) 664 return acpipci_iort_map_node(node, rid, its); 665 break; 666 } 667 offset += node->length; 668 } 669 670 return rid; 671} 672