aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-card.c
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 /drivers/firewire/fw-card.c
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>
Diffstat (limited to 'drivers/firewire/fw-card.c')
-rw-r--r--drivers/firewire/fw-card.c127
1 files changed, 108 insertions, 19 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;