/* Release a CPPI Channel. */ static void cppi_channel_release(struct dma_channel *channel) { struct cppi_channel *c; void __iomem *tibase; /* REVISIT: for paranoia, check state and abort if needed... */ c = container_of(channel, struct cppi_channel, channel); tibase = c->controller->tibase; if (!c->hw_ep) DBG(1, "releasing idle DMA channel %p\n", c); else if (!c->transmit) core_rxirq_enable(tibase, c->index + 1); /* for now, leave its cppi IRQ enabled (we won't trigger it) */ c->hw_ep = NULL; channel->status = MUSB_DMA_STATUS_UNKNOWN; }
/** * cppi_next_rx_segment - dma read for the next chunk of a buffer * @musb: the controller * @rx: dma channel * @onepacket: true unless caller treats short reads as errors, and * performs fault recovery above usbcore. * Context: controller irqlocked * * See above notes about why we can't use multi-BD RX queues except in * rare cases (mass storage class), and can never use the hardware "rndis" * mode (since it's not a "true" RNDIS mode) with complete safety.. * * It's ESSENTIAL that callers specify "onepacket" mode unless they kick in * code to recover from corrupted datastreams after each short transfer. */ static void cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket) { unsigned maxpacket = rx->maxpacket; dma_addr_t addr = rx->buf_dma + rx->offset; size_t length = rx->buf_len - rx->offset; struct cppi_descriptor *bd, *tail; unsigned n_bds; unsigned i; void __iomem *tibase = musb->ctrl_base; int is_rndis = 0; struct cppi_rx_stateram __iomem *rx_ram = rx->state_ram; struct cppi_descriptor *d; if (onepacket) { /* almost every USB driver, host or peripheral side */ n_bds = 1; /* maybe apply the heuristic above */ if (cppi_rx_rndis && is_peripheral_active(musb) && length > maxpacket && (length & ~0xffff) == 0 && (length & 0x0fff) != 0 && (length & (maxpacket - 1)) == 0) { maxpacket = length; is_rndis = 1; } } else { /* virtually nothing except mass storage class */ if (length > 0xffff) { n_bds = 0xffff / maxpacket; length = n_bds * maxpacket; } else { n_bds = DIV_ROUND_UP(length, maxpacket); } if (n_bds == 1) onepacket = 1; else n_bds = min(n_bds, (unsigned) NUM_RXCHAN_BD); } /* In host mode, autorequest logic can generate some IN tokens; it's * tricky since we can't leave REQPKT set in RXCSR after the transfer * finishes. So: multipacket transfers involve two or more segments. * And always at least two IRQs ... RNDIS mode is not an option. */ if (is_host_active(musb)) n_bds = cppi_autoreq_update(rx, tibase, onepacket, n_bds); cppi_rndis_update(rx, 1, musb->ctrl_base, is_rndis); length = min(n_bds * maxpacket, length); musb_dbg(musb, "RX DMA%d seg, maxp %d %s bds %d (cnt %d) " "dma 0x%llx len %u %u/%u", rx->index, maxpacket, onepacket ? (is_rndis ? "rndis" : "onepacket") : "multipacket", n_bds, musb_readl(tibase, DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4)) & 0xffff, (unsigned long long)addr, length, rx->channel.actual_len, rx->buf_len); /* only queue one segment at a time, since the hardware prevents * correct queue shutdown after unexpected short packets */ bd = cppi_bd_alloc(rx); rx->head = bd; /* Build BDs for all packets in this segment */ for (i = 0, tail = NULL; bd && i < n_bds; i++, tail = bd) { u32 bd_len; if (i) { bd = cppi_bd_alloc(rx); if (!bd) break; tail->next = bd; tail->hw_next = bd->dma; } bd->hw_next = 0; /* all but the last packet will be maxpacket size */ if (maxpacket < length) bd_len = maxpacket; else bd_len = length; bd->hw_bufp = addr; addr += bd_len; rx->offset += bd_len; bd->hw_off_len = (0 /*offset*/ << 16) + bd_len; bd->buflen = bd_len; bd->hw_options = CPPI_OWN_SET | (i == 0 ? length : 0); length -= bd_len; } /* we always expect at least one reusable BD! */ if (!tail) { WARNING("rx dma%d -- no BDs? need %d\n", rx->index, n_bds); return; } else if (i < n_bds) WARNING("rx dma%d -- only %d of %d BDs\n", rx->index, i, n_bds); tail->next = NULL; tail->hw_next = 0; bd = rx->head; rx->tail = tail; /* short reads and other faults should terminate this entire * dma segment. we want one "dma packet" per dma segment, not * one per USB packet, terminating the whole queue at once... * NOTE that current hardware seems to ignore SOP and EOP. */ bd->hw_options |= CPPI_SOP_SET; tail->hw_options |= CPPI_EOP_SET; for (d = rx->head; d; d = d->next) cppi_dump_rxbd("S", d); /* in case the preceding transfer left some state... */ tail = rx->last_processed; if (tail) { tail->next = bd; tail->hw_next = bd->dma; } core_rxirq_enable(tibase, rx->index + 1); /* BDs live in DMA-coherent memory, but writes might be pending */ cpu_drain_writebuffer(); /* REVISIT specs say to write this AFTER the BUFCNT register * below ... but that loses badly. */ musb_writel(&rx_ram->rx_head, 0, bd->dma); /* bufferCount must be at least 3, and zeroes on completion * unless it underflows below zero, or stops at two, or keeps * growing ... grr. */ i = musb_readl(tibase, DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4)) & 0xffff; if (!i) musb_writel(tibase, DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4), n_bds + 2); else if (n_bds > (i - 3)) musb_writel(tibase, DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4), n_bds - (i - 3)); i = musb_readl(tibase, DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4)) & 0xffff; if (i < (2 + n_bds)) { musb_dbg(musb, "bufcnt%d underrun - %d (for %d)", rx->index, i, n_bds); musb_writel(tibase, DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4), n_bds + 2); } cppi_dump_rx(4, rx, "/S"); }