/** * 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; }
/* 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; }