struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, nasid_t nasid, int slice) { int vector; int cpuid; #ifdef CONFIG_SMP int cpuphys; #endif int64_t bridge; int local_widget, status; nasid_t local_nasid; struct sn_irq_info *new_irq_info; struct sn_pcibus_provider *pci_provider; bridge = (u64) sn_irq_info->irq_bridge; if (!bridge) { return NULL; /* 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); vector = sn_irq_info->irq_irq; /* Make use of SAL_INTR_REDIRECT if PROM supports it */ status = sn_intr_redirect(local_nasid, local_widget, sn_irq_info, nasid, slice); if (!status) { new_irq_info = sn_irq_info; goto finish_up; } /* * PROM does not support SAL_INTR_REDIRECT, or it failed. * Revert to old method. */ new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); if (new_irq_info == NULL) return NULL; memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); /* Free the old PROM new_irq_info structure */ sn_intr_free(local_nasid, local_widget, new_irq_info); unregister_intr_pda(new_irq_info); /* allocate a new PROM new_irq_info struct */ status = sn_intr_alloc(local_nasid, local_widget, new_irq_info, vector, nasid, slice); /* SAL call failed */ if (status) { kfree(new_irq_info); return NULL; } register_intr_pda(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); finish_up: /* Update kernels new_irq_info with new target info */ cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid, new_irq_info->irq_slice); new_irq_info->irq_cpuid = cpuid; pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; /* * If this represents a line interrupt, target it. If it's * an msi (irq_int_bit < 0), it's already targeted. */ if (new_irq_info->irq_int_bit >= 0 && pci_provider && pci_provider->target_interrupt) (pci_provider->target_interrupt)(new_irq_info); #ifdef CONFIG_SMP cpuphys = cpu_physical_id(cpuid); set_irq_affinity_info((vector & 0xff), cpuphys, 0); #endif return new_irq_info; }
/* ARGSUSED */ static void __init klhwg_add_node(vertex_hdl_t hwgraph_root, cnodeid_t cnode) { nasid_t nasid; lboard_t *brd; klhub_t *hub; vertex_hdl_t node_vertex = NULL; char path_buffer[100]; int rv; char *s; int board_disabled = 0; klcpu_t *cpu; vertex_hdl_t cpu_dir; nasid = cnodeid_to_nasid(cnode); brd = find_lboard_any((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); ASSERT(brd); /* Generate a hardware graph path for this board. */ board_to_path(brd, path_buffer); rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex); if (rv != GRAPH_SUCCESS) { printk("Node vertex creation failed. Path == %s", path_buffer); return; } HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created path for SHUB node.\n"); hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); ASSERT(hub); if(hub->hub_info.flags & KLINFO_ENABLE) board_disabled = 0; else board_disabled = 1; if(!board_disabled) { mark_nodevertex_as_node(node_vertex, cnode); s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer)); NODEPDA(cnode)->hwg_node_name = kmalloc(strlen(s) + 1, GFP_KERNEL); if (NODEPDA(cnode)->hwg_node_name <= 0) { printk("%s: no memory\n", __FUNCTION__); return; } strcpy(NODEPDA(cnode)->hwg_node_name, s); hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo); NODEPDA(cnode)->slotdesc = brd->brd_slot; NODEPDA(cnode)->geoid = brd->brd_geoid; NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid)); klhwg_add_hub(node_vertex, hub, cnode); } /* * If there's at least 1 CPU, add a "cpu" directory to represent * the collection of all CPUs attached to this node. */ cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); if (cpu) { graph_error_t rv; rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir); if (rv != GRAPH_SUCCESS) { printk("klhwg_add_node: Cannot create CPU directory\n"); return; } HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, cpu_dir, NULL, "Created cpu directiry on SHUB node.\n"); } while (cpu) { cpuid_t cpu_id; cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid); if (cpu_online(cpu_id)) klhwg_add_cpu(node_vertex, cnode, cpu); else klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot); cpu = (klcpu_t *) find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU); } }