in rio_cm.c [635:692]
static void rio_txcq_handler(struct cm_dev *cm, int slot)
{
int ack_slot;
/* ATTN: Add TX completion notification if/when direct buffer
* transfer is implemented. At this moment only correct tracking
* of tx_count is important.
*/
riocm_debug(TX_EVENT, "for mport_%d slot %d tx_cnt %d",
cm->mport->id, slot, cm->tx_cnt);
spin_lock(&cm->tx_lock);
ack_slot = cm->tx_ack_slot;
if (ack_slot == slot)
riocm_debug(TX_EVENT, "slot == ack_slot");
while (cm->tx_cnt && ((ack_slot != slot) ||
(cm->tx_cnt == RIOCM_TX_RING_SIZE))) {
cm->tx_buf[ack_slot] = NULL;
++ack_slot;
ack_slot &= (RIOCM_TX_RING_SIZE - 1);
cm->tx_cnt--;
}
if (cm->tx_cnt < 0 || cm->tx_cnt > RIOCM_TX_RING_SIZE)
riocm_error("tx_cnt %d out of sync", cm->tx_cnt);
WARN_ON((cm->tx_cnt < 0) || (cm->tx_cnt > RIOCM_TX_RING_SIZE));
cm->tx_ack_slot = ack_slot;
/*
* If there are pending requests, insert them into transmit queue
*/
if (!list_empty(&cm->tx_reqs) && (cm->tx_cnt < RIOCM_TX_RING_SIZE)) {
struct tx_req *req, *_req;
int rc;
list_for_each_entry_safe(req, _req, &cm->tx_reqs, node) {
list_del(&req->node);
cm->tx_buf[cm->tx_slot] = req->buffer;
rc = rio_add_outb_message(cm->mport, req->rdev, cmbox,
req->buffer, req->len);
kfree(req->buffer);
kfree(req);
++cm->tx_cnt;
++cm->tx_slot;
cm->tx_slot &= (RIOCM_TX_RING_SIZE - 1);
if (cm->tx_cnt == RIOCM_TX_RING_SIZE)
break;
}
}
spin_unlock(&cm->tx_lock);
}