Esempio n. 1
0
/* Start queued scatter-gather DMA transfers. */
void omap24xxcam_sgdma_process(struct omap24xxcam_sgdma *sgdma)
{
	unsigned long flags;
	int queued_sgdma, sgslot;
	struct sgdma_state *sg_state;
	const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR
		| CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR
		| CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP;

	spin_lock_irqsave(&sgdma->lock, flags);

	queued_sgdma = NUM_SG_DMA - sgdma->free_sgdma;
	sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA;
	while (queued_sgdma > 0) {
		sg_state = sgdma->sg_state + sgslot;
		while ((sg_state->next_sglist < sg_state->sglen) &&
		       !(sg_state->csr & csr_error)) {
			const struct scatterlist *sglist;
			unsigned int len;

			sglist = sg_state->sglist + sg_state->next_sglist;
			/* try to start the next DMA transfer */
			if (sg_state->next_sglist + 1 == sg_state->sglen) {
				/*
				 *  On the last sg, we handle the case where
				 *  cam->img.pix.sizeimage % PAGE_ALIGN != 0
				 */
				len = sg_state->len - sg_state->bytes_read;
			} else {
				len = sg_dma_len(sglist);
			}

			if (omap24xxcam_dma_start(&sgdma->dma,
						  sg_dma_address(sglist),
						  len,
						  omap24xxcam_sgdma_callback,
						  (void *)sgslot)) {
				/* DMA start failed */
				spin_unlock_irqrestore(&sgdma->lock, flags);
				return;
			} else {
				unsigned long expires;
				/* DMA start was successful */
				sg_state->next_sglist++;
				sg_state->bytes_read += len;
				sg_state->queued_sglist++;

				/* We start the reset timer */
				expires = jiffies + HZ;
				mod_timer(&sgdma->reset_timer, expires);
			}
		}
		queued_sgdma--;
		sgslot = (sgslot + 1) % NUM_SG_DMA;
	}

	spin_unlock_irqrestore(&sgdma->lock, flags);
}
Esempio n. 2
0
void omap24xxcam_sgdma_process(struct omap24xxcam_sgdma *sgdma)
{
	unsigned long flags;
	int queued_sgdma, sgslot;
	struct sgdma_state *sg_state;
	const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR
		| CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR
		| CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP;

	spin_lock_irqsave(&sgdma->lock, flags);

	queued_sgdma = NUM_SG_DMA - sgdma->free_sgdma;
	sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA;
	while (queued_sgdma > 0) {
		sg_state = sgdma->sg_state + sgslot;
		while ((sg_state->next_sglist < sg_state->sglen) &&
		       !(sg_state->csr & csr_error)) {
			const struct scatterlist *sglist;
			unsigned int len;

			sglist = sg_state->sglist + sg_state->next_sglist;
			
			if (sg_state->next_sglist + 1 == sg_state->sglen) {
				
				len = sg_state->len - sg_state->bytes_read;
			} else {
				len = sg_dma_len(sglist);
			}

			if (omap24xxcam_dma_start(&sgdma->dma,
						  sg_dma_address(sglist),
						  len,
						  omap24xxcam_sgdma_callback,
						  (void *)sgslot)) {
				
				spin_unlock_irqrestore(&sgdma->lock, flags);
				return;
			} else {
				unsigned long expires;
				
				sg_state->next_sglist++;
				sg_state->bytes_read += len;
				sg_state->queued_sglist++;

				
				expires = jiffies + HZ;
				mod_timer(&sgdma->reset_timer, expires);
			}
		}
		queued_sgdma--;
		sgslot = (sgslot + 1) % NUM_SG_DMA;
	}

	spin_unlock_irqrestore(&sgdma->lock, flags);
}