in sdk/linux_kernel_drivers/xdma/libxdma.c [1362:1449]
static irqreturn_t xdma_isr(int irq, void *dev_id)
{
u32 ch_irq;
u32 user_irq;
u32 mask;
struct xdma_dev *xdev;
struct interrupt_regs *irq_regs;
if (unlikely(!dev_id)) {
pr_err("irq %d, xdev NULL.\n", irq);
return IRQ_NONE;
}
dbg_irq("(irq=%d, dev 0x%p) <<<< ISR.\n", irq, dev_id);
xdev = (struct xdma_dev *)dev_id;
irq_regs = (struct interrupt_regs *)(xdev->bar[xdev->config_bar_idx] +
XDMA_OFS_INT_CTRL);
/* read channel interrupt requests */
ch_irq = read_register(&irq_regs->channel_int_request);
dbg_irq("ch_irq = 0x%08x\n", ch_irq);
/*
* disable all interrupts that fired; these are re-enabled individually
* after the causing module has been fully serviced.
*/
if (ch_irq)
channel_interrupts_disable(xdev, ch_irq);
/* read user interrupts - this read also flushes the above write */
user_irq = read_register(&irq_regs->user_int_request);
dbg_irq("user_irq = 0x%08x\n", user_irq);
if (user_irq) {
int user = 0;
u32 mask = 1;
int max = xdev->h2c_channel_max;
for (; user < max && user_irq; user++, mask <<= 1) {
if (user_irq & mask) {
user_irq &= ~mask;
user_irq_service(irq, &xdev->user_irq[user]);
}
}
}
mask = ch_irq & xdev->mask_irq_h2c;
if (mask) {
int channel = 0;
int max = xdev->h2c_channel_max;
/* iterate over H2C (PCIe read) */
for (channel = 0; channel < max && mask; channel++) {
struct xdma_engine *engine = &xdev->engine_h2c[channel];
/* engine present and its interrupt fired? */
if ((engine->irq_bitmask & mask) &&
(engine->magic == MAGIC_ENGINE)) {
mask &= ~engine->irq_bitmask;
dbg_tfr("schedule_work, %s.\n", engine->name);
schedule_work(&engine->work);
}
}
}
mask = ch_irq & xdev->mask_irq_c2h;
if (mask) {
int channel = 0;
int max = xdev->c2h_channel_max;
/* iterate over C2H (PCIe write) */
for (channel = 0; channel < max && mask; channel++) {
struct xdma_engine *engine = &xdev->engine_c2h[channel];
/* engine present and its interrupt fired? */
if ((engine->irq_bitmask & mask) &&
(engine->magic == MAGIC_ENGINE)) {
mask &= ~engine->irq_bitmask;
dbg_tfr("schedule_work, %s.\n", engine->name);
schedule_work(&engine->work);
}
}
}
xdev->irq_count++;
return IRQ_HANDLED;
}