Пример #1
0
/**
 * SIPC header_create() family functions
 *
 * Create SIPC5 header
 *
 * sipc5_hdr_create_skb()
 *	Create common SIPC5 header
 *
 * sipc5_hdr_create_legacy_rfs()
 *	Create SIPC5 header with IPC4.1 RFS header
 *	Because IMC modem used the 256KB rfs packet and RILD check the full
 *	packet with RFS header len, kernel remove the SIPC5 header and add the
 *	lagacy RFS header.
 *
 * sipc5_hdr_create_multifmt()
 *	TBD
 *
 * sipc5_hdr_create_skb_handover()
 *	Remove the ethernet frame When use `handover' with Network Bridge,
 *	user -> bridge device(rmnet0) -> real rmnet(xxxx_rmnet0) -> here.
 *	bridge device is ethernet device unlike xxxx_rmnet(net device).
 *	We remove the an ethernet header of skb before using skb->len,
 *	because bridge device added an ethernet header to skb.
 *
 * RETURN
 *	Returns the socket buffer that added SIPC5 header.
 *
 **/
static struct sk_buff *sipc5_hdr_create(struct io_device *iod,
				struct sipc_hdr *hdr, struct sk_buff *skb)
{
	struct sipc5_link_hdr *sipc5h;
	struct link_device *ld = get_current_link(iod);

	if (skb->len > 0xFFFF - SIPC5_HDR_LEN_MAX) {
		sipc5h = (struct sipc5_link_hdr *)
					skb_push(skb, SIPC5_HDR_LEN_EXT);
		sipc5h->cfg = SIPC5_HDR_CFG_START | SIPC5_HDR_EXT;
		*((u32 *)&sipc5h->len) = (u32)(skb->len);
	} else {
		sipc5h = (struct sipc5_link_hdr *)
					skb_push(skb, SIPC5_HDR_LEN);
		sipc5h->cfg = SIPC5_HDR_CFG_START;
		sipc5h->len = (u16)(skb->len);
	}
	sipc5h->ch = iod->id;

	/* Should check the alignment for dynamic switch link dev*/
	if (ld->aligned) {
		sipc5h->cfg |= SIPC5_HDR_PAD;
		skb_set_tail_pointer(skb, SIPC_ALIGN(skb->len));
		skb->len = SIPC_ALIGN(skb->len);
	}
	skbpriv(skb)->sipch = (void *)sipc5h;
	return skb;
}
Пример #2
0
/* TODO: not verified */
static struct sk_buff *sipc5_hdr_create_multifmt(struct io_device *iod,
				struct sipc_hdr *hdr, struct sk_buff *skb)
{
	struct sipc5_link_hdr *sipc5h;
	struct link_device *ld = get_current_link(iod);

	if (hdr->multifmt) {
		sipc5h = (struct sipc5_link_hdr *)
					skb_push(skb, SIPC5_HDR_LEN_CTRL);
		sipc5h->cfg = SIPC5_HDR_CFG_START | SIPC5_HDR_CONTROL;
		sipc5h->len = skb->len;
		sipc5h->ext.ctl = hdr->multifmt;
		sipc5h->ch = iod->id;

		/* Should check the alignment for dynamic switch link dev*/
		if (ld->aligned) {
			sipc5h->cfg |= SIPC5_HDR_PAD;
			skb_set_tail_pointer(skb, SIPC_ALIGN(skb->len));
			skb->len = SIPC_ALIGN(skb->len);
		}
		skbpriv(skb)->sipch = (void *)sipc5h;
		return skb;
	}
	return sipc5_hdr_create(iod, hdr, skb);
}
static struct sk_buff *sipc5_hdr_create_ipcloopback(struct io_device *iod,
				struct sipc_hdr *hdr, struct sk_buff *skb)
{
	struct sipc5_link_hdr *sipc5h;
	struct link_device *ld = get_current_link(iod);

	sipc5h = (struct sipc5_link_hdr *)
				skb_push(skb, SIPC5_HDR_LEN);
	sipc5h->cfg = SIPC5_HDR_CFG_START;
	sipc5h->len = (u16)(skb->len);

	mif_info("send ipcloopback data: %d\n", skb->len);
	sipc5h->ch = SIPC5_CH_ID_FMT_0;

	/* Should check the alignment for dynamic switch link dev*/
	if (ld->aligned) {
		sipc5h->cfg |= SIPC5_HDR_PAD;
		skb_set_tail_pointer(skb, SIPC_ALIGN(skb->len));
		skb->len = SIPC_ALIGN(skb->len);
	}
	skbpriv(skb)->sipch = (void *)sipc5h;
	return skb;
}