static int handle_recv_skb()

in capi/capi.c [405:477]


static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
{
	unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data);
	struct tty_struct *tty;
	struct sk_buff *nskb;
	u16 errcode, datahandle;
	struct tty_ldisc *ld;
	int ret = -1;

	tty = tty_port_tty_get(&mp->port);
	if (!tty) {
		pr_debug("capi: currently no receiver\n");
		return -1;
	}

	ld = tty_ldisc_ref(tty);
	if (!ld) {
		/* fatal error, do not requeue */
		ret = 0;
		kfree_skb(skb);
		goto deref_tty;
	}

	if (ld->ops->receive_buf == NULL) {
		pr_debug("capi: ldisc has no receive_buf function\n");
		/* fatal error, do not requeue */
		goto free_skb;
	}
	if (mp->ttyinstop) {
		pr_debug("capi: recv tty throttled\n");
		goto deref_ldisc;
	}

	if (tty->receive_room < datalen) {
		pr_debug("capi: no room in tty\n");
		goto deref_ldisc;
	}

	nskb = gen_data_b3_resp_for(mp, skb);
	if (!nskb) {
		printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
		goto deref_ldisc;
	}

	datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4);

	errcode = capi20_put_message(mp->ap, nskb);

	if (errcode == CAPI_NOERROR) {
		skb_pull(skb, CAPIMSG_LEN(skb->data));
		pr_debug("capi: DATA_B3_RESP %u len=%d => ldisc\n",
			 datahandle, skb->len);
		ld->ops->receive_buf(tty, skb->data, NULL, skb->len);
	} else {
		printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
		       errcode);
		kfree_skb(nskb);

		if (errcode == CAPI_SENDQUEUEFULL)
			goto deref_ldisc;
	}

free_skb:
	ret = 0;
	kfree_skb(skb);

deref_ldisc:
	tty_ldisc_deref(ld);

deref_tty:
	tty_kref_put(tty);
	return ret;
}