Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions drivers/soundwire/cadence_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,14 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)

cdns_read_response(cdns);

/*
* Clear interrupt before signalling the completion to avoid
* a race between this thread and the main thread starting
* another TX.
*/
cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_RX_WL);
int_status &= ~CDNS_MCP_INT_RX_WL;

if (defer && defer->msg) {
cdns_fill_msg_resp(cdns, defer->msg,
defer->length, 0);
Expand All @@ -942,6 +950,12 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
}
}

/*
* Clear interrupts before handling them so we don't lose
* events that re-trigger while this code is running.
*/
cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status);

if (int_status & CDNS_MCP_INT_PARITY) {
/* Parity error detected by Master */
dev_err_ratelimited(cdns->dev, "Parity error\n");
Expand Down Expand Up @@ -974,12 +988,6 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
}

if (int_status & CDNS_MCP_INT_SLAVE_MASK) {
/* Mask the Slave interrupt and wake thread */
cdns_updatel(cdns, CDNS_MCP_INTMASK,
CDNS_MCP_INT_SLAVE_MASK, 0);

int_status &= ~CDNS_MCP_INT_SLAVE_MASK;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rfvirgil @shumingfan Is it possible that a Peripheral can generate a new event while handling a special event and lead to an infinite loop in a corner case?

/*
* Deal with possible race condition between interrupt
* handling and disabling interrupts on suspend.
Expand All @@ -991,7 +999,6 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
schedule_work(&cdns->work);
}

cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status);
return IRQ_HANDLED;
}
EXPORT_SYMBOL(sdw_cdns_irq);
Expand Down Expand Up @@ -1102,11 +1109,6 @@ static void cdns_update_slave_status_work(struct work_struct *work)
retry_count);
}
}

/* unmask Slave interrupt now */
cdns_updatel(cdns, CDNS_MCP_INTMASK,
CDNS_MCP_INT_SLAVE_MASK, CDNS_MCP_INT_SLAVE_MASK);

}

/* paranoia check to make sure self-cleared bits are indeed cleared */
Expand Down
Loading