Skip to content

Commit

Permalink
Merge branch 'for-4.1-fixes' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/tj/libata

Pull libata fixes from Tejun Heo:
 "Rather big for fixes pull.

   - SCC controllers never lived to see the light of the day.  Both
     libata and ide drivers removed.

   - In some configurations, link power management policy changes
     sometimes cause delayed spurious PHY events which can develop into
     noticeable failures.  This has been reported several times over the
     years.  Gabriele's patches suppress PHY events for a while after
     LPM policy changes which should help most of these failures without
     causing too much problem for hotplug use cases.

   - A few controller specific fixes"

[ Hmm.  I don't think removing SSC support is really a "fix", but hey, it
  removes a lot of lines of code.  Which I like.  So ...  good riddance ]

* 'for-4.1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ahci: avoton port-disable reset-quirk
  ata: select DW_DMAC in case of SATA_DWC
  libata: Blacklist queued TRIM on all Samsung 800-series
  libata: Ignore spurious PHY event on LPM policy change
  libata: Add helper to determine when PHY events should be ignored
  ata: ahci_st: fixup layering violations / drvdata errors
  Remove celleb-only SCC PATA drivers
  • Loading branch information
torvalds committed May 11, 2015
2 parents c91aa67 + dbfe8ef commit b3e5838
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 2,053 deletions.
10 changes: 1 addition & 9 deletions drivers/ata/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ config ATA_PIIX
config SATA_DWC
tristate "DesignWare Cores SATA support"
depends on 460EX
select DW_DMAC
help
This option enables support for the on-chip SATA controller of the
AppliedMicro processor 460EX.
Expand Down Expand Up @@ -729,15 +730,6 @@ config PATA_SC1200

If unsure, say N.

config PATA_SCC
tristate "Toshiba's Cell Reference Set IDE support"
depends on PCI && PPC_CELLEB
help
This option enables support for the built-in IDE controller on
Toshiba Cell Reference Board.

If unsure, say N.

config PATA_SCH
tristate "Intel SCH PATA support"
depends on PCI
Expand Down
1 change: 0 additions & 1 deletion drivers/ata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
obj-$(CONFIG_PATA_RDC) += pata_rdc.o
obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
obj-$(CONFIG_PATA_SCC) += pata_scc.o
obj-$(CONFIG_PATA_SCH) += pata_sch.o
obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
Expand Down
103 changes: 95 additions & 8 deletions drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ enum board_ids {
board_ahci_yes_fbs,

/* board IDs for specific chipsets in alphabetical order */
board_ahci_avn,
board_ahci_mcp65,
board_ahci_mcp77,
board_ahci_mcp89,
Expand All @@ -84,6 +85,8 @@ enum board_ids {
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
static bool is_mcp89_apple(struct pci_dev *pdev);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
Expand All @@ -107,6 +110,11 @@ static struct ata_port_operations ahci_p5wdh_ops = {
.hardreset = ahci_p5wdh_hardreset,
};

static struct ata_port_operations ahci_avn_ops = {
.inherits = &ahci_ops,
.hardreset = ahci_avn_hardreset,
};

static const struct ata_port_info ahci_port_info[] = {
/* by features */
[board_ahci] = {
Expand Down Expand Up @@ -151,6 +159,12 @@ static const struct ata_port_info ahci_port_info[] = {
.port_ops = &ahci_ops,
},
/* by chipsets */
[board_ahci_avn] = {
.flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_avn_ops,
},
[board_ahci_mcp65] = {
AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
AHCI_HFLAG_YES_NCQ),
Expand Down Expand Up @@ -290,14 +304,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
Expand Down Expand Up @@ -670,6 +684,79 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
return rc;
}

/*
* ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
*
* It has been observed with some SSDs that the timing of events in the
* link synchronization phase can leave the port in a state that can not
* be recovered by a SATA-hard-reset alone. The failing signature is
* SStatus.DET stuck at 1 ("Device presence detected but Phy
* communication not established"). It was found that unloading and
* reloading the driver when this problem occurs allows the drive
* connection to be recovered (DET advanced to 0x3). The critical
* component of reloading the driver is that the port state machines are
* reset by bouncing "port enable" in the AHCI PCS configuration
* register. So, reproduce that effect by bouncing a port whenever we
* see DET==1 after a reset.
*/
static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
struct ata_port *ap = link->ap;
struct ahci_port_priv *pp = ap->private_data;
struct ahci_host_priv *hpriv = ap->host->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
unsigned long tmo = deadline - jiffies;
struct ata_taskfile tf;
bool online;
int rc, i;

DPRINTK("ENTER\n");

ahci_stop_engine(ap);

for (i = 0; i < 2; i++) {
u16 val;
u32 sstatus;
int port = ap->port_no;
struct ata_host *host = ap->host;
struct pci_dev *pdev = to_pci_dev(host->dev);

/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(link->device, &tf);
tf.command = ATA_BUSY;
ata_tf_to_fis(&tf, 0, 0, d2h_fis);

rc = sata_link_hardreset(link, timing, deadline, &online,
ahci_check_ready);

if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
(sstatus & 0xf) != 1)
break;

ata_link_printk(link, KERN_INFO, "avn bounce port%d\n",
port);

pci_read_config_word(pdev, 0x92, &val);
val &= ~(1 << port);
pci_write_config_word(pdev, 0x92, val);
ata_msleep(ap, 1000);
val |= 1 << port;
pci_write_config_word(pdev, 0x92, val);
deadline += tmo;
}

hpriv->start_engine(ap);

if (online)
*class = ahci_dev_classify(ap);

DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
return rc;
}


#ifdef CONFIG_PM
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
Expand Down
49 changes: 24 additions & 25 deletions drivers/ata/ahci_st.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ struct st_ahci_drv_data {
struct reset_control *pwr;
struct reset_control *sw_rst;
struct reset_control *pwr_rst;
struct ahci_host_priv *hpriv;
};

static void st_ahci_configure_oob(void __iomem *mmio)
Expand All @@ -55,9 +54,10 @@ static void st_ahci_configure_oob(void __iomem *mmio)
writel(new_val, mmio + ST_AHCI_OOBR);
}

static int st_ahci_deassert_resets(struct device *dev)
static int st_ahci_deassert_resets(struct ahci_host_priv *hpriv,
struct device *dev)
{
struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
struct st_ahci_drv_data *drv_data = hpriv->plat_data;
int err;

if (drv_data->pwr) {
Expand Down Expand Up @@ -90,8 +90,8 @@ static int st_ahci_deassert_resets(struct device *dev)
static void st_ahci_host_stop(struct ata_host *host)
{
struct ahci_host_priv *hpriv = host->private_data;
struct st_ahci_drv_data *drv_data = hpriv->plat_data;
struct device *dev = host->dev;
struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
int err;

if (drv_data->pwr) {
Expand All @@ -103,29 +103,30 @@ static void st_ahci_host_stop(struct ata_host *host)
ahci_platform_disable_resources(hpriv);
}

static int st_ahci_probe_resets(struct platform_device *pdev)
static int st_ahci_probe_resets(struct ahci_host_priv *hpriv,
struct device *dev)
{
struct st_ahci_drv_data *drv_data = platform_get_drvdata(pdev);
struct st_ahci_drv_data *drv_data = hpriv->plat_data;

drv_data->pwr = devm_reset_control_get(&pdev->dev, "pwr-dwn");
drv_data->pwr = devm_reset_control_get(dev, "pwr-dwn");
if (IS_ERR(drv_data->pwr)) {
dev_info(&pdev->dev, "power reset control not defined\n");
dev_info(dev, "power reset control not defined\n");
drv_data->pwr = NULL;
}

drv_data->sw_rst = devm_reset_control_get(&pdev->dev, "sw-rst");
drv_data->sw_rst = devm_reset_control_get(dev, "sw-rst");
if (IS_ERR(drv_data->sw_rst)) {
dev_info(&pdev->dev, "soft reset control not defined\n");
dev_info(dev, "soft reset control not defined\n");
drv_data->sw_rst = NULL;
}

drv_data->pwr_rst = devm_reset_control_get(&pdev->dev, "pwr-rst");
drv_data->pwr_rst = devm_reset_control_get(dev, "pwr-rst");
if (IS_ERR(drv_data->pwr_rst)) {
dev_dbg(&pdev->dev, "power soft reset control not defined\n");
dev_dbg(dev, "power soft reset control not defined\n");
drv_data->pwr_rst = NULL;
}

return st_ahci_deassert_resets(&pdev->dev);
return st_ahci_deassert_resets(hpriv, dev);
}

static struct ata_port_operations st_ahci_port_ops = {
Expand Down Expand Up @@ -154,23 +155,20 @@ static int st_ahci_probe(struct platform_device *pdev)
if (!drv_data)
return -ENOMEM;

platform_set_drvdata(pdev, drv_data);

hpriv = ahci_platform_get_resources(pdev);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
hpriv->plat_data = drv_data;

drv_data->hpriv = hpriv;

err = st_ahci_probe_resets(pdev);
err = st_ahci_probe_resets(hpriv, &pdev->dev);
if (err)
return err;

err = ahci_platform_enable_resources(hpriv);
if (err)
return err;

st_ahci_configure_oob(drv_data->hpriv->mmio);
st_ahci_configure_oob(hpriv->mmio);

err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info,
&ahci_platform_sht);
Expand All @@ -185,8 +183,9 @@ static int st_ahci_probe(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int st_ahci_suspend(struct device *dev)
{
struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = drv_data->hpriv;
struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data;
struct st_ahci_drv_data *drv_data = hpriv->plat_data;
int err;

err = ahci_platform_suspend_host(dev);
Expand All @@ -208,21 +207,21 @@ static int st_ahci_suspend(struct device *dev)

static int st_ahci_resume(struct device *dev)
{
struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = drv_data->hpriv;
struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data;
int err;

err = ahci_platform_enable_resources(hpriv);
if (err)
return err;

err = st_ahci_deassert_resets(dev);
err = st_ahci_deassert_resets(hpriv, dev);
if (err) {
ahci_platform_disable_resources(hpriv);
return err;
}

st_ahci_configure_oob(drv_data->hpriv->mmio);
st_ahci_configure_oob(hpriv->mmio);

return ahci_platform_resume_host(dev);
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/ata/libahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1707,8 +1707,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
if (unlikely(resetting))
status &= ~PORT_IRQ_BAD_PMP;

/* if LPM is enabled, PHYRDY doesn't mean anything */
if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
if (sata_lpm_ignore_phy_events(&ap->link)) {
status &= ~PORT_IRQ_PHYRDY;
ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
}
Expand Down
34 changes: 33 additions & 1 deletion drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4235,7 +4235,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Samsung SSD 850 PRO*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
{ "Samsung SSD 8*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },

/*
Expand Down Expand Up @@ -6752,6 +6752,38 @@ u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val,
return tmp;
}

/**
* sata_lpm_ignore_phy_events - test if PHY event should be ignored
* @link: Link receiving the event
*
* Test whether the received PHY event has to be ignored or not.
*
* LOCKING:
* None:
*
* RETURNS:
* True if the event has to be ignored.
*/
bool sata_lpm_ignore_phy_events(struct ata_link *link)
{
unsigned long lpm_timeout = link->last_lpm_change +
msecs_to_jiffies(ATA_TMOUT_SPURIOUS_PHY);

/* if LPM is enabled, PHYRDY doesn't mean anything */
if (link->lpm_policy > ATA_LPM_MAX_POWER)
return true;

/* ignore the first PHY event after the LPM policy changed
* as it is might be spurious
*/
if ((link->flags & ATA_LFLAG_CHANGED) &&
time_before(jiffies, lpm_timeout))
return true;

return false;
}
EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events);

/*
* Dummy port_ops
*/
Expand Down
3 changes: 3 additions & 0 deletions drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -3597,6 +3597,9 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
}
}

link->last_lpm_change = jiffies;
link->flags |= ATA_LFLAG_CHANGED;

return 0;

fail:
Expand Down
Loading

0 comments on commit b3e5838

Please sign in to comment.