drivers/hwtracing/coresight/coresight-trace-id.c

Source file repositories/reference/linux-study-clean/drivers/hwtracing/coresight/coresight-trace-id.c

File Facts

System
Linux kernel
Corpus path
drivers/hwtracing/coresight/coresight-trace-id.c
Extension
.c
Size
8744 bytes
Lines
301
Domain
Driver Families
Bucket
drivers/hwtracing
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (!test_bit(preferred_id, id_map->used_ids)) {
			id = preferred_id;
			goto trace_id_allocated;
		} else if (flags & TRACE_ID_REQ_STATIC)
			return -EBUSY;
	} else if (flags & TRACE_ID_PREFER_ODD) {
	/* may use odd ids to avoid preferred legacy cpu IDs */
		id = coresight_trace_id_find_odd_id(id_map);
		if (id)
			goto trace_id_allocated;
	} else if (!IS_VALID_CS_TRACE_ID(preferred_id) &&
			(flags & TRACE_ID_REQ_STATIC))
		return -EINVAL;

	/*
	 * skip reserved bit 0, look at bitmap length of
	 * CORESIGHT_TRACE_ID_RES_TOP from offset of bit 1.
	 */
	id = find_next_zero_bit(id_map->used_ids, CORESIGHT_TRACE_ID_RES_TOP, 1);
	if (id >= CORESIGHT_TRACE_ID_RES_TOP)
		return -EINVAL;

	/* mark as used */
trace_id_allocated:
	set_bit(id, id_map->used_ids);
	return id;
}

static void coresight_trace_id_free(int id, struct coresight_trace_id_map *id_map)
{
	if (WARN(!IS_VALID_CS_TRACE_ID(id), "Invalid Trace ID %d\n", id))
		return;
	if (WARN(!test_bit(id, id_map->used_ids), "Freeing unused ID %d\n", id))
		return;
	clear_bit(id, id_map->used_ids);
}

/*
 * Release all IDs and clear CPU associations.
 */
static void coresight_trace_id_release_all(struct coresight_trace_id_map *id_map)
{
	unsigned long flags;
	int cpu;

	raw_spin_lock_irqsave(&id_map->lock, flags);
	bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX);
	for_each_possible_cpu(cpu)
		atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
	raw_spin_unlock_irqrestore(&id_map->lock, flags);
	DUMP_ID_MAP(id_map);
}

static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
{
	unsigned long flags;
	int id;

	raw_spin_lock_irqsave(&id_map->lock, flags);

	/* check for existing allocation for this CPU */
	id = _coresight_trace_id_read_cpu_id(cpu, id_map);
	if (id)
		goto get_cpu_id_out_unlock;

	/*
	 * Find a new ID.
	 *
	 * Use legacy values where possible in the dynamic trace ID allocator to
	 * allow older tools to continue working if they are not upgraded at the
	 * same time as the kernel drivers.
	 *
	 * If the generated legacy ID is invalid, or not available then the next
	 * available dynamic ID will be used.
	 */
	id = coresight_trace_id_alloc_new_id(id_map,
					     CORESIGHT_LEGACY_CPU_TRACE_ID(cpu),
					     TRACE_ID_ANY);
	if (!IS_VALID_CS_TRACE_ID(id))
		goto get_cpu_id_out_unlock;

	/* allocate the new id to the cpu */
	atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id);

get_cpu_id_out_unlock:
	raw_spin_unlock_irqrestore(&id_map->lock, flags);

	DUMP_ID_CPU(cpu, id);
	DUMP_ID_MAP(id_map);
	return id;

Annotation

Implementation Notes