aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-01-26 00:38:45 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:02:48 -0500
commit931c4834c8d1e1bf0dcc256b89449a01711f970d (patch)
tree2d1b26b4418a034528acc98d38e179b57e2b3a56
parent9fc82689bf2920e9b3a8cc1766bcb6ad6454a7c4 (diff)
firewire: Implement compliant bus management.
Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/firewire/fw-card.c127
-rw-r--r--drivers/firewire/fw-device.c2
-rw-r--r--drivers/firewire/fw-topology.c7
-rw-r--r--drivers/firewire/fw-transaction.h6
4 files changed, 117 insertions, 25 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 307c8b851382..f94874ce58af 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -92,7 +92,7 @@ generate_config_rom (struct fw_card *card, size_t *config_rom_length)
92 bib_generation(card->config_rom_generation++ % 14 + 2) | 92 bib_generation(card->config_rom_generation++ % 14 + 2) |
93 bib_max_rom(2) | 93 bib_max_rom(2) |
94 bib_max_receive(card->max_receive) | 94 bib_max_receive(card->max_receive) |
95 bib_isc | bib_cmc | bib_imc; 95 bib_bmc | bib_isc | bib_cmc | bib_imc;
96 config_rom[3] = card->guid >> 32; 96 config_rom[3] = card->guid >> 32;
97 config_rom[4] = card->guid; 97 config_rom[4] = card->guid;
98 98
@@ -190,48 +190,137 @@ static const char gap_count_table[] = {
190 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 190 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
191}; 191};
192 192
193struct bm_data {
194 struct fw_transaction t;
195 struct {
196 __be32 arg;
197 __be32 data;
198 } lock;
199 u32 old;
200 int rcode;
201 struct completion done;
202};
203
193static void 204static void
194fw_card_irm_work(struct work_struct *work) 205complete_bm_lock(struct fw_card *card, int rcode,
206 void *payload, size_t length, void *data)
207{
208 struct bm_data *bmd = data;
209
210 if (rcode == RCODE_COMPLETE)
211 bmd->old = be32_to_cpu(*(__be32 *) payload);
212 bmd->rcode = rcode;
213 complete(&bmd->done);
214}
215
216static void
217fw_card_bm_work(struct work_struct *work)
195{ 218{
196 struct fw_card *card = container_of(work, struct fw_card, work.work); 219 struct fw_card *card = container_of(work, struct fw_card, work.work);
197 struct fw_device *root; 220 struct fw_device *root;
221 struct bm_data bmd;
198 unsigned long flags; 222 unsigned long flags;
199 int root_id, new_irm_id, gap_count, generation, do_reset = 0; 223 int root_id, new_root_id, irm_id, gap_count, generation, grace;
200 224 int do_reset = 0;
201 /* FIXME: This simple bus management unconditionally picks a
202 * cycle master if the current root can't do it. We need to
203 * not do this if there is a bus manager already. Also, some
204 * hubs set the contender bit, which is bogus, so we should
205 * probably do a little sanity check on the IRM (like, read
206 * the bandwidth register) if it's not us. */
207 225
208 spin_lock_irqsave(&card->lock, flags); 226 spin_lock_irqsave(&card->lock, flags);
209 227
210 generation = card->generation; 228 generation = card->generation;
211 root = card->root_node->data; 229 root = card->root_node->data;
212 root_id = card->root_node->node_id; 230 root_id = card->root_node->node_id;
231 grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10));
232
233 if (card->bm_generation + 1 == generation ||
234 (card->bm_generation != generation && grace)) {
235 /* This first step is to figure out who is IRM and
236 * then try to become bus manager. If the IRM is not
237 * well defined (e.g. does not have an active link
238 * layer or does not responds to our lock request, we
239 * will have to do a little vigilante bus management.
240 * In that case, we do a goto into the gap count logic
241 * so that when we do the reset, we still optimize the
242 * gap count. That could well save a reset in the
243 * next generation. */
244
245 irm_id = card->irm_node->node_id;
246 if (!card->irm_node->link_on) {
247 new_root_id = card->local_node->node_id;
248 fw_notify("IRM has link off, making local node (%02x) root.\n",
249 new_root_id);
250 goto pick_me;
251 }
252
253 bmd.lock.arg = cpu_to_be32(0x3f);
254 bmd.lock.data = cpu_to_be32(card->local_node->node_id);
255
256 spin_unlock_irqrestore(&card->lock, flags);
257
258 init_completion(&bmd.done);
259 fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP,
260 irm_id, generation,
261 SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
262 &bmd.lock, sizeof bmd.lock,
263 complete_bm_lock, &bmd);
264 wait_for_completion(&bmd.done);
265
266 if (bmd.rcode == RCODE_GENERATION) {
267 /* Another bus reset happened. Just return,
268 * the BM work has been rescheduled. */
269 return;
270 }
271
272 if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f)
273 /* Somebody else is BM, let them do the work. */
274 return;
275
276 spin_lock_irqsave(&card->lock, flags);
277 if (bmd.rcode != RCODE_COMPLETE) {
278 /* The lock request failed, maybe the IRM
279 * isn't really IRM capable after all. Let's
280 * do a bus reset and pick the local node as
281 * root, and thus, IRM. */
282 new_root_id = card->local_node->node_id;
283 fw_notify("BM lock failed, making local node (%02x) root.\n",
284 new_root_id);
285 goto pick_me;
286 }
287 } else if (card->bm_generation != generation) {
288 /* OK, we weren't BM in the last generation, and it's
289 * less than 100ms since last bus reset. Reschedule
290 * this task 100ms from now. */
291 spin_unlock_irqrestore(&card->lock, flags);
292 schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10));
293 return;
294 }
295
296 /* We're bus manager for this generation, so next step is to
297 * make sure we have an active cycle master and do gap count
298 * optimization. */
299 card->bm_generation = generation;
213 300
214 if (root == NULL) { 301 if (root == NULL) {
215 /* Either link_on is false, or we failed to read the 302 /* Either link_on is false, or we failed to read the
216 * config rom. In either case, pick another root. */ 303 * config rom. In either case, pick another root. */
217 new_irm_id = card->local_node->node_id; 304 new_root_id = card->local_node->node_id;
218 } else if (root->state != FW_DEVICE_RUNNING) { 305 } else if (root->state != FW_DEVICE_RUNNING) {
219 /* If we haven't probed this device yet, bail out now 306 /* If we haven't probed this device yet, bail out now
220 * and let's try again once that's done. */ 307 * and let's try again once that's done. */
221 new_irm_id = root_id; 308 spin_unlock_irqrestore(&card->lock, flags);
309 return;
222 } else if (root->config_rom[2] & bib_cmc) { 310 } else if (root->config_rom[2] & bib_cmc) {
223 /* FIXME: I suppose we should set the cmstr bit in the 311 /* FIXME: I suppose we should set the cmstr bit in the
224 * STATE_CLEAR register of this node, as described in 312 * STATE_CLEAR register of this node, as described in
225 * 1394-1995, 8.4.2.6. Also, send out a force root 313 * 1394-1995, 8.4.2.6. Also, send out a force root
226 * packet for this node. */ 314 * packet for this node. */
227 new_irm_id = root_id; 315 new_root_id = root_id;
228 } else { 316 } else {
229 /* Current root has an active link layer and we 317 /* Current root has an active link layer and we
230 * successfully read the config rom, but it's not 318 * successfully read the config rom, but it's not
231 * cycle master capable. */ 319 * cycle master capable. */
232 new_irm_id = card->local_node->node_id; 320 new_root_id = card->local_node->node_id;
233 } 321 }
234 322
323 pick_me:
235 /* Now figure out what gap count to set. */ 324 /* Now figure out what gap count to set. */
236 if (card->topology_type == FW_TOPOLOGY_A && 325 if (card->topology_type == FW_TOPOLOGY_A &&
237 card->root_node->max_hops < ARRAY_SIZE(gap_count_table)) 326 card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
@@ -243,16 +332,16 @@ fw_card_irm_work(struct work_struct *work)
243 * done less that 5 resets with the same physical topology and we 332 * done less that 5 resets with the same physical topology and we
244 * have either a new root or a new gap count setting, let's do it. */ 333 * have either a new root or a new gap count setting, let's do it. */
245 334
246 if (card->irm_retries++ < 5 && 335 if (card->bm_retries++ < 5 &&
247 (card->gap_count != gap_count || new_irm_id != root_id)) 336 (card->gap_count != gap_count || new_root_id != root_id))
248 do_reset = 1; 337 do_reset = 1;
249 338
250 spin_unlock_irqrestore(&card->lock, flags); 339 spin_unlock_irqrestore(&card->lock, flags);
251 340
252 if (do_reset) { 341 if (do_reset) {
253 fw_notify("phy config: card %d, new root=%x, gap_count=%d\n", 342 fw_notify("phy config: card %d, new root=%x, gap_count=%d\n",
254 card->index, new_irm_id, gap_count); 343 card->index, new_root_id, gap_count);
255 fw_send_phy_config(card, new_irm_id, generation, gap_count); 344 fw_send_phy_config(card, new_root_id, generation, gap_count);
256 fw_core_initiate_bus_reset(card, 1); 345 fw_core_initiate_bus_reset(card, 1);
257 } 346 }
258} 347}
@@ -294,7 +383,7 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
294 383
295 card->local_node = NULL; 384 card->local_node = NULL;
296 385
297 INIT_DELAYED_WORK(&card->work, fw_card_irm_work); 386 INIT_DELAYED_WORK(&card->work, fw_card_bm_work);
298 387
299 card->card_device.bus = &fw_bus_type; 388 card->card_device.bus = &fw_bus_type;
300 card->card_device.release = release_card; 389 card->card_device.release = release_card;
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index d71824bb61cb..4ea8d4d08a61 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -449,6 +449,8 @@ static void fw_device_init(struct work_struct *work)
449 } else { 449 } else {
450 fw_notify("giving up on config rom for node id %x\n", 450 fw_notify("giving up on config rom for node id %x\n",
451 device->node_id); 451 device->node_id);
452 if (device->node == device->card->root_node)
453 schedule_delayed_work(&device->card->work, 0);
452 fw_device_release(&device->device); 454 fw_device_release(&device->device);
453 } 455 }
454 return; 456 return;
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index fc8f1e7d3b07..27c6cb9c8367 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -476,12 +476,13 @@ fw_core_handle_bus_reset(struct fw_card *card,
476 * changed, either nodes were added or removed. In that case we 476 * changed, either nodes were added or removed. In that case we
477 * reset the IRM reset counter. */ 477 * reset the IRM reset counter. */
478 if (card->self_id_count != self_id_count) 478 if (card->self_id_count != self_id_count)
479 card->irm_retries = 0; 479 card->bm_retries = 0;
480 480
481 card->node_id = node_id; 481 card->node_id = node_id;
482 card->self_id_count = self_id_count; 482 card->self_id_count = self_id_count;
483 card->generation = generation; 483 card->generation = generation;
484 memcpy(card->self_ids, self_ids, self_id_count * 4); 484 memcpy(card->self_ids, self_ids, self_id_count * 4);
485 card->reset_jiffies = jiffies;
485 486
486 local_node = build_tree(card); 487 local_node = build_tree(card);
487 488
@@ -497,9 +498,7 @@ fw_core_handle_bus_reset(struct fw_card *card,
497 update_tree(card, local_node); 498 update_tree(card, local_node);
498 } 499 }
499 500
500 /* If we're not the root node, we may have to do some IRM work. */ 501 schedule_delayed_work(&card->work, 0);
501 if (card->local_node != card->root_node)
502 schedule_delayed_work(&card->work, 0);
503 502
504 spin_unlock_irqrestore(&card->lock, flags); 503 spin_unlock_irqrestore(&card->lock, flags);
505} 504}
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index ad7ba32755eb..50ec2c683a31 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -276,6 +276,7 @@ struct fw_card {
276 int current_tlabel, tlabel_mask; 276 int current_tlabel, tlabel_mask;
277 struct list_head transaction_list; 277 struct list_head transaction_list;
278 struct timer_list flush_timer; 278 struct timer_list flush_timer;
279 unsigned long reset_jiffies;
279 280
280 unsigned long long guid; 281 unsigned long long guid;
281 int max_receive; 282 int max_receive;
@@ -301,9 +302,10 @@ struct fw_card {
301 302
302 struct list_head link; 303 struct list_head link;
303 304
304 /* Work struct for IRM duties. */ 305 /* Work struct for BM duties. */
305 struct delayed_work work; 306 struct delayed_work work;
306 int irm_retries; 307 int bm_retries;
308 int bm_generation;
307}; 309};
308 310
309struct fw_card *fw_card_get(struct fw_card *card); 311struct fw_card *fw_card_get(struct fw_card *card);