static void ctcmpc_chx_rx()

in net/ctcm_fsms.c [1372:1465]


static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
{
	struct channel		*ch = arg;
	struct net_device	*dev = ch->netdev;
	struct ctcm_priv	*priv = dev->ml_priv;
	struct mpc_group	*grp = priv->mpcg;
	struct sk_buff		*skb = ch->trans_skb;
	struct sk_buff		*new_skb;
	unsigned long		saveflags = 0;	/* avoids compiler warning */
	int len	= ch->max_bufsize - ch->irb->scsw.cmd.count;

	CTCM_PR_DEBUG("%s: %s: cp:%i %s maxbuf : %04x, len: %04x\n",
			CTCM_FUNTAIL, dev->name, smp_processor_id(),
				ch->id, ch->max_bufsize, len);
	fsm_deltimer(&ch->timer);

	if (skb == NULL) {
		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
			"%s(%s): TRANS_SKB = NULL",
				CTCM_FUNTAIL, dev->name);
			goto again;
	}

	if (len < TH_HEADER_LENGTH) {
		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
				"%s(%s): packet length %d to short",
					CTCM_FUNTAIL, dev->name, len);
		priv->stats.rx_dropped++;
		priv->stats.rx_length_errors++;
	} else {
		/* must have valid th header or game over */
		__u32	block_len = len;
		len = TH_HEADER_LENGTH + XID2_LENGTH + 4;
		new_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC);

		if (new_skb == NULL) {
			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
				"%s(%s): skb allocation failed",
						CTCM_FUNTAIL, dev->name);
			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
					goto again;
		}
		switch (fsm_getstate(grp->fsm)) {
		case MPCG_STATE_RESET:
		case MPCG_STATE_INOP:
			dev_kfree_skb_any(new_skb);
			break;
		case MPCG_STATE_FLOWC:
		case MPCG_STATE_READY:
			skb_put_data(new_skb, skb->data, block_len);
			skb_queue_tail(&ch->io_queue, new_skb);
			tasklet_schedule(&ch->ch_tasklet);
			break;
		default:
			skb_put_data(new_skb, skb->data, len);
			skb_queue_tail(&ch->io_queue, new_skb);
			tasklet_hi_schedule(&ch->ch_tasklet);
			break;
		}
	}

again:
	switch (fsm_getstate(grp->fsm)) {
	int rc, dolock;
	case MPCG_STATE_FLOWC:
	case MPCG_STATE_READY:
		if (ctcm_checkalloc_buffer(ch))
			break;
		ch->trans_skb->data = ch->trans_skb_data;
		skb_reset_tail_pointer(ch->trans_skb);
		ch->trans_skb->len = 0;
		ch->ccw[1].count = ch->max_bufsize;
			if (do_debug_ccw)
			ctcmpc_dumpit((char *)&ch->ccw[0],
					sizeof(struct ccw1) * 3);
		dolock = !in_hardirq();
		if (dolock)
			spin_lock_irqsave(
				get_ccwdev_lock(ch->cdev), saveflags);
		rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);
		if (dolock) /* see remark about conditional locking */
			spin_unlock_irqrestore(
				get_ccwdev_lock(ch->cdev), saveflags);
		if (rc != 0)
			ctcm_ccw_check_rc(ch, rc, "normal RX");
		break;
	default:
		break;
	}

	CTCM_PR_DEBUG("Exit %s: %s, ch=0x%p, id=%s\n",
			__func__, dev->name, ch, ch->id);

}