📄 ml_iograph.c
字号:
/* $Id$ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. * Copyright (C) 2000 by Colin Ngam */#include <linux/types.h>#include <linux/config.h>#include <linux/slab.h>#include <linux/ctype.h>#include <asm/sn/sgi.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/hcl_util.h>#include <asm/sn/labelcl.h>#include <asm/sn/xtalk/xbow.h>#include <asm/sn/pci/bridge.h>#include <asm/sn/klconfig.h>#include <asm/sn/eeprom.h>#include <asm/sn/sn_private.h>#include <asm/sn/pci/pcibr.h>#include <asm/sn/xtalk/xtalk.h>#include <asm/sn/xtalk/xswitch.h>#include <asm/sn/xtalk/xwidget.h>#include <asm/sn/xtalk/xtalk_private.h>#include <asm/sn/xtalk/xtalkaddrs.h>extern int maxnodes;/* #define IOGRAPH_DEBUG */#ifdef IOGRAPH_DEBUG#define DBG(x...) printk(x)#else#define DBG(x...)#endif /* IOGRAPH_DEBUG *//* #define PROBE_TEST *//* At most 2 hubs can be connected to an xswitch */#define NUM_XSWITCH_VOLUNTEER 2/* * Track which hubs have volunteered to manage devices hanging off of * a Crosstalk Switch (e.g. xbow). This structure is allocated, * initialized, and hung off the xswitch vertex early on when the * xswitch vertex is created. */typedef struct xswitch_vol_s { mutex_t xswitch_volunteer_mutex; int xswitch_volunteer_count; devfs_handle_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];} *xswitch_vol_t;voidxswitch_vertex_init(devfs_handle_t xswitch){ xswitch_vol_t xvolinfo; int rc; xvolinfo = kmalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL); mutex_init(&xvolinfo->xswitch_volunteer_mutex); xvolinfo->xswitch_volunteer_count = 0; rc = hwgraph_info_add_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t)xvolinfo); ASSERT(rc == GRAPH_SUCCESS); rc = rc;}/* * When assignment of hubs to widgets is complete, we no longer need the * xswitch volunteer structure hanging around. Destroy it. */static voidxswitch_volunteer_delete(devfs_handle_t xswitch){ xswitch_vol_t xvolinfo; int rc; rc = hwgraph_info_remove_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo);#ifdef LATER ASSERT(rc == GRAPH_SUCCESS); rc = rc;#endif kfree(xvolinfo);}/* * A Crosstalk master volunteers to manage xwidgets on the specified xswitch. *//* ARGSUSED */static voidvolunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master){ xswitch_vol_t xvolinfo = NULL; (void)hwgraph_info_get_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) {#ifdef LATER if (!is_headless_node_vertex(master)) {#if defined(SUPPORT_PRINTING_V_FORMAT) PRINT_WARNING("volunteer for widgets: vertex %v has no info label", xswitch);#else PRINT_WARNING("volunteer for widgets: vertex 0x%x has no info label", xswitch);#endif }#endif /* LATER */ return; } mutex_lock(&xvolinfo->xswitch_volunteer_mutex); ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER); xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master; xvolinfo->xswitch_volunteer_count++; mutex_unlock(&xvolinfo->xswitch_volunteer_mutex);}extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum);/* * Assign all the xwidgets hanging off the specified xswitch to the * Crosstalk masters that have volunteered for xswitch duty. *//* ARGSUSED */static voidassign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv){ int curr_volunteer, num_volunteer; xwidgetnum_t widgetnum; xswitch_info_t xswitch_info; xswitch_vol_t xvolinfo = NULL; nasid_t nasid; hubinfo_t hubinfo; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; xswitch_info = xswitch_info_get(xswitch); ASSERT(xswitch_info != NULL); (void)hwgraph_info_get_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) {#ifdef LATER if (!is_headless_node_vertex(hubv)) {#if defined(SUPPORT_PRINTING_V_FORMAT) PRINT_WARNING("assign_widgets_to_volunteers:vertex %v has " " no info label", xswitch);#else PRINT_WARNING("assign_widgets_to_volunteers:vertex 0x%x has " " no info label", xswitch);#endif }#endif /* LATER */ return; } num_volunteer = xvolinfo->xswitch_volunteer_count; ASSERT(num_volunteer > 0); curr_volunteer = 0; /* Assign master hub for xswitch itself. */ if (HUB_WIDGET_ID_MIN > 0) { hubv = xvolinfo->xswitch_volunteer[0]; xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv); } /* * TBD: Use administrative information to alter assignment of * widgets to hubs. */ for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {#ifndef BRINGUP int i;#endif /* * Ignore disabled/empty ports. */ if (!xbow_port_io_enabled(nasid, widgetnum)) continue; /* * If this is the master IO board, assign it to the same * hub that owned it in the prom. */ if (is_master_nasid_widget(nasid, widgetnum)) { int i; for (i=0; i<num_volunteer; i++) { hubv = xvolinfo->xswitch_volunteer[i]; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; if (nasid == get_console_nasid()) goto do_assignment; }#ifdef LATER PRINT_PANIC("Nasid == %d, console nasid == %d", nasid, get_console_nasid());#endif } /* * Do a round-robin assignment among the volunteer nodes. */ hubv = xvolinfo->xswitch_volunteer[curr_volunteer]; curr_volunteer = (curr_volunteer + 1) % num_volunteer; /* fall through */do_assignment: /* * At this point, we want to make hubv the master of widgetnum. */ xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv); } xswitch_volunteer_delete(xswitch);}/* * Early iograph initialization. Called by master CPU in mlreset(). * Useful for including iograph.o in kernel.o. */voidiograph_early_init(void){/* * Need new way to get this information .. */ cnodeid_t cnode; nasid_t nasid; lboard_t *board; /* * Init. the board-to-hwgraph link early, so FRU analyzer * doesn't trip on leftover values if we panic early on. */ for(cnode = 0; cnode < numnodes; cnode++) { nasid = COMPACT_TO_NASID_NODEID(cnode); board = (lboard_t *)KL_CONFIG_INFO(nasid); DBG("iograph_early_init: Found board 0x%p\n", board); /* Check out all the board info stored on a node */ while(board) { board->brd_graph_link = GRAPH_VERTEX_NONE; board = KLCF_NEXT(board); DBG("iograph_early_init: Found board 0x%p\n", board); } } hubio_init();}#ifdef LATER/* There is an identical definition of this in os/scheduler/runq.c */#define INIT_COOKIE(cookie) cookie.must_run = 0; cookie.cpu = PDA_RUNANYWHERE/* * These functions absolutely doesn't belong here. It's here, though, * until the scheduler provides a platform-independent version * that works the way it should. The interface will definitely change, * too. Currently used only in this file and by io/cdl.c in order to * bind various I/O threads to a CPU on the proper node. */cpu_cookie_tsetnoderun(cnodeid_t cnodeid){ int i; cpuid_t cpunum; cpu_cookie_t cookie; INIT_COOKIE(cookie); if (cnodeid == CNODEID_NONE) return(cookie); /* * Do a setmustrun to one of the CPUs on the specified * node. */ if ((cpunum = CNODE_TO_CPU_BASE(cnodeid)) == CPU_NONE) { return(cookie); } cpunum += CNODE_NUM_CPUS(cnodeid) - 1; for (i = 0; i < CNODE_NUM_CPUS(cnodeid); i++, cpunum--) { if (cpu_enabled(cpunum)) { cookie = setmustrun(cpunum); break; } } return(cookie);}voidrestorenoderun(cpu_cookie_t cookie){ restoremustrun(cookie);}#endif /* LATER */#ifdef LINUX_KERNEL_THREADSstatic struct semaphore io_init_sema;#endif/* * Let boot processor know that we're done initializing our node's IO * and then exit. *//* ARGSUSED */static voidio_init_done(cnodeid_t cnodeid,cpu_cookie_t c){ /* Let boot processor know that we're done. */#ifdef LINUX_KERNEL_THREADS up(&io_init_sema);#endif#ifdef LATER /* This is for the setnoderun done when the io_init thread * started */ restorenoderun(c); sthread_exit();#endif}/* * Probe to see if this hub's xtalk link is active. If so, * return the Crosstalk Identification of the widget that we talk to. * This is called before any of the Crosstalk infrastructure for * this hub is set up. It's usually called on the node that we're * probing, but not always. * * TBD: Prom code should actually do this work, and pass through * hwid for our use. */static voidearly_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid){ hubreg_t llp_csr_reg; nasid_t nasid; hubinfo_t hubinfo; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); /* * If link is up, read the widget's part number. * A direct connect widget must respond to widgetnum=0. */ if (llp_csr_reg & IIO_LLP_CSR_IS_UP) { /* TBD: Put hub into "indirect" mode */ /* * We're able to read from a widget because our hub's * WIDGET_ID was set up earlier. */ widgetreg_t widget_id = *(volatile widgetreg_t *) (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); DBG("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id, (volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) ); hwid->part_num = XWIDGET_PART_NUM(widget_id); hwid->rev_num = XWIDGET_REV_NUM(widget_id); hwid->mfg_num = XWIDGET_MFG_NUM(widget_id); /* TBD: link reset */ } else { hwid->part_num = XWIDGET_PART_NUM_NONE; hwid->rev_num = XWIDGET_REV_NUM_NONE; hwid->mfg_num = XWIDGET_MFG_NUM_NONE; }}/* Add inventory information to the widget vertex * Right now (module,slot,revision) is being * added as inventory information. */static voidxwidget_inventory_add(devfs_handle_t widgetv, lboard_t *board, struct xwidget_hwid_s hwid){ if (!board) return; /* Donot add inventory information for the baseio * on a speedo with an xbox. It has already been * taken care of in SN00_vmc. * Speedo with xbox's baseio comes in at slot io1 (widget 9) */ device_inventory_add(widgetv,INV_IOBD,board->brd_type, board->brd_module, SLOTNUM_GETSLOT(board->brd_slot), hwid.rev_num);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -