/** * msq_get_free_slot * @trq : pointer to an instance of mem_status_queue structure * * Succeeds always by dropping the oldest slot if a "msq" is full. */ struct mem_status *msq_get_free_slot(struct mem_status_queue *msq) { int qsize = MAX_MEM_LOG_CNT; int in; int out; unsigned long flags; struct mem_status *stat; spin_lock_irqsave(&msq->lock, flags); in = msq->in; out = msq->out; if (circ_get_space(qsize, in, out) < 1) { /* Make the oldest slot empty */ out++; msq->out = (out == qsize) ? 0 : out; } /* Get a free slot */ stat = &msq->stat[in]; /* Make it as "data" slot */ in++; msq->in = (in == qsize) ? 0 : in; spin_unlock_irqrestore(&msq->lock, flags); memset(stat, 0, sizeof(struct mem_status)); return stat; }
/** * trq_get_free_slot * @trq : pointer to an instance of trace_data_queue structure * * Succeeds always by dropping the oldest slot if a "trq" is full. */ struct trace_data *trq_get_free_slot(struct trace_data_queue *trq) { int qsize = MAX_TRACE_SIZE; int in; int out; unsigned long flags; struct trace_data *trd; spin_lock_irqsave(&trq->lock, flags); in = trq->in; out = trq->out; /* The oldest slot can be dropped. */ if (circ_get_space(qsize, in, out) < 1) { /* Free the data buffer in the oldest slot */ trd = &trq->trd[out]; kfree(trd->data); /* Make the oldest slot empty */ out++; trq->out = (out == qsize) ? 0 : out; } /* Get a free slot and make it occupied */ trd = &trq->trd[in++]; trq->in = (in == qsize) ? 0 : in; spin_unlock_irqrestore(&trq->lock, flags); memset(trd, 0, sizeof(struct trace_data)); return trd; }
/** @brief print a REQ_ACK Prints a snapshot of the status of the @b @@dev circular queue when AP sends or receives an REQ_ACK. @param mld the pointer to a mem_link_device instance @param mst the pointer to a mem_snapshot instance @param dev the pointer to a mem_ipc_device instance (IPC_FMT, etc.) @param dir the direction of communication (TX or RX) */ void print_req_ack(struct mem_link_device *mld, struct mem_snapshot *mst, struct mem_ipc_device *dev, enum direction dir) { #ifdef DEBUG_MODEM_IF_FLOW_CTRL struct link_device *ld = &mld->link_dev; struct modem_ctl *mc = ld->mc; enum dev_format id = dev->id; unsigned int qsize = get_size(cq(dev, dir)); unsigned int in = mst->head[id][dir]; unsigned int out = mst->tail[id][dir]; unsigned int usage = circ_get_usage(qsize, in, out); unsigned int space = circ_get_space(qsize, in, out); mif_info("REQ_ACK: %s%s%s: %s_%s.%d " "{in:%u out:%u usage:%u space:%u}\n", ld->name, arrow(dir), mc->name, dev->name, q_dir(dir), dev->req_ack_cnt[dir], in, out, usage, space); #endif }
/** @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 check the free space in a circular TXQ @param mld the pointer to a mem_link_device instance @param dev the pointer to a mem_ipc_device instance @param qsize the size of the buffer in @b @@dev TXQ @param in the IN (HEAD) pointer value of the TXQ @param out the OUT (TAIL) pointer value of the TXQ @param count the size of the data to be transmitted @retval "> 0" the size of free space in the @b @@dev TXQ @retval "< 0" an error code */ static inline int check_txq_space(struct mem_link_device *mld, struct mem_ipc_device *dev, unsigned int qsize, unsigned int in, unsigned int out, unsigned int count) { struct link_device *ld = &mld->link_dev; struct modem_ctl *mc = ld->mc; unsigned int usage; unsigned int space; if (!circ_valid(qsize, in, out)) { mif_err("%s: ERR! Invalid %s_TXQ{qsize:%d in:%d out:%d}\n", ld->name, dev->name, qsize, in, out); return -EIO; } usage = circ_get_usage(qsize, in, out); if (unlikely(usage > SHM_UL_USAGE_LIMIT) && cp_online(mc)) { #ifdef DEBUG_MODEM_IF mif_debug("%s: CAUTION! BUSY in %s_TXQ{qsize:%d in:%d out:%d "\ "usage:%d (count:%d)}\n", ld->name, dev->name, qsize, in, out, usage, count); #endif return -EBUSY; } space = circ_get_space(qsize, in, out); if (unlikely(space < count)) { #ifdef DEBUG_MODEM_IF if (cp_online(mc)) { mif_err("%s: CAUTION! NOSPC in %s_TXQ{qsize:%d in:%d "\ "out:%d space:%d count:%d}\n", ld->name, dev->name, qsize, in, out, space, count); } #endif return -ENOSPC; } return space; }
static inline int check_udl_space(struct mem_link_device *mld, struct mem_ipc_device *dev, unsigned int qsize, unsigned int in, unsigned int out, unsigned int count) { struct link_device *ld = &mld->link_dev; unsigned int space; if (!circ_valid(qsize, in, out)) { mif_err("%s: ERR! Invalid %s_TXQ{qsize:%d in:%d out:%d}\n", ld->name, dev->name, qsize, in, out); return -EIO; } space = circ_get_space(qsize, in, out); if (unlikely(space < count)) { mif_err("%s: NOSPC in %s_TXQ{qsize:%d in:%d " "out:%d space:%d count:%d}\n", ld->name, dev->name, qsize, in, out, space, count); return -ENOSPC; } return 0; }