drivers/firewire/core-topology.c

Source file repositories/reference/linux-study-clean/drivers/firewire/core-topology.c

File Facts

System
Linux kernel
Corpus path
drivers/firewire/core-topology.c
Extension
.c
Size
14991 bytes
Lines
510
Domain
Driver Families
Bucket
drivers/firewire
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 (node->ports[i]->max_depth > depths[0]) {
			depths[1] = depths[0];
			depths[0] = node->ports[i]->max_depth;
		} else if (node->ports[i]->max_depth > depths[1])
			depths[1] = node->ports[i]->max_depth;
	}

	node->max_depth = depths[0] + 1;
	node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2);
}

static inline struct fw_node *fw_node(struct list_head *l)
{
	return list_entry(l, struct fw_node, link);
}

/*
 * This function builds the tree representation of the topology given
 * by the self IDs from the latest bus reset.  During the construction
 * of the tree, the function checks that the self IDs are valid and
 * internally consistent.  On success this function returns the
 * fw_node corresponding to the local card otherwise NULL.
 */
static struct fw_node *build_tree(struct fw_card *card, const u32 *sid, int self_id_count,
				  unsigned int generation)
{
	struct self_id_sequence_enumerator enumerator = {
		.cursor = sid,
		.quadlet_count = self_id_count,
	};
	struct fw_node *node, *child, *local_node, *irm_node;
	struct list_head stack;
	int phy_id, stack_depth;
	int gap_count;
	bool beta_repeaters_present;

	local_node = NULL;
	node = NULL;
	INIT_LIST_HEAD(&stack);
	stack_depth = 0;
	phy_id = 0;
	irm_node = NULL;
	gap_count = phy_packet_self_id_zero_get_gap_count(*sid);
	beta_repeaters_present = false;

	while (enumerator.quadlet_count > 0) {
		unsigned int child_port_count = 0;
		unsigned int total_port_count = 0;
		unsigned int parent_count = 0;
		unsigned int quadlet_count;
		const u32 *self_id_sequence;
		unsigned int port_capacity;
		enum phy_packet_self_id_port_status port_status;
		unsigned int port_index;
		struct list_head *h;
		int i;

		self_id_sequence = self_id_sequence_enumerator_next(&enumerator, &quadlet_count);
		if (IS_ERR(self_id_sequence)) {
			if (PTR_ERR(self_id_sequence) != -ENODATA) {
				fw_err(card, "inconsistent extended self IDs: %ld\n",
				       PTR_ERR(self_id_sequence));
				return NULL;
			}
			break;
		}

		port_capacity = self_id_sequence_get_port_capacity(quadlet_count);
		trace_self_id_sequence(card->index, self_id_sequence, quadlet_count, generation);

		for (port_index = 0; port_index < port_capacity; ++port_index) {
			port_status = self_id_sequence_get_port_status(self_id_sequence, quadlet_count,
								       port_index);
			switch (port_status) {
			case PHY_PACKET_SELF_ID_PORT_STATUS_CHILD:
				++child_port_count;
				fallthrough;
			case PHY_PACKET_SELF_ID_PORT_STATUS_PARENT:
			case PHY_PACKET_SELF_ID_PORT_STATUS_NCONN:
				++total_port_count;
				fallthrough;
			case PHY_PACKET_SELF_ID_PORT_STATUS_NONE:
			default:
				break;
			}
		}

		if (phy_id != phy_packet_self_id_get_phy_id(self_id_sequence[0])) {
			fw_err(card, "PHY ID mismatch in self ID: %d != %d\n",
			       phy_id, phy_packet_self_id_get_phy_id(self_id_sequence[0]));

Annotation

Implementation Notes