⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xbow.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		else {			return 0;		}	}	else {		/* WAR: port 0xf on PIC is missing present bit */		/* Need this for PIC */		if (IS_PIC_XBOW(xbow->xb_wid_id) && port == 0xf) {			return 1;		}		return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT;	}}static intxbow_link_alive(xbow_t * xbow, int port){    xbwX_stat_t             xbow_linkstat;    xbow_linkstat.linkstatus = xbow->xb_link(port).link_status;    return (xbow_linkstat.link_alive);}/* * xbow_widget_lookup *      Lookup the edges connected to the xbow specified, and *      retrieve the handle corresponding to the widgetnum *      specified. *      If not found, return 0. */devfs_handle_txbow_widget_lookup(devfs_handle_t vhdl,		   int widgetnum){    xswitch_info_t          xswitch_info;    devfs_handle_t            conn;    xswitch_info = xswitch_info_get(vhdl);    conn = xswitch_info_vhdl_get(xswitch_info, widgetnum);    return conn;}/* * xbow_intr_preset: called during mlreset time * if the platform specific code needs to route * an xbow interrupt before the xtalk infrastructure * is available for use. * * Also called from xbow_setwidint, so we don't * replicate the guts of the routine. * * XXX- probably should be renamed xbow_wid_intr_set or * something to reduce confusion. *//*ARGSUSED3 */voidxbow_intr_preset(void *which_widget,		 int which_widget_intr,		 xwidgetnum_t targ,		 iopaddr_t addr,		 xtalk_intr_vector_t vect){    xbow_t                 *xbow = (xbow_t *) which_widget;    xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) |			      (0x000F0000 & (targ << 16)) |			      XTALK_ADDR_TO_UPPER(addr));    xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);}int                     xbow_xmit_retry_errors = 0;intxbow_xmit_retry_error(xbow_soft_t soft,		      int port){    xswitch_info_t          info;    devfs_handle_t            vhdl;    widget_cfg_t           *wid;    widgetreg_t             id;    int                     part;    int                     mfgr;    wid = soft->wpio[port - BASE_XBOW_PORT];    if (wid == NULL) {	/* If we can't track down a PIO	 * pointer to our widget yet,	 * leave our caller knowing that	 * we are interested in this	 * interrupt if it occurs in	 * the future.	 */	info = xswitch_info_get(soft->busv);	if (!info)	    return 1;	vhdl = xswitch_info_vhdl_get(info, port);	if (vhdl == GRAPH_VERTEX_NONE)	    return 1;	wid = (widget_cfg_t *) xtalk_piotrans_addr	    (vhdl, 0, 0, sizeof *wid, 0);	if (!wid)	    return 1;	soft->wpio[port - BASE_XBOW_PORT] = wid;    }    id = wid->w_id;    part = XWIDGET_PART_NUM(id);    mfgr = XWIDGET_MFG_NUM(id);    /* If this thing is not a Bridge,     * do not activate the WAR, and     * tell our caller we do not need     * to be called again.     */    if ((part != BRIDGE_WIDGET_PART_NUM) ||	(mfgr != BRIDGE_WIDGET_MFGR_NUM)) {		/* FIXME: add Xbridge to the WAR.		 * Shouldn't hurt anything.  Later need to		 * check if we can remove this.                 */    		if ((part != XBRIDGE_WIDGET_PART_NUM) ||		    (mfgr != XBRIDGE_WIDGET_MFGR_NUM))			return 0;    }    /* count how many times we     * have picked up after     * LLP Transmit problems.     */    xbow_xmit_retry_errors++;    /* rewrite the control register     * to fix things up.     */    wid->w_control = wid->w_control;    wid->w_control;    return 1;}voidxbow_update_perf_counters(devfs_handle_t vhdl){    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);    xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;    xbow_perf_link_t       *xbow_plink = xbow_soft->xbow_perflink;    xbow_perfcount_t        perf_reg;    unsigned long           s;    int                     link, i;    for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) {	if (xbow_perf->xp_mode == XBOW_MONITOR_NONE)	    continue;	s = mutex_spinlock(&xbow_soft->xbow_perf_lock);	perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;	link = perf_reg.xb_perf.link_select;	(xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] +=	    ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK);	xbow_perf->xp_current = perf_reg.xb_perf.count;	mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);    }}xbow_perf_link_t       *xbow_get_perf_counters(devfs_handle_t vhdl){    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);    xbow_perf_link_t       *xbow_perf_link = xbow_soft->xbow_perflink;    return xbow_perf_link;}intxbow_enable_perf_counter(devfs_handle_t vhdl, int link, int mode, int counter){    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);    xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;    xbow_linkctrl_t         xbow_link_ctrl;    xbow_t                 *xbow = xbow_soft->base;    xbow_perfcount_t        perf_reg;    unsigned long           s;    int                     i;    link -= BASE_XBOW_PORT;    if ((link < 0) || (link >= MAX_XBOW_PORTS))	return -1;    if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK))	return -1;    if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS))	return -1;    s = mutex_spinlock(&xbow_soft->xbow_perf_lock);    if ((xbow_perf + counter)->xp_mode && mode) {	mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);	return -1;    }    for (i = 0; i < XBOW_PERF_COUNTERS; i++) {	if (i == counter)	    continue;	if (((xbow_perf + i)->xp_link == link) &&	    ((xbow_perf + i)->xp_mode)) {	    mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);	    return -1;	}    }    xbow_perf += counter;    xbow_perf->xp_curlink = xbow_perf->xp_link = link;    xbow_perf->xp_curmode = xbow_perf->xp_mode = mode;    xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control;    xbow_link_ctrl.xb_linkcontrol.perf_mode = mode;    xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword;    perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;    perf_reg.xb_perf.link_select = link;    *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val;    xbow_perf->xp_current = perf_reg.xb_perf.count;    mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);    return 0;}xbow_link_status_t     *xbow_get_llp_status(devfs_handle_t vhdl){    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);    xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;    return xbow_llp_status;}voidxbow_update_llp_status(devfs_handle_t vhdl){    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);    xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;    xbow_t                 *xbow;    xbwX_stat_t             lnk_sts;    xbow_aux_link_status_t  aux_sts;    int                     link;    devfs_handle_t	    xwidget_vhdl;    char		   *xwidget_name;	    xbow = (xbow_t *) xbow_soft->base;    for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) {	/* Get the widget name corresponding the current link.	 * Note : 0 <= link < MAX_XBOW_PORTS(8).	 * 	  BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10)	 */	xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT);	xwidget_name = xwidget_name_get(xwidget_vhdl);	aux_sts.aux_linkstatus	    = xbow->xb_link_raw[link].link_aux_status;	lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr;	if (lnk_sts.link_alive == 0)	    continue;	xbow_llp_status->rx_err_count +=	    aux_sts.xb_aux_linkstatus.rx_err_cnt;	xbow_llp_status->tx_retry_count +=	    aux_sts.xb_aux_linkstatus.tx_retry_cnt;	if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) {#ifdef	LATER	    printk(KERN_WARNING  "link %d[%s]: bad status 0x%x\n",		    link, xwidget_name, lnk_sts.linkstatus);#endif	}    }}intxbow_disable_llp_monitor(devfs_handle_t vhdl){    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);    int                     port;    for (port = 0; port < MAX_XBOW_PORTS; port++) {	xbow_soft->xbow_link_status[port].rx_err_count = 0;	xbow_soft->xbow_link_status[port].tx_retry_count = 0;    }    xbow_soft->link_monitor = 0;    return 0;}intxbow_enable_llp_monitor(devfs_handle_t vhdl){    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);    xbow_soft->link_monitor = 1;    return 0;}intxbow_reset_link(devfs_handle_t xconn_vhdl){    xwidget_info_t          widget_info;    xwidgetnum_t            port;    xbow_t                 *xbow;    xbowreg_t               ctrl;    xbwX_stat_t             stat;    unsigned                itick;    unsigned                dtick;    static int              ticks_per_ms = 0;    if (!ticks_per_ms) {	itick = get_timestamp();	us_delay(1000);	ticks_per_ms = get_timestamp() - itick;    }    widget_info = xwidget_info_get(xconn_vhdl);    port = xwidget_info_id_get(widget_info);#ifdef XBOW_K1PTR			/* defined if we only have one xbow ... */    xbow = XBOW_K1PTR;#else    {	devfs_handle_t            xbow_vhdl;	xbow_soft_t             xbow_soft;	hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl);	xbow_soft = xbow_soft_get(xbow_vhdl);	xbow = xbow_soft->base;    }#endif    /*     * This requires three PIOs (reset the link, check for the     * reset, restore the control register for the link) plus     * 10us to wait for the reset. We allow up to 1ms for the     * widget to come out of reset before giving up and     * returning a failure.     */    ctrl = xbow->xb_link(port).link_control;    xbow->xb_link(port).link_reset = 0;    itick = get_timestamp();    while (1) {	stat.linkstatus = xbow->xb_link(port).link_status;	if (stat.link_alive)	    break;	dtick = get_timestamp() - itick;	if (dtick > ticks_per_ms) {	    return -1;			/* never came out of reset */	}	DELAY(2);			/* don't beat on link_status */    }    xbow->xb_link(port).link_control = ctrl;    return 0;}/* * Dump xbow registers. * input parameter is either a pointer to * the xbow chip or the vertex handle for * an xbow vertex. */voididbg_xbowregs(int64_t regs){    xbow_t                 *xbow;    int                     i;    xb_linkregs_t          *link;    xbow = (xbow_t *) regs;#ifdef LATER    qprintf("Printing xbow registers starting at 0x%x\n", xbow);    qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %x\n",	    xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper,	    xbow->xb_wid_err_lower, xbow->xb_wid_control,	    xbow->xb_wid_req_timeout);    qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %x\n",	    xbow->xb_wid_int_upper, xbow->xb_wid_int_lower,	    xbow->xb_wid_err_cmdword, xbow->xb_wid_llp,	    xbow->xb_wid_arb_reload);#endif    for (i = 8; i <= 0xf; i++) {	link = &xbow->xb_link(i);#ifdef LATER	qprintf("Link %d registers\n", i);	qprintf("\tctrl %x stat %x arbuppr %x arblowr %x auxstat %x\n",		link->link_control, link->link_status,		link->link_arb_upper, link->link_arb_lower,		link->link_aux_status);#endif    }}#define XBOW_ARB_RELOAD_TICKS		25					/* granularity: 4 MB/s, max: 124 MB/s */#define GRANULARITY			((100 * 1000000) / XBOW_ARB_RELOAD_TICKS)#define XBOW_BYTES_TO_GBR(BYTES_per_s)	(int) (BYTES_per_s / GRANULARITY)#define XBOW_GBR_TO_BYTES(cnt)		(bandwidth_t) ((cnt) * GRANULARITY)#define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec)	\			((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr)#define XBOW_ARB_GBR_MAX		31#define ABS(x)				((x > 0) ? (x) : (-1 * x))					/* absolute value */intxbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec){    int                     gbr_granted;    int                     new_total_gbr;    int                     change_gbr;    bandwidth_t             new_total_bw;#ifdef GRIO_DEBUG    printk("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lld\n",		old_bytes_per_sec, bytes_per_sec);#endif	/* GRIO_DEBUG */    gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)),			old_bytes_per_sec);    new_total_bw = old_bytes_per_sec + bytes_per_sec;    new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)),			new_total_bw);    change_gbr = new_total_gbr - gbr_granted;#ifdef GRIO_DEBUG    printk("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %d\n",		gbr_granted, new_total_gbr, change_gbr);#endif	/* GRIO_DEBUG */    return (change_gbr);}/* Conversion from GBR to bytes */bandwidth_txbow_gbr_to_bytes(int gbr){    return (XBOW_GBR_TO_BYTES(gbr));}/* Given the vhdl for the desired xbow, the src and dest. widget ids * and the req_bw value, this xbow driver entry point accesses the * xbow registers and allocates the desired bandwidth if available. * * If bandwidth allocation is successful, return success else return failure. */intxbow_prio_bw_alloc(devfs_handle_t vhdl,		xwidgetnum_t src_wid,		xwidgetnum_t dest_wid,		unsigned long long old_alloc_bw,		unsigned long long req_bw){    xbow_soft_t             soft = xbow_soft_get(vhdl);    volatile xbowreg_t     *xreg;    xbowreg_t               mask;    unsigned long           s;    int                     error = 0;    bandwidth_t             old_bw_BYTES, req_bw_BYTES;    xbowreg_t               old_xreg;    int                     old_bw_GBR, req_bw_GBR, new_bw_GBR;#ifdef GRIO_DEBUG    printk("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lld\n",		(int) vhdl, (int) src_wid, (int) dest_wid, req_bw);#endif    ASSERT(XBOW_WIDGET_IS_VALID(src_wid));    ASSERT(XBOW_WIDGET_IS_VALID(dest_wid));    s = mutex_spinlock(&soft->xbow_bw_alloc_lock);    /* Get pointer to the correct register */    xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid);    /* Get mask for GBR count value */    mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid);    req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw);    req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR)))		: xbow_gbr_to_bytes(req_bw_GBR);#ifdef GRIO_DEBUG    printk("req_bw %lld req_bw_BYTES %lld req_bw_GBR %d\n",		req_bw, req_bw_BYTES, req_bw_GBR);#endif	/* GRIO_DEBUG */    old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS];    old_xreg = *xreg;    old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid));#ifdef GRIO_DEBUG    ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR);    printk("old_bw_BYTES %lld old_bw_GBR %d\n", old_bw_BYTES, old_bw_GBR);    printk("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lld\n",		req_bw_BYTES, old_bw_BYTES,		soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]);	   #endif				/* GRIO_DEBUG */    /* Accept the request only if we don't exceed the destination     * port HIWATER_MARK *AND* the max. link GBR arbitration count     */    if (((old_bw_BYTES + req_bw_BYTES) <=		soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) &&		(req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) {	new_bw_GBR = (old_bw_GBR + req_bw_GBR);	/* Set this in the xbow link register */	*xreg = (old_xreg & ~mask) | \	    (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask);	soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] =			xbow_gbr_to_bytes(new_bw_GBR);    } else {	error = 1;    }    mutex_spinunlock(&soft->xbow_bw_alloc_lock, s);    return (error);}

⌨️ 快捷键说明

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