/** @brief copy UDL data in an skb to a circular TXQ Enqueues a frame in @b @@skb to the @b @@dev TXQ if there is enough space in the TXQ, then releases @b @@skb. @param mld the pointer to a mem_link_device instance @param dev the pointer to a mem_ipc_device instance @param skb the pointer to an sk_buff instance @retval "> 0" the size of the frame written in the TXQ @retval "< 0" an error code (-EBUSY, -ENOSPC, or -EIO) */ static inline int udl_write(struct mem_link_device *mld, struct mem_ipc_device *dev, struct sk_buff *skb) { unsigned int count = skb->len; char *src = skb->data; char *dst = get_txq_buff(dev); unsigned int qsize = get_txq_buff_size(dev); unsigned int in = get_txq_head(dev); unsigned int out = get_txq_tail(dev); int space; space = check_udl_space(mld, dev, qsize, in, out, count); if (unlikely(space < 0)) return space; barrier(); circ_write(dst, src, qsize, in, count); barrier(); set_txq_head(dev, circ_new_ptr(qsize, in, count)); /* Commit the item before incrementing the head */ smp_mb(); return count; }
/** @brief take a snapshot of the current status of a memory interface Get a memory status and store the status data to @b @@mst @param mld the pointer to a mem_link_device instance @param dir the direction of a communication (TX or RX) @param[out] mst the pointer to a mem_status instance */ static void __take_mem_status(struct mem_link_device *mld, enum direction dir, struct mem_snapshot *mst) { int i; getnstimeofday(&mst->ts); mst->dir = dir; mst->magic = get_magic(mld); mst->access = get_access(mld); for (i = 0; i < MAX_SIPC5_DEVICES; i++) { struct mem_ipc_device *dev = mld->dev[i]; mst->head[i][TX] = get_txq_head(dev); mst->tail[i][TX] = get_txq_tail(dev); mst->head[i][RX] = get_rxq_head(dev); mst->tail[i][RX] = get_rxq_tail(dev); } if (mld->recv_cp2ap_irq) mst->int2ap = mld->recv_cp2ap_irq(mld); else mst->int2ap = 0; if (mld->read_ap2cp_irq) mst->int2cp = mld->read_ap2cp_irq(mld); else mst->int2cp = 0; }
/** @brief copy data in an skb to a circular TXQ Enqueues a frame in @b @@skb to the @b @@dev TXQ if there is enough space in the TXQ, then releases @b @@skb. @param mld the pointer to a mem_link_device instance @param dev the pointer to a mem_ipc_device instance @param skb the pointer to an sk_buff instance @retval "> 0" the size of the frame written in the TXQ @retval "< 0" an error code (-EBUSY, -ENOSPC, or -EIO) */ static int txq_write(struct mem_link_device *mld, struct mem_ipc_device *dev, struct sk_buff *skb) { char *src = skb->data; unsigned int count = skb->len; char *dst = get_txq_buff(dev); unsigned int qsize = get_txq_buff_size(dev); unsigned int in = get_txq_head(dev); unsigned int out = get_txq_tail(dev); int space; space = check_txq_space(mld, dev, qsize, in, out, count); if (unlikely(space < 0)) return space; #ifdef DEBUG_MODEM_IF_LINK_TX /* Record the time-stamp */ getnstimeofday(&skbpriv(skb)->ts); #endif circ_write(dst, src, qsize, in, count); set_txq_head(dev, circ_new_ptr(qsize, in, count)); /* Commit the item before incrementing the head */ smp_mb(); #ifdef DEBUG_MODEM_IF_LINK_TX if (likely(src)) log_ipc_pkt(sipc5_get_ch_id(src), LINK, TX, skb, true, true); #endif dev_kfree_skb_any(skb); return count; }