ml_iograph.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 771 行 · 第 1/2 页

C
771
字号
/* * 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-2003 Silicon Graphics, Inc. All rights reserved. */#include <linux/ctype.h>#include <asm/sn/sgi.h>#include <asm/sn/sn_sal.h>#include <asm/sn/iograph.h>#include <asm/sn/hcl.h>#include <asm/sn/hcl_util.h>#include <asm/sn/sn_private.h>#include <asm/sn/pci/pcibr_private.h>#include <asm/sn/xtalk/xtalkaddrs.h>#include <asm/sn/ksys/l1.h>/* #define IOGRAPH_DEBUG */#ifdef IOGRAPH_DEBUG#define DBG(x...) printk(x)#else#define DBG(x...)#endif /* IOGRAPH_DEBUG *//* 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 {	struct semaphore xswitch_volunteer_mutex;	int		xswitch_volunteer_count;	vertex_hdl_t	xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];} *xswitch_vol_t;voidxswitch_vertex_init(vertex_hdl_t xswitch){	xswitch_vol_t xvolinfo;	int rc;	xvolinfo = kmalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL);	if (!xvolinfo) {		printk(KERN_WARNING "xswitch_vertex_init(): Unable to "			"allocate memory\n");		return;	}       	memset(xvolinfo, 0, sizeof(struct xswitch_vol_s));	init_MUTEX(&xvolinfo->xswitch_volunteer_mutex);	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(vertex_hdl_t xswitch){	xswitch_vol_t xvolinfo;	int rc;	rc = hwgraph_info_remove_LBL(xswitch, 				INFO_LBL_XSWITCH_VOL,				(arbitrary_info_t *)&xvolinfo);	if (xvolinfo > 0)		kfree(xvolinfo);}/* * A Crosstalk master volunteers to manage xwidgets on the specified xswitch. *//* ARGSUSED */static voidvolunteer_for_widgets(vertex_hdl_t xswitch, vertex_hdl_t master){	xswitch_vol_t xvolinfo = NULL;	vertex_hdl_t hubv;	hubinfo_t hubinfo;	(void)hwgraph_info_get_LBL(xswitch, 				INFO_LBL_XSWITCH_VOL, 				(arbitrary_info_t *)&xvolinfo);	if (xvolinfo == NULL) {	    if (!is_headless_node_vertex(master)) {		    char name[MAXDEVNAME];		    printk(KERN_WARNING			"volunteer for widgets: vertex %s has no info label",			vertex_to_name(xswitch, name, MAXDEVNAME));	    }	    return;	}	down(&xvolinfo->xswitch_volunteer_mutex);	ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER);	xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master;	xvolinfo->xswitch_volunteer_count++;	/*	 * if dual ported, make the lowest widgetid always be 	 * xswitch_volunteer[0].	 */	if (xvolinfo->xswitch_volunteer_count == NUM_XSWITCH_VOLUNTEER) {		hubv = xvolinfo->xswitch_volunteer[0];		hubinfo_get(hubv, &hubinfo);		if (hubinfo->h_widgetid != XBOW_HUBLINK_LOW) {			xvolinfo->xswitch_volunteer[0] = 						xvolinfo->xswitch_volunteer[1];			xvolinfo->xswitch_volunteer[1] = hubv;		}	}	up(&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(vertex_hdl_t xswitch, vertex_hdl_t hubv){	xswitch_info_t xswitch_info;	xswitch_vol_t xvolinfo = NULL;	xwidgetnum_t widgetnum;	int num_volunteer;	nasid_t nasid;	hubinfo_t hubinfo;	extern int iobrick_type_get_nasid(nasid_t);	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) {	    if (!is_headless_node_vertex(hubv)) {		    char name[MAXDEVNAME];		    printk(KERN_WARNING			"assign_widgets_to_volunteers:vertex %s has "			" no info label",			vertex_to_name(xswitch, name, MAXDEVNAME));	    }	    return;	}	num_volunteer = xvolinfo->xswitch_volunteer_count;	ASSERT(num_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++) {		int i;		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_baseio_nasid_widget(nasid, widgetnum)) {			extern nasid_t snia_get_master_baseio_nasid(void);			for (i=0; i<num_volunteer; i++) {				hubv = xvolinfo->xswitch_volunteer[i];				hubinfo_get(hubv, &hubinfo);				nasid = hubinfo->h_nasid;				if (nasid == snia_get_master_baseio_nasid())					goto do_assignment;			}			printk("Nasid == %d, console nasid == %d",				nasid, snia_get_master_baseio_nasid());			nasid = 0;		}		/*		 * Assuming that we're dual-hosted and that PCI cards 		 * are naturally placed left-to-right, alternate PCI 		 * buses across both Cbricks.   For Pbricks, and Ibricks,                 * io_brick_map_widget() returns the PCI bus number                 * associated with the given brick type and widget number.                 * For Xbricks, it returns the XIO slot number.		 */		i = 0;		if (num_volunteer > 1) {                        int	       bt;                       	bt = iobrick_type_get_nasid(nasid);                        if (bt >= 0) {			        i = io_brick_map_widget(bt, widgetnum) & 1;                        }                }		hubv = xvolinfo->xswitch_volunteer[i];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);}/*  * 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(vertex_hdl_t hubv, xwidget_hwid_t hwid){	nasid_t nasid;	hubinfo_t hubinfo;	hubreg_t llp_csr_reg;	widgetreg_t widget_id;	int result = 0;	hwid->part_num = XWIDGET_PART_NUM_NONE;	hwid->rev_num = XWIDGET_REV_NUM_NONE;	hwid->mfg_num = XWIDGET_MFG_NUM_NONE;	hubinfo_get(hubv, &hubinfo);	nasid = hubinfo->h_nasid;	llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);	if (!(llp_csr_reg & IIO_LLP_CSR_IS_UP))		return;	/* Read the Cross-Talk Widget Id on the other end */	result = snia_badaddr_val((volatile void *)			(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID), 			4, (void *) &widget_id);	if (result == 0) { /* Found something connected */		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;	}}/* * io_xswitch_widget_init *	 */static voidio_xswitch_widget_init(vertex_hdl_t  	xswitchv,		       vertex_hdl_t	hubv,		       xwidgetnum_t	widgetnum){	xswitch_info_t		xswitch_info;	xwidgetnum_t		hub_widgetid;	vertex_hdl_t		widgetv;	cnodeid_t		cnode;	widgetreg_t		widget_id;	nasid_t			nasid, peer_nasid;	struct xwidget_hwid_s 	hwid;	hubinfo_t		hubinfo;	/*REFERENCED*/	int			rc;	char 			pathname[128];	lboard_t		*board = NULL;	char			buffer[16];	char			bt;	moduleid_t		io_module;	slotid_t get_widget_slotnum(int xbow, int widget);		DBG("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum);	/*	 * Verify that xswitchv is indeed an attached xswitch.	 */	xswitch_info = xswitch_info_get(xswitchv);	ASSERT(xswitch_info != NULL);	hubinfo_get(hubv, &hubinfo);	nasid = hubinfo->h_nasid;	cnode = nasid_to_cnodeid(nasid);	hub_widgetid = hubinfo->h_widgetid;	/*	 * Check that the widget is an io widget and is enabled	 * on this nasid or the `peer' nasid.  The peer nasid	 * is the other hub/bedrock connected to the xbow.	 */	peer_nasid = NODEPDA(cnode)->xbow_peer;	if (peer_nasid == INVALID_NASID)		/* If I don't have a peer, use myself. */		peer_nasid = nasid;	if (!xbow_port_io_enabled(nasid, widgetnum) &&	    !xbow_port_io_enabled(peer_nasid, widgetnum)) {		return;	}	if (xswitch_info_link_ok(xswitch_info, widgetnum)) {		char			name[4];		lboard_t dummy;		/*		 * If the current hub is not supposed to be the master 		 * for this widgetnum, then skip this widget.		 */		if (xswitch_info_master_assignment_get(xswitch_info,						       widgetnum) != hubv) {			return;		}		board = find_lboard_class_nasid( (lboard_t *)KL_CONFIG_INFO(nasid),				nasid, KLCLASS_IOBRICK);		if (!board && NODEPDA(cnode)->xbow_peer != INVALID_NASID) {		    	board = find_lboard_class_nasid(				(lboard_t *)KL_CONFIG_INFO( NODEPDA(cnode)->xbow_peer),					NODEPDA(cnode)->xbow_peer, KLCLASS_IOBRICK);		}		if (board) {			DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type);		} else {			DBG("io_xswitch_widget_init: FIXME did not find IOBOARD\n");			board = &dummy;		}		/* Copy over the nodes' geoid info */		{			lboard_t *brd;			brd = find_lboard_any((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);			if ( brd != (lboard_t *)0 ) {				board->brd_geoid = brd->brd_geoid;			}		}		/* 		 * Make sure we really want to say xbrick, pbrick,		 * etc. rather than XIO, graphics, etc. 		 */		memset(buffer, 0, 16);		format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF);		sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%s" "/%s/%d",			buffer,			geo_slab(board->brd_geoid),			(board->brd_type == KLTYPE_PXBRICK) ? EDGE_LBL_PXBRICK :			(board->brd_type == KLTYPE_IXBRICK) ? EDGE_LBL_IXBRICK :			(board->brd_type == KLTYPE_CGBRICK) ? EDGE_LBL_CGBRICK :

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?