aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-card.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@localhost.localdomain>2007-01-26 00:37:50 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:02:44 -0500
commit83db801ce8c644edee49f4364c7ebdfef1657762 (patch)
tree8180198c618d78ce7b774951ffa4e1a6d553a7e1 /drivers/firewire/fw-card.c
parentcfb01381f4ffcd05aefe76c74911ba6bc996e8ba (diff)
firewire: Implement gap count optimization.
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.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index c8b7d695c81d..307c8b851382 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -186,14 +186,17 @@ fw_core_remove_descriptor (struct fw_descriptor *desc)
186} 186}
187EXPORT_SYMBOL(fw_core_remove_descriptor); 187EXPORT_SYMBOL(fw_core_remove_descriptor);
188 188
189static const char gap_count_table[] = {
190 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
191};
192
189static void 193static void
190fw_card_irm_work(struct work_struct *work) 194fw_card_irm_work(struct work_struct *work)
191{ 195{
192 struct fw_card *card = 196 struct fw_card *card = container_of(work, struct fw_card, work.work);
193 container_of(work, struct fw_card, work.work);
194 struct fw_device *root; 197 struct fw_device *root;
195 unsigned long flags; 198 unsigned long flags;
196 int new_irm_id, generation; 199 int root_id, new_irm_id, gap_count, generation, do_reset = 0;
197 200
198 /* FIXME: This simple bus management unconditionally picks a 201 /* FIXME: This simple bus management unconditionally picks a
199 * cycle master if the current root can't do it. We need to 202 * cycle master if the current root can't do it. We need to
@@ -206,35 +209,50 @@ fw_card_irm_work(struct work_struct *work)
206 209
207 generation = card->generation; 210 generation = card->generation;
208 root = card->root_node->data; 211 root = card->root_node->data;
212 root_id = card->root_node->node_id;
209 213
210 if (root == NULL) 214 if (root == NULL) {
211 /* Either link_on is false, or we failed to read the 215 /* Either link_on is false, or we failed to read the
212 * config rom. In either case, pick another root. */ 216 * config rom. In either case, pick another root. */
213 new_irm_id = card->local_node->node_id; 217 new_irm_id = card->local_node->node_id;
214 else if (root->state != FW_DEVICE_RUNNING) 218 } else if (root->state != FW_DEVICE_RUNNING) {
215 /* If we haven't probed this device yet, bail out now 219 /* If we haven't probed this device yet, bail out now
216 * and let's try again once that's done. */ 220 * and let's try again once that's done. */
217 new_irm_id = -1; 221 new_irm_id = root_id;
218 else if (root->config_rom[2] & bib_cmc) 222 } else if (root->config_rom[2] & bib_cmc) {
219 /* FIXME: I suppose we should set the cmstr bit in the 223 /* FIXME: I suppose we should set the cmstr bit in the
220 * STATE_CLEAR register of this node, as described in 224 * STATE_CLEAR register of this node, as described in
221 * 1394-1995, 8.4.2.6. Also, send out a force root 225 * 1394-1995, 8.4.2.6. Also, send out a force root
222 * packet for this node. */ 226 * packet for this node. */
223 new_irm_id = -1; 227 new_irm_id = root_id;
224 else 228 } else {
225 /* Current root has an active link layer and we 229 /* Current root has an active link layer and we
226 * successfully read the config rom, but it's not 230 * successfully read the config rom, but it's not
227 * cycle master capable. */ 231 * cycle master capable. */
228 new_irm_id = card->local_node->node_id; 232 new_irm_id = card->local_node->node_id;
233 }
234
235 /* Now figure out what gap count to set. */
236 if (card->topology_type == FW_TOPOLOGY_A &&
237 card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
238 gap_count = gap_count_table[card->root_node->max_hops];
239 else
240 gap_count = 63;
241
242 /* Finally, figure out if we should do a reset or not. If we've
243 * 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. */
229 245
230 if (card->irm_retries++ > 5) 246 if (card->irm_retries++ < 5 &&
231 new_irm_id = -1; 247 (card->gap_count != gap_count || new_irm_id != root_id))
248 do_reset = 1;
232 249
233 spin_unlock_irqrestore(&card->lock, flags); 250 spin_unlock_irqrestore(&card->lock, flags);
234 251
235 if (new_irm_id > 0) { 252 if (do_reset) {
236 fw_notify("Trying to become root (card %d)\n", card->index); 253 fw_notify("phy config: card %d, new root=%x, gap_count=%d\n",
237 fw_send_force_root(card, new_irm_id, generation); 254 card->index, new_irm_id, gap_count);
255 fw_send_phy_config(card, new_irm_id, generation, gap_count);
238 fw_core_initiate_bus_reset(card, 1); 256 fw_core_initiate_bus_reset(card, 1);
239 } 257 }
240} 258}