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

📄 ctcmain.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||	    (ch->protocol != CTC_PROTO_S390))		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);	*((__u16 *) ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;	ch->ccw[1].count = 2;	/* Transfer only length */	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)		     ? CH_STATE_RXINIT : CH_STATE_TXINIT);	rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);	if (rc != 0) {		fsm_deltimer(&ch->timer);		fsm_newstate(fi, CH_STATE_SETUPWAIT);		ccw_check_return_code(ch, rc, "init IO");	}	/**	 * If in compatibility mode since we don磘 setup a timer, we	 * also signal RX channel up immediately. This enables us	 * to send packets early which in turn usually triggers some	 * reply from VM TCP which brings up the RX channel to it磗	 * final state.	 */	if ((CHANNEL_DIRECTION(ch->flags) == READ) &&	    (ch->protocol == CTC_PROTO_S390)) {		struct net_device *dev = ch->netdev;		fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXUP,			  dev);	}}/** * Got initial data, check it. If OK, * notify device statemachine that we are up and * running. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_rxidle(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	struct net_device *dev = ch->netdev;	__u16 buflen;	int rc;	DBF_TEXT(trace, 4, __FUNCTION__);	fsm_deltimer(&ch->timer);	buflen = *((__u16 *) ch->trans_skb->data);#ifdef DEBUG	ctc_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);#endif	if (buflen >= CTC_INITIAL_BLOCKLEN) {		if (ctc_checkalloc_buffer(ch, 1))			return;		ch->ccw[1].count = ch->max_bufsize;		fsm_newstate(fi, CH_STATE_RXIDLE);		rc = ccw_device_start(ch->cdev, &ch->ccw[0],				      (unsigned long) ch, 0xff, 0);		if (rc != 0) {			fsm_newstate(fi, CH_STATE_RXINIT);			ccw_check_return_code(ch, rc, "initial RX");		} else			fsm_event(((struct ctc_priv *) dev->priv)->fsm,				  DEV_EVENT_RXUP, dev);	} else {		ctc_pr_debug("%s: Initial RX count %d not %d\n",			     dev->name, buflen, CTC_INITIAL_BLOCKLEN);		ch_action_firstio(fi, event, arg);	}}/** * Set channel into extended mode. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_setmode(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	int rc;	unsigned long saveflags;	DBF_TEXT(trace, 4, __FUNCTION__);	fsm_deltimer(&ch->timer);	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);	fsm_newstate(fi, CH_STATE_SETUPWAIT);	saveflags = 0;	/* avoids compiler warning with			   spin_unlock_irqrestore */	if (event == CH_EVENT_TIMER)	// only for timer not yet locked		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);	rc = ccw_device_start(ch->cdev, &ch->ccw[6], (unsigned long) ch, 0xff, 0);	if (event == CH_EVENT_TIMER)		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);	if (rc != 0) {		fsm_deltimer(&ch->timer);		fsm_newstate(fi, CH_STATE_STARTWAIT);		ccw_check_return_code(ch, rc, "set Mode");	} else		ch->retry = 0;}/** * Setup channel. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_start(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	unsigned long saveflags;	int rc;	struct net_device *dev;	DBF_TEXT(trace, 4, __FUNCTION__);	if (ch == NULL) {		ctc_pr_warn("ch_action_start ch=NULL\n");		return;	}	if (ch->netdev == NULL) {		ctc_pr_warn("ch_action_start dev=NULL, id=%s\n", ch->id);		return;	}	dev = ch->netdev;#ifdef DEBUG	ctc_pr_debug("%s: %s channel start\n", dev->name,		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");#endif	if (ch->trans_skb != NULL) {		clear_normalized_cda(&ch->ccw[1]);		dev_kfree_skb(ch->trans_skb);		ch->trans_skb = NULL;	}	if (CHANNEL_DIRECTION(ch->flags) == READ) {		ch->ccw[1].cmd_code = CCW_CMD_READ;		ch->ccw[1].flags = CCW_FLAG_SLI;		ch->ccw[1].count = 0;	} else {		ch->ccw[1].cmd_code = CCW_CMD_WRITE;		ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;		ch->ccw[1].count = 0;	}	if (ctc_checkalloc_buffer(ch, 0)) {		ctc_pr_notice(			"%s: Could not allocate %s trans_skb, delaying "			"allocation until first transfer\n",			dev->name,			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");	}	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;	ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;	ch->ccw[0].count = 0;	ch->ccw[0].cda = 0;	ch->ccw[2].cmd_code = CCW_CMD_NOOP;	/* jointed CE + DE */	ch->ccw[2].flags = CCW_FLAG_SLI;	ch->ccw[2].count = 0;	ch->ccw[2].cda = 0;	memcpy(&ch->ccw[3], &ch->ccw[0], sizeof (struct ccw1) * 3);	ch->ccw[4].cda = 0;	ch->ccw[4].flags &= ~CCW_FLAG_IDA;	fsm_newstate(fi, CH_STATE_STARTWAIT);	fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);	if (rc != 0) {		if (rc != -EBUSY)		    fsm_deltimer(&ch->timer);		ccw_check_return_code(ch, rc, "initial HaltIO");	}#ifdef DEBUG	ctc_pr_debug("ctc: %s(): leaving\n", __func__);#endif}/** * Shutdown a channel. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_haltio(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	unsigned long saveflags;	int rc;	int oldstate;	DBF_TEXT(trace, 3, __FUNCTION__);	fsm_deltimer(&ch->timer);	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);	saveflags = 0;	/* avoids comp warning with			   spin_unlock_irqrestore */	if (event == CH_EVENT_STOP)	// only for STOP not yet locked		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);	oldstate = fsm_getstate(fi);	fsm_newstate(fi, CH_STATE_TERM);	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);	if (event == CH_EVENT_STOP)		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);	if (rc != 0) {		if (rc != -EBUSY) {		    fsm_deltimer(&ch->timer);		    fsm_newstate(fi, oldstate);		}		ccw_check_return_code(ch, rc, "HaltIO in ch_action_haltio");	}}/** * A channel has successfully been halted. * Cleanup it's queue and notify interface statemachine. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_stopped(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	struct net_device *dev = ch->netdev;	DBF_TEXT(trace, 3, __FUNCTION__);	fsm_deltimer(&ch->timer);	fsm_newstate(fi, CH_STATE_STOPPED);	if (ch->trans_skb != NULL) {		clear_normalized_cda(&ch->ccw[1]);		dev_kfree_skb(ch->trans_skb);		ch->trans_skb = NULL;	}	if (CHANNEL_DIRECTION(ch->flags) == READ) {		skb_queue_purge(&ch->io_queue);		fsm_event(((struct ctc_priv *) dev->priv)->fsm,			  DEV_EVENT_RXDOWN, dev);	} else {		ctc_purge_skb_queue(&ch->io_queue);		spin_lock(&ch->collect_lock);		ctc_purge_skb_queue(&ch->collect_queue);		ch->collect_len = 0;		spin_unlock(&ch->collect_lock);		fsm_event(((struct ctc_priv *) dev->priv)->fsm,			  DEV_EVENT_TXDOWN, dev);	}}/** * A stop command from device statemachine arrived and we are in * not operational mode. Set state to stopped. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_stop(fsm_instance * fi, int event, void *arg){	fsm_newstate(fi, CH_STATE_STOPPED);}/** * A machine check for no path, not operational status or gone device has * happened. * Cleanup queue and notify interface statemachine. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_fail(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	struct net_device *dev = ch->netdev;	DBF_TEXT(trace, 3, __FUNCTION__);	fsm_deltimer(&ch->timer);	fsm_newstate(fi, CH_STATE_NOTOP);	if (CHANNEL_DIRECTION(ch->flags) == READ) {		skb_queue_purge(&ch->io_queue);		fsm_event(((struct ctc_priv *) dev->priv)->fsm,			  DEV_EVENT_RXDOWN, dev);	} else {		ctc_purge_skb_queue(&ch->io_queue);		spin_lock(&ch->collect_lock);		ctc_purge_skb_queue(&ch->collect_queue);		ch->collect_len = 0;		spin_unlock(&ch->collect_lock);		fsm_event(((struct ctc_priv *) dev->priv)->fsm,			  DEV_EVENT_TXDOWN, dev);	}}/** * Handle error during setup of channel. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_setuperr(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	struct net_device *dev = ch->netdev;	DBF_TEXT(setup, 3, __FUNCTION__);	/**	 * Special case: Got UC_RCRESET on setmode.	 * This means that remote side isn't setup. In this case	 * simply retry after some 10 secs...	 */	if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&	    ((event == CH_EVENT_UC_RCRESET) ||	     (event == CH_EVENT_UC_RSRESET))) {		fsm_newstate(fi, CH_STATE_STARTRETRY);		fsm_deltimer(&ch->timer);		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);		if (CHANNEL_DIRECTION(ch->flags) == READ) {			int rc = ccw_device_halt(ch->cdev, (unsigned long) ch);			if (rc != 0)				ccw_check_return_code(					ch, rc, "HaltIO in ch_action_setuperr");		}		return;	}	ctc_pr_debug("%s: Error %s during %s channel setup state=%s\n",		     dev->name, ch_event_names[event],		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",		     fsm_getstate_str(fi));	if (CHANNEL_DIRECTION(ch->flags) == READ) {		fsm_newstate(fi, CH_STATE_RXERR);		fsm_event(((struct ctc_priv *) dev->priv)->fsm,			  DEV_EVENT_RXDOWN, dev);	} else {		fsm_newstate(fi, CH_STATE_TXERR);		fsm_event(((struct ctc_priv *) dev->priv)->fsm,			  DEV_EVENT_TXDOWN, dev);	}}/** * Restart a channel after an error. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_restart(fsm_instance * fi, int event, void *arg){	unsigned long saveflags;	int oldstate;	int rc;	struct channel *ch = (struct channel *) arg;	struct net_device *dev = ch->netdev;	DBF_TEXT(trace, 3, __FUNCTION__);	fsm_deltimer(&ch->timer);	ctc_pr_debug("%s: %s channel restart\n", dev->name,		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);	oldstate = fsm_getstate(fi);	fsm_newstate(fi, CH_STATE_STARTWAIT);	saveflags = 0;	/* avoids compiler warning with			   spin_unlock_irqrestore */	if (event == CH_EVENT_TIMER)	// only for timer not yet locked		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);	rc = ccw_device_halt(ch->cdev, (unsigned long) ch);	if (event == CH_EVENT_TIMER)		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);	if (rc != 0) {		if (rc != -EBUSY) {		    fsm_deltimer(&ch->timer);		    fsm_newstate(fi, oldstate);		}		ccw_check_return_code(ch, rc, "HaltIO in ch_action_restart");	}}/** * Handle error during RX initial handshake (exchange of * 0-length block header) * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_rxiniterr(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	struct net_device *dev = ch->netdev;	DBF_TEXT(setup, 3, __FUNCTION__);	if (event == CH_EVENT_TIMER) {		fsm_deltimer(&ch->timer);		ctc_pr_debug("%s: Timeout during RX init handshake\n", dev->name);		if (ch->retry++ < 3)			ch_action_restart(fi, event, arg);		else {			fsm_newstate(fi, CH_STATE_RXERR);			fsm_event(((struct ctc_priv *) dev->priv)->fsm,				  DEV_EVENT_RXDOWN, dev);		}	} else		ctc_pr_warn("%s: Error during RX init handshake\n", dev->name);}/** * Notify device statemachine if we gave up initialization * of RX channel. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_rxinitfail(fsm_instance * fi, int event, void *arg){	struct channel *ch = (struct channel *) arg;	struct net_device *dev = ch->netdev;	DBF_TEXT(setup, 3, __FUNCTION__);	fsm_newstate(fi, CH_STATE_RXERR);	ctc_pr_warn("%s: RX initialization failed\n", dev->name);	ctc_pr_warn("%s: RX <-> RX connection detected\n", dev->name);	fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);}/** * Handle RX Unit check remote reset (remote disconnected) * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static voidch_action_rxdisc(fsm_instance * fi, int event, void *arg)

⌨️ 快捷键说明

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