static irqreturn_t cp_idpram_irq_handler(int irq, void *data)
{
	struct dpram_link_device *dpld = (struct dpram_link_device *)data;
	struct link_device *ld = (struct link_device *)&dpld->ld;
	u16 int2ap;

	if (unlikely(ld->mode == LINK_MODE_OFFLINE))
		return IRQ_HANDLED;

	if (dpram_wake_up(dpld) < 0) {
		log_dpram_status(dpld);
		trigger_force_cp_crash(dpld);
		return IRQ_HANDLED;
	}

	int2ap = recv_intr(dpld);

	dpram_intr_handler(dpld, int2ap);

	clear_intr(dpld);

	dpram_allow_sleep(dpld);

	return IRQ_HANDLED;
}
Example #2
0
static irqreturn_t dpram_irq_handler(int irq, void *data)
{
	struct dpram_link_device *dpld = (struct dpram_link_device *)data;
	struct link_device *ld = (struct link_device *)&dpld->ld;
	u16 int2ap = 0;

	if (unlikely(ld->mode == LINK_MODE_OFFLINE))
		return IRQ_HANDLED;

	if (dpram_wake_up(dpld) < 0) {
		log_dpram_status(dpld);
		trigger_force_cp_crash(dpld);
		return IRQ_HANDLED;
	}

	int2ap = recv_intr(dpld);

	if (unlikely(int2ap == INT_POWERSAFE_FAIL)) {
		mif_info("%s: int2ap == INT_POWERSAFE_FAIL\n", ld->name);
		goto exit;
	} else if (int2ap == 0x1234 || int2ap == 0xDBAB || int2ap == 0xABCD) {
		if (dpld->ext_op && dpld->ext_op->dload_cmd_handler) {
			dpld->ext_op->dload_cmd_handler(dpld, int2ap);
			goto exit;
		}
	}

	if (unlikely(EXT_UDL_CMD(int2ap))) {
		if (likely(EXT_INT_VALID(int2ap))) {
			if (UDL_CMD_VALID(int2ap))
				udl_command_handler(dpld, int2ap);
			else if (EXT_CMD_VALID(int2ap))
				ext_command_handler(dpld, int2ap);
			else
				mif_info("%s: ERR! invalid intr 0x%04X\n",
					ld->name, int2ap);
		} else {
			mif_info("%s: ERR! invalid intr 0x%04X\n",
				ld->name, int2ap);
		}
	} else {
		if (likely(INT_VALID(int2ap))) {
			if (unlikely(INT_CMD_VALID(int2ap)))
				command_handler(dpld, int2ap);
			else
				non_command_handler(dpld, int2ap);
		} else {
			mif_info("%s: ERR! invalid intr 0x%04X\n",
				ld->name, int2ap);
		}
	}

exit:
	clear_intr(dpld);
	dpram_allow_sleep(dpld);
	return IRQ_HANDLED;
}
static void dpram_send_ipc(struct link_device *ld, int dev,
			struct io_device *iod, struct sk_buff *skb)
{
	struct dpram_link_device *dpld = to_dpram_link_device(ld);
	struct sk_buff_head *txq = ld->skb_txq[dev];
	int ret;
	u16 mask;

	skb_queue_tail(txq, skb);
	if (txq->qlen > 1024) {
		mif_debug("%s: %s txq->qlen %d > 1024\n",
			ld->name, get_dev_name(dev), txq->qlen);
	}

	if (dpld->dp_type == CP_IDPRAM) {
		if (dpram_wake_up(dpld) < 0) {
			trigger_force_cp_crash(dpld);
			return;
		}
	}

	if (!dpram_ipc_active(dpld))
		goto exit;

	if (atomic_read(&dpld->res_required[dev]) > 0) {
		mif_debug("%s: %s_TXQ is full\n", ld->name, get_dev_name(dev));
		goto exit;
	}

	ret = dpram_try_ipc_tx(dpld, dev);
	if (ret > 0) {
		mask = get_mask_send(dpld, dev);
		send_intr(dpld, INT_NON_CMD(mask));
	} else if (ret == -ENOSPC) {
		mask = get_mask_req_ack(dpld, dev);
		send_intr(dpld, INT_NON_CMD(mask));
		mif_info("%s: Send REQ_ACK 0x%04X\n", ld->name, mask);
	} else {
		mif_info("%s: dpram_try_ipc_tx fail (err %d)\n", ld->name, ret);
	}

exit:
	if (dpld->dp_type == CP_IDPRAM)
		dpram_allow_sleep(dpld);
}