/* 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; }
/* ret < 0 : error ret == 0 : no data ret > 0 : valid data */ static int dpram_ipc_recv_data_with_rxb(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; u32 out; u32 rcvd; struct mif_irq_map map; rcvd = dpram_get_rxq_rcvd(dpld, dev, qsize, &in, &out); if (rcvd <= 0) return rcvd; if (dev == IPC_FMT) { set_dpram_map(dpld, &map); mif_irq_log(ld->mc->msd, map, "ipc_recv", sizeof("ipc_recv")); } /* 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; }