diff options
author | Tejun Heo <htejun@gmail.com> | 2008-04-07 09:47:19 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-17 15:44:22 -0400 |
commit | 9dadd45b24145d6aee2fabb28d7aef972301892b (patch) | |
tree | c97c323e2edd400bc94eaceddf20f84e9a6da005 | |
parent | a89611e8489ac24f371c9fd6fef6605b170b16ba (diff) |
libata: move generic hardreset code from sata_sff_hardreset() to sata_link_hardreset()
sata_sff_hardreset() contains link readiness wait logic which isn't
SFF specific. Move that part into sata_link_hardreset(), which now
takes two more parameters - @online and @check_ready. Both are
optional. The former is out parameter for link onlineness after
reset. The latter is used to wait for link readiness after hardreset.
Users of sata_link_hardreset() is updated to use new funtionality and
ahci_hardreset() is updated to use sata_link_hardreset() instead of
sata_sff_hardreset(). This doesn't really cause any behavior change.
Signed-off-by: Tejun Heo <htejun@gmail.com>
-rw-r--r-- | drivers/ata/ahci.c | 35 | ||||
-rw-r--r-- | drivers/ata/ata_piix.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 50 | ||||
-rw-r--r-- | drivers/ata/libata-pmp.c | 7 | ||||
-rw-r--r-- | drivers/ata/libata-sff.c | 49 | ||||
-rw-r--r-- | include/linux/libata.h | 10 |
6 files changed, 92 insertions, 61 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 7e251a2cbda5..0f553aaa6f79 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -1343,10 +1343,12 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class, | |||
1343 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, | 1343 | static int ahci_hardreset(struct ata_link *link, unsigned int *class, |
1344 | unsigned long deadline) | 1344 | unsigned long deadline) |
1345 | { | 1345 | { |
1346 | const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); | ||
1346 | struct ata_port *ap = link->ap; | 1347 | struct ata_port *ap = link->ap; |
1347 | struct ahci_port_priv *pp = ap->private_data; | 1348 | struct ahci_port_priv *pp = ap->private_data; |
1348 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; | 1349 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; |
1349 | struct ata_taskfile tf; | 1350 | struct ata_taskfile tf; |
1351 | bool online; | ||
1350 | int rc; | 1352 | int rc; |
1351 | 1353 | ||
1352 | DPRINTK("ENTER\n"); | 1354 | DPRINTK("ENTER\n"); |
@@ -1358,14 +1360,14 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, | |||
1358 | tf.command = 0x80; | 1360 | tf.command = 0x80; |
1359 | ata_tf_to_fis(&tf, 0, 0, d2h_fis); | 1361 | ata_tf_to_fis(&tf, 0, 0, d2h_fis); |
1360 | 1362 | ||
1361 | rc = sata_sff_hardreset(link, class, deadline); | 1363 | rc = sata_link_hardreset(link, timing, deadline, &online, |
1364 | ahci_check_ready); | ||
1362 | 1365 | ||
1363 | ahci_start_engine(ap); | 1366 | ahci_start_engine(ap); |
1364 | 1367 | ||
1365 | if (rc == 0 && ata_link_online(link)) | 1368 | *class = ATA_DEV_NONE; |
1369 | if (online) | ||
1366 | *class = ahci_dev_classify(ap); | 1370 | *class = ahci_dev_classify(ap); |
1367 | if (rc != -EAGAIN && *class == ATA_DEV_UNKNOWN) | ||
1368 | *class = ATA_DEV_NONE; | ||
1369 | 1371 | ||
1370 | DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); | 1372 | DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); |
1371 | return rc; | 1373 | return rc; |
@@ -1376,6 +1378,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, | |||
1376 | { | 1378 | { |
1377 | struct ata_port *ap = link->ap; | 1379 | struct ata_port *ap = link->ap; |
1378 | u32 serror; | 1380 | u32 serror; |
1381 | bool online; | ||
1379 | int rc; | 1382 | int rc; |
1380 | 1383 | ||
1381 | DPRINTK("ENTER\n"); | 1384 | DPRINTK("ENTER\n"); |
@@ -1383,7 +1386,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, | |||
1383 | ahci_stop_engine(ap); | 1386 | ahci_stop_engine(ap); |
1384 | 1387 | ||
1385 | rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), | 1388 | rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), |
1386 | deadline); | 1389 | deadline, &online, NULL); |
1387 | 1390 | ||
1388 | /* vt8251 needs SError cleared for the port to operate */ | 1391 | /* vt8251 needs SError cleared for the port to operate */ |
1389 | ahci_scr_read(ap, SCR_ERROR, &serror); | 1392 | ahci_scr_read(ap, SCR_ERROR, &serror); |
@@ -1396,7 +1399,8 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, | |||
1396 | /* vt8251 doesn't clear BSY on signature FIS reception, | 1399 | /* vt8251 doesn't clear BSY on signature FIS reception, |
1397 | * request follow-up softreset. | 1400 | * request follow-up softreset. |
1398 | */ | 1401 | */ |
1399 | return rc ?: -EAGAIN; | 1402 | *class = ATA_DEV_NONE; |
1403 | return online ? -EAGAIN : rc; | ||
1400 | } | 1404 | } |
1401 | 1405 | ||
1402 | static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, | 1406 | static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, |
@@ -1406,6 +1410,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, | |||
1406 | struct ahci_port_priv *pp = ap->private_data; | 1410 | struct ahci_port_priv *pp = ap->private_data; |
1407 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; | 1411 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; |
1408 | struct ata_taskfile tf; | 1412 | struct ata_taskfile tf; |
1413 | bool online; | ||
1409 | int rc; | 1414 | int rc; |
1410 | 1415 | ||
1411 | ahci_stop_engine(ap); | 1416 | ahci_stop_engine(ap); |
@@ -1416,13 +1421,10 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, | |||
1416 | ata_tf_to_fis(&tf, 0, 0, d2h_fis); | 1421 | ata_tf_to_fis(&tf, 0, 0, d2h_fis); |
1417 | 1422 | ||
1418 | rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), | 1423 | rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), |
1419 | deadline); | 1424 | deadline, &online, NULL); |
1420 | 1425 | ||
1421 | ahci_start_engine(ap); | 1426 | ahci_start_engine(ap); |
1422 | 1427 | ||
1423 | if (rc || ata_link_offline(link)) | ||
1424 | return rc; | ||
1425 | |||
1426 | /* The pseudo configuration device on SIMG4726 attached to | 1428 | /* The pseudo configuration device on SIMG4726 attached to |
1427 | * ASUS P5W-DH Deluxe doesn't send signature FIS after | 1429 | * ASUS P5W-DH Deluxe doesn't send signature FIS after |
1428 | * hardreset if no device is attached to the first downstream | 1430 | * hardreset if no device is attached to the first downstream |
@@ -1436,11 +1438,14 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, | |||
1436 | * have to be reset again. For most cases, this should | 1438 | * have to be reset again. For most cases, this should |
1437 | * suffice while making probing snappish enough. | 1439 | * suffice while making probing snappish enough. |
1438 | */ | 1440 | */ |
1439 | rc = ata_wait_after_reset(link, jiffies + 2 * HZ, ahci_check_ready); | 1441 | if (online) { |
1440 | if (rc) | 1442 | rc = ata_wait_after_reset(link, jiffies + 2 * HZ, |
1441 | ahci_kick_engine(ap, 0); | 1443 | ahci_check_ready); |
1442 | 1444 | if (rc) | |
1443 | return 0; | 1445 | ahci_kick_engine(ap, 0); |
1446 | } | ||
1447 | *class = ATA_DEV_NONE; | ||
1448 | return rc; | ||
1444 | } | 1449 | } |
1445 | 1450 | ||
1446 | static void ahci_postreset(struct ata_link *link, unsigned int *class) | 1451 | static void ahci_postreset(struct ata_link *link, unsigned int *class) |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 7ab76a413cdf..f59a55bfade4 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -1022,7 +1022,7 @@ static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class, | |||
1022 | int rc; | 1022 | int rc; |
1023 | 1023 | ||
1024 | /* do hardreset */ | 1024 | /* do hardreset */ |
1025 | rc = sata_link_hardreset(link, timing, deadline); | 1025 | rc = sata_link_hardreset(link, timing, deadline, NULL, NULL); |
1026 | if (rc) { | 1026 | if (rc) { |
1027 | ata_link_printk(link, KERN_ERR, | 1027 | ata_link_printk(link, KERN_ERR, |
1028 | "COMRESET failed (errno=%d)\n", rc); | 1028 | "COMRESET failed (errno=%d)\n", rc); |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3bad6f189190..b607292b6480 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -3557,8 +3557,18 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline) | |||
3557 | * @link: link to reset | 3557 | * @link: link to reset |
3558 | * @timing: timing parameters { interval, duratinon, timeout } in msec | 3558 | * @timing: timing parameters { interval, duratinon, timeout } in msec |
3559 | * @deadline: deadline jiffies for the operation | 3559 | * @deadline: deadline jiffies for the operation |
3560 | * @online: optional out parameter indicating link onlineness | ||
3561 | * @check_ready: optional callback to check link readiness | ||
3560 | * | 3562 | * |
3561 | * SATA phy-reset @link using DET bits of SControl register. | 3563 | * SATA phy-reset @link using DET bits of SControl register. |
3564 | * After hardreset, link readiness is waited upon using | ||
3565 | * ata_wait_ready() if @check_ready is specified. LLDs are | ||
3566 | * allowed to not specify @check_ready and wait itself after this | ||
3567 | * function returns. Device classification is LLD's | ||
3568 | * responsibility. | ||
3569 | * | ||
3570 | * *@online is set to one iff reset succeeded and @link is online | ||
3571 | * after reset. | ||
3562 | * | 3572 | * |
3563 | * LOCKING: | 3573 | * LOCKING: |
3564 | * Kernel thread context (may sleep) | 3574 | * Kernel thread context (may sleep) |
@@ -3567,13 +3577,17 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline) | |||
3567 | * 0 on success, -errno otherwise. | 3577 | * 0 on success, -errno otherwise. |
3568 | */ | 3578 | */ |
3569 | int sata_link_hardreset(struct ata_link *link, const unsigned long *timing, | 3579 | int sata_link_hardreset(struct ata_link *link, const unsigned long *timing, |
3570 | unsigned long deadline) | 3580 | unsigned long deadline, |
3581 | bool *online, int (*check_ready)(struct ata_link *)) | ||
3571 | { | 3582 | { |
3572 | u32 scontrol; | 3583 | u32 scontrol; |
3573 | int rc; | 3584 | int rc; |
3574 | 3585 | ||
3575 | DPRINTK("ENTER\n"); | 3586 | DPRINTK("ENTER\n"); |
3576 | 3587 | ||
3588 | if (online) | ||
3589 | *online = false; | ||
3590 | |||
3577 | if (sata_set_spd_needed(link)) { | 3591 | if (sata_set_spd_needed(link)) { |
3578 | /* SATA spec says nothing about how to reconfigure | 3592 | /* SATA spec says nothing about how to reconfigure |
3579 | * spd. To be on the safe side, turn off phy during | 3593 | * spd. To be on the safe side, turn off phy during |
@@ -3607,7 +3621,41 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing, | |||
3607 | 3621 | ||
3608 | /* bring link back */ | 3622 | /* bring link back */ |
3609 | rc = sata_link_resume(link, timing, deadline); | 3623 | rc = sata_link_resume(link, timing, deadline); |
3624 | if (rc) | ||
3625 | goto out; | ||
3626 | /* if link is offline nothing more to do */ | ||
3627 | if (ata_link_offline(link)) | ||
3628 | goto out; | ||
3629 | |||
3630 | /* Link is online. From this point, -ENODEV too is an error. */ | ||
3631 | if (online) | ||
3632 | *online = true; | ||
3633 | |||
3634 | if ((link->ap->flags & ATA_FLAG_PMP) && ata_is_host_link(link)) { | ||
3635 | /* If PMP is supported, we have to do follow-up SRST. | ||
3636 | * Some PMPs don't send D2H Reg FIS after hardreset if | ||
3637 | * the first port is empty. Wait only for | ||
3638 | * ATA_TMOUT_PMP_SRST_WAIT. | ||
3639 | */ | ||
3640 | if (check_ready) { | ||
3641 | unsigned long pmp_deadline; | ||
3642 | |||
3643 | pmp_deadline = jiffies + ATA_TMOUT_PMP_SRST_WAIT; | ||
3644 | if (time_after(pmp_deadline, deadline)) | ||
3645 | pmp_deadline = deadline; | ||
3646 | ata_wait_ready(link, pmp_deadline, check_ready); | ||
3647 | } | ||
3648 | rc = -EAGAIN; | ||
3649 | goto out; | ||
3650 | } | ||
3651 | |||
3652 | rc = 0; | ||
3653 | if (check_ready) | ||
3654 | rc = ata_wait_ready(link, deadline, check_ready); | ||
3610 | out: | 3655 | out: |
3656 | if (rc && rc != -EAGAIN) | ||
3657 | ata_link_printk(link, KERN_ERR, | ||
3658 | "COMRESET failed (errno=%d)\n", rc); | ||
3611 | DPRINTK("EXIT, rc=%d\n", rc); | 3659 | DPRINTK("EXIT, rc=%d\n", rc); |
3612 | return rc; | 3660 | return rc; |
3613 | } | 3661 | } |
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index a7cb1498c9b2..7f1a87f01ab2 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c | |||
@@ -239,13 +239,14 @@ int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class, | |||
239 | unsigned long deadline) | 239 | unsigned long deadline) |
240 | { | 240 | { |
241 | const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); | 241 | const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); |
242 | bool online; | ||
242 | u32 tmp; | 243 | u32 tmp; |
243 | int rc; | 244 | int rc; |
244 | 245 | ||
245 | DPRINTK("ENTER\n"); | 246 | DPRINTK("ENTER\n"); |
246 | 247 | ||
247 | /* do hardreset */ | 248 | /* do hardreset */ |
248 | rc = sata_link_hardreset(link, timing, deadline); | 249 | rc = sata_link_hardreset(link, timing, deadline, &online, NULL); |
249 | if (rc) { | 250 | if (rc) { |
250 | ata_link_printk(link, KERN_ERR, | 251 | ata_link_printk(link, KERN_ERR, |
251 | "COMRESET failed (errno=%d)\n", rc); | 252 | "COMRESET failed (errno=%d)\n", rc); |
@@ -261,7 +262,7 @@ int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class, | |||
261 | } | 262 | } |
262 | 263 | ||
263 | /* if device is present, follow up with srst to wait for !BSY */ | 264 | /* if device is present, follow up with srst to wait for !BSY */ |
264 | if (ata_link_online(link)) | 265 | if (online) |
265 | rc = -EAGAIN; | 266 | rc = -EAGAIN; |
266 | out: | 267 | out: |
267 | /* if SCR isn't accessible, we need to reset the PMP */ | 268 | /* if SCR isn't accessible, we need to reset the PMP */ |
@@ -916,7 +917,7 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap) | |||
916 | * SError.N working. | 917 | * SError.N working. |
917 | */ | 918 | */ |
918 | sata_link_hardreset(link, sata_deb_timing_normal, | 919 | sata_link_hardreset(link, sata_deb_timing_normal, |
919 | jiffies + ATA_TMOUT_INTERNAL_QUICK); | 920 | jiffies + ATA_TMOUT_INTERNAL_QUICK, NULL, NULL); |
920 | 921 | ||
921 | /* unconditionally clear SError.N */ | 922 | /* unconditionally clear SError.N */ |
922 | rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG); | 923 | rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG); |
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 78912c5011ad..0b97e84d3af6 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -1921,50 +1921,19 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes, | |||
1921 | int sata_sff_hardreset(struct ata_link *link, unsigned int *class, | 1921 | int sata_sff_hardreset(struct ata_link *link, unsigned int *class, |
1922 | unsigned long deadline) | 1922 | unsigned long deadline) |
1923 | { | 1923 | { |
1924 | struct ata_port *ap = link->ap; | 1924 | struct ata_eh_context *ehc = &link->eh_context; |
1925 | const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); | 1925 | const unsigned long *timing = sata_ehc_deb_timing(ehc); |
1926 | bool online; | ||
1926 | int rc; | 1927 | int rc; |
1927 | 1928 | ||
1928 | DPRINTK("ENTER\n"); | 1929 | rc = sata_link_hardreset(link, timing, deadline, &online, |
1929 | 1930 | ata_sff_check_ready); | |
1930 | /* do hardreset */ | 1931 | *class = ATA_DEV_NONE; |
1931 | rc = sata_link_hardreset(link, timing, deadline); | 1932 | if (online) |
1932 | if (rc) { | 1933 | *class = ata_sff_dev_classify(link->device, 1, NULL); |
1933 | ata_link_printk(link, KERN_ERR, | ||
1934 | "COMRESET failed (errno=%d)\n", rc); | ||
1935 | return rc; | ||
1936 | } | ||
1937 | |||
1938 | /* TODO: phy layer with polling, timeouts, etc. */ | ||
1939 | if (ata_link_offline(link)) { | ||
1940 | *class = ATA_DEV_NONE; | ||
1941 | DPRINTK("EXIT, link offline\n"); | ||
1942 | return 0; | ||
1943 | } | ||
1944 | |||
1945 | /* If PMP is supported, we have to do follow-up SRST. Note | ||
1946 | * that some PMPs don't send D2H Reg FIS after hardreset at | ||
1947 | * all if the first port is empty. Wait for it just for a | ||
1948 | * second and request follow-up SRST. | ||
1949 | */ | ||
1950 | if (ap->flags & ATA_FLAG_PMP) { | ||
1951 | ata_sff_wait_after_reset(link, 1, jiffies + HZ); | ||
1952 | return -EAGAIN; | ||
1953 | } | ||
1954 | |||
1955 | /* wait for the link to become online */ | ||
1956 | rc = ata_sff_wait_after_reset(link, 1, deadline); | ||
1957 | /* link occupied, -ENODEV too is an error */ | ||
1958 | if (rc) { | ||
1959 | ata_link_printk(link, KERN_ERR, | ||
1960 | "COMRESET failed (errno=%d)\n", rc); | ||
1961 | return rc; | ||
1962 | } | ||
1963 | |||
1964 | *class = ata_sff_dev_classify(link->device, 1, NULL); | ||
1965 | 1934 | ||
1966 | DPRINTK("EXIT, class=%u\n", *class); | 1935 | DPRINTK("EXIT, class=%u\n", *class); |
1967 | return 0; | 1936 | return rc; |
1968 | } | 1937 | } |
1969 | 1938 | ||
1970 | /** | 1939 | /** |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 4bbf2524e473..d9ebce2bf5e7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -261,6 +261,13 @@ enum { | |||
261 | */ | 261 | */ |
262 | ATA_WAIT_AFTER_RESET_MSECS = 150, | 262 | ATA_WAIT_AFTER_RESET_MSECS = 150, |
263 | 263 | ||
264 | /* If PMP is supported, we have to do follow-up SRST. As some | ||
265 | * PMPs don't send D2H Reg FIS after hardreset, LLDs are | ||
266 | * advised to wait only for the following duration before | ||
267 | * doing SRST. | ||
268 | */ | ||
269 | ATA_TMOUT_PMP_SRST_WAIT = 1 * HZ, | ||
270 | |||
264 | /* ATA bus states */ | 271 | /* ATA bus states */ |
265 | BUS_UNKNOWN = 0, | 272 | BUS_UNKNOWN = 0, |
266 | BUS_DMA = 1, | 273 | BUS_DMA = 1, |
@@ -844,7 +851,8 @@ extern int sata_link_debounce(struct ata_link *link, | |||
844 | extern int sata_link_resume(struct ata_link *link, const unsigned long *params, | 851 | extern int sata_link_resume(struct ata_link *link, const unsigned long *params, |
845 | unsigned long deadline); | 852 | unsigned long deadline); |
846 | extern int sata_link_hardreset(struct ata_link *link, | 853 | extern int sata_link_hardreset(struct ata_link *link, |
847 | const unsigned long *timing, unsigned long deadline); | 854 | const unsigned long *timing, unsigned long deadline, |
855 | bool *online, int (*check_ready)(struct ata_link *)); | ||
848 | extern void ata_std_postreset(struct ata_link *link, unsigned int *classes); | 856 | extern void ata_std_postreset(struct ata_link *link, unsigned int *classes); |
849 | extern void ata_port_disable(struct ata_port *); | 857 | extern void ata_port_disable(struct ata_port *); |
850 | 858 | ||