diff options
Diffstat (limited to 'drivers/ata/libata-pmp.c')
| -rw-r--r-- | drivers/ata/libata-pmp.c | 183 | 
1 files changed, 93 insertions, 90 deletions
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 3120596d4af..7ccc084bf1d 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -8,6 +8,7 @@   */  #include <linux/kernel.h> +#include <linux/export.h>  #include <linux/libata.h>  #include <linux/slab.h>  #include "libata.h" @@ -147,8 +148,8 @@ int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *r_val)  	err_mask = sata_pmp_read(link, reg, r_val);  	if (err_mask) { -		ata_link_printk(link, KERN_WARNING, "failed to read SCR %d " -				"(Emask=0x%x)\n", reg, err_mask); +		ata_link_warn(link, "failed to read SCR %d (Emask=0x%x)\n", +			      reg, err_mask);  		return -EIO;  	}  	return 0; @@ -178,8 +179,8 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)  	err_mask = sata_pmp_write(link, reg, val);  	if (err_mask) { -		ata_link_printk(link, KERN_WARNING, "failed to write SCR %d " -				"(Emask=0x%x)\n", reg, err_mask); +		ata_link_warn(link, "failed to write SCR %d (Emask=0x%x)\n", +			      reg, err_mask);  		return -EIO;  	}  	return 0; @@ -231,8 +232,8 @@ static int sata_pmp_read_gscr(struct ata_device *dev, u32 *gscr)  		err_mask = sata_pmp_read(dev->link, reg, &gscr[reg]);  		if (err_mask) { -			ata_dev_printk(dev, KERN_ERR, "failed to read PMP " -				"GSCR[%d] (Emask=0x%x)\n", reg, err_mask); +			ata_dev_err(dev, "failed to read PMP GSCR[%d] (Emask=0x%x)\n", +				    reg, err_mask);  			return -EIO;  		}  	} @@ -288,49 +289,48 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)  	/* Disable sending Early R_OK.  	 * With "cached read" HDD testing and multiple ports busy on a SATA -	 * host controller, 3726 PMP will very rarely drop a deferred +	 * host controller, 3x26 PMP will very rarely drop a deferred  	 * R_OK that was intended for the host. Symptom will be all  	 * 5 drives under test will timeout, get reset, and recover.  	 */ -	if (vendor == 0x1095 && devid == 0x3726) { +	if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {  		u32 reg;  		err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, ®);  		if (err_mask) {  			rc = -EIO; -			reason = "failed to read Sil3726 Private Register"; +			reason = "failed to read Sil3x26 Private Register";  			goto fail;  		}  		reg &= ~0x1;  		err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);  		if (err_mask) {  			rc = -EIO; -			reason = "failed to write Sil3726 Private Register"; +			reason = "failed to write Sil3x26 Private Register";  			goto fail;  		}  	}  	if (print_info) { -		ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, " -			       "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", -			       sata_pmp_spec_rev_str(gscr), vendor, devid, -			       sata_pmp_gscr_rev(gscr), -			       nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN], -			       gscr[SATA_PMP_GSCR_FEAT]); +		ata_dev_info(dev, "Port Multiplier %s, " +			     "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", +			     sata_pmp_spec_rev_str(gscr), vendor, devid, +			     sata_pmp_gscr_rev(gscr), +			     nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN], +			     gscr[SATA_PMP_GSCR_FEAT]);  		if (!(dev->flags & ATA_DFLAG_AN)) -			ata_dev_printk(dev, KERN_INFO, +			ata_dev_info(dev,  				"Asynchronous notification not supported, " -				"hotplug won't\n         work on fan-out " -				"ports. Use warm-plug instead.\n"); +				"hotplug won't work on fan-out ports. Use warm-plug instead.\n");  	}  	return 0;   fail: -	ata_dev_printk(dev, KERN_ERR, -		       "failed to configure Port Multiplier (%s, Emask=0x%x)\n", -		       reason, err_mask); +	ata_dev_err(dev, +		    "failed to configure Port Multiplier (%s, Emask=0x%x)\n", +		    reason, err_mask);  	return rc;  } @@ -383,14 +383,15 @@ static void sata_pmp_quirks(struct ata_port *ap)  	u16 devid = sata_pmp_gscr_devid(gscr);  	struct ata_link *link; -	if (vendor == 0x1095 && devid == 0x3726) { -		/* sil3726 quirks */ +	if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) { +		/* sil3x26 quirks */  		ata_for_each_link(link, ap, EDGE) {  			/* link reports offline after LPM */  			link->flags |= ATA_LFLAG_NO_LPM; -			/* Class code report is unreliable and SRST -			 * times out under certain configurations. +			/* +			 * Class code report is unreliable and SRST times +			 * out under certain configurations.  			 */  			if (link->pmp < 5)  				link->flags |= ATA_LFLAG_NO_SRST | @@ -402,20 +403,17 @@ static void sata_pmp_quirks(struct ata_port *ap)  					       ATA_LFLAG_ASSUME_SEMB;  		}  	} else if (vendor == 0x1095 && devid == 0x4723) { -		/* sil4723 quirks */ -		ata_for_each_link(link, ap, EDGE) { -			/* link reports offline after LPM */ -			link->flags |= ATA_LFLAG_NO_LPM; - -			/* class code report is unreliable */ -			if (link->pmp < 2) -				link->flags |= ATA_LFLAG_ASSUME_ATA; - -			/* the config device at port 2 locks up on SRST */ -			if (link->pmp == 2) -				link->flags |= ATA_LFLAG_NO_SRST | -					       ATA_LFLAG_ASSUME_ATA; -		} +		/* +		 * sil4723 quirks +		 * +		 * Link reports offline after LPM.  Class code report is +		 * unreliable.  SIMG PMPs never got SRST reliable and the +		 * config device at port 2 locks up on SRST. +		 */ +		ata_for_each_link(link, ap, EDGE) +			link->flags |= ATA_LFLAG_NO_LPM | +				       ATA_LFLAG_NO_SRST | +				       ATA_LFLAG_ASSUME_ATA;  	} else if (vendor == 0x1095 && devid == 0x4726) {  		/* sil4726 quirks */  		ata_for_each_link(link, ap, EDGE) { @@ -449,6 +447,19 @@ static void sata_pmp_quirks(struct ata_port *ap)  		 * otherwise.  Don't try hard to recover it.  		 */  		ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY; +	} else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) { +		/* +		 * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350? +		 * 0x0325: jmicron JMB394. +		 */ +		ata_for_each_link(link, ap, EDGE) { +			/* SRST breaks detection and disks get misclassified +			 * LPM disabled to avoid potential problems +			 */ +			link->flags |= ATA_LFLAG_NO_LPM | +				       ATA_LFLAG_NO_SRST | +				       ATA_LFLAG_ASSUME_ATA; +		}  	}  } @@ -475,20 +486,17 @@ int sata_pmp_attach(struct ata_device *dev)  	/* is it hanging off the right place? */  	if (!sata_pmp_supported(ap)) { -		ata_dev_printk(dev, KERN_ERR, -			       "host does not support Port Multiplier\n"); +		ata_dev_err(dev, "host does not support Port Multiplier\n");  		return -EINVAL;  	}  	if (!ata_is_host_link(link)) { -		ata_dev_printk(dev, KERN_ERR, -			       "Port Multipliers cannot be nested\n"); +		ata_dev_err(dev, "Port Multipliers cannot be nested\n");  		return -EINVAL;  	}  	if (dev->devno) { -		ata_dev_printk(dev, KERN_ERR, -			       "Port Multiplier must be the first device\n"); +		ata_dev_err(dev, "Port Multiplier must be the first device\n");  		return -EINVAL;  	} @@ -507,8 +515,7 @@ int sata_pmp_attach(struct ata_device *dev)  	rc = sata_pmp_init_links(ap, sata_pmp_gscr_ports(dev->gscr));  	if (rc) { -		ata_dev_printk(dev, KERN_INFO, -			       "failed to initialize PMP links\n"); +		ata_dev_info(dev, "failed to initialize PMP links\n");  		goto fail;  	} @@ -526,8 +533,6 @@ int sata_pmp_attach(struct ata_device *dev)  	ata_for_each_link(tlink, ap, EDGE)  		sata_link_init_spd(tlink); -	ata_acpi_associate_sata_port(ap); -  	return 0;   fail: @@ -552,7 +557,7 @@ static void sata_pmp_detach(struct ata_device *dev)  	struct ata_link *tlink;  	unsigned long flags; -	ata_dev_printk(dev, KERN_INFO, "Port Multiplier detaching\n"); +	ata_dev_info(dev, "Port Multiplier detaching\n");  	WARN_ON(!ata_is_host_link(link) || dev->devno ||  		link->pmp != SATA_PMP_CTRL_PORT); @@ -567,8 +572,6 @@ static void sata_pmp_detach(struct ata_device *dev)  	ap->nr_pmp_links = 0;  	link->pmp = 0;  	spin_unlock_irqrestore(ap->lock, flags); - -	ata_acpi_associate_sata_port(ap);  }  /** @@ -599,23 +602,23 @@ static int sata_pmp_same_pmp(struct ata_device *dev, const u32 *new_gscr)  	new_nr_ports = sata_pmp_gscr_ports(new_gscr);  	if (old_vendor != new_vendor) { -		ata_dev_printk(dev, KERN_INFO, "Port Multiplier " -			       "vendor mismatch '0x%x' != '0x%x'\n", -			       old_vendor, new_vendor); +		ata_dev_info(dev, +			     "Port Multiplier vendor mismatch '0x%x' != '0x%x'\n", +			     old_vendor, new_vendor);  		return 0;  	}  	if (old_devid != new_devid) { -		ata_dev_printk(dev, KERN_INFO, "Port Multiplier " -			       "device ID mismatch '0x%x' != '0x%x'\n", -			       old_devid, new_devid); +		ata_dev_info(dev, +			     "Port Multiplier device ID mismatch '0x%x' != '0x%x'\n", +			     old_devid, new_devid);  		return 0;  	}  	if (old_nr_ports != new_nr_ports) { -		ata_dev_printk(dev, KERN_INFO, "Port Multiplier " -			       "nr_ports mismatch '0x%x' != '0x%x'\n", -			       old_nr_ports, new_nr_ports); +		ata_dev_info(dev, +			     "Port Multiplier nr_ports mismatch '0x%x' != '0x%x'\n", +			     old_nr_ports, new_nr_ports);  		return 0;  	} @@ -681,8 +684,7 @@ static int sata_pmp_revalidate(struct ata_device *dev, unsigned int new_class)  	return 0;   fail: -	ata_dev_printk(dev, KERN_ERR, -		       "PMP revalidation failed (errno=%d)\n", rc); +	ata_dev_err(dev, "PMP revalidation failed (errno=%d)\n", rc);  	DPRINTK("EXIT, rc=%d\n", rc);  	return rc;  } @@ -706,13 +708,14 @@ static int sata_pmp_revalidate_quick(struct ata_device *dev)  	err_mask = sata_pmp_read(dev->link, SATA_PMP_GSCR_PROD_ID, &prod_id);  	if (err_mask) { -		ata_dev_printk(dev, KERN_ERR, "failed to read PMP product ID " -			       "(Emask=0x%x)\n", err_mask); +		ata_dev_err(dev, +			    "failed to read PMP product ID (Emask=0x%x)\n", +			    err_mask);  		return -EIO;  	}  	if (prod_id != dev->gscr[SATA_PMP_GSCR_PROD_ID]) { -		ata_dev_printk(dev, KERN_ERR, "PMP product ID mismatch\n"); +		ata_dev_err(dev, "PMP product ID mismatch\n");  		/* something weird is going on, request full PMP recovery */  		return -EIO;  	} @@ -767,8 +770,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,  		rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,  				  postreset);  		if (rc) { -			ata_link_printk(link, KERN_ERR, -					"failed to reset PMP, giving up\n"); +			ata_link_err(link, "failed to reset PMP, giving up\n");  			goto fail;  		} @@ -809,9 +811,9 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,  			ehc->i.action |= ATA_EH_RESET;  			goto retry;  		} else { -			ata_dev_printk(dev, KERN_ERR, "failed to recover PMP " -				       "after %d tries, giving up\n", -				       ATA_EH_PMP_TRIES); +			ata_dev_err(dev, +				    "failed to recover PMP after %d tries, giving up\n", +				    ATA_EH_PMP_TRIES);  			goto fail;  		}  	} @@ -857,8 +859,9 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)  		/* unconditionally clear SError.N */  		rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);  		if (rc) { -			ata_link_printk(link, KERN_ERR, "failed to clear " -					"SError.N (errno=%d)\n", rc); +			ata_link_err(link, +				     "failed to clear SError.N (errno=%d)\n", +				     rc);  			return rc;  		} @@ -880,7 +883,7 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)  	/* disable this link */  	if (!(link->flags & ATA_LFLAG_DISABLED)) { -		ata_link_printk(link, KERN_WARNING, +		ata_link_warn(link,  			"failed to recover link after %d tries, disabling\n",  			ATA_EH_PMP_LINK_TRIES); @@ -964,7 +967,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,  					  gscr[SATA_PMP_GSCR_FEAT_EN]);  		if (err_mask) { -			ata_link_printk(pmp_link, KERN_WARNING, +			ata_link_warn(pmp_link,  				"failed to disable NOTIFY (err_mask=0x%x)\n",  				err_mask);  			goto pmp_fail; @@ -1008,8 +1011,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,  					  gscr[SATA_PMP_GSCR_FEAT_EN]);  		if (err_mask) { -			ata_dev_printk(pmp_dev, KERN_ERR, "failed to write " -				       "PMP_FEAT_EN (Emask=0x%x)\n", err_mask); +			ata_dev_err(pmp_dev, +				    "failed to write PMP_FEAT_EN (Emask=0x%x)\n", +				    err_mask);  			rc = -EIO;  			goto pmp_fail;  		} @@ -1018,8 +1022,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  	/* check GSCR_ERROR */  	err_mask = sata_pmp_read(pmp_link, SATA_PMP_GSCR_ERROR, &gscr_error);  	if (err_mask) { -		ata_dev_printk(pmp_dev, KERN_ERR, "failed to read " -			       "PMP_GSCR_ERROR (Emask=0x%x)\n", err_mask); +		ata_dev_err(pmp_dev, +			    "failed to read PMP_GSCR_ERROR (Emask=0x%x)\n", +			    err_mask);  		rc = -EIO;  		goto pmp_fail;  	} @@ -1033,17 +1038,16 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  			ata_ehi_hotplugged(&link->eh_context.i);  			cnt++;  		} else { -			ata_link_printk(link, KERN_WARNING, -				"PHY status changed but maxed out on retries, " -				"giving up\n"); -			ata_link_printk(link, KERN_WARNING, -				"Manully issue scan to resume this link\n"); +			ata_link_warn(link, +				"PHY status changed but maxed out on retries, giving up\n"); +			ata_link_warn(link, +				"Manually issue scan to resume this link\n");  		}  	}  	if (cnt) { -		ata_port_printk(ap, KERN_INFO, "PMP SError.N set for some " -				"ports, repeating recovery\n"); +		ata_port_info(ap, +			"PMP SError.N set for some ports, repeating recovery\n");  		goto retry;  	} @@ -1071,9 +1075,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  		goto retry;  	} -	ata_port_printk(ap, KERN_ERR, -			"failed to recover PMP after %d tries, giving up\n", -			ATA_EH_PMP_TRIES); +	ata_port_err(ap, "failed to recover PMP after %d tries, giving up\n", +		     ATA_EH_PMP_TRIES);  	sata_pmp_detach(pmp_dev);  	ata_dev_disable(pmp_dev);  | 
