in rio_cm.c [866:927]
static int riocm_ch_receive(struct rio_channel *ch, void **buf, long timeout)
{
void *rxmsg = NULL;
int i, ret = 0;
long wret;
if (!riocm_cmp(ch, RIO_CM_CONNECTED)) {
ret = -EAGAIN;
goto out;
}
if (ch->rx_ring.inuse_cnt == RIOCM_RX_RING_SIZE) {
/* If we do not have entries to track buffers given to upper
* layer, reject request.
*/
ret = -ENOMEM;
goto out;
}
wret = wait_for_completion_interruptible_timeout(&ch->comp, timeout);
riocm_debug(WAIT, "wait on %d returned %ld", ch->id, wret);
if (!wret)
ret = -ETIME;
else if (wret == -ERESTARTSYS)
ret = -EINTR;
else
ret = riocm_cmp(ch, RIO_CM_CONNECTED) ? 0 : -ECONNRESET;
if (ret)
goto out;
spin_lock_bh(&ch->lock);
rxmsg = ch->rx_ring.buf[ch->rx_ring.tail];
ch->rx_ring.buf[ch->rx_ring.tail] = NULL;
ch->rx_ring.count--;
ch->rx_ring.tail++;
ch->rx_ring.tail %= RIOCM_RX_RING_SIZE;
ret = -ENOMEM;
for (i = 0; i < RIOCM_RX_RING_SIZE; i++) {
if (ch->rx_ring.inuse[i] == NULL) {
ch->rx_ring.inuse[i] = rxmsg;
ch->rx_ring.inuse_cnt++;
ret = 0;
break;
}
}
if (ret) {
/* We have no entry to store pending message: drop it */
kfree(rxmsg);
rxmsg = NULL;
}
spin_unlock_bh(&ch->lock);
out:
*buf = rxmsg;
return ret;
}