static void pass_skb_to_net(struct mem_link_device *mld, struct sk_buff *skb) { struct link_device *ld = &mld->link_dev; struct skbuff_private *priv; struct io_device *iod; int ret; priv = skbpriv(skb); if (unlikely(!priv)) { mif_err("%s: ERR! No PRIV in skb@%p\n", ld->name, skb); dev_kfree_skb_any(skb); modemctl_notify_event(MDM_CRASH_INVALID_SKBCB); return; } iod = priv->iod; if (unlikely(!iod)) { mif_err("%s: ERR! No IOD in skb@%p\n", ld->name, skb); dev_kfree_skb_any(skb); modemctl_notify_event(MDM_CRASH_INVALID_SKBIOD); return; } log_ipc_pkt(LNK_RX, iod->id, skb); ret = iod->recv_net_skb(iod, ld, skb); if (unlikely(ret < 0)) { struct modem_ctl *mc = ld->mc; mif_err_limited("%s: %s<-%s: ERR! %s->recv_net_skb fail (%d)\n", ld->name, iod->name, mc->name, iod->name, ret); dev_kfree_skb_any(skb); } }
static void pass_skb_to_net(struct mem_link_device *mld, struct sk_buff *skb) { struct link_device *ld = &mld->link_dev; struct skbuff_private *priv; struct io_device *iod; int ret; priv = skbpriv(skb); if (unlikely(!priv)) { mif_err("%s: ERR! No PRIV in skb@%p\n", ld->name, skb); dev_kfree_skb_any(skb); mem_forced_cp_crash(mld); return; } iod = priv->iod; if (unlikely(!iod)) { mif_err("%s: ERR! No IOD in skb@%p\n", ld->name, skb); dev_kfree_skb_any(skb); mem_forced_cp_crash(mld); return; } #if defined(DEBUG_MODEM_IF_LINK_RX) && defined(DEBUG_MODEM_IF_PS_DATA) log_ipc_pkt(iod->id, LINK, RX, skb, priv->lnk_hdr ? skb->data : NULL); #endif ret = iod->recv_net_skb(iod, ld, skb); if (unlikely(ret < 0)) { struct modem_ctl *mc = ld->mc; mif_err_limited("%s: %s<-%s: ERR! %s->recv_net_skb fail (%d)\n", ld->name, iod->name, mc->name, iod->name, ret); dev_kfree_skb_any(skb); } }
static void pass_skb_to_demux(struct mem_link_device *mld, struct sk_buff *skb) { struct link_device *ld = &mld->link_dev; struct io_device *iod = skbpriv(skb)->iod; int ret; u8 ch = skbpriv(skb)->sipc_ch; #ifdef DEBUG_MODEM_IF_LINK_RX u8 *hdr; #endif if (unlikely(!iod)) { mif_err("%s: ERR! No IOD for CH.%d\n", ld->name, ch); dev_kfree_skb_any(skb); mem_forced_cp_crash(mld); return; } #ifdef DEBUG_MODEM_IF_LINK_RX hdr = skbpriv(skb)->lnk_hdr ? skb->data : NULL; log_ipc_pkt(ch, LINK, RX, skb, hdr); #endif ret = iod->recv_skb_single(iod, ld, skb); if (unlikely(ret < 0)) { struct modem_ctl *mc = ld->mc; mif_err_limited("%s: %s<-%s: ERR! %s->recv_skb fail (%d)\n", ld->name, iod->name, mc->name, iod->name, ret); dev_kfree_skb_any(skb); } }
/** @brief transmit an IPC message packet @param mld the pointer to a mem_link_device instance @param ch the channel ID @param skb the pointer to an skb that will be transmitted @retval "> 0" the size of the data in @b @@skb @retval "< 0" an error code (-ENODEV, -EBUSY) */ static int xmit_ipc_to_rb(struct mem_link_device *mld, enum sipc_ch_id ch, struct sk_buff *skb) { int ret; struct link_device *ld = &mld->link_dev; struct io_device *iod = skbpriv(skb)->iod; struct modem_ctl *mc = ld->mc; struct sbd_ring_buffer *rb = sbd_ch2rb(&mld->sbd_link_dev, ch, TX); struct sk_buff_head *skb_txq; unsigned long flags; if (!rb) { mif_err("%s: %s->%s: ERR! NO SBD RB {ch:%d}\n", ld->name, iod->name, mc->name, ch); return -ENODEV; } skb_txq = &rb->skb_q; #ifdef CONFIG_LINK_POWER_MANAGEMENT if (cp_online(mc) && mld->forbid_cp_sleep) mld->forbid_cp_sleep(mld); #endif spin_lock_irqsave(&rb->lock, flags); if (unlikely(skb_txq->qlen >= MAX_SKB_TXQ_DEPTH)) { mif_err_limited("%s: %s->%s: ERR! {ch:%d} " "skb_txq.len %d >= limit %d\n", ld->name, iod->name, mc->name, ch, skb_txq->qlen, MAX_SKB_TXQ_DEPTH); ret = -EBUSY; } else { skb->len = min_t(int, skb->len, rb->buff_size); ret = skb->len; skb_queue_tail(skb_txq, skb); start_tx_timer(mld, &mld->sbd_tx_timer); #ifdef DEBUG_MODEM_IF trace_mif_event(skb, skb->len, FUNC); #endif } spin_unlock_irqrestore(&rb->lock, flags); #ifdef CONFIG_LINK_POWER_MANAGEMENT if (cp_online(mc) && mld->permit_cp_sleep) mld->permit_cp_sleep(mld); #endif return ret; }
static int xmit_ipc_to_dev(struct mem_link_device *mld, enum sipc_ch_id ch, struct sk_buff *skb) { int ret; struct link_device *ld = &mld->link_dev; struct io_device *iod = skbpriv(skb)->iod; struct modem_ctl *mc = ld->mc; struct mem_ipc_device *dev = mld->dev[dev_id(ch)]; struct sk_buff_head *skb_txq; unsigned long flags; if (!dev) { mif_err("%s: %s->%s: ERR! NO IPC DEV {ch:%d}\n", ld->name, iod->name, mc->name, ch); return -ENODEV; } skb_txq = dev->skb_txq; #ifdef CONFIG_LINK_POWER_MANAGEMENT if (cp_online(mc) && mld->forbid_cp_sleep) mld->forbid_cp_sleep(mld); #endif spin_lock_irqsave(dev->tx_lock, flags); if (unlikely(skb_txq->qlen >= MAX_SKB_TXQ_DEPTH)) { mif_err_limited("%s: %s->%s: ERR! %s TXQ.qlen %d >= limit %d\n", ld->name, iod->name, mc->name, dev->name, skb_txq->qlen, MAX_SKB_TXQ_DEPTH); ret = -EBUSY; } else { ret = skb->len; skb_queue_tail(dev->skb_txq, skb); start_tx_timer(mld, &mld->tx_timer); } spin_unlock_irqrestore(dev->tx_lock, flags); #ifdef CONFIG_LINK_POWER_MANAGEMENT if (cp_online(mc) && mld->permit_cp_sleep) mld->permit_cp_sleep(mld); #endif return ret; }
/** @brief check the free space in a SBD RB @param rb the pointer to an SBD RB instance @retval "> 0" the size of free space in the @b @@dev TXQ @retval "< 0" an error code */ static inline int check_rb_space(struct sbd_ring_buffer *rb, unsigned int qlen, unsigned int in, unsigned int out) { unsigned int space; if (!circ_valid(qlen, in, out)) { mif_err("ERR! TXQ[%d:%d] DIRTY (qlen:%d in:%d out:%d)\n", rb->id, rb->ch, qlen, in, out); return -EIO; } space = circ_get_space(qlen, in, out); if (unlikely(space < 1)) { mif_err_limited("TXQ[%d:%d] NOSPC (qlen:%d in:%d out:%d)\n", rb->id, rb->ch, qlen, in, out); return -ENOSPC; } return space; }
/** @brief pass a socket buffer to the DEMUX layer Invokes the recv_skb_single method in the io_device instance to perform receiving IPC messages from each skb. @param mld the pointer to a mem_link_device instance @param skb the pointer to an sk_buff instance @retval "> 0" if succeeded to pass an @b @@skb to the DEMUX layer @retval "< 0" an error code */ static void pass_skb_to_demux(struct mem_link_device *mld, struct sk_buff *skb) { struct link_device *ld = &mld->link_dev; struct io_device *iod = skbpriv(skb)->iod; int ret; u8 ch = skbpriv(skb)->sipc_ch; if (unlikely(!iod)) { mif_err("%s: ERR! No IOD for CH.%d\n", ld->name, ch); dev_kfree_skb_any(skb); modemctl_notify_event(MDM_CRASH_INVALID_IOD); return; } log_ipc_pkt(LNK_RX, ch, skb); ret = iod->recv_skb_single(iod, ld, skb); if (unlikely(ret < 0)) { struct modem_ctl *mc = ld->mc; mif_err_limited("%s: %s<-%s: ERR! %s->recv_skb fail (%d)\n", ld->name, iod->name, mc->name, iod->name, ret); dev_kfree_skb_any(skb); } }