aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2009-03-10 16:09:28 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-03-24 15:56:52 -0400
commit7889b60ee71eafaf50699a154a2455424bb92daa (patch)
treed5bb3a4d274bf186e32605284a34a36398475818 /drivers
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')
-rw-r--r--drivers/firewire/fw-card.c85
-rw-r--r--drivers/firewire/fw-device.c45
-rw-r--r--drivers/firewire/fw-device.h5
-rw-r--r--drivers/firewire/fw-topology.c1
-rw-r--r--drivers/firewire/fw-transaction.h6
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 184static 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 */
190int 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;
209tryagain_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 &regval, 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);
239tryagain_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 &regval, 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
759enum { BC_UNKNOWN = 0, BC_UNIMPLEMENTED, BC_IMPLEMENTED, };
760
761void 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
759static void fw_device_init(struct work_struct *work) 797static 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
110struct fw_device *fw_device_get_by_devt(dev_t devt); 112struct fw_device *fw_device_get_by_devt(dev_t devt);
111int fw_device_enable_phys_dma(struct fw_device *device); 113int fw_device_enable_phys_dma(struct fw_device *device);
114void fw_device_set_broadcast_channel(struct fw_device *device, int generation);
112 115
113void fw_device_cdev_update(struct fw_device *device); 116void fw_device_cdev_update(struct fw_device *device);
114void fw_device_cdev_remove(struct fw_device *device); 117void 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};