static void dpram_reset_tx_circ(struct dpram_link_device *dpld, int dev) { set_tx_head(dpld, dev, 0); set_tx_tail(dpld, dev, 0); if (dev == IPC_FMT) trigger_force_cp_crash(dpld); }
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 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); dpram_trigger_force_cp_crash(dpld); } }
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; }
/* get free space in the TXQ as well as in & out pointers */ static inline int get_txq_space(struct dpram_link_device *dpld, int dev, u32 qsize, u32 *in, u32 *out) { struct link_device *ld = &dpld->ld; int cnt = 3; int space; do { *in = get_tx_head(dpld, dev); *out = get_tx_tail(dpld, dev); if (dpram_circ_valid(qsize, *in, *out)) { space = (*in < *out) ? (*out - *in - 1) : (qsize + *out - *in - 1); return space; } mif_info("%s: CAUTION! <%pf> " "%s_TXQ invalid (size:%d in:%d out:%d)\n", ld->name, __builtin_return_address(0), get_dev_name(dev), qsize, *in, *out); udelay(100); } while (cnt--); if (dev == IPC_FMT) { dpram_trigger_force_cp_crash(dpld); } else { set_tx_head(dpld, dev, 0); set_tx_tail(dpld, dev, 0); } *in = 0; *out = 0; return -EINVAL; }