aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-06-10 02:40:49 -0400
committerClemens Ladisch <clemens@ladisch.de>2010-06-10 02:40:49 -0400
commite91b2787d0a2e4719b016e8dec0afd2d5ab6c30f (patch)
treee76a3665243ed9fb7275228d9a14dcb0eb5b567a /drivers/firewire
parent7e0e314f198d5048b74c8f0ef9f4c1c02e5ecfc9 (diff)
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: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/core-card.c16
-rw-r--r--drivers/firewire/core-topology.c3
-rw-r--r--drivers/firewire/core.h1
-rw-r--r--drivers/firewire/ohci.c18
4 files changed, 26 insertions, 12 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 7c4cf6cfa74..faf2eee473b 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -208,13 +208,19 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation)
208{ 208{
209 int channel, bandwidth = 0; 209 int channel, bandwidth = 0;
210 210
211 fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, 211 if (!card->broadcast_channel_allocated) {
212 &bandwidth, true, card->bm_transaction_data); 212 fw_iso_resource_manage(card, generation, 1ULL << 31,
213 if (channel == 31) { 213 &channel, &bandwidth, true,
214 card->bm_transaction_data);
215 if (channel != 31) {
216 fw_notify("failed to allocate broadcast channel\n");
217 return;
218 }
214 card->broadcast_channel_allocated = true; 219 card->broadcast_channel_allocated = true;
215 device_for_each_child(card->device, (void *)(long)generation,
216 fw_device_set_broadcast_channel);
217 } 220 }
221
222 device_for_each_child(card->device, (void *)(long)generation,
223 fw_device_set_broadcast_channel);
218} 224}
219 225
220static const char gap_count_table[] = { 226static const char gap_count_table[] = {
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index ca3c6531816..00a556f3a58 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -543,7 +543,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
543 543
544 spin_lock_irqsave(&card->lock, flags); 544 spin_lock_irqsave(&card->lock, flags);
545 545
546 card->broadcast_channel_allocated = false; 546 card->broadcast_channel_allocated = (card->driver->get_features(card) &
547 FEATURE_CHANNEL_31_ALLOCATED) != 0;
547 card->node_id = node_id; 548 card->node_id = node_id;
548 /* 549 /*
549 * Update node_id before generation to prevent anybody from using 550 * Update node_id before generation to prevent anybody from using
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index a9ace1f8dc3..3f9e39b60bc 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -39,6 +39,7 @@ struct fw_packet;
39#define BROADCAST_CHANNEL_VALID (1 << 30) 39#define BROADCAST_CHANNEL_VALID (1 << 30)
40 40
41#define FEATURE_PRIORITY_BUDGET 0x01 41#define FEATURE_PRIORITY_BUDGET 0x01
42#define FEATURE_CHANNEL_31_ALLOCATED 0x02
42 43
43#define CSR_STATE_BIT_CMSTR (1 << 8) 44#define CSR_STATE_BIT_CMSTR (1 << 8)
44#define CSR_STATE_BIT_ABDICATE (1 << 10) 45#define CSR_STATE_BIT_ABDICATE (1 << 10)
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 1dcc2e427eb..51a55808d88 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -171,6 +171,7 @@ struct fw_ohci {
171 int request_generation; /* for timestamping incoming requests */ 171 int request_generation; /* for timestamping incoming requests */
172 unsigned quirks; 172 unsigned quirks;
173 unsigned int pri_req_max; 173 unsigned int pri_req_max;
174 unsigned int features;
174 u32 bus_time; 175 u32 bus_time;
175 bool is_root; 176 bool is_root;
176 177
@@ -1694,7 +1695,7 @@ static int ohci_enable(struct fw_card *card,
1694{ 1695{
1695 struct fw_ohci *ohci = fw_ohci(card); 1696 struct fw_ohci *ohci = fw_ohci(card);
1696 struct pci_dev *dev = to_pci_dev(card->device); 1697 struct pci_dev *dev = to_pci_dev(card->device);
1697 u32 lps, seconds, irqs; 1698 u32 lps, seconds, version, irqs;
1698 int i, ret; 1699 int i, ret;
1699 1700
1700 if (software_reset(ohci)) { 1701 if (software_reset(ohci)) {
@@ -1747,10 +1748,19 @@ static int ohci_enable(struct fw_card *card,
1747 reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); 1748 reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25);
1748 ohci->bus_time = seconds & ~0x3f; 1749 ohci->bus_time = seconds & ~0x3f;
1749 1750
1751 version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
1752 if (version >= OHCI_VERSION_1_1) {
1753 reg_write(ohci, OHCI1394_InitialChannelsAvailableHi,
1754 0xfffffffe);
1755 ohci->features |= FEATURE_CHANNEL_31_ALLOCATED;
1756 }
1757
1750 /* Get implemented bits of the priority arbitration request counter. */ 1758 /* Get implemented bits of the priority arbitration request counter. */
1751 reg_write(ohci, OHCI1394_FairnessControl, 0x3f); 1759 reg_write(ohci, OHCI1394_FairnessControl, 0x3f);
1752 ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f; 1760 ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f;
1753 reg_write(ohci, OHCI1394_FairnessControl, 0); 1761 reg_write(ohci, OHCI1394_FairnessControl, 0);
1762 if (ohci->pri_req_max != 0)
1763 ohci->features |= FEATURE_PRIORITY_BUDGET;
1754 1764
1755 ar_context_run(&ohci->ar_request_ctx); 1765 ar_context_run(&ohci->ar_request_ctx);
1756 ar_context_run(&ohci->ar_response_ctx); 1766 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)
2124static unsigned int ohci_get_features(struct fw_card *card) 2134static unsigned int ohci_get_features(struct fw_card *card)
2125{ 2135{
2126 struct fw_ohci *ohci = fw_ohci(card); 2136 struct fw_ohci *ohci = fw_ohci(card);
2127 unsigned int features = 0;
2128
2129 if (ohci->pri_req_max != 0)
2130 features |= FEATURE_PRIORITY_BUDGET;
2131 2137
2132 return features; 2138 return ohci->features;
2133} 2139}
2134 2140
2135static void copy_iso_headers(struct iso_context *ctx, void *p) 2141static void copy_iso_headers(struct iso_context *ctx, void *p)