/** @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; }
/** @brief transmit a BOOT/DUMP data 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 (-EIO or -EBUSY) */ static int xmit_udl(struct mem_link_device *mld, enum sipc_ch_id ch, struct sk_buff *skb) { struct mem_ipc_device *dev = mld->dev[dev_id(ch)]; int ret = skb->len; unsigned long flags; spin_lock_irqsave(dev->tx_lock, flags); skb_queue_tail(dev->skb_txq, skb); start_tx_timer(mld, &mld->tx_timer); spin_unlock_irqrestore(dev->tx_lock, flags); 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 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 (-EIO or -EBUSY) */ static int xmit_ipc(struct mem_link_device *mld, enum sipc_ch_id ch, struct sk_buff *skb) { struct mem_ipc_device *dev = mld->dev[dev_id(ch)]; int ret; unsigned long flags; spin_lock_irqsave(dev->tx_lock, flags); ret = check_tx_link(mld, dev, skb); if (unlikely(ret < 0)) goto exit; skb_queue_tail(dev->skb_txq, skb); start_tx_timer(mld, &mld->tx_timer); exit: spin_unlock_irqrestore(dev->tx_lock, flags); return ret; }