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; }
static void dpram_reset_rx_circ(struct dpram_link_device *dpld, int dev) { set_rx_head(dpld, dev, 0); set_rx_tail(dpld, dev, 0); if (dev == IPC_FMT) trigger_force_cp_crash(dpld); }
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); }
static void dpram_ipc_write(struct dpram_link_device *dpld, int dev, u32 qsize, u32 in, u32 out, struct sk_buff *skb) { struct link_device *ld = &dpld->ld; u8 __iomem *buff = get_tx_buff(dpld, dev); u8 *src = skb->data; u32 len = skb->len; u32 inp; struct mif_irq_map map; if (in < out) { /* +++++++++ in ---------- out ++++++++++ */ memcpy((buff + in), src, len); } else { /* ------ out +++++++++++ in ------------ */ u32 space = qsize - in; /* 1) in -> buffer end */ memcpy((buff + in), src, ((len > space) ? space : len)); /* 2) buffer start -> out */ if (len > space) memcpy(buff, (src + space), (len - space)); } /* update new in pointer */ inp = in + len; if (inp >= qsize) inp -= qsize; set_tx_head(dpld, dev, inp); if (dev == IPC_FMT) { set_dpram_map(dpld, &map); mif_irq_log(ld->mc->msd, map, "ipc_write", sizeof("ipc_write")); mif_ipc_log(MIF_IPC_AP2CP, ld->mc->msd, skb->data, skb->len); } if (ld->aligned && memcmp16_to_io((buff + in), src, 4)) { mif_err("%s: memcmp16_to_io fail\n", ld->name); trigger_force_cp_crash(dpld); } }
static inline void set_rx_tail(struct dpram_link_device *dpld, int id, u32 out) { int cnt = 3; u32 val = 0; iowrite16((u16)out, dpld->dev[id]->rxq.tail); do { /* Check tail value written */ val = ioread16(dpld->dev[id]->rxq.tail); if (val == out) return; mif_err("ERR: %s rxq.tail(%d) != out(%d)\n", get_dev_name(id), val, out); udelay(100); /* Write tail value again */ iowrite16((u16)out, dpld->dev[id]->rxq.tail); } while (cnt--); trigger_force_cp_crash(dpld); }
static inline void set_rx_head(struct dpram_link_device *dpld, int id, u32 in) { int cnt = 3; u32 val = 0; iowrite16((u16)in, dpld->dev[id]->rxq.head); do { /* Check head value written */ val = ioread16(dpld->dev[id]->rxq.head); if (val == in) return; mif_err("ERR: %s rxq.head(%d) != in(%d)\n", get_dev_name(id), val, in); udelay(100); /* Write head value again */ iowrite16((u16)in, dpld->dev[id]->rxq.head); } while (cnt--); trigger_force_cp_crash(dpld); }
static int dpram_force_dump(struct link_device *ld, struct io_device *iod) { struct dpram_link_device *dpld = to_dpram_link_device(ld); trigger_force_cp_crash(dpld); return 0; }