in devices/tsi721.c [381:447]
static void tsi721_db_dpc(struct work_struct *work)
{
struct tsi721_device *priv = container_of(work, struct tsi721_device,
idb_work);
struct rio_mport *mport;
struct rio_dbell *dbell;
int found = 0;
u32 wr_ptr, rd_ptr;
u64 *idb_entry;
u32 regval;
union {
u64 msg;
u8 bytes[8];
} idb;
/*
* Process queued inbound doorbells
*/
mport = &priv->mport;
wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE;
rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE)) % IDB_QSIZE;
while (wr_ptr != rd_ptr) {
idb_entry = (u64 *)(priv->idb_base +
(TSI721_IDB_ENTRY_SIZE * rd_ptr));
rd_ptr++;
rd_ptr %= IDB_QSIZE;
idb.msg = *idb_entry;
*idb_entry = 0;
/* Process one doorbell */
list_for_each_entry(dbell, &mport->dbells, node) {
if ((dbell->res->start <= DBELL_INF(idb.bytes)) &&
(dbell->res->end >= DBELL_INF(idb.bytes))) {
found = 1;
break;
}
}
if (found) {
dbell->dinb(mport, dbell->dev_id, DBELL_SID(idb.bytes),
DBELL_TID(idb.bytes), DBELL_INF(idb.bytes));
} else {
tsi_debug(DBELL, &priv->pdev->dev,
"spurious IDB sid %2.2x tid %2.2x info %4.4x",
DBELL_SID(idb.bytes), DBELL_TID(idb.bytes),
DBELL_INF(idb.bytes));
}
wr_ptr = ioread32(priv->regs +
TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE;
}
iowrite32(rd_ptr & (IDB_QSIZE - 1),
priv->regs + TSI721_IDQ_RP(IDB_QUEUE));
/* Re-enable IDB interrupts */
regval = ioread32(priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
regval |= TSI721_SR_CHINT_IDBQRCV;
iowrite32(regval,
priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE;
if (wr_ptr != rd_ptr)
schedule_work(&priv->idb_work);
}