void * pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { int nasid, cnode, j; cnodeid_t near_cnode; struct hubdev_info *hubdev_info; struct pcibus_info *soft; struct sn_flush_device_kernel *sn_flush_device_kernel; struct sn_flush_device_common *common; if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { return NULL; } /* * Allocate kernel bus soft and copy from prom. */ soft = kmalloc(sizeof(struct pcibus_info), GFP_KERNEL); if (!soft) { return NULL; } memcpy(soft, prom_bussoft, sizeof(struct pcibus_info)); soft->pbi_buscommon.bs_base = (((u64) soft->pbi_buscommon. bs_base << 4) >> 4) | __IA64_UNCACHED_OFFSET; spin_lock_init(&soft->pbi_lock); /* * register the bridge's error interrupt handler */ if (request_irq(SGI_PCIASIC_ERROR, (void *)pcibr_error_intr_handler, IRQF_SHARED, "PCIBR error", (void *)(soft))) { printk(KERN_WARNING "pcibr cannot allocate interrupt for error handler\n"); } /* * Update the Bridge with the "kernel" pagesize */ if (PAGE_SIZE < 16384) { pcireg_control_bit_clr(soft, PCIBR_CTRL_PAGE_SIZE); } else { pcireg_control_bit_set(soft, PCIBR_CTRL_PAGE_SIZE); } nasid = NASID_GET(soft->pbi_buscommon.bs_base); cnode = nasid_to_cnodeid(nasid); hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); if (hubdev_info->hdi_flush_nasid_list.widget_p) { sn_flush_device_kernel = hubdev_info->hdi_flush_nasid_list. widget_p[(int)soft->pbi_buscommon.bs_xid]; if (sn_flush_device_kernel) { for (j = 0; j < DEV_PER_WIDGET; j++, sn_flush_device_kernel++) { common = sn_flush_device_kernel->common; if (common->sfdl_slot == -1) continue; if ((common->sfdl_persistent_segment == soft->pbi_buscommon.bs_persist_segment) && (common->sfdl_persistent_busnum == soft->pbi_buscommon.bs_persist_busnum)) common->sfdl_pcibus_info = soft; } } } /* Setup the PMU ATE map */ soft->pbi_int_ate_resource.lowest_free_index = 0; soft->pbi_int_ate_resource.ate = kzalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); if (!soft->pbi_int_ate_resource.ate) { kfree(soft); return NULL; } if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { /* TIO PCI Bridge: find nearest node with CPUs */ int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode); if (e < 0) { near_cnode = (cnodeid_t)-1; /* use any node */ printk(KERN_WARNING "pcibr_bus_fixup: failed to find " "near node with CPUs to TIO node %d, err=%d\n", cnode, e); } controller->node = near_cnode; } else controller->node = cnode; return soft; }
void * pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { int nasid, cnode, j; struct hubdev_info *hubdev_info; struct pcibus_info *soft; struct sn_flush_device_kernel *sn_flush_device_kernel; struct sn_flush_device_common *common; if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { return NULL; } /* * Allocate kernel bus soft and copy from prom. */ soft = kmalloc(sizeof(struct pcibus_info), GFP_KERNEL); if (!soft) { return NULL; } memcpy(soft, prom_bussoft, sizeof(struct pcibus_info)); soft->pbi_buscommon.bs_base = (unsigned long) ioremap(REGION_OFFSET(soft->pbi_buscommon.bs_base), sizeof(struct pic)); spin_lock_init(&soft->pbi_lock); /* * register the bridge's error interrupt handler */ if (request_irq(SGI_PCIASIC_ERROR, pcibr_error_intr_handler, IRQF_SHARED, "PCIBR error", (void *)(soft))) { printk(KERN_WARNING "pcibr cannot allocate interrupt for error handler\n"); } sn_set_err_irq_affinity(SGI_PCIASIC_ERROR); /* * Update the Bridge with the "kernel" pagesize */ if (PAGE_SIZE < 16384) { pcireg_control_bit_clr(soft, PCIBR_CTRL_PAGE_SIZE); } else { pcireg_control_bit_set(soft, PCIBR_CTRL_PAGE_SIZE); } nasid = NASID_GET(soft->pbi_buscommon.bs_base); cnode = nasid_to_cnodeid(nasid); hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); if (hubdev_info->hdi_flush_nasid_list.widget_p) { sn_flush_device_kernel = hubdev_info->hdi_flush_nasid_list. widget_p[(int)soft->pbi_buscommon.bs_xid]; if (sn_flush_device_kernel) { for (j = 0; j < DEV_PER_WIDGET; j++, sn_flush_device_kernel++) { common = sn_flush_device_kernel->common; if (common->sfdl_slot == -1) continue; if ((common->sfdl_persistent_segment == soft->pbi_buscommon.bs_persist_segment) && (common->sfdl_persistent_busnum == soft->pbi_buscommon.bs_persist_busnum)) common->sfdl_pcibus_info = soft; } } } /* Setup the PMU ATE map */ soft->pbi_int_ate_resource.lowest_free_index = 0; soft->pbi_int_ate_resource.ate = kzalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); if (!soft->pbi_int_ate_resource.ate) { kfree(soft); return NULL; } return soft; }
void * pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { int nasid, cnode, j; struct hubdev_info *hubdev_info; struct pcibus_info *soft; struct sn_flush_device_list *sn_flush_device_list; if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { return NULL; } /* * Allocate kernel bus soft and copy from prom. */ soft = kmalloc(sizeof(struct pcibus_info), GFP_KERNEL); if (!soft) { return NULL; } memcpy(soft, prom_bussoft, sizeof(struct pcibus_info)); soft->pbi_buscommon.bs_base = (((u64) soft->pbi_buscommon. bs_base << 4) >> 4) | __IA64_UNCACHED_OFFSET; spin_lock_init(&soft->pbi_lock); /* * register the bridge's error interrupt handler */ if (request_irq(SGI_PCIBR_ERROR, (void *)pcibr_error_intr_handler, SA_SHIRQ, "PCIBR error", (void *)(soft))) { printk(KERN_WARNING "pcibr cannot allocate interrupt for error handler\n"); } /* * Update the Bridge with the "kernel" pagesize */ if (PAGE_SIZE < 16384) { pcireg_control_bit_clr(soft, PCIBR_CTRL_PAGE_SIZE); } else { pcireg_control_bit_set(soft, PCIBR_CTRL_PAGE_SIZE); } nasid = NASID_GET(soft->pbi_buscommon.bs_base); cnode = nasid_to_cnodeid(nasid); hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); if (hubdev_info->hdi_flush_nasid_list.widget_p) { sn_flush_device_list = hubdev_info->hdi_flush_nasid_list. widget_p[(int)soft->pbi_buscommon.bs_xid]; if (sn_flush_device_list) { for (j = 0; j < DEV_PER_WIDGET; j++, sn_flush_device_list++) { if (sn_flush_device_list->sfdl_slot == -1) continue; if (sn_flush_device_list-> sfdl_persistent_busnum == soft->pbi_buscommon.bs_persist_busnum) sn_flush_device_list->sfdl_pcibus_info = soft; } } } /* Setup the PMU ATE map */ soft->pbi_int_ate_resource.lowest_free_index = 0; soft->pbi_int_ate_resource.ate = kmalloc(soft->pbi_int_ate_size * sizeof(uint64_t), GFP_KERNEL); memset(soft->pbi_int_ate_resource.ate, 0, (soft->pbi_int_ate_size * sizeof(uint64_t))); if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) /* * TIO PCI Bridge with no closest node information. * FIXME: Find another way to determine the closest node */ controller->node = -1; else controller->node = cnode; return soft; }
static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) { struct sn_irq_info *sn_irq_info, *sn_irq_info_safe; int cpuid, cpuphys; cpuid = first_cpu(mask); cpuphys = cpu_physical_id(cpuid); list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, sn_irq_lh[irq], list) { uint64_t bridge; int local_widget, status; nasid_t local_nasid; struct sn_irq_info *new_irq_info; new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); if (new_irq_info == NULL) break; memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); bridge = (uint64_t) new_irq_info->irq_bridge; if (!bridge) { kfree(new_irq_info); break; /* irq is not a device interrupt */ } local_nasid = NASID_GET(bridge); if (local_nasid & 1) local_widget = TIO_SWIN_WIDGETNUM(bridge); else local_widget = SWIN_WIDGETNUM(bridge); /* Free the old PROM new_irq_info structure */ sn_intr_free(local_nasid, local_widget, new_irq_info); /* Update kernels new_irq_info with new target info */ unregister_intr_pda(new_irq_info); /* allocate a new PROM new_irq_info struct */ status = sn_intr_alloc(local_nasid, local_widget, __pa(new_irq_info), irq, cpuid_to_nasid(cpuid), cpuid_to_slice(cpuid)); /* SAL call failed */ if (status) { kfree(new_irq_info); break; } new_irq_info->irq_cpuid = cpuid; register_intr_pda(new_irq_info); if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type)) pcibr_change_devices_irq(new_irq_info); spin_lock(&sn_irq_info_lock); list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); spin_unlock(&sn_irq_info_lock); call_rcu(&sn_irq_info->rcu, sn_irq_info_free); #ifdef CONFIG_SMP set_irq_affinity_info((irq & 0xff), cpuphys, 0); #endif }