/**
 * 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;
}
Ejemplo n.º 6
0
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;
}