📄 io_init.c
字号:
if (!pcidev_info) BUG(); /* Cannot afford to run out of memory */ sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); if (!sn_irq_info) BUG(); /* Cannot afford to run out of memory */ /* Call to retrieve pci device information needed by kernel. */ status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, dev->devfn, (u64) __pa(pcidev_info), (u64) __pa(sn_irq_info)); if (status) BUG(); /* Cannot get platform pci device information */ /* Add pcidev_info to list in sn_pci_controller struct */ list_add_tail(&pcidev_info->pdi_list, &(SN_PCI_CONTROLLER(dev->bus)->pcidev_info)); /* Copy over PIO Mapped Addresses */ for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { unsigned long start, end, addr; if (!pcidev_info->pdi_pio_mapped_addr[idx]) { pci_addrs[idx] = -1; continue; } start = dev->resource[idx].start; end = dev->resource[idx].end; size = end - start; if (size == 0) { pci_addrs[idx] = -1; continue; } pci_addrs[idx] = start; count++; addr = pcidev_info->pdi_pio_mapped_addr[idx]; addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; dev->resource[idx].start = addr; dev->resource[idx].end = addr + size;#ifndef XEN if (dev->resource[idx].flags & IORESOURCE_IO) dev->resource[idx].parent = &ioport_resource; else dev->resource[idx].parent = &iomem_resource;#endif } /* Create a pci_window in the pci_controller struct for * each device resource. */ if (count > 0) sn_pci_window_fixup(dev, count, pci_addrs); /* * Using the PROMs values for the PCI host bus, get the Linux * PCI host_pci_dev struct and set up host bus linkages */ bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff; devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff; host_pci_bus = pci_find_bus(segment, bus_no); host_pci_dev = pci_get_slot(host_pci_bus, devfn); pcidev_info->host_pci_dev = host_pci_dev; pcidev_info->pdi_linux_pcidev = dev; pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev); bs = SN_PCIBUS_BUSSOFT(dev->bus); pcidev_info->pdi_pcibus_info = bs; if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type]; } else { SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider; } /* Only set up IRQ stuff if this device has a host bus context */ if (bs && sn_irq_info->irq_irq) { pcidev_info->pdi_sn_irq_info = sn_irq_info; dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq; sn_irq_fixup(dev, sn_irq_info); } else { pcidev_info->pdi_sn_irq_info = NULL; kfree(sn_irq_info); }}#endif/* * sn_pci_controller_fixup() - This routine sets up a bus's resources * consistent with the Linux PCI abstraction layer. */void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus){ int status; int nasid, cnode; struct pci_controller *controller; struct sn_pci_controller *sn_controller; struct pcibus_bussoft *prom_bussoft_ptr; struct hubdev_info *hubdev_info; void *provider_soft; struct sn_pcibus_provider *provider; status = sal_get_pcibus_info((u64) segment, (u64) busnum, (u64) ia64_tpa(&prom_bussoft_ptr)); if (status > 0) return; /*bus # does not exist */ prom_bussoft_ptr = __va(prom_bussoft_ptr); /* Allocate a sn_pci_controller, which has a pci_controller struct * as the first member. */ sn_controller = kzalloc(sizeof(struct sn_pci_controller), GFP_KERNEL); if (!sn_controller) BUG(); INIT_LIST_HEAD(&sn_controller->pcidev_info); controller = &sn_controller->pci_controller; controller->segment = segment;#ifndef XEN if (bus == NULL) { bus = pci_scan_bus(busnum, &pci_root_ops, controller); if (bus == NULL) goto error_return; /* error, or bus already scanned */ bus->sysdata = NULL; } if (bus->sysdata) goto error_return; /* sysdata already alloc'd */ /* * Per-provider fixup. Copies the contents from prom to local * area and links SN_PCIBUS_BUSSOFT(). */ if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) goto error_return; /* unsupported asic type */ if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB) goto error_return; /* no further fixup necessary */#endif provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type]; if (provider == NULL) goto error_return; /* no provider registerd for this asic */ bus->sysdata = controller; if (provider->bus_fixup) provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller); else provider_soft = NULL; if (provider_soft == NULL) { /* fixup failed or not applicable */ bus->sysdata = NULL; goto error_return; } /* * Setup pci_windows for legacy IO and MEM space. * (Temporary until ACPI support is in place.) */ controller->window = kcalloc(2, sizeof(struct pci_window), GFP_KERNEL); if (controller->window == NULL) BUG(); controller->window[0].offset = prom_bussoft_ptr->bs_legacy_io; controller->window[0].resource.name = "legacy_io"; controller->window[0].resource.flags = IORESOURCE_IO; controller->window[0].resource.start = prom_bussoft_ptr->bs_legacy_io; controller->window[0].resource.end = controller->window[0].resource.start + 0xffff;#ifndef XEN controller->window[0].resource.parent = &ioport_resource;#endif controller->window[1].offset = prom_bussoft_ptr->bs_legacy_mem; controller->window[1].resource.name = "legacy_mem"; controller->window[1].resource.flags = IORESOURCE_MEM; controller->window[1].resource.start = prom_bussoft_ptr->bs_legacy_mem; controller->window[1].resource.end = controller->window[1].resource.start + (1024 * 1024) - 1;#ifndef XEN controller->window[1].resource.parent = &iomem_resource;#endif controller->windows = 2; /* * Generic bus fixup goes here. Don't reference prom_bussoft_ptr * after this point. */ PCI_CONTROLLER(bus)->platform_data = provider_soft; nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base); cnode = nasid_to_cnodeid(nasid); hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info = &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]); /* * If the node information we obtained during the fixup phase is invalid * then set controller->node to -1 (undetermined) */ if (controller->node >= num_online_nodes()) { struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus); printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u" "L_IO=%lx L_MEM=%lx BASE=%lx\n", b->bs_asic_type, b->bs_xid, b->bs_persist_busnum, b->bs_legacy_io, b->bs_legacy_mem, b->bs_base); printk(KERN_WARNING "on node %d but only %d nodes online." "Association set to undetermined.\n", controller->node, num_online_nodes()); controller->node = -1; } return;error_return: kfree(sn_controller); return;}#ifndef XENvoid sn_bus_store_sysdata(struct pci_dev *dev){ struct sysdata_el *element; element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL); if (!element) { dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__); return; } element->sysdata = SN_PCIDEV_INFO(dev); list_add(&element->entry, &sn_sysdata_list);}void sn_bus_free_sysdata(void){ struct sysdata_el *element; struct list_head *list, *safe; list_for_each_safe(list, safe, &sn_sysdata_list) { element = list_entry(list, struct sysdata_el, entry); list_del(&element->entry); list_del(&(((struct pcidev_info *) (element->sysdata))->pdi_list)); kfree(element->sysdata); kfree(element); } return;}#endif/* * Ugly hack to get PCI setup until we have a proper ACPI namespace. */#define PCI_BUSES_TO_SCAN 256static int __init sn_io_early_init(void){ int i, j;#ifndef XEN struct pci_dev *pci_dev = NULL;#endif if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) return 0; /* * prime sn_pci_provider[]. Individial provider init routines will * override their respective default entries. */ for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++) sn_pci_provider[i] = &sn_pci_default_provider;#ifndef XEN pcibr_init_provider(); tioca_init_provider(); tioce_init_provider();#endif /* * This is needed to avoid bounce limit checks in the blk layer */ ia64_max_iommu_merge_mask = ~PAGE_MASK;#ifndef XEN sn_fixup_ionodes();#endif sn_irq_lh_init(); INIT_LIST_HEAD(&sn_sysdata_list);#ifndef XEN sn_init_cpei_timer();#ifdef CONFIG_PROC_FS register_sn_procfs();#endif#endif /* busses are not known yet ... */ for (i = 0; i <= max_segment_number; i++) for (j = 0; j <= max_pcibus_number; j++) sn_pci_controller_fixup(i, j, NULL); /* * Generic Linux PCI Layer has created the pci_bus and pci_dev * structures - time for us to add our SN PLatform specific * information. */#ifndef XEN while ((pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL) sn_pci_fixup_slot(pci_dev);#endif sn_ioif_inited = 1; /* sn I/O infrastructure now initialized */ return 0;}/* * hubdev_init_node() - Creates the HUB data structure and link them to it's * own NODE specific data area. */void hubdev_init_node(nodepda_t * npda, cnodeid_t node){ struct hubdev_info *hubdev_info; int size;#ifndef XEN pg_data_t *pg;#else struct pglist_data *pg;#endif size = sizeof(struct hubdev_info); if (node >= num_online_nodes()) /* Headless/memless IO nodes */ pg = NODE_DATA(0); else pg = NODE_DATA(node); hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size); npda->pdinfo = (void *)hubdev_info;}geoid_tcnodeid_get_geoid(cnodeid_t cnode){ struct hubdev_info *hubdev; hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); return hubdev->hdi_geoid;}#ifndef XENvoid sn_generate_path(struct pci_bus *pci_bus, char *address){ nasid_t nasid; cnodeid_t cnode; geoid_t geoid; moduleid_t moduleid; u16 bricktype; nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base); cnode = nasid_to_cnodeid(nasid); geoid = cnodeid_get_geoid(cnode); moduleid = geo_module(geoid); snprintf(address, 15, "module_%c%c%c%c%.2d", '0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)), '0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)), '0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)), MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid)); /* Tollhouse requires slot id to be displayed */ bricktype = MODULE_GET_BTYPE(moduleid); if ((bricktype == L1_BRICKTYPE_191010) || (bricktype == L1_BRICKTYPE_1932)) snprintf(address, 15+8, "%s^%d", address, geo_slot(geoid));}#endif#ifdef XEN__initcall(sn_io_early_init);#elsesubsys_initcall(sn_io_early_init);#endif#ifndef XENEXPORT_SYMBOL(sn_pci_fixup_slot);EXPORT_SYMBOL(sn_pci_unfixup_slot);EXPORT_SYMBOL(sn_pci_controller_fixup);EXPORT_SYMBOL(sn_bus_store_sysdata);EXPORT_SYMBOL(sn_bus_free_sysdata);EXPORT_SYMBOL(sn_generate_path);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -