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;
}
Beispiel #3
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);
	}
}
Beispiel #4
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;
}
Beispiel #5
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;
}