[PATCH] arm: mvebu: sata_mv failed to identify HDDs during cold start

Stefan Roese sr at denx.de
Sat Jul 31 09:31:53 CEST 2021


Hi Tony,

On 25.07.21 23:57, Tony Dinh wrote:
> During cold start, with some HDDs, mv_sata_identify() does not populate
> the ID words on the 1st ATA ID command. In fact, the first ATA ID
> command will only power up the drive, and then the ATA ID command
> processing is lost in the process.
> 
> Tests with:
> 
> - Seagate ST9250320AS 250GB HDD and Seagate ST4000DM004-2CV104 4TB HDD.
> - Zyxel NSA310S (Kirkwood 88F6702), Marvell Dreamplug (Kirkwood 88F6281),
>   Seagate GoFlex Home (Kirkwood 88F6281), Pogoplug V4 (Kirkwood 88F6192).
> 
> Observation:
> 
> - The Seagate ST9250320AS 250GB took about 3 seconds to spin up.
> - The Seagate ST4000DM004-2CV104 4TB took about 8 seconds to spin up.
> - mv_sata_identify() did not populate the ID words after the call to
>   mv_ata_exec_ata_cmd_nondma().
> - Attempt to insert a long delay of 30 seconds, ie. mdelay(30_000), after
> the call to ata_wait_register() inside mv_ata_exec_ata_cmd_nondma() did
> not help with the 4TB drive. The ID words were still empty after that 30s
> delay.

IIRC, I've seen similar issues with a SATA SSD on theadorable before as
well. Thanks for digging into this.

One some nit below...

> Patch Description:
> 
> - Added a second ATA ID command in mv_sata_identify(), which will be
> executed if the 1st ATA ID command did not return with valid ID words.
> - Use the HDD drive capacity in the ID words as a successful indicator of
> ATA ID command.
> - In the scenario where a box is rebooted, the 1st ATA ID command is always
> successful, so there is no extra time wasted.
> - In the scenario where a box is cold started, the 1st ATA command is the
> power up command. The 2nd ATA ID command alleviates the uncertainty of
> how long we have to wait for the ID words to be populated by the SATA
> controller.
> 
> Signed-off-by: Tony Dinh <mibodhi at gmail.com>
> ---
> 
>   drivers/ata/sata_mv.c | 29 +++++++++++++++++++++++++++--
>   1 file changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
> index 1012cb5374..7d1515d5f8 100644
> --- a/drivers/ata/sata_mv.c
> +++ b/drivers/ata/sata_mv.c
> @@ -809,6 +809,7 @@ static int mv_ata_exec_ata_cmd_nondma(struct udevice *dev, int port,
>   static int mv_sata_identify(struct udevice *dev, int port, u16 *id)
>   {
>   	struct sata_fis_h2d h2d;
> +	int len;
>   
>   	memset(&h2d, 0, sizeof(struct sata_fis_h2d));
>   
> @@ -818,8 +819,32 @@ static int mv_sata_identify(struct udevice *dev, int port, u16 *id)
>   	/* Give device time to get operational */
>   	mdelay(10);
>   
> -	return mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id,
> -					  ATA_ID_WORDS * 2, READ_CMD);
> +	/* During cold start, with some HDDs, the first ATA ID command does
> +	 * not populate the ID words. In fact, the first ATA ID
> +	 * command will only power up the drive, and then the ATA ID command
> +	 * processing is lost in the process.
> +	 */
> +	len = mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id,
> +					 ATA_ID_WORDS * 2, READ_CMD);
> +
> +	/* If drive capacity has been filled in, then it was successfully
> +	 * identified (the drive has been powered up before, i.e.
> +	 * this function is invoked during a reboot)
> +	 */
> +	if (ata_id_n_sectors(id) != 0)
> +		return len;
> +
> +	/* Issue the 2nd ATA ID command to make sure the ID words are
> +	 * populated properly.
> +	 */
> +	mdelay(10);
> +	len = mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id,
> +					 ATA_ID_WORDS * 2, READ_CMD);
> +	if (ata_id_n_sectors(id) != 0)
> +		return len;
> +
> +	printf("Err: Failed to identify SATA device %d\n", port);
> +	return -1;

Perhaps better to return -ENODEV or something similar instead of the -1
here?

Thanks,
Stefan


More information about the U-Boot mailing list