diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 121 |
1 files changed, 120 insertions, 1 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 83d1451fa714..d5f03a6e3334 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -67,6 +67,8 @@ enum { | |||
67 | ATA_ECAT_DUBIOUS_UNK_DEV = 7, | 67 | ATA_ECAT_DUBIOUS_UNK_DEV = 7, |
68 | ATA_ECAT_NR = 8, | 68 | ATA_ECAT_NR = 8, |
69 | 69 | ||
70 | ATA_EH_CMD_DFL_TIMEOUT = 5000, | ||
71 | |||
70 | /* always put at least this amount of time between resets */ | 72 | /* always put at least this amount of time between resets */ |
71 | ATA_EH_RESET_COOL_DOWN = 5000, | 73 | ATA_EH_RESET_COOL_DOWN = 5000, |
72 | 74 | ||
@@ -93,6 +95,53 @@ static const unsigned long ata_eh_reset_timeouts[] = { | |||
93 | ULONG_MAX, /* > 1 min has elapsed, give up */ | 95 | ULONG_MAX, /* > 1 min has elapsed, give up */ |
94 | }; | 96 | }; |
95 | 97 | ||
98 | static const unsigned long ata_eh_identify_timeouts[] = { | ||
99 | 5000, /* covers > 99% of successes and not too boring on failures */ | ||
100 | 10000, /* combined time till here is enough even for media access */ | ||
101 | 30000, /* for true idiots */ | ||
102 | ULONG_MAX, | ||
103 | }; | ||
104 | |||
105 | static const unsigned long ata_eh_other_timeouts[] = { | ||
106 | 5000, /* same rationale as identify timeout */ | ||
107 | 10000, /* ditto */ | ||
108 | /* but no merciful 30sec for other commands, it just isn't worth it */ | ||
109 | ULONG_MAX, | ||
110 | }; | ||
111 | |||
112 | struct ata_eh_cmd_timeout_ent { | ||
113 | const u8 *commands; | ||
114 | const unsigned long *timeouts; | ||
115 | }; | ||
116 | |||
117 | /* The following table determines timeouts to use for EH internal | ||
118 | * commands. Each table entry is a command class and matches the | ||
119 | * commands the entry applies to and the timeout table to use. | ||
120 | * | ||
121 | * On the retry after a command timed out, the next timeout value from | ||
122 | * the table is used. If the table doesn't contain further entries, | ||
123 | * the last value is used. | ||
124 | * | ||
125 | * ehc->cmd_timeout_idx keeps track of which timeout to use per | ||
126 | * command class, so if SET_FEATURES times out on the first try, the | ||
127 | * next try will use the second timeout value only for that class. | ||
128 | */ | ||
129 | #define CMDS(cmds...) (const u8 []){ cmds, 0 } | ||
130 | static const struct ata_eh_cmd_timeout_ent | ||
131 | ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = { | ||
132 | { .commands = CMDS(ATA_CMD_ID_ATA, ATA_CMD_ID_ATAPI), | ||
133 | .timeouts = ata_eh_identify_timeouts, }, | ||
134 | { .commands = CMDS(ATA_CMD_READ_NATIVE_MAX, ATA_CMD_READ_NATIVE_MAX_EXT), | ||
135 | .timeouts = ata_eh_other_timeouts, }, | ||
136 | { .commands = CMDS(ATA_CMD_SET_MAX, ATA_CMD_SET_MAX_EXT), | ||
137 | .timeouts = ata_eh_other_timeouts, }, | ||
138 | { .commands = CMDS(ATA_CMD_SET_FEATURES), | ||
139 | .timeouts = ata_eh_other_timeouts, }, | ||
140 | { .commands = CMDS(ATA_CMD_INIT_DEV_PARAMS), | ||
141 | .timeouts = ata_eh_other_timeouts, }, | ||
142 | }; | ||
143 | #undef CMDS | ||
144 | |||
96 | static void __ata_port_freeze(struct ata_port *ap); | 145 | static void __ata_port_freeze(struct ata_port *ap); |
97 | #ifdef CONFIG_PM | 146 | #ifdef CONFIG_PM |
98 | static void ata_eh_handle_port_suspend(struct ata_port *ap); | 147 | static void ata_eh_handle_port_suspend(struct ata_port *ap); |
@@ -238,6 +287,73 @@ void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset, | |||
238 | 287 | ||
239 | #endif /* CONFIG_PCI */ | 288 | #endif /* CONFIG_PCI */ |
240 | 289 | ||
290 | static int ata_lookup_timeout_table(u8 cmd) | ||
291 | { | ||
292 | int i; | ||
293 | |||
294 | for (i = 0; i < ATA_EH_CMD_TIMEOUT_TABLE_SIZE; i++) { | ||
295 | const u8 *cur; | ||
296 | |||
297 | for (cur = ata_eh_cmd_timeout_table[i].commands; *cur; cur++) | ||
298 | if (*cur == cmd) | ||
299 | return i; | ||
300 | } | ||
301 | |||
302 | return -1; | ||
303 | } | ||
304 | |||
305 | /** | ||
306 | * ata_internal_cmd_timeout - determine timeout for an internal command | ||
307 | * @dev: target device | ||
308 | * @cmd: internal command to be issued | ||
309 | * | ||
310 | * Determine timeout for internal command @cmd for @dev. | ||
311 | * | ||
312 | * LOCKING: | ||
313 | * EH context. | ||
314 | * | ||
315 | * RETURNS: | ||
316 | * Determined timeout. | ||
317 | */ | ||
318 | unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd) | ||
319 | { | ||
320 | struct ata_eh_context *ehc = &dev->link->eh_context; | ||
321 | int ent = ata_lookup_timeout_table(cmd); | ||
322 | int idx; | ||
323 | |||
324 | if (ent < 0) | ||
325 | return ATA_EH_CMD_DFL_TIMEOUT; | ||
326 | |||
327 | idx = ehc->cmd_timeout_idx[dev->devno][ent]; | ||
328 | return ata_eh_cmd_timeout_table[ent].timeouts[idx]; | ||
329 | } | ||
330 | |||
331 | /** | ||
332 | * ata_internal_cmd_timed_out - notification for internal command timeout | ||
333 | * @dev: target device | ||
334 | * @cmd: internal command which timed out | ||
335 | * | ||
336 | * Notify EH that internal command @cmd for @dev timed out. This | ||
337 | * function should be called only for commands whose timeouts are | ||
338 | * determined using ata_internal_cmd_timeout(). | ||
339 | * | ||
340 | * LOCKING: | ||
341 | * EH context. | ||
342 | */ | ||
343 | void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd) | ||
344 | { | ||
345 | struct ata_eh_context *ehc = &dev->link->eh_context; | ||
346 | int ent = ata_lookup_timeout_table(cmd); | ||
347 | int idx; | ||
348 | |||
349 | if (ent < 0) | ||
350 | return; | ||
351 | |||
352 | idx = ehc->cmd_timeout_idx[dev->devno][ent]; | ||
353 | if (ata_eh_cmd_timeout_table[ent].timeouts[idx + 1] != ULONG_MAX) | ||
354 | ehc->cmd_timeout_idx[dev->devno][ent]++; | ||
355 | } | ||
356 | |||
241 | static void ata_ering_record(struct ata_ering *ering, unsigned int eflags, | 357 | static void ata_ering_record(struct ata_ering *ering, unsigned int eflags, |
242 | unsigned int err_mask) | 358 | unsigned int err_mask) |
243 | { | 359 | { |
@@ -2600,8 +2716,11 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) | |||
2600 | ata_eh_detach_dev(dev); | 2716 | ata_eh_detach_dev(dev); |
2601 | 2717 | ||
2602 | /* schedule probe if necessary */ | 2718 | /* schedule probe if necessary */ |
2603 | if (ata_eh_schedule_probe(dev)) | 2719 | if (ata_eh_schedule_probe(dev)) { |
2604 | ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; | 2720 | ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; |
2721 | memset(ehc->cmd_timeout_idx[dev->devno], 0, | ||
2722 | sizeof(ehc->cmd_timeout_idx[dev->devno])); | ||
2723 | } | ||
2605 | 2724 | ||
2606 | return 1; | 2725 | return 1; |
2607 | } else { | 2726 | } else { |