diff options
| author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-03-10 16:09:28 -0400 |
|---|---|---|
| committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-03-24 15:56:52 -0400 |
| commit | 7889b60ee71eafaf50699a154a2455424bb92daa (patch) | |
| tree | d5bb3a4d274bf186e32605284a34a36398475818 /drivers | |
| parent | cbae787c0f288c3ad385ad4165ae30b5500a1f23 (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')
| -rw-r--r-- | drivers/firewire/fw-card.c | 85 | ||||
| -rw-r--r-- | drivers/firewire/fw-device.c | 45 | ||||
| -rw-r--r-- | drivers/firewire/fw-device.h | 5 | ||||
| -rw-r--r-- | drivers/firewire/fw-topology.c | 1 | ||||
| -rw-r--r-- | drivers/firewire/fw-transaction.h | 6 |
5 files changed, 52 insertions, 90 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index d63d0ed9e048..8b8c8c22f0fc 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c | |||
| @@ -181,83 +181,9 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) | |||
| 181 | mutex_unlock(&card_mutex); | 181 | mutex_unlock(&card_mutex); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | #define IRM_RETRIES 2 | 184 | static int set_broadcast_channel(struct device *dev, void *data) |
| 185 | |||
| 186 | /* | ||
| 187 | * The abi is set by device_for_each_child(), even though we have no use | ||
| 188 | * for data, nor do we have a meaningful return value. | ||
| 189 | */ | ||
| 190 | int fw_irm_set_broadcast_channel_register(struct device *dev, void *data) | ||
| 191 | { | 185 | { |
| 192 | struct fw_device *d; | 186 | fw_device_set_broadcast_channel(fw_device(dev), (long)data); |
| 193 | int rcode; | ||
| 194 | int node_id; | ||
| 195 | int max_speed; | ||
| 196 | int retries; | ||
| 197 | int generation; | ||
| 198 | __be32 regval; | ||
| 199 | struct fw_card *card; | ||
| 200 | |||
| 201 | d = fw_device(dev); | ||
| 202 | /* FIXME: do we need locking here? */ | ||
| 203 | generation = d->generation; | ||
| 204 | smp_rmb(); /* Ensure generation is at least as old as node_id */ | ||
| 205 | node_id = d->node_id; | ||
| 206 | max_speed = d->max_speed; | ||
| 207 | retries = IRM_RETRIES; | ||
| 208 | card = d->card; | ||
| 209 | tryagain_r: | ||
| 210 | rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST, | ||
| 211 | node_id, generation, max_speed, | ||
| 212 | CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, | ||
| 213 | ®val, 4); | ||
| 214 | switch (rcode) { | ||
| 215 | case RCODE_BUSY: | ||
| 216 | if (retries--) | ||
| 217 | goto tryagain_r; | ||
| 218 | fw_notify("node %x read broadcast channel busy\n", | ||
| 219 | node_id); | ||
| 220 | return 0; | ||
| 221 | |||
| 222 | default: | ||
| 223 | fw_notify("node %x read broadcast channel failed %x\n", | ||
| 224 | node_id, rcode); | ||
| 225 | return 0; | ||
| 226 | |||
| 227 | case RCODE_COMPLETE: | ||
| 228 | /* | ||
| 229 | * Paranoid reporting of nonstandard broadcast channel | ||
| 230 | * contents goes here | ||
| 231 | */ | ||
| 232 | if (regval != cpu_to_be32(BROADCAST_CHANNEL_INITIAL)) | ||
| 233 | return 0; | ||
| 234 | break; | ||
| 235 | } | ||
| 236 | retries = IRM_RETRIES; | ||
| 237 | regval = cpu_to_be32(BROADCAST_CHANNEL_INITIAL | | ||
| 238 | BROADCAST_CHANNEL_VALID); | ||
| 239 | tryagain_w: | ||
| 240 | rcode = fw_run_transaction(card, | ||
| 241 | TCODE_WRITE_QUADLET_REQUEST, node_id, | ||
| 242 | generation, max_speed, | ||
| 243 | CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, | ||
| 244 | ®val, 4); | ||
| 245 | switch (rcode) { | ||
| 246 | case RCODE_BUSY: | ||
| 247 | if (retries--) | ||
| 248 | goto tryagain_w; | ||
| 249 | fw_notify("node %x write broadcast channel busy\n", | ||
| 250 | node_id); | ||
| 251 | return 0; | ||
| 252 | |||
| 253 | default: | ||
| 254 | fw_notify("node %x write broadcast channel failed %x\n", | ||
| 255 | node_id, rcode); | ||
| 256 | return 0; | ||
| 257 | |||
| 258 | case RCODE_COMPLETE: | ||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | return 0; | 187 | return 0; |
| 262 | } | 188 | } |
| 263 | 189 | ||
| @@ -268,9 +194,9 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) | |||
| 268 | fw_iso_resource_manage(card, generation, 1ULL << 31, | 194 | fw_iso_resource_manage(card, generation, 1ULL << 31, |
| 269 | &channel, &bandwidth, true); | 195 | &channel, &bandwidth, true); |
| 270 | if (channel == 31) { | 196 | if (channel == 31) { |
| 271 | card->is_irm = true; | 197 | card->broadcast_channel_allocated = true; |
| 272 | device_for_each_child(card->device, NULL, | 198 | device_for_each_child(card->device, (void *)(long)generation, |
| 273 | fw_irm_set_broadcast_channel_register); | 199 | set_broadcast_channel); |
| 274 | } | 200 | } |
| 275 | } | 201 | } |
| 276 | 202 | ||
| @@ -302,7 +228,6 @@ static void fw_card_bm_work(struct work_struct *work) | |||
| 302 | __be32 lock_data[2]; | 228 | __be32 lock_data[2]; |
| 303 | 229 | ||
| 304 | spin_lock_irqsave(&card->lock, flags); | 230 | spin_lock_irqsave(&card->lock, flags); |
| 305 | card->is_irm = false; | ||
| 306 | 231 | ||
| 307 | if (card->local_node == NULL) { | 232 | if (card->local_node == NULL) { |
| 308 | spin_unlock_irqrestore(&card->lock, flags); | 233 | spin_unlock_irqrestore(&card->lock, flags); |
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index a40444e8eb20..a47e2129d83d 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) | |||
| 518 | 518 | ||
| 519 | kfree(old_rom); | 519 | kfree(old_rom); |
| 520 | ret = 0; | 520 | ret = 0; |
| 521 | device->cmc = rom[2] & 1 << 30; | 521 | device->cmc = rom[2] >> 30 & 1; |
| 522 | out: | 522 | out: |
| 523 | kfree(rom); | 523 | kfree(rom); |
| 524 | 524 | ||
| @@ -756,6 +756,44 @@ static int lookup_existing_device(struct device *dev, void *data) | |||
| 756 | return match; | 756 | return match; |
| 757 | } | 757 | } |
| 758 | 758 | ||
| 759 | enum { BC_UNKNOWN = 0, BC_UNIMPLEMENTED, BC_IMPLEMENTED, }; | ||
| 760 | |||
| 761 | void fw_device_set_broadcast_channel(struct fw_device *device, int generation) | ||
| 762 | { | ||
| 763 | struct fw_card *card = device->card; | ||
| 764 | __be32 data; | ||
| 765 | int rcode; | ||
| 766 | |||
| 767 | if (!card->broadcast_channel_allocated) | ||
| 768 | return; | ||
| 769 | |||
| 770 | if (device->bc_implemented == BC_UNKNOWN) { | ||
| 771 | rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST, | ||
| 772 | device->node_id, generation, device->max_speed, | ||
| 773 | CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, | ||
| 774 | &data, 4); | ||
| 775 | switch (rcode) { | ||
| 776 | case RCODE_COMPLETE: | ||
| 777 | if (data & cpu_to_be32(1 << 31)) { | ||
| 778 | device->bc_implemented = BC_IMPLEMENTED; | ||
| 779 | break; | ||
| 780 | } | ||
| 781 | /* else fall through to case address error */ | ||
| 782 | case RCODE_ADDRESS_ERROR: | ||
| 783 | device->bc_implemented = BC_UNIMPLEMENTED; | ||
| 784 | } | ||
| 785 | } | ||
| 786 | |||
| 787 | if (device->bc_implemented == BC_IMPLEMENTED) { | ||
| 788 | data = cpu_to_be32(BROADCAST_CHANNEL_INITIAL | | ||
| 789 | BROADCAST_CHANNEL_VALID); | ||
| 790 | fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, | ||
| 791 | device->node_id, generation, device->max_speed, | ||
| 792 | CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL, | ||
| 793 | &data, 4); | ||
| 794 | } | ||
| 795 | } | ||
| 796 | |||
| 759 | static void fw_device_init(struct work_struct *work) | 797 | static void fw_device_init(struct work_struct *work) |
| 760 | { | 798 | { |
| 761 | struct fw_device *device = | 799 | struct fw_device *device = |
| @@ -849,9 +887,8 @@ static void fw_device_init(struct work_struct *work) | |||
| 849 | device->config_rom[3], device->config_rom[4], | 887 | device->config_rom[3], device->config_rom[4], |
| 850 | 1 << device->max_speed); | 888 | 1 << device->max_speed); |
| 851 | device->config_rom_retries = 0; | 889 | device->config_rom_retries = 0; |
| 852 | if (device->card->is_irm) | 890 | |
| 853 | fw_irm_set_broadcast_channel_register(&device->device, | 891 | fw_device_set_broadcast_channel(device, device->generation); |
| 854 | NULL); | ||
| 855 | } | 892 | } |
| 856 | 893 | ||
| 857 | /* | 894 | /* |
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 3085a74669b5..97588937c018 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h | |||
| @@ -71,7 +71,6 @@ struct fw_device { | |||
| 71 | int node_id; | 71 | int node_id; |
| 72 | int generation; | 72 | int generation; |
| 73 | unsigned max_speed; | 73 | unsigned max_speed; |
| 74 | bool cmc; | ||
| 75 | struct fw_card *card; | 74 | struct fw_card *card; |
| 76 | struct device device; | 75 | struct device device; |
| 77 | 76 | ||
| @@ -81,6 +80,9 @@ struct fw_device { | |||
| 81 | u32 *config_rom; | 80 | u32 *config_rom; |
| 82 | size_t config_rom_length; | 81 | size_t config_rom_length; |
| 83 | int config_rom_retries; | 82 | int config_rom_retries; |
| 83 | unsigned cmc:1; | ||
| 84 | unsigned bc_implemented:2; | ||
| 85 | |||
| 84 | struct delayed_work work; | 86 | struct delayed_work work; |
| 85 | struct fw_attribute_group attribute_group; | 87 | struct fw_attribute_group attribute_group; |
| 86 | }; | 88 | }; |
| @@ -109,6 +111,7 @@ static inline void fw_device_put(struct fw_device *device) | |||
| 109 | 111 | ||
| 110 | struct fw_device *fw_device_get_by_devt(dev_t devt); | 112 | struct fw_device *fw_device_get_by_devt(dev_t devt); |
| 111 | int fw_device_enable_phys_dma(struct fw_device *device); | 113 | int fw_device_enable_phys_dma(struct fw_device *device); |
| 114 | void fw_device_set_broadcast_channel(struct fw_device *device, int generation); | ||
| 112 | 115 | ||
| 113 | void fw_device_cdev_update(struct fw_device *device); | 116 | void fw_device_cdev_update(struct fw_device *device); |
| 114 | void fw_device_cdev_remove(struct fw_device *device); | 117 | void fw_device_cdev_remove(struct fw_device *device); |
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index b44131cf0c62..d0deecc4de93 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c | |||
| @@ -526,6 +526,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, | |||
| 526 | 526 | ||
| 527 | spin_lock_irqsave(&card->lock, flags); | 527 | spin_lock_irqsave(&card->lock, flags); |
| 528 | 528 | ||
| 529 | card->broadcast_channel_allocated = false; | ||
| 529 | card->node_id = node_id; | 530 | card->node_id = node_id; |
| 530 | /* | 531 | /* |
| 531 | * Update node_id before generation to prevent anybody from using | 532 | * Update node_id before generation to prevent anybody from using |
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index d4f42cecbdfa..dfa799068f89 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
| @@ -230,11 +230,6 @@ struct fw_card { | |||
| 230 | u8 color; /* must be u8 to match the definition in struct fw_node */ | 230 | u8 color; /* must be u8 to match the definition in struct fw_node */ |
| 231 | int gap_count; | 231 | int gap_count; |
| 232 | bool beta_repeaters_present; | 232 | bool beta_repeaters_present; |
| 233 | /* | ||
| 234 | * Set if the local device is the IRM and the broadcast channel | ||
| 235 | * was allocated. | ||
| 236 | */ | ||
| 237 | bool is_irm; | ||
| 238 | 233 | ||
| 239 | int index; | 234 | int index; |
| 240 | 235 | ||
| @@ -245,6 +240,7 @@ struct fw_card { | |||
| 245 | int bm_retries; | 240 | int bm_retries; |
| 246 | int bm_generation; | 241 | int bm_generation; |
| 247 | 242 | ||
| 243 | bool broadcast_channel_allocated; | ||
| 248 | u32 broadcast_channel; | 244 | u32 broadcast_channel; |
| 249 | u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; | 245 | u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; |
| 250 | }; | 246 | }; |
