aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-eh.c30
-rw-r--r--include/linux/libata.h3
2 files changed, 32 insertions, 1 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 8f8ed4dfb171..fbbf79163900 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1308,6 +1308,7 @@ static void ata_eh_analyze_serror(struct ata_link *link)
1308 struct ata_eh_context *ehc = &link->eh_context; 1308 struct ata_eh_context *ehc = &link->eh_context;
1309 u32 serror = ehc->i.serror; 1309 u32 serror = ehc->i.serror;
1310 unsigned int err_mask = 0, action = 0; 1310 unsigned int err_mask = 0, action = 0;
1311 u32 hotplug_mask;
1311 1312
1312 if (serror & SERR_PERSISTENT) { 1313 if (serror & SERR_PERSISTENT) {
1313 err_mask |= AC_ERR_ATA_BUS; 1314 err_mask |= AC_ERR_ATA_BUS;
@@ -1326,7 +1327,20 @@ static void ata_eh_analyze_serror(struct ata_link *link)
1326 err_mask |= AC_ERR_SYSTEM; 1327 err_mask |= AC_ERR_SYSTEM;
1327 action |= ATA_EH_HARDRESET; 1328 action |= ATA_EH_HARDRESET;
1328 } 1329 }
1329 if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) 1330
1331 /* Determine whether a hotplug event has occurred. Both
1332 * SError.N/X are considered hotplug events for enabled or
1333 * host links. For disabled PMP links, only N bit is
1334 * considered as X bit is left at 1 for link plugging.
1335 */
1336 hotplug_mask = 0;
1337
1338 if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
1339 hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG;
1340 else
1341 hotplug_mask = SERR_PHYRDY_CHG;
1342
1343 if (serror & hotplug_mask)
1330 ata_ehi_hotplugged(&ehc->i); 1344 ata_ehi_hotplugged(&ehc->i);
1331 1345
1332 ehc->i.err_mask |= err_mask; 1346 ehc->i.err_mask |= err_mask;
@@ -2227,6 +2241,10 @@ static int ata_eh_skip_recovery(struct ata_link *link)
2227 struct ata_eh_context *ehc = &link->eh_context; 2241 struct ata_eh_context *ehc = &link->eh_context;
2228 struct ata_device *dev; 2242 struct ata_device *dev;
2229 2243
2244 /* skip disabled links */
2245 if (link->flags & ATA_LFLAG_DISABLED)
2246 return 1;
2247
2230 /* thaw frozen port, resume link and recover failed devices */ 2248 /* thaw frozen port, resume link and recover failed devices */
2231 if ((link->ap->pflags & ATA_PFLAG_FROZEN) || 2249 if ((link->ap->pflags & ATA_PFLAG_FROZEN) ||
2232 (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link)) 2250 (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link))
@@ -2327,6 +2345,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
2327 struct ata_device *dev; 2345 struct ata_device *dev;
2328 int nr_failed_devs, nr_disabled_devs; 2346 int nr_failed_devs, nr_disabled_devs;
2329 int reset, rc; 2347 int reset, rc;
2348 unsigned long flags;
2330 2349
2331 DPRINTK("ENTER\n"); 2350 DPRINTK("ENTER\n");
2332 2351
@@ -2334,6 +2353,15 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
2334 ata_port_for_each_link(link, ap) { 2353 ata_port_for_each_link(link, ap) {
2335 struct ata_eh_context *ehc = &link->eh_context; 2354 struct ata_eh_context *ehc = &link->eh_context;
2336 2355
2356 /* re-enable link? */
2357 if (ehc->i.action & ATA_EH_ENABLE_LINK) {
2358 ata_eh_about_to_do(link, NULL, ATA_EH_ENABLE_LINK);
2359 spin_lock_irqsave(ap->lock, flags);
2360 link->flags &= ~ATA_LFLAG_DISABLED;
2361 spin_unlock_irqrestore(ap->lock, flags);
2362 ata_eh_done(link, NULL, ATA_EH_ENABLE_LINK);
2363 }
2364
2337 ata_link_for_each_dev(dev, link) { 2365 ata_link_for_each_dev(dev, link) {
2338 if (link->flags & ATA_LFLAG_NO_RETRY) 2366 if (link->flags & ATA_LFLAG_NO_RETRY)
2339 ehc->tries[dev->devno] = 1; 2367 ehc->tries[dev->devno] = 1;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index adeee7397cdb..2bd1d26c9c8d 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -170,6 +170,7 @@ enum {
170 ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */ 170 ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */
171 ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB, 171 ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
172 ATA_LFLAG_NO_RETRY = (1 << 5), /* don't retry this link */ 172 ATA_LFLAG_NO_RETRY = (1 << 5), /* don't retry this link */
173 ATA_LFLAG_DISABLED = (1 << 6), /* link is disabled */
173 174
174 /* struct ata_port flags */ 175 /* struct ata_port flags */
175 ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ 176 ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
@@ -289,6 +290,7 @@ enum {
289 ATA_EH_REVALIDATE = (1 << 0), 290 ATA_EH_REVALIDATE = (1 << 0),
290 ATA_EH_SOFTRESET = (1 << 1), 291 ATA_EH_SOFTRESET = (1 << 1),
291 ATA_EH_HARDRESET = (1 << 2), 292 ATA_EH_HARDRESET = (1 << 2),
293 ATA_EH_ENABLE_LINK = (1 << 3),
292 294
293 ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, 295 ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
294 ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, 296 ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE,
@@ -999,6 +1001,7 @@ static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
999{ 1001{
1000 ata_ehi_schedule_probe(ehi); 1002 ata_ehi_schedule_probe(ehi);
1001 ehi->flags |= ATA_EHI_HOTPLUGGED; 1003 ehi->flags |= ATA_EHI_HOTPLUGGED;
1004 ehi->action |= ATA_EH_ENABLE_LINK;
1002 ehi->err_mask |= AC_ERR_ATA_BUS; 1005 ehi->err_mask |= AC_ERR_ATA_BUS;
1003} 1006}
1004 1007