Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e91b2787 authored by Clemens Ladisch's avatar Clemens Ladisch
Browse files

firewire: allocate broadcast channel in hardware



On OHCI 1.1 controllers, let the hardware allocate the broadcast channel
automatically.  This removes a theoretical race condition directly after
a bus reset where it could be possible to read the channel allocation
register with channel 31 still being unallocated.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent 7e0e314f
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -208,14 +208,20 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation)
{
	int channel, bandwidth = 0;

	fw_iso_resource_manage(card, generation, 1ULL << 31, &channel,
			       &bandwidth, true, card->bm_transaction_data);
	if (channel == 31) {
	if (!card->broadcast_channel_allocated) {
		fw_iso_resource_manage(card, generation, 1ULL << 31,
				       &channel, &bandwidth, true,
				       card->bm_transaction_data);
		if (channel != 31) {
			fw_notify("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);
}
}

static const char gap_count_table[] = {
	63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
+2 −1
Original line number Diff line number Diff line
@@ -543,7 +543,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,

	spin_lock_irqsave(&card->lock, flags);

	card->broadcast_channel_allocated = false;
	card->broadcast_channel_allocated = (card->driver->get_features(card) &
					     FEATURE_CHANNEL_31_ALLOCATED) != 0;
	card->node_id = node_id;
	/*
	 * Update node_id before generation to prevent anybody from using
+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ struct fw_packet;
#define BROADCAST_CHANNEL_VALID		(1 << 30)

#define FEATURE_PRIORITY_BUDGET		0x01
#define FEATURE_CHANNEL_31_ALLOCATED	0x02

#define CSR_STATE_BIT_CMSTR	(1 << 8)
#define CSR_STATE_BIT_ABDICATE	(1 << 10)
+12 −6
Original line number Diff line number Diff line
@@ -171,6 +171,7 @@ struct fw_ohci {
	int request_generation;	/* for timestamping incoming requests */
	unsigned quirks;
	unsigned int pri_req_max;
	unsigned int features;
	u32 bus_time;
	bool is_root;

@@ -1694,7 +1695,7 @@ static int ohci_enable(struct fw_card *card,
{
	struct fw_ohci *ohci = fw_ohci(card);
	struct pci_dev *dev = to_pci_dev(card->device);
	u32 lps, seconds, irqs;
	u32 lps, seconds, version, irqs;
	int i, ret;

	if (software_reset(ohci)) {
@@ -1747,10 +1748,19 @@ static int ohci_enable(struct fw_card *card,
	reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25);
	ohci->bus_time = seconds & ~0x3f;

	version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
	if (version >= OHCI_VERSION_1_1) {
		reg_write(ohci, OHCI1394_InitialChannelsAvailableHi,
			  0xfffffffe);
		ohci->features |= FEATURE_CHANNEL_31_ALLOCATED;
	}

	/* Get implemented bits of the priority arbitration request counter. */
	reg_write(ohci, OHCI1394_FairnessControl, 0x3f);
	ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f;
	reg_write(ohci, OHCI1394_FairnessControl, 0);
	if (ohci->pri_req_max != 0)
		ohci->features |= FEATURE_PRIORITY_BUDGET;

	ar_context_run(&ohci->ar_request_ctx);
	ar_context_run(&ohci->ar_response_ctx);
@@ -2124,12 +2134,8 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value)
static unsigned int ohci_get_features(struct fw_card *card)
{
	struct fw_ohci *ohci = fw_ohci(card);
	unsigned int features = 0;

	if (ohci->pri_req_max != 0)
		features |= FEATURE_PRIORITY_BUDGET;

	return features;
	return ohci->features;
}

static void copy_iso_headers(struct iso_context *ctx, void *p)