static irqreturn_t qcom_slim_handle_rx_irq()

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;
}