aboutsummaryrefslogtreecommitdiff
path: root/drivers/ata/libata-pmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-pmp.c')
-rw-r--r--drivers/ata/libata-pmp.c183
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, &reg);
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);