drivers/firewire/core-card.c

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

File Facts

System
Linux kernel
Corpus path
drivers/firewire/core-card.c
Extension
.c
Size
26102 bytes
Lines
838
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

time_is_after_jiffies64(card->reset_jiffies + secs_to_jiffies(2))) {
		trace_bus_reset_postpone(card->index, card->generation, card->br_short);

		if (!queue_delayed_work(fw_workqueue, &card->br_work, secs_to_jiffies(2)))
			fw_card_put(card);
		return;
	}

	fw_send_phy_config(card, FW_PHY_CONFIG_NO_NODE_ID, card->generation,
			   FW_PHY_CONFIG_CURRENT_GAP_COUNT);
	reset_bus(card, card->br_short);
	fw_card_put(card);
}

static void allocate_broadcast_channel(struct fw_card *card, int generation)
{
	int channel, bandwidth = 0;

	if (!card->broadcast_channel_allocated) {
		fw_iso_resource_manage(card, generation, 1ULL << 31,
				       &channel, &bandwidth, true);
		if (channel != 31) {
			fw_notice(card, "failed to allocate broadcast channel\n");
			return;
		}
		card->broadcast_channel_allocated = true;
	}

	device_for_each_child(card->device, (void *)(long)generation,
			      fw_device_set_broadcast_channel);
}

void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
{
	fw_card_get(card);
	if (!schedule_delayed_work(&card->bm_work, delay))
		fw_card_put(card);
}

enum bm_contention_outcome {
	// The bus management contention window is not expired.
	BM_CONTENTION_OUTCOME_WITHIN_WINDOW = 0,
	// The IRM node has link off.
	BM_CONTENTION_OUTCOME_IRM_HAS_LINK_OFF,
	// The IRM node complies IEEE 1394:1994 only.
	BM_CONTENTION_OUTCOME_IRM_COMPLIES_1394_1995_ONLY,
	// Another bus reset, BM work has been rescheduled.
	BM_CONTENTION_OUTCOME_AT_NEW_GENERATION,
	// We have been unable to send the lock request to IRM node due to some local problem.
	BM_CONTENTION_OUTCOME_LOCAL_PROBLEM_AT_TRANSACTION,
	// The lock request failed, maybe the IRM isn't really IRM capable after all.
	BM_CONTENTION_OUTCOME_IRM_IS_NOT_CAPABLE_FOR_IRM,
	// Somebody else is BM.
	BM_CONTENTION_OUTCOME_IRM_HOLDS_ANOTHER_NODE_AS_BM,
	// The local node succeeds after contending for bus manager.
	BM_CONTENTION_OUTCOME_IRM_HOLDS_LOCAL_NODE_AS_BM,
};

static enum bm_contention_outcome contend_for_bm(struct fw_card *card)
__must_hold(&card->lock)
{
	int generation = card->generation;
	int local_id = card->local_node->node_id;
	__be32 data[2] = {
		cpu_to_be32(BUS_MANAGER_ID_NOT_REGISTERED),
		cpu_to_be32(local_id),
	};
	bool grace = time_is_before_jiffies64(card->reset_jiffies + msecs_to_jiffies(125));
	struct fw_node *irm_node;
	struct fw_device *irm_device;
	int irm_node_id, irm_device_quirks = 0;
	int rcode;

	lockdep_assert_held(&card->lock);

	if (!grace) {
		if (!is_next_generation(generation, card->bm_generation) || card->bm_abdicate)
			return BM_CONTENTION_OUTCOME_WITHIN_WINDOW;
	}

	irm_node = card->irm_node;
	if (!irm_node->link_on) {
		fw_notice(card, "IRM has link off, making local node (%02x) root\n", local_id);
		return BM_CONTENTION_OUTCOME_IRM_HAS_LINK_OFF;
	}

	// NOTE: It is likely that the quirk detection for IRM device has not done yet.
	irm_device = fw_node_get_device(irm_node);
	if (irm_device)
		irm_device_quirks = READ_ONCE(irm_device->quirks);

Annotation

Implementation Notes