diff options
author | Kristian Høgsberg <krh@localhost.localdomain> | 2007-01-26 00:37:50 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-03-09 16:02:44 -0500 |
commit | 83db801ce8c644edee49f4364c7ebdfef1657762 (patch) | |
tree | 8180198c618d78ce7b774951ffa4e1a6d553a7e1 /drivers/firewire/fw-card.c | |
parent | cfb01381f4ffcd05aefe76c74911ba6bc996e8ba (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.c | 46 |
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 | } |
187 | EXPORT_SYMBOL(fw_core_remove_descriptor); | 187 | EXPORT_SYMBOL(fw_core_remove_descriptor); |
188 | 188 | ||
189 | static const char gap_count_table[] = { | ||
190 | 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 | ||
191 | }; | ||
192 | |||
189 | static void | 193 | static void |
190 | fw_card_irm_work(struct work_struct *work) | 194 | fw_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 | } |