mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-11-01 09:13:37 +00:00 
			
		
		
		
	libata: retry link resume if necessary
Interestingly, when SIDPR is used in ata_piix, writes to DET in SControl sometimes get ignored leading to detection failure. Update sata_link_resume() such that it reads back SControl after clearing DET and retry if it's not clear. Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: fengxiangjun <fengxiangjun@neusoft.com> Reported-by: Jim Faulkner <jfaulkne@ccs.neu.edu> Cc: stable@kernel.org Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
		
							parent
							
								
									0b67c7439f
								
							
						
					
					
						commit
						5040ab67a2
					
				
					 2 changed files with 35 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -3790,21 +3790,45 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params,
 | 
			
		|||
int sata_link_resume(struct ata_link *link, const unsigned long *params,
 | 
			
		||||
		     unsigned long deadline)
 | 
			
		||||
{
 | 
			
		||||
	int tries = ATA_LINK_RESUME_TRIES;
 | 
			
		||||
	u32 scontrol, serror;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
	scontrol = (scontrol & 0x0f0) | 0x300;
 | 
			
		||||
 | 
			
		||||
	if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol)))
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
	/* Some PHYs react badly if SStatus is pounded immediately
 | 
			
		||||
	 * after resuming.  Delay 200ms before debouncing.
 | 
			
		||||
	/*
 | 
			
		||||
	 * Writes to SControl sometimes get ignored under certain
 | 
			
		||||
	 * controllers (ata_piix SIDPR).  Make sure DET actually is
 | 
			
		||||
	 * cleared.
 | 
			
		||||
	 */
 | 
			
		||||
	msleep(200);
 | 
			
		||||
	do {
 | 
			
		||||
		scontrol = (scontrol & 0x0f0) | 0x300;
 | 
			
		||||
		if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol)))
 | 
			
		||||
			return rc;
 | 
			
		||||
		/*
 | 
			
		||||
		 * Some PHYs react badly if SStatus is pounded
 | 
			
		||||
		 * immediately after resuming.  Delay 200ms before
 | 
			
		||||
		 * debouncing.
 | 
			
		||||
		 */
 | 
			
		||||
		msleep(200);
 | 
			
		||||
 | 
			
		||||
		/* is SControl restored correctly? */
 | 
			
		||||
		if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
 | 
			
		||||
			return rc;
 | 
			
		||||
	} while ((scontrol & 0xf0f) != 0x300 && --tries);
 | 
			
		||||
 | 
			
		||||
	if ((scontrol & 0xf0f) != 0x300) {
 | 
			
		||||
		ata_link_printk(link, KERN_ERR,
 | 
			
		||||
				"failed to resume link (SControl %X)\n",
 | 
			
		||||
				scontrol);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tries < ATA_LINK_RESUME_TRIES)
 | 
			
		||||
		ata_link_printk(link, KERN_WARNING,
 | 
			
		||||
				"link resume succeeded after %d retries\n",
 | 
			
		||||
				ATA_LINK_RESUME_TRIES - tries);
 | 
			
		||||
 | 
			
		||||
	if ((rc = sata_link_debounce(link, params, deadline)))
 | 
			
		||||
		return rc;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -354,6 +354,9 @@ enum {
 | 
			
		|||
	/* max tries if error condition is still set after ->error_handler */
 | 
			
		||||
	ATA_EH_MAX_TRIES	= 5,
 | 
			
		||||
 | 
			
		||||
	/* sometimes resuming a link requires several retries */
 | 
			
		||||
	ATA_LINK_RESUME_TRIES	= 5,
 | 
			
		||||
 | 
			
		||||
	/* how hard are we gonna try to probe/recover devices */
 | 
			
		||||
	ATA_PROBE_MAX_TRIES	= 3,
 | 
			
		||||
	ATA_EH_DEV_TRIES	= 3,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue