drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
Extension
.c
Size
15983 bytes
Lines
577
Domain
Driver Families
Bucket
drivers/gpu
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 (mux->ring_entry[i].ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT) {
			e = &mux->ring_entry[i];
			break;
		}
	}

	if (!e) {
		DRM_ERROR("%s no low priority ring found\n", __func__);
		return;
	}

	last_seq = atomic_read(&e->ring->fence_drv.last_seq);
	seq = mux->seqno_to_resubmit;
	if (last_seq < seq) {
		/*resubmit all the fences between (last_seq, seq]*/
		list_for_each_entry(chunk, &e->list, entry) {
			if (chunk->sync_seq > last_seq && chunk->sync_seq <= seq) {
				amdgpu_fence_update_start_timestamp(e->ring,
								    chunk->sync_seq,
								    ktime_get());
				if (chunk->sync_seq ==
					le32_to_cpu(*(e->ring->fence_drv.cpu_addr + 2))) {
					if (chunk->cntl_offset <= e->ring->buf_mask)
						amdgpu_ring_patch_cntl(e->ring,
								       chunk->cntl_offset);
					if (chunk->ce_offset <= e->ring->buf_mask)
						amdgpu_ring_patch_ce(e->ring, chunk->ce_offset);
					if (chunk->de_offset <= e->ring->buf_mask)
						amdgpu_ring_patch_de(e->ring, chunk->de_offset);
				}
				amdgpu_ring_mux_copy_pkt_from_sw_ring(mux, e->ring,
								      chunk->start,
								      chunk->end);
				mux->wptr_resubmit = chunk->end;
				amdgpu_ring_commit(mux->real_ring);
			}
		}
	}

	timer_delete(&mux->resubmit_timer);
	mux->s_resubmit = false;
}

static void amdgpu_ring_mux_schedule_resubmit(struct amdgpu_ring_mux *mux)
{
	mod_timer(&mux->resubmit_timer, jiffies + AMDGPU_MUX_RESUBMIT_JIFFIES_TIMEOUT);
}

static void amdgpu_mux_resubmit_fallback(struct timer_list *t)
{
	struct amdgpu_ring_mux *mux = timer_container_of(mux, t,
							 resubmit_timer);

	if (!spin_trylock(&mux->lock)) {
		amdgpu_ring_mux_schedule_resubmit(mux);
		DRM_ERROR("reschedule resubmit\n");
		return;
	}
	amdgpu_mux_resubmit_chunks(mux);
	spin_unlock(&mux->lock);
}

int amdgpu_ring_mux_init(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring,
			 unsigned int entry_size)
{
	mux->real_ring = ring;
	mux->num_ring_entries = 0;

	mux->ring_entry = kzalloc_objs(struct amdgpu_mux_entry, entry_size);
	if (!mux->ring_entry)
		return -ENOMEM;

	mux->ring_entry_size = entry_size;
	mux->s_resubmit = false;

	amdgpu_mux_chunk_slab = KMEM_CACHE(amdgpu_mux_chunk, SLAB_HWCACHE_ALIGN);
	if (!amdgpu_mux_chunk_slab) {
		DRM_ERROR("create amdgpu_mux_chunk cache failed\n");
		return -ENOMEM;
	}

	spin_lock_init(&mux->lock);
	timer_setup(&mux->resubmit_timer, amdgpu_mux_resubmit_fallback, 0);

	return 0;
}

void amdgpu_ring_mux_fini(struct amdgpu_ring_mux *mux)
{
	struct amdgpu_mux_entry *e;

Annotation

Implementation Notes