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

📄 xbow.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	XEM_ADD_VAR(wid_err_lower);	XEM_ADD_VAR(wid_err_addr);	XEM_ADD_VAR(port);	XEM_ADD_VAR(link_control);	XEM_ADD_VAR(link_status);	XEM_ADD_VAR(link_aux_status);#if !DEBUG    }#endif    /* caller will dump raw ioerror data     * in DEBUG and kdebug kernels.     */    return retval;}#endif	/* LATER */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);    }    /* Do port /mode multiplexing here */#ifdef LATER    (void) timeout(xbow_update_perf_counters,		   (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT);#endif}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;#ifdef LATER    (void) timeout(xbow_update_perf_counters,		   (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT);#endif    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	    PRINT_WARNING("link %d[%s]: bad status 0x%x\n",		    link, xwidget_name, lnk_sts.linkstatus);#endif	}    }#ifdef LATER    if (xbow_soft->link_monitor)	(void) timeout(xbow_update_llp_status,		       (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT);#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);#ifdef LATER    (void) timeout(xbow_update_llp_status,		   (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT);#endif    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;#ifdef LATER    if (dev_is_vertex((devfs_handle_t) regs)) {	devfs_handle_t            vhdl = (devfs_handle_t) regs;	xbow_soft_t             soft = xbow_soft_get(vhdl);	xbow = soft->base;    } else#endif    {	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    printf("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    printf("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    printf("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    printf("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);    printf("old_bw_BYTES %lld old_bw_GBR %d\n", old_bw_BYTES, old_bw_GBR);    printf("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 + -