aboutsummaryrefslogtreecommitdiff
path: root/drivers/firewire/fw-device.c
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2009-03-10 21:09:28 +0100
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-03-24 20:56:52 +0100
commit7889b60ee71eafaf50699a154a2455424bb92daa (patch)
treed5bb3a4d274bf186e32605284a34a36398475818 /drivers/firewire/fw-device.c
parentcbae787c0f288c3ad385ad4165ae30b5500a1f23 (diff)
firewire: core: optimize propagation of BROADCAST_CHANNEL
Cache the test result of whether a device implements BROADCAST_CHANNEL. This minimizes traffic on the bus after each bus reset. A majority of devices does not implement BROADCAST_CHANNEL. Remove busy retries; just rely on the hardware to retry requests to busy responders. Remove unnecessary log messages. Rename the flag is_irm to broadcast_channel_allocated to better reflect its meaning. Reset the flag earlier in fw_core_handle_bus_reset. Pass the generation down as a call parameter; that way generation can't be newer than card->broadcast_channel_allocated and device->node_id. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-device.c')
-rw-r--r--drivers/firewire/fw-device.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index a40444e8eb2..a47e2129d83 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -518,7 +518,7 @@ static int read_bus_info_block(struct fw_device *device, int generation)
kfree(old_rom);
ret = 0;
- device->cmc = rom[2] & 1 << 30;
+ device->cmc = rom[2] >> 30 & 1;
out:
kfree(rom);
@@ -756,6 +756,44 @@ static int lookup_existing_device(struct device *dev, void *data)
return match;
}
+enum { BC_UNKNOWN = 0, BC_UNIMPLEMENTED, BC_IMPLEMENTED, };
+
+void fw_device_set_broadcast_channel(struct fw_device *device, int generation)
+{
+ struct fw_card *card = device->card;
+ __be32 data;
+ int rcode;
+
+ if (!card->broadcast_channel_allocated)
+ return;
+
+ if (device->bc_implemented == BC_UNKNOWN) {
+ rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST,
+ device->node_id, generation, device->max_speed,
+ CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL,
+ &data, 4);
+ switch (rcode) {
+ case RCODE_COMPLETE:
+ if (data & cpu_to_be32(1 << 31)) {
+ device->bc_implemented = BC_IMPLEMENTED;
+ break;
+ }
+ /* else fall through to case address error */
+ case RCODE_ADDRESS_ERROR:
+ device->bc_implemented = BC_UNIMPLEMENTED;
+ }
+ }
+
+ if (device->bc_implemented == BC_IMPLEMENTED) {
+ data = cpu_to_be32(BROADCAST_CHANNEL_INITIAL |
+ BROADCAST_CHANNEL_VALID);
+ fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST,
+ device->node_id, generation, device->max_speed,
+ CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL,
+ &data, 4);
+ }
+}
+
static void fw_device_init(struct work_struct *work)
{
struct fw_device *device =
@@ -849,9 +887,8 @@ static void fw_device_init(struct work_struct *work)
device->config_rom[3], device->config_rom[4],
1 << device->max_speed);
device->config_rom_retries = 0;
- if (device->card->is_irm)
- fw_irm_set_broadcast_channel_register(&device->device,
- NULL);
+
+ fw_device_set_broadcast_channel(device, device->generation);
}
/*