Module Name: src Committed By: jmcneill Date: Sun Dec 20 00:14:30 UTC 2020
Modified Files: src/sys/dev/ic: ahcisata_core.c Log Message: Retry clearing WDCTL_RST a few times before giving up. Makes SATA work in Solidrun Honeycomb LX2K. To generate a diff of this commit: cvs rdiff -u -r1.84 -r1.85 src/sys/dev/ic/ahcisata_core.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/ahcisata_core.c diff -u src/sys/dev/ic/ahcisata_core.c:1.84 src/sys/dev/ic/ahcisata_core.c:1.85 --- src/sys/dev/ic/ahcisata_core.c:1.84 Sat Dec 19 19:12:02 2020 +++ src/sys/dev/ic/ahcisata_core.c Sun Dec 20 00:14:30 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: ahcisata_core.c,v 1.84 2020/12/19 19:12:02 jmcneill Exp $ */ +/* $NetBSD: ahcisata_core.c,v 1.85 2020/12/20 00:14:30 jmcneill Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.84 2020/12/19 19:12:02 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.85 2020/12/20 00:14:30 jmcneill Exp $"); #include <sys/types.h> #include <sys/malloc.h> @@ -810,7 +810,7 @@ ahci_do_reset_drive(struct ata_channel * struct ahci_cmd_header *cmd_h; int i, error = 0; uint32_t sig, cmd; - int noclo_retry = 0; + int noclo_retry = 0, retry; ata_channel_lock_owned(chp); @@ -892,22 +892,34 @@ again: */ ata_delay(chp, 10, "ahcirstw", flags); - cmd_h->cmdh_flags = htole16(RHD_FISLEN / 4 | - (drive << AHCI_CMDH_F_PMP_SHIFT)); - cmd_h->cmdh_prdbc = 0; - memset(cmd_tbl->cmdt_cfis, 0, 64); - cmd_tbl->cmdt_cfis[fis_type] = RHD_FISTYPE; - cmd_tbl->cmdt_cfis[rhd_c] = drive; - cmd_tbl->cmdt_cfis[rhd_control] = WDCTL_4BIT; - switch (ahci_exec_fis(chp, 310, flags, c_slot)) { - case ERR_DF: - case TIMEOUT: + /* + * Try to clear WDCTL_RST a few times before giving up. + */ + for (error = EBUSY, retry = 0; error != 0 && retry < 5; retry++) { + cmd_h->cmdh_flags = htole16(RHD_FISLEN / 4 | + (drive << AHCI_CMDH_F_PMP_SHIFT)); + cmd_h->cmdh_prdbc = 0; + memset(cmd_tbl->cmdt_cfis, 0, 64); + cmd_tbl->cmdt_cfis[fis_type] = RHD_FISTYPE; + cmd_tbl->cmdt_cfis[rhd_c] = drive; + cmd_tbl->cmdt_cfis[rhd_control] = WDCTL_4BIT; + switch (ahci_exec_fis(chp, 310, flags, c_slot)) { + case ERR_DF: + case TIMEOUT: + error = EBUSY; + break; + default: + error = 0; + break; + } + if (error == 0) { + break; + } + } + if (error == EBUSY) { aprint_error("%s port %d: clearing WDCTL_RST failed " "for drive %d\n", AHCINAME(sc), chp->ch_channel, drive); - error = EBUSY; goto end; - default: - break; } skip_reset: