static unsigned sipc5_get_pad_len(struct sipc5_link_hdr *hdr, unsigned len) { return (hdr->cfg & SIPC5_HDR_PAD) ? sipc5_calc_padding_size(len) : 0; }
/* ret < 0 : error ret == 0 : no data ret > 0 : valid data */ static int dpram_ipc_recv_data_with_skb(struct dpram_link_device *dpld, int dev) { struct link_device *ld = &dpld->ld; struct io_device *iod = dpld->iod[dev]; struct sk_buff *skb; u8 __iomem *src = get_rx_buff(dpld, dev); u32 qsize = get_rx_buff_size(dpld, dev); u32 in; u32 out; u32 rcvd; int rest; u8 *frm; u8 *dst; unsigned int len; unsigned int pad; unsigned int tot; struct mif_irq_map map; rcvd = dpram_get_rxq_rcvd(dpld, dev, qsize, &in, &out); if (rcvd <= 0) return rcvd; if (dev == IPC_FMT) { set_dpram_map(dpld, &map); mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv")); } rest = rcvd; while (rest > 0) { frm = src + out; if (unlikely(!sipc5_start_valid(frm[0]))) { mif_err("%s: ERR! %s invalid start 0x%02X\n", ld->name, get_dev_name(dev), frm[0]); skb_queue_purge(&dpld->skb_rxq[dev]); return -EBADMSG; } len = sipc5_get_frame_sz16(frm); if (unlikely(len > rest)) { mif_err("%s: ERR! %s len %d > rest %d\n", ld->name, get_dev_name(dev), len, rest); skb_queue_purge(&dpld->skb_rxq[dev]); return -EBADMSG; } pad = sipc5_calc_padding_size(len); tot = len + pad; /* Allocate an skb */ skb = dev_alloc_skb(tot); if (!skb) { mif_err("%s: ERR! %s dev_alloc_skb fail\n", ld->name, get_dev_name(dev)); return -ENOMEM; } /* Read data from each DPRAM buffer */ dst = skb_put(skb, tot); dpram_ipc_read(dpld, dev, dst, src, out, tot, qsize); skb_trim(skb, len); iod->recv_skb(iod, ld, skb); /* Calculate and set new out */ rest -= tot; out += tot; if (out >= qsize) out -= qsize; } set_rx_tail(dpld, dev, out); return rcvd; }