in qcom-ctrl.c [207:261]
static irqreturn_t qcom_slim_handle_rx_irq(struct qcom_slim_ctrl *ctrl,
u32 stat)
{
u32 *rx_buf, pkt[10];
bool q_rx = false;
u8 mc, mt, len;
pkt[0] = readl_relaxed(ctrl->base + MGR_RX_MSG);
mt = SLIM_HEADER_GET_MT(pkt[0]);
len = SLIM_HEADER_GET_RL(pkt[0]);
mc = SLIM_HEADER_GET_MC(pkt[0]>>8);
/*
* this message cannot be handled by ISR, so
* let work-queue handle it
*/
if (mt == SLIM_MSG_MT_CORE && mc == SLIM_MSG_MC_REPORT_PRESENT) {
rx_buf = (u32 *)slim_alloc_rxbuf(ctrl);
if (!rx_buf) {
dev_err(ctrl->dev, "dropping RX:0x%x due to RX full\n",
pkt[0]);
goto rx_ret_irq;
}
rx_buf[0] = pkt[0];
} else {
rx_buf = pkt;
}
__ioread32_copy(rx_buf + 1, ctrl->base + MGR_RX_MSG + 4,
DIV_ROUND_UP(len, 4));
switch (mc) {
case SLIM_MSG_MC_REPORT_PRESENT:
q_rx = true;
break;
case SLIM_MSG_MC_REPLY_INFORMATION:
case SLIM_MSG_MC_REPLY_VALUE:
slim_msg_response(&ctrl->ctrl, (u8 *)(rx_buf + 1),
(u8)(*rx_buf >> 24), (len - 4));
break;
default:
dev_err(ctrl->dev, "unsupported MC,%x MT:%x\n",
mc, mt);
break;
}
rx_ret_irq:
writel(MGR_INT_RX_MSG_RCVD, ctrl->base +
MGR_INT_CLR);
if (q_rx)
queue_work(ctrl->rxwq, &ctrl->wd);
return IRQ_HANDLED;
}