diff options
-rw-r--r-- | drivers/scsi/libata-core.c | 65 | ||||
-rw-r--r-- | include/linux/libata.h | 3 |
2 files changed, 52 insertions, 16 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 68fa64d2472..33b5bff58cc 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -1370,11 +1370,18 @@ err_out_nosup: | |||
1370 | static int ata_bus_probe(struct ata_port *ap) | 1370 | static int ata_bus_probe(struct ata_port *ap) |
1371 | { | 1371 | { |
1372 | unsigned int classes[ATA_MAX_DEVICES]; | 1372 | unsigned int classes[ATA_MAX_DEVICES]; |
1373 | int i, rc, found = 0; | 1373 | int tries[ATA_MAX_DEVICES]; |
1374 | int i, rc, down_xfermask; | ||
1374 | struct ata_device *dev; | 1375 | struct ata_device *dev; |
1375 | 1376 | ||
1376 | ata_port_probe(ap); | 1377 | ata_port_probe(ap); |
1377 | 1378 | ||
1379 | for (i = 0; i < ATA_MAX_DEVICES; i++) | ||
1380 | tries[i] = ATA_PROBE_MAX_TRIES; | ||
1381 | |||
1382 | retry: | ||
1383 | down_xfermask = 0; | ||
1384 | |||
1378 | /* reset and determine device classes */ | 1385 | /* reset and determine device classes */ |
1379 | for (i = 0; i < ATA_MAX_DEVICES; i++) | 1386 | for (i = 0; i < ATA_MAX_DEVICES; i++) |
1380 | classes[i] = ATA_DEV_UNKNOWN; | 1387 | classes[i] = ATA_DEV_UNKNOWN; |
@@ -1404,21 +1411,23 @@ static int ata_bus_probe(struct ata_port *ap) | |||
1404 | dev = &ap->device[i]; | 1411 | dev = &ap->device[i]; |
1405 | dev->class = classes[i]; | 1412 | dev->class = classes[i]; |
1406 | 1413 | ||
1407 | if (!ata_dev_enabled(dev)) | 1414 | if (!tries[i]) { |
1408 | continue; | 1415 | ata_down_xfermask_limit(ap, dev, 1); |
1409 | 1416 | ata_dev_disable(ap, dev); | |
1410 | WARN_ON(dev->id != NULL); | ||
1411 | if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) { | ||
1412 | dev->class = ATA_DEV_NONE; | ||
1413 | continue; | ||
1414 | } | 1417 | } |
1415 | 1418 | ||
1416 | if (ata_dev_configure(ap, dev, 1)) { | 1419 | if (!ata_dev_enabled(dev)) |
1417 | ata_dev_disable(ap, dev); | ||
1418 | continue; | 1420 | continue; |
1419 | } | ||
1420 | 1421 | ||
1421 | found = 1; | 1422 | kfree(dev->id); |
1423 | dev->id = NULL; | ||
1424 | rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id); | ||
1425 | if (rc) | ||
1426 | goto fail; | ||
1427 | |||
1428 | rc = ata_dev_configure(ap, dev, 1); | ||
1429 | if (rc) | ||
1430 | goto fail; | ||
1422 | } | 1431 | } |
1423 | 1432 | ||
1424 | /* configure transfer mode */ | 1433 | /* configure transfer mode */ |
@@ -1427,12 +1436,18 @@ static int ata_bus_probe(struct ata_port *ap) | |||
1427 | * return error code and failing device on failure as | 1436 | * return error code and failing device on failure as |
1428 | * ata_set_mode() does. | 1437 | * ata_set_mode() does. |
1429 | */ | 1438 | */ |
1430 | if (found) | 1439 | for (i = 0; i < ATA_MAX_DEVICES; i++) |
1431 | ap->ops->set_mode(ap); | 1440 | if (ata_dev_enabled(&ap->device[i])) { |
1441 | ap->ops->set_mode(ap); | ||
1442 | break; | ||
1443 | } | ||
1432 | rc = 0; | 1444 | rc = 0; |
1433 | } else { | 1445 | } else { |
1434 | while (ata_set_mode(ap, &dev)) | 1446 | rc = ata_set_mode(ap, &dev); |
1435 | ata_dev_disable(ap, dev); | 1447 | if (rc) { |
1448 | down_xfermask = 1; | ||
1449 | goto fail; | ||
1450 | } | ||
1436 | } | 1451 | } |
1437 | 1452 | ||
1438 | for (i = 0; i < ATA_MAX_DEVICES; i++) | 1453 | for (i = 0; i < ATA_MAX_DEVICES; i++) |
@@ -1443,6 +1458,24 @@ static int ata_bus_probe(struct ata_port *ap) | |||
1443 | ata_port_disable(ap); | 1458 | ata_port_disable(ap); |
1444 | ap->ops->port_disable(ap); | 1459 | ap->ops->port_disable(ap); |
1445 | return -ENODEV; | 1460 | return -ENODEV; |
1461 | |||
1462 | fail: | ||
1463 | switch (rc) { | ||
1464 | case -EINVAL: | ||
1465 | case -ENODEV: | ||
1466 | tries[dev->devno] = 0; | ||
1467 | break; | ||
1468 | case -EIO: | ||
1469 | ata_down_sata_spd_limit(ap); | ||
1470 | /* fall through */ | ||
1471 | default: | ||
1472 | tries[dev->devno]--; | ||
1473 | if (down_xfermask && | ||
1474 | ata_down_xfermask_limit(ap, dev, tries[dev->devno] == 1)) | ||
1475 | tries[dev->devno] = 0; | ||
1476 | } | ||
1477 | |||
1478 | goto retry; | ||
1446 | } | 1479 | } |
1447 | 1480 | ||
1448 | /** | 1481 | /** |
diff --git a/include/linux/libata.h b/include/linux/libata.h index a5207e66ca5..a4a1e6304e7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -211,6 +211,9 @@ enum { | |||
211 | /* Masks for port functions */ | 211 | /* Masks for port functions */ |
212 | ATA_PORT_PRIMARY = (1 << 0), | 212 | ATA_PORT_PRIMARY = (1 << 0), |
213 | ATA_PORT_SECONDARY = (1 << 1), | 213 | ATA_PORT_SECONDARY = (1 << 1), |
214 | |||
215 | /* how hard are we gonna try to probe/recover devices */ | ||
216 | ATA_PROBE_MAX_TRIES = 3, | ||
214 | }; | 217 | }; |
215 | 218 | ||
216 | enum hsm_task_states { | 219 | enum hsm_task_states { |