drivers/dma/mv_xor.c

Source file repositories/reference/linux-study-clean/drivers/dma/mv_xor.c

File Facts

System
Linux kernel
Corpus path
drivers/dma/mv_xor.c
Extension
.c
Size
38256 bytes
Lines
1480
Domain
Driver Families
Bucket
drivers/dma
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (async_tx_test_ack(&iter->async_tx)) {
			list_move_tail(&iter->node, &mv_chan->free_slots);
			if (!list_empty(&iter->sg_tx_list)) {
				list_splice_tail_init(&iter->sg_tx_list,
							&mv_chan->free_slots);
			}
		}
	}
	return 0;
}

static int
mv_desc_clean_slot(struct mv_xor_desc_slot *desc,
		   struct mv_xor_chan *mv_chan)
{
	dev_dbg(mv_chan_to_devp(mv_chan), "%s %d: desc %p flags %d\n",
		__func__, __LINE__, desc, desc->async_tx.flags);

	/* the client is allowed to attach dependent operations
	 * until 'ack' is set
	 */
	if (!async_tx_test_ack(&desc->async_tx)) {
		/* move this slot to the completed_slots */
		list_move_tail(&desc->node, &mv_chan->completed_slots);
		if (!list_empty(&desc->sg_tx_list)) {
			list_splice_tail_init(&desc->sg_tx_list,
					      &mv_chan->completed_slots);
		}
	} else {
		list_move_tail(&desc->node, &mv_chan->free_slots);
		if (!list_empty(&desc->sg_tx_list)) {
			list_splice_tail_init(&desc->sg_tx_list,
					      &mv_chan->free_slots);
		}
	}

	return 0;
}

/* This function must be called with the mv_xor_chan spinlock held */
static void mv_chan_slot_cleanup(struct mv_xor_chan *mv_chan)
{
	struct mv_xor_desc_slot *iter, *_iter;
	dma_cookie_t cookie = 0;
	int busy = mv_chan_is_busy(mv_chan);
	u32 current_desc = mv_chan_get_current_desc(mv_chan);
	int current_cleaned = 0;
	struct mv_xor_desc *hw_desc;

	dev_dbg(mv_chan_to_devp(mv_chan), "%s %d\n", __func__, __LINE__);
	dev_dbg(mv_chan_to_devp(mv_chan), "current_desc %x\n", current_desc);
	mv_chan_clean_completed_slots(mv_chan);

	/* free completed slots from the chain starting with
	 * the oldest descriptor
	 */

	list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
				 node) {

		/* clean finished descriptors */
		hw_desc = iter->hw_desc;
		if (hw_desc->status & XOR_DESC_SUCCESS) {
			cookie = mv_desc_run_tx_complete_actions(iter, mv_chan,
								 cookie);

			/* done processing desc, clean slot */
			mv_desc_clean_slot(iter, mv_chan);

			/* break if we did cleaned the current */
			if (iter->async_tx.phys == current_desc) {
				current_cleaned = 1;
				break;
			}
		} else {
			if (iter->async_tx.phys == current_desc) {
				current_cleaned = 0;
				break;
			}
		}
	}

	if ((busy == 0) && !list_empty(&mv_chan->chain)) {
		if (current_cleaned) {
			/*
			 * current descriptor cleaned and removed, run
			 * from list head
			 */
			iter = list_entry(mv_chan->chain.next,
					  struct mv_xor_desc_slot,

Annotation

Implementation Notes