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); }
/* ret < 0 : error ret == 0 : no data ret > 0 : valid data */ static int dpram_ipc_recv_data(struct dpram_link_device *dpld, int dev) { struct link_device *ld = &dpld->ld; struct dpram_rxb *rxb; u8 __iomem *src = get_rx_buff(dpld, dev); u32 qsize = get_rx_buff_size(dpld, dev); u32 in = get_rx_head(dpld, dev); u32 out = get_rx_tail(dpld, dev); u32 rcvd = 0; struct mif_irq_map map; if (in == out) return 0; if (dev == IPC_FMT) { set_dpram_map(dpld, &map); mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv")); } /* Get data length in DPRAM*/ rcvd = (in > out) ? (in - out) : (qsize - out + in); mif_debug("%s: %s qsize[%u] in[%u] out[%u] rcvd[%u]\n", ld->name, get_dev_name(dev), qsize, in, out, rcvd); /* Check each queue */ if (!dpram_circ_valid(qsize, in, out)) { mif_err("%s: ERR! %s_RXQ invalid (size:%d in:%d out:%d)\n", ld->name, get_dev_name(dev), qsize, in, out); #if 0 set_rx_head(dpld, dev, 0); set_rx_tail(dpld, dev, 0); #else dpram_trigger_force_cp_crash(dpld); #endif return -EINVAL; } /* Allocate an rxb */ rxb = rxbq_get_free_rxb(&dpld->rxbq[dev]); if (!rxb) { mif_info("%s: ERR! %s rxbq_get_free_rxb fail\n", ld->name, get_dev_name(dev)); return -ENOMEM; } /* Read data from each DPRAM buffer */ dpram_ipc_read(dpld, dev, rxb_put(rxb, rcvd), src, out, rcvd, qsize); /* Calculate and set new out */ out += rcvd; if (out >= qsize) out -= qsize; set_rx_tail(dpld, dev, out); return rcvd; }
static int dpram_init_ipc(struct dpram_link_device *dpld) { struct link_device *ld = &dpld->ld; int i; if (ld->mode == LINK_MODE_IPC && get_magic(dpld) == DPRAM_MAGIC_CODE && get_access(dpld) == 1) mif_info("%s: IPC already initialized\n", ld->name); /* Clear pointers in every circular queue */ for (i = 0; i < dpld->max_ipc_dev; i++) { set_tx_head(dpld, i, 0); set_tx_tail(dpld, i, 0); set_rx_head(dpld, i, 0); set_rx_tail(dpld, i, 0); } /* Initialize variables for efficient TX/RX processing */ for (i = 0; i < dpld->max_ipc_dev; i++) dpld->iod[i] = link_get_iod_with_format(ld, i); dpld->iod[IPC_RAW] = link_get_iod_with_format(ld, IPC_MULTI_RAW); if (dpld->iod[IPC_RAW]->recv_skb) dpld->use_skb = true; for (i = 0; i < dpld->max_ipc_dev; i++) { spin_lock_init(&dpld->tx_lock[i]); atomic_set(&dpld->res_required[i], 0); skb_queue_purge(&dpld->skb_rxq[i]); } /* Enable IPC */ atomic_set(&dpld->accessing, 0); set_magic(dpld, DPRAM_MAGIC_CODE); set_access(dpld, 1); if (get_magic(dpld) != DPRAM_MAGIC_CODE || get_access(dpld) != 1) return -EACCES; ld->mode = LINK_MODE_IPC; if (wake_lock_active(&dpld->wlock)) wake_unlock(&dpld->wlock); return 0; }
static int dpram_init_ipc(struct dpram_link_device *dpld) { struct link_device *ld = &dpld->ld; int i; if (ld->mode == LINK_MODE_IPC && get_magic(dpld) == DPRAM_MAGIC_CODE && get_access(dpld) == 1) mif_info("%s: IPC already initialized\n", ld->name); /* Clear pointers in every circular queue */ for (i = 0; i < dpld->max_ipc_dev; i++) { set_tx_head(dpld, i, 0); set_tx_tail(dpld, i, 0); set_rx_head(dpld, i, 0); set_rx_tail(dpld, i, 0); } for (i = 0; i < dpld->max_ipc_dev; i++) { spin_lock_init(&dpld->tx_lock[i]); atomic_set(&dpld->res_required[i], 0); } atomic_set(&dpld->accessing, 0); /* Enable IPC */ set_magic(dpld, DPRAM_MAGIC_CODE); set_access(dpld, 1); if (get_magic(dpld) != DPRAM_MAGIC_CODE || get_access(dpld) != 1) return -EACCES; ld->mode = LINK_MODE_IPC; if (wake_lock_active(&dpld->wlock)) wake_unlock(&dpld->wlock); return 0; }