Commit 51562cba authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev

Pull libata changes from Jeff Garzik:
 "Minor libata updates, nothing notable.

   1) Apply -- and then revert -- the FUA feature.  Caused disk
      corruption in linux-next, proving it cannot be turned on by
      default.

      Net effect to upstream tree:  zero

   2) New AHCI platform driver sata_highbank

   3) Improve SCSI MODE SENSE handling; support MODE SELECT

   4) AHCI: support aggressive device sleep (power mgmt)

   5) sata_fsl: minor fix

   6) pata_arasan: clk support"

* tag 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  sata_mv: Fix warnings when no PCI
  [libata] Makefile: Fix build error in sata_highbank
  [libata] export ata_dev_set_feature()
  libata-core: use ATA_LBA in ata_build_rw_tf()
  ata/ahci_platform: Add clock framework support
  pata_arasan: add Device Tree probing capability
  pata_arasan: Add clk_{un}prepare() support
  ata: add platform driver for Calxeda AHCI controller
  sata_fsl: add workaround for data length mismatch on freescale V2 controller
  ahci: implement aggressive SATA device sleep support
  ata: define enum constants for IDENTIFY DEVICE
  Revert "libata: enable SATA disk fua detection on default"
  [libata] scsi: implement MODE SELECT command
  [libata] scsi: support MODE SENSE request for changeable and default parameters
  [libata] scsi: Remove unlikely() from FUA check
  libata: enable SATA disk fua detection on default
parents 7fe0b14b 13b74085
Calxeda Highbank Combination Phys for SATA
Properties:
- compatible : Should be "calxeda,hb-combophy"
- #phy-cells: Should be 1.
- reg : Address and size for Combination Phy registers.
- phydev: device ID for programming the combophy.
Example:
combophy5: combo-phy@fff5d000 {
compatible = "calxeda,hb-combophy";
#phy-cells = <1>;
reg = <0xfff5d000 0x1000>;
phydev = <31>;
};
...@@ -8,9 +8,17 @@ Required properties: ...@@ -8,9 +8,17 @@ Required properties:
- interrupts : <interrupt mapping for SATA IRQ> - interrupts : <interrupt mapping for SATA IRQ>
- reg : <registers mapping> - reg : <registers mapping>
Optional properties:
- calxeda,port-phys: phandle-combophy and lane assignment, which maps each
SATA port to a combophy and a lane within that
combophy
Example: Example:
sata@ffe08000 { sata@ffe08000 {
compatible = "calxeda,hb-ahci"; compatible = "calxeda,hb-ahci";
reg = <0xffe08000 0x1000>; reg = <0xffe08000 0x1000>;
interrupts = <115>; interrupts = <115>;
calxeda,port-phys = <&combophy5 0 &combophy0 0 &combophy0 1
&combophy0 2 &combophy0 3>;
}; };
* ARASAN PATA COMPACT FLASH CONTROLLER
Required properties:
- compatible: "arasan,cf-spear1340"
- reg: Address range of the CF registers
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupt: Should contain the CF interrupt number
Example:
cf@fc000000 {
compatible = "arasan,cf-spear1340";
reg = <0xfc000000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <12>;
};
...@@ -121,6 +121,9 @@ sata@ffe08000 { ...@@ -121,6 +121,9 @@ sata@ffe08000 {
compatible = "calxeda,hb-ahci"; compatible = "calxeda,hb-ahci";
reg = <0xffe08000 0x10000>; reg = <0xffe08000 0x10000>;
interrupts = <0 83 4>; interrupts = <0 83 4>;
calxeda,port-phys = <&combophy5 0 &combophy0 0
&combophy0 1 &combophy0 2
&combophy0 3>;
}; };
sdhci@ffe0e000 { sdhci@ffe0e000 {
...@@ -306,5 +309,19 @@ ethernet@fff51000 { ...@@ -306,5 +309,19 @@ ethernet@fff51000 {
reg = <0xfff51000 0x1000>; reg = <0xfff51000 0x1000>;
interrupts = <0 80 4 0 81 4 0 82 4>; interrupts = <0 80 4 0 81 4 0 82 4>;
}; };
combophy0: combo-phy@fff58000 {
compatible = "calxeda,hb-combophy";
#phy-cells = <1>;
reg = <0xfff58000 0x1000>;
phydev = <5>;
};
combophy5: combo-phy@fff5d000 {
compatible = "calxeda,hb-combophy";
#phy-cells = <1>;
reg = <0xfff5d000 0x1000>;
phydev = <31>;
};
}; };
}; };
...@@ -214,6 +214,14 @@ config SATA_DWC_VDEBUG ...@@ -214,6 +214,14 @@ config SATA_DWC_VDEBUG
help help
This option enables the taskfile dumping and NCQ debugging. This option enables the taskfile dumping and NCQ debugging.
config SATA_HIGHBANK
tristate "Calxeda Highbank SATA support"
help
This option enables support for the Calxeda Highbank SoC's
onboard SATA.
If unsure, say N.
config SATA_MV config SATA_MV
tristate "Marvell SATA support" tristate "Marvell SATA support"
help help
......
...@@ -9,6 +9,7 @@ obj-$(CONFIG_SATA_FSL) += sata_fsl.o ...@@ -9,6 +9,7 @@ obj-$(CONFIG_SATA_FSL) += sata_fsl.o
obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
obj-$(CONFIG_SATA_SIL24) += sata_sil24.o obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
# SFF w/ custom DMA # SFF w/ custom DMA
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#ifndef _AHCI_H #ifndef _AHCI_H
#define _AHCI_H #define _AHCI_H
#include <linux/clk.h>
#include <linux/libata.h> #include <linux/libata.h>
/* Enclosure Management Control */ /* Enclosure Management Control */
...@@ -115,6 +116,9 @@ enum { ...@@ -115,6 +116,9 @@ enum {
HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */ HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */
HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */ HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */
HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */ HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */
HOST_CAP2_SDS = (1 << 3), /* Support device sleep */
HOST_CAP2_SADM = (1 << 4), /* Support aggressive DevSlp */
HOST_CAP2_DESO = (1 << 5), /* DevSlp from slumber only */
/* registers for each SATA port */ /* registers for each SATA port */
PORT_LST_ADDR = 0x00, /* command list DMA addr */ PORT_LST_ADDR = 0x00, /* command list DMA addr */
...@@ -133,6 +137,7 @@ enum { ...@@ -133,6 +137,7 @@ enum {
PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */ PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */ PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
PORT_FBS = 0x40, /* FIS-based Switching */ PORT_FBS = 0x40, /* FIS-based Switching */
PORT_DEVSLP = 0x44, /* device sleep */
/* PORT_IRQ_{STAT,MASK} bits */ /* PORT_IRQ_{STAT,MASK} bits */
PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */ PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
...@@ -186,6 +191,7 @@ enum { ...@@ -186,6 +191,7 @@ enum {
PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
/* PORT_FBS bits */
PORT_FBS_DWE_OFFSET = 16, /* FBS device with error offset */ PORT_FBS_DWE_OFFSET = 16, /* FBS device with error offset */
PORT_FBS_ADO_OFFSET = 12, /* FBS active dev optimization offset */ PORT_FBS_ADO_OFFSET = 12, /* FBS active dev optimization offset */
PORT_FBS_DEV_OFFSET = 8, /* FBS device to issue offset */ PORT_FBS_DEV_OFFSET = 8, /* FBS device to issue offset */
...@@ -194,6 +200,15 @@ enum { ...@@ -194,6 +200,15 @@ enum {
PORT_FBS_DEC = (1 << 1), /* FBS device error clear */ PORT_FBS_DEC = (1 << 1), /* FBS device error clear */
PORT_FBS_EN = (1 << 0), /* Enable FBS */ PORT_FBS_EN = (1 << 0), /* Enable FBS */
/* PORT_DEVSLP bits */
PORT_DEVSLP_DM_OFFSET = 25, /* DITO multiplier offset */
PORT_DEVSLP_DM_MASK = (0xf << 25), /* DITO multiplier mask */
PORT_DEVSLP_DITO_OFFSET = 15, /* DITO offset */
PORT_DEVSLP_MDAT_OFFSET = 10, /* Minimum assertion time */
PORT_DEVSLP_DETO_OFFSET = 2, /* DevSlp exit timeout */
PORT_DEVSLP_DSP = (1 << 1), /* DevSlp present */
PORT_DEVSLP_ADSE = (1 << 0), /* Aggressive DevSlp enable */
/* hpriv->flags bits */ /* hpriv->flags bits */
#define AHCI_HFLAGS(flags) .private_data = (void *)(flags) #define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
...@@ -302,6 +317,7 @@ struct ahci_host_priv { ...@@ -302,6 +317,7 @@ struct ahci_host_priv {
u32 em_loc; /* enclosure management location */ u32 em_loc; /* enclosure management location */
u32 em_buf_sz; /* EM buffer size in byte */ u32 em_buf_sz; /* EM buffer size in byte */
u32 em_msg_type; /* EM message type */ u32 em_msg_type; /* EM message type */
struct clk *clk; /* Only for platforms supporting clk */
}; };
extern int ahci_ignore_sss; extern int ahci_ignore_sss;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* any later version. * any later version.
*/ */
#include <linux/clk.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -118,6 +119,17 @@ static int __init ahci_probe(struct platform_device *pdev) ...@@ -118,6 +119,17 @@ static int __init ahci_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
hpriv->clk = clk_get(dev, NULL);
if (IS_ERR(hpriv->clk)) {
dev_err(dev, "can't get clock\n");
} else {
rc = clk_prepare_enable(hpriv->clk);
if (rc) {
dev_err(dev, "clock prepare enable failed");
goto free_clk;
}
}
/* /*
* Some platforms might need to prepare for mmio region access, * Some platforms might need to prepare for mmio region access,
* which could be done in the following init call. So, the mmio * which could be done in the following init call. So, the mmio
...@@ -127,7 +139,7 @@ static int __init ahci_probe(struct platform_device *pdev) ...@@ -127,7 +139,7 @@ static int __init ahci_probe(struct platform_device *pdev)
if (pdata && pdata->init) { if (pdata && pdata->init) {
rc = pdata->init(dev, hpriv->mmio); rc = pdata->init(dev, hpriv->mmio);
if (rc) if (rc)
return rc; goto disable_unprepare_clk;
} }
ahci_save_initial_config(dev, hpriv, ahci_save_initial_config(dev, hpriv,
...@@ -153,7 +165,7 @@ static int __init ahci_probe(struct platform_device *pdev) ...@@ -153,7 +165,7 @@ static int __init ahci_probe(struct platform_device *pdev)
host = ata_host_alloc_pinfo(dev, ppi, n_ports); host = ata_host_alloc_pinfo(dev, ppi, n_ports);
if (!host) { if (!host) {
rc = -ENOMEM; rc = -ENOMEM;
goto err0; goto pdata_exit;
} }
host->private_data = hpriv; host->private_data = hpriv;
...@@ -183,7 +195,7 @@ static int __init ahci_probe(struct platform_device *pdev) ...@@ -183,7 +195,7 @@ static int __init ahci_probe(struct platform_device *pdev)
rc = ahci_reset_controller(host); rc = ahci_reset_controller(host);
if (rc) if (rc)
goto err0; goto pdata_exit;
ahci_init_controller(host); ahci_init_controller(host);
ahci_print_info(host, "platform"); ahci_print_info(host, "platform");
...@@ -191,12 +203,18 @@ static int __init ahci_probe(struct platform_device *pdev) ...@@ -191,12 +203,18 @@ static int __init ahci_probe(struct platform_device *pdev)
rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
&ahci_platform_sht); &ahci_platform_sht);
if (rc) if (rc)
goto err0; goto pdata_exit;
return 0; return 0;
err0: pdata_exit:
if (pdata && pdata->exit) if (pdata && pdata->exit)
pdata->exit(dev); pdata->exit(dev);
disable_unprepare_clk:
if (!IS_ERR(hpriv->clk))
clk_disable_unprepare(hpriv->clk);
free_clk:
if (!IS_ERR(hpriv->clk))
clk_put(hpriv->clk);
return rc; return rc;
} }
...@@ -205,12 +223,18 @@ static int __devexit ahci_remove(struct platform_device *pdev) ...@@ -205,12 +223,18 @@ static int __devexit ahci_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ahci_platform_data *pdata = dev_get_platdata(dev);
struct ata_host *host = dev_get_drvdata(dev); struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data;
ata_host_detach(host); ata_host_detach(host);
if (pdata && pdata->exit) if (pdata && pdata->exit)
pdata->exit(dev); pdata->exit(dev);
if (!IS_ERR(hpriv->clk)) {
clk_disable_unprepare(hpriv->clk);
clk_put(hpriv->clk);
}
return 0; return 0;
} }
...@@ -245,6 +269,10 @@ static int ahci_suspend(struct device *dev) ...@@ -245,6 +269,10 @@ static int ahci_suspend(struct device *dev)
if (pdata && pdata->suspend) if (pdata && pdata->suspend)
return pdata->suspend(dev); return pdata->suspend(dev);
if (!IS_ERR(hpriv->clk))
clk_disable_unprepare(hpriv->clk);
return 0; return 0;
} }
...@@ -252,18 +280,27 @@ static int ahci_resume(struct device *dev) ...@@ -252,18 +280,27 @@ static int ahci_resume(struct device *dev)
{ {
struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ahci_platform_data *pdata = dev_get_platdata(dev);
struct ata_host *host = dev_get_drvdata(dev); struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data;
int rc; int rc;
if (!IS_ERR(hpriv->clk)) {
rc = clk_prepare_enable(hpriv->clk);
if (rc) {
dev_err(dev, "clock prepare enable failed");
return rc;
}
}
if (pdata && pdata->resume) { if (pdata && pdata->resume) {
rc = pdata->resume(dev); rc = pdata->resume(dev);
if (rc) if (rc)
return rc; goto disable_unprepare_clk;
} }
if (dev->power.power_state.event == PM_EVENT_SUSPEND) { if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
rc = ahci_reset_controller(host); rc = ahci_reset_controller(host);
if (rc) if (rc)
return rc; goto disable_unprepare_clk;
ahci_init_controller(host); ahci_init_controller(host);
} }
...@@ -271,13 +308,18 @@ static int ahci_resume(struct device *dev) ...@@ -271,13 +308,18 @@ static int ahci_resume(struct device *dev)
ata_host_resume(host); ata_host_resume(host);
return 0; return 0;
disable_unprepare_clk:
if (!IS_ERR(hpriv->clk))
clk_disable_unprepare(hpriv->clk);
return rc;
} }
#endif #endif
SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
static const struct of_device_id ahci_of_match[] = { static const struct of_device_id ahci_of_match[] = {
{ .compatible = "calxeda,hb-ahci", },
{ .compatible = "snps,spear-ahci", }, { .compatible = "snps,spear-ahci", },
{}, {},
}; };
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <linux/libata.h> #include <linux/libata.h>
#include "ahci.h" #include "ahci.h"
#include "libata.h"
static int ahci_skip_host_reset; static int ahci_skip_host_reset;
int ahci_ignore_sss; int ahci_ignore_sss;
...@@ -76,6 +77,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc); ...@@ -76,6 +77,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc); static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc);
static void ahci_freeze(struct ata_port *ap); static void ahci_freeze(struct ata_port *ap);
static void ahci_thaw(struct ata_port *ap); static void ahci_thaw(struct ata_port *ap);
static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep);
static void ahci_enable_fbs(struct ata_port *ap); static void ahci_enable_fbs(struct ata_port *ap);
static void ahci_disable_fbs(struct ata_port *ap); static void ahci_disable_fbs(struct ata_port *ap);
static void ahci_pmp_attach(struct ata_port *ap); static void ahci_pmp_attach(struct ata_port *ap);
...@@ -193,6 +195,10 @@ module_param(ahci_em_messages, int, 0444); ...@@ -193,6 +195,10 @@ module_param(ahci_em_messages, int, 0444);
MODULE_PARM_DESC(ahci_em_messages, MODULE_PARM_DESC(ahci_em_messages,
"AHCI Enclosure Management Message control (0 = off, 1 = on)"); "AHCI Enclosure Management Message control (0 = off, 1 = on)");
int devslp_idle_timeout = 1000; /* device sleep idle timeout in ms */
module_param(devslp_idle_timeout, int, 0644);
MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout");
static void ahci_enable_ahci(void __iomem *mmio) static void ahci_enable_ahci(void __iomem *mmio)
{ {
int i; int i;
...@@ -702,6 +708,16 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, ...@@ -702,6 +708,16 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
} }
} }
/* set aggressive device sleep */
if ((hpriv->cap2 & HOST_CAP2_SDS) &&
(hpriv->cap2 & HOST_CAP2_SADM) &&
(link->device->flags & ATA_DFLAG_DEVSLP)) {
if (policy == ATA_LPM_MIN_POWER)
ahci_set_aggressive_devslp(ap, true);
else
ahci_set_aggressive_devslp(ap, false);
}
if (policy == ATA_LPM_MAX_POWER) { if (policy == ATA_LPM_MAX_POWER) {
sata_link_scr_lpm(link, policy, false); sata_link_scr_lpm(link, policy, false);
...@@ -1890,6 +1906,81 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) ...@@ -1890,6 +1906,81 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
ahci_kick_engine(ap); ahci_kick_engine(ap);
} }
static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
{
void __iomem *port_mmio = ahci_port_base(ap);
struct ata_device *dev = ap->link.device;
u32 devslp, dm, dito, mdat, deto;
int rc;
unsigned int err_mask;
devslp = readl(port_mmio + PORT_DEVSLP);
if (!(devslp & PORT_DEVSLP_DSP)) {
dev_err(ap->host->dev, "port does not support device sleep\n");
return;
}
/* disable device sleep */
if (!sleep) {
if (devslp & PORT_DEVSLP_ADSE) {
writel(devslp & ~PORT_DEVSLP_ADSE,
port_mmio + PORT_DEVSLP);
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_DISABLE,
SATA_DEVSLP);
if (err_mask && err_mask != AC_ERR_DEV)
ata_dev_warn(dev, "failed to disable DEVSLP\n");
}
return;
}
/* device sleep was already enabled */
if (devslp & PORT_DEVSLP_ADSE)
return;
/* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */
rc = ahci_stop_engine(ap);
if (rc)
return;
dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
dito = devslp_idle_timeout / (dm + 1);
if (dito > 0x3ff)
dito = 0x3ff;
/* Use the nominal value 10 ms if the read MDAT is zero,
* the nominal value of DETO is 20 ms.
*/
if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] &
ATA_LOG_DEVSLP_VALID_MASK) {
mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] &
ATA_LOG_DEVSLP_MDAT_MASK;
if (!mdat)
mdat = 10;
deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO];
if (!deto)
deto = 20;
} else {
mdat = 10;
deto = 20;
}
devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) |
(mdat << PORT_DEVSLP_MDAT_OFFSET) |
(deto << PORT_DEVSLP_DETO_OFFSET) |
PORT_DEVSLP_ADSE);
writel(devslp, port_mmio + PORT_DEVSLP);
ahci_start_engine(ap);
/* enable device sleep feature for the drive */
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_ENABLE,
SATA_DEVSLP);
if (err_mask && err_mask != AC_ERR_DEV)
ata_dev_warn(dev, "failed to enable DEVSLP\n");
}
static void ahci_enable_fbs(struct ata_port *ap) static void ahci_enable_fbs(struct ata_port *ap)
{ {
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
...@@ -2164,7 +2255,8 @@ void ahci_print_info(struct ata_host *host, const char *scc_s) ...@@ -2164,7 +2255,8 @@ void ahci_print_info(struct ata_host *host, const char *scc_s)
"flags: " "flags: "
"%s%s%s%s%s%s%s" "%s%s%s%s%s%s%s"
"%s%s%s%s%s%s%s" "%s%s%s%s%s%s%s"
"%s%s%s%s%s%s\n" "%s%s%s%s%s%s%s"
"%s%s\n"
, ,
cap & HOST_CAP_64 ? "64bit " : "", cap & HOST_CAP_64 ? "64bit " : "",
...@@ -2184,6 +2276,9 @@ void ahci_print_info(struct ata_host *host, const char *scc_s) ...@@ -2184,6 +2276,9 @@ void ahci_print_info(struct ata_host *host, const char *scc_s)
cap & HOST_CAP_CCC ? "ccc " : "", cap & HOST_CAP_CCC ? "ccc " : "",
cap & HOST_CAP_EMS ? "ems " : "", cap & HOST_CAP_EMS ? "ems " : "",
cap & HOST_CAP_SXS ? "sxs " : "", cap & HOST_CAP_SXS ? "sxs " : "",
cap2 & HOST_CAP2_DESO ? "deso " : "",
cap2 & HOST_CAP2_SADM ? "sadm " : "",
cap2 & HOST_CAP2_SDS ? "sds " : "",
cap2 & HOST_CAP2_APST ? "apst " : "", cap2 & HOST_CAP2_APST ? "apst " : "",
cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "", cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
cap2 & HOST_CAP2_BOH ? "boh " : "" cap2 & HOST_CAP2_BOH ? "boh " : ""
......
...@@ -774,7 +774,7 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, ...@@ -774,7 +774,7 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
tf->lbam = (block >> 8) & 0xff; tf->lbam = (block >> 8) & 0xff;
tf->lbal = block & 0xff; tf->lbal = block & 0xff;
tf->device = 1 << 6; tf->device = ATA_LBA;
if (tf->flags & ATA_TFLAG_FUA) if (tf->flags & ATA_TFLAG_FUA)
tf->device |= 1 << 7; tf->device |= 1 << 7;
} else if (dev->flags & ATA_DFLAG_LBA) { } else if (dev->flags & ATA_DFLAG_LBA) {
...@@ -2155,6 +2155,7 @@ int ata_dev_configure(struct ata_device *dev) ...@@ -2155,6 +2155,7 @@ int ata_dev_configure(struct ata_device *dev)
int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
const u16 *id = dev->id; const u16 *id = dev->id;
unsigned long xfer_mask; unsigned long xfer_mask;
unsigned int err_mask;
char revbuf[7]; /* XYZ-99\0 */ char revbuf[7]; /* XYZ-99\0 */
char fwrevbuf[ATA_ID_FW_REV_LEN+1]; char fwrevbuf[ATA_ID_FW_REV_LEN+1];
char modelbuf[ATA_ID_PROD_LEN+1]; char modelbuf[ATA_ID_PROD_LEN+1];
...@@ -2323,6 +2324,26 @@ int ata_dev_configure(struct ata_device *dev) ...@@ -2323,6 +2324,26 @@ int ata_dev_configure(struct ata_device *dev)
} }
} }
/* check and mark DevSlp capability */
if (ata_id_has_devslp(dev->id))
dev->flags |= ATA_DFLAG_DEVSLP;
/* Obtain SATA Settings page from Identify Device Data Log,
* which contains DevSlp timing variables etc.
* Exclude old devices with ata_id_has_ncq()
*/
if (ata_id_has_ncq(dev->id)) {
err_mask = ata_read_log_page(dev,
ATA_LOG_SATA_ID_DEV_DATA,
ATA_LOG_SATA_SETTINGS,
dev->sata_settings,
1);
if (err_mask)
ata_dev_dbg(dev,
"failed to get Identify Device Data, Emask 0x%x\n",
err_mask);
}
dev->cdb_len = 16; dev->cdb_len = 16;
} }
...@@ -2351,8 +2372,6 @@ int ata_dev_configure(struct ata_device *dev) ...@@ -2351,8 +2372,6 @@ int ata_dev_configure(struct ata_device *dev)
(ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) && (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
(!sata_pmp_attached(ap) || (!sata_pmp_attached(ap) ||
sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) { sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
unsigned int err_mask;
/* issue SET feature command to turn this on */ /* issue SET feature command to turn this on */
err_mask = ata_dev_set_feature(dev, err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_ENABLE, SATA_AN); SETFEATURES_SATA_ENABLE, SATA_AN);
...@@ -3598,7 +3617,7 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy, ...@@ -3598,7 +3617,7 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
switch (policy) { switch (policy) {
case ATA_LPM_MAX_POWER: case ATA_LPM_MAX_POWER:
/* disable all LPM transitions */ /* disable all LPM transitions */
scontrol |= (0x3 << 8); scontrol |= (0x7 << 8);
/* initiate transition to active state */ /* initiate transition to active state */
if (spm_wakeup) { if (spm_wakeup) {
scontrol |= (0x4 << 12); scontrol |= (0x4 << 12);
...@@ -3608,12 +3627,12 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy, ...@@ -3608,12 +3627,12 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
case ATA_LPM_MED_POWER: case ATA_LPM_MED_POWER:
/* allow LPM to PARTIAL */ /* allow LPM to PARTIAL */
scontrol &= ~(0x1 << 8); scontrol &= ~(0x1 << 8);
scontrol |= (0x2 << 8); scontrol |= (0x6 << 8);
break; break;
case ATA_LPM_MIN_POWER: case ATA_LPM_MIN_POWER:
if (ata_link_nr_enabled(link) > 0) if (ata_link_nr_enabled(link) > 0)
/* no restrictions on LPM transitions */ /* no restrictions on LPM transitions */
scontrol &= ~(0x3 << 8); scontrol &= ~(0x7 << 8);
else { else {
/* empty port, power off */ /* empty port, power off */
scontrol &= ~0xf; scontrol &= ~0xf;
...@@ -4472,6 +4491,7 @@ unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature) ...@@ -4472,6 +4491,7 @@ unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature)
DPRINTK("EXIT, err_mask=%x\n", err_mask); DPRINTK("EXIT, err_mask=%x\n", err_mask);
return err_mask; return err_mask;
} }
EXPORT_SYMBOL_GPL(ata_dev_set_feature);
/** /**
* ata_dev_init_params - Issue INIT DEV PARAMS command * ata_dev_init_params - Issue INIT DEV PARAMS command
......
...@@ -1487,6 +1487,7 @@ static const char *ata_err_string(unsigned int err_mask) ...@@ -1487,6 +1487,7 @@ static const char *ata_err_string(unsigned int err_mask)
/** /**
* ata_read_log_page - read a specific log page * ata_read_log_page - read a specific log page
* @dev: target device * @dev: target device
* @log: log to read
* @page: page to read * @page: page to read
* @buf: buffer to store read page * @buf: buffer to store read page
* @sectors: number of sectors to read * @sectors: number of sectors to read
...@@ -1499,17 +1500,18 @@ static const char *ata_err_string(unsigned int err_mask) ...@@ -1499,17 +1500,18 @@ static const char *ata_err_string(unsigned int err_mask)
* RETURNS: * RETURNS:
* 0 on success, AC_ERR_* mask otherwise. * 0 on success, AC_ERR_* mask otherwise.
*/ */
static unsigned int ata_read_log_page(struct ata_device *dev, unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
u8 page, void *buf, unsigned int sectors) u8 page, void *buf, unsigned int sectors)
{ {
struct ata_taskfile tf; struct ata_taskfile tf;
unsigned int err_mask; unsigned int err_mask;
DPRINTK("read log page - page %d\n", page); DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
ata_tf_init(dev, &tf); ata_tf_init(dev, &tf);
tf.command = ATA_CMD_READ_LOG_EXT; tf.command = ATA_CMD_READ_LOG_EXT;
tf.lbal = page; tf.lbal = log;
tf.lbam = page;
tf.nsect = sectors; tf.nsect = sectors;
tf.hob_nsect = sectors >> 8; tf.hob_nsect = sectors >> 8;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
...@@ -1545,7 +1547,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev, ...@@ -1545,7 +1547,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
u8 csum; u8 csum;
int i; int i;
err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1); err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, 0, buf, 1);
if (err_mask) if (err_mask)
return -EIO; return -EIO;
......
...@@ -1655,7 +1655,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) ...@@ -1655,7 +1655,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
if (unlikely(scmd->cmd_len < 10)) if (unlikely(scmd->cmd_len < 10))
goto invalid_fld; goto invalid_fld;
scsi_10_lba_len(cdb, &block, &n_block); scsi_10_lba_len(cdb, &block, &n_block);
if (unlikely(cdb[1] & (1 << 3))) if (cdb[1] & (1 << 3))
tf_flags |= ATA_TFLAG_FUA; tf_flags |= ATA_TFLAG_FUA;
break; break;
case READ_6: case READ_6:
...@@ -1675,7 +1675,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) ...@@ -1675,7 +1675,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
if (unlikely(scmd->cmd_len < 16)) if (unlikely(scmd->cmd_len < 16))
goto invalid_fld; goto invalid_fld;
scsi_16_lba_len(cdb, &block, &n_block); scsi_16_lba_len(cdb, &block, &n_block);
if (unlikely(cdb[1] & (1 << 3))) if (cdb[1] & (1 << 3))
tf_flags |= ATA_TFLAG_FUA; tf_flags |= ATA_TFLAG_FUA;
break; break;
default: default:
...@@ -2204,10 +2204,34 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf) ...@@ -2204,10 +2204,34 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
return 0; return 0;
} }
/**
* modecpy - Prepare response for MODE SENSE
* @dest: output buffer
* @src: data being copied
* @n: length of mode page
* @changeable: whether changeable parameters are requested
*
* Generate a generic MODE SENSE page for either current or changeable
* parameters.
*
* LOCKING:
* None.
*/
static void modecpy(u8 *dest, const u8 *src, int n, bool changeable)
{
if (changeable) {
memcpy(dest, src, 2);
memset(dest + 2, 0, n - 2);
} else {
memcpy(dest, src, n);
}
}
/** /**
* ata_msense_caching - Simulate MODE SENSE caching info page * ata_msense_caching - Simulate MODE SENSE caching info page
* @id: device IDENTIFY data * @id: device IDENTIFY data
* @buf: output buffer * @buf: output buffer
* @changeable: whether changeable parameters are requested
* *
* Generate a caching info page, which conditionally indicates * Generate a caching info page, which conditionally indicates
* write caching to the SCSI layer, depending on device * write caching to the SCSI layer, depending on device
...@@ -2216,12 +2240,12 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf) ...@@ -2216,12 +2240,12 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
* LOCKING: * LOCKING:
* None. * None.
*/ */
static unsigned int ata_msense_caching(u16 *id, u8 *buf) static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
{ {
memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage)); modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable);
if (ata_id_wcache_enabled(id)) if (changeable || ata_id_wcache_enabled(id))
buf[2] |= (1 << 2); /* write cache enable */ buf[2] |= (1 << 2); /* write cache enable */
if (!ata_id_rahead_enabled(id)) if (!changeable && !ata_id_rahead_enabled(id))
buf[12] |= (1 << 5); /* disable read ahead */ buf[12] |= (1 << 5); /* disable read ahead */
return sizeof(def_cache_mpage); return sizeof(def_cache_mpage);
} }
...@@ -2229,30 +2253,33 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf) ...@@ -2229,30 +2253,33 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf)
/** /**
* ata_msense_ctl_mode - Simulate MODE SENSE control mode page * ata_msense_ctl_mode - Simulate MODE SENSE control mode page
* @buf: output buffer * @buf: output buffer
* @changeable: whether changeable parameters are requested
* *
* Generate a generic MODE SENSE control mode page. * Generate a generic MODE SENSE control mode page.
* *
* LOCKING: * LOCKING:
* None. * None.
*/ */
static unsigned int ata_msense_ctl_mode(u8 *buf) static unsigned int ata_msense_ctl_mode(u8 *buf, bool changeable)
{ {
memcpy(buf, def_control_mpage, sizeof(def_control_mpage)); modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable);
return sizeof(def_control_mpage); return sizeof(def_control_mpage);
} }
/** /**
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
* @buf: output buffer * @buf: output buffer
* @changeable: whether changeable parameters are requested
* *
* Generate a generic MODE SENSE r/w error recovery page. * Generate a generic MODE SENSE r/w error recovery page.
* *
* LOCKING: * LOCKING:
* None. * None.
*/ */
static unsigned int ata_msense_rw_recovery(u8 *buf) static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable)
{ {
memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage)); modecpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage),
changeable);
return sizeof(def_rw_recovery_mpage); return sizeof(def_rw_recovery_mpage);
} }
...@@ -2316,11 +2343,11 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) ...@@ -2316,11 +2343,11 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
page_control = scsicmd[2] >> 6; page_control = scsicmd[2] >> 6;
switch (page_control) { switch (page_control) {
case 0: /* current */ case 0: /* current */
case 1: /* changeable */
case 2: /* defaults */
break; /* supported */ break; /* supported */
case 3: /* saved */ case 3: /* saved */
goto saving_not_supp; goto saving_not_supp;
case 1: /* changeable */
case 2: /* defaults */
default: default:
goto invalid_fld; goto invalid_fld;
} }
...@@ -2341,21 +2368,21 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) ...@@ -2341,21 +2368,21 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
switch(pg) { switch(pg) {
case RW_RECOVERY_MPAGE: case RW_RECOVERY_MPAGE:
p += ata_msense_rw_recovery(p); p += ata_msense_rw_recovery(p, page_control == 1);
break; break;
case CACHE_MPAGE: case CACHE_MPAGE:
p += ata_msense_caching(args->id, p); p += ata_msense_caching(args->id, p, page_control == 1);
break; break;
case CONTROL_MPAGE: case CONTROL_MPAGE:
p += ata_msense_ctl_mode(p); p += ata_msense_ctl_mode(p, page_control == 1);
break; break;
case ALL_MPAGES: case ALL_MPAGES:
p += ata_msense_rw_recovery(p); p += ata_msense_rw_recovery(p, page_control == 1);
p += ata_msense_caching(args->id, p); p += ata_msense_caching(args->id, p, page_control == 1);
p += ata_msense_ctl_mode(p); p += ata_msense_ctl_mode(p, page_control == 1);
break; break;
default: /* invalid page code */ default: /* invalid page code */
...@@ -3079,6 +3106,188 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) ...@@ -3079,6 +3106,188 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
return 1; return 1;
} }
/**
* ata_mselect_caching - Simulate MODE SELECT for caching info page
* @qc: Storage for translated ATA taskfile
* @buf: input buffer
* @len: number of valid bytes in the input buffer
*
* Prepare a taskfile to modify caching information for the device.
*
* LOCKING:
* None.
*/
static int ata_mselect_caching(struct ata_queued_cmd *qc,
const u8 *buf, int len)
{
struct ata_taskfile *tf = &qc->tf;
struct ata_device *dev = qc->dev;
char mpage[CACHE_MPAGE_LEN];
u8 wce;
/*
* The first two bytes of def_cache_mpage are a header, so offsets
* in mpage are off by 2 compared to buf. Same for len.
*/
if (len != CACHE_MPAGE_LEN - 2)
return -EINVAL;
wce = buf[0] & (1 << 2);
/*
* Check that read-only bits are not modified.
*/
ata_msense_caching(dev->id, mpage, false);
mpage[2] &= ~(1 << 2);
mpage[2] |= wce;
if (memcmp(mpage + 2, buf, CACHE_MPAGE_LEN - 2) != 0)
return -EINVAL;
tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
tf->protocol = ATA_PROT_NODATA;
tf->nsect = 0;
tf->command = ATA_CMD_SET_FEATURES;
tf->feature = wce ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
return 0;
}
/**
* ata_scsiop_mode_select - Simulate MODE SELECT 6, 10 commands
* @qc: Storage for translated ATA taskfile
*
* Converts a MODE SELECT command to an ATA SET FEATURES taskfile.
* Assume this is invoked for direct access devices (e.g. disks) only.
* There should be no block descriptor for other device types.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
const u8 *cdb = scmd->cmnd;
const u8 *p;
u8 pg, spg;
unsigned six_byte, pg_len, hdr_len, bd_len;
int len;
VPRINTK("ENTER\n");
six_byte = (cdb[0] == MODE_SELECT);
if (six_byte) {
if (scmd->cmd_len < 5)
goto invalid_fld;
len = cdb[4];
hdr_len = 4;
} else {
if (scmd->cmd_len < 9)
goto invalid_fld;
len = (cdb[7] << 8) + cdb[8];
hdr_len = 8;
}
/* We only support PF=1, SP=0. */
if ((cdb[1] & 0x11) != 0x10)
goto invalid_fld;
/* Test early for possible overrun. */
if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len)
goto invalid_param_len;
p = page_address(sg_page(scsi_sglist(scmd)));
/* Move past header and block descriptors. */
if (len < hdr_len)
goto invalid_param_len;
if (six_byte)
bd_len = p[3];
else
bd_len = (p[6] << 8) + p[7];
len -= hdr_len;
p += hdr_len;
if (len < bd_len)
goto invalid_param_len;
if (bd_len != 0 && bd_len != 8)
goto invalid_param;
len -= bd_len;
p += bd_len;
if (len == 0)
goto skip;
/* Parse both possible formats for the mode page headers. */
pg = p[0] & 0x3f;
if (p[0] & 0x40) {
if (len < 4)
goto invalid_param_len;
spg = p[1];
pg_len = (p[2] << 8) | p[3];
p += 4;
len -= 4;
} else {
if (len < 2)
goto invalid_param_len;
spg = 0;
pg_len = p[1];
p += 2;
len -= 2;
}
/*
* No mode subpages supported (yet) but asking for _all_
* subpages may be valid
*/
if (spg && (spg != ALL_SUB_MPAGES))
goto invalid_param;
if (pg_len > len)
goto invalid_param_len;
switch (pg) {
case CACHE_MPAGE:
if (ata_mselect_caching(qc, p, pg_len) < 0)
goto invalid_param;
break;
default: /* invalid page code */
goto invalid_param;
}
/*
* Only one page has changeable data, so we only support setting one
* page at a time.
*/
if (len > pg_len)
goto invalid_param;
return 0;
invalid_fld:
/* "Invalid field in CDB" */
ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
return 1;
invalid_param:
/* "Invalid field in parameter list" */
ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x26, 0x0);
return 1;
invalid_param_len:
/* "Parameter list length error" */
ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
return 1;
skip:
scmd->result = SAM_STAT_GOOD;
return 1;
}
/** /**
* ata_get_xlat_func - check if SCSI to ATA translation is possible * ata_get_xlat_func - check if SCSI to ATA translation is possible
* @dev: ATA device * @dev: ATA device
...@@ -3119,6 +3328,11 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) ...@@ -3119,6 +3328,11 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
case ATA_16: case ATA_16:
return ata_scsi_pass_thru; return ata_scsi_pass_thru;
case MODE_SELECT:
case MODE_SELECT_10:
return ata_scsi_mode_select_xlat;
break;
case START_STOP: case START_STOP:
return ata_scsi_start_stop_xlat; return ata_scsi_start_stop_xlat;
} }
...@@ -3311,11 +3525,6 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) ...@@ -3311,11 +3525,6 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense); ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
break; break;
case MODE_SELECT: /* unconditionally return */
case MODE_SELECT_10: /* bad-field-in-cdb */
ata_scsi_invalid_field(cmd);
break;
case READ_CAPACITY: case READ_CAPACITY:
ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
break; break;
......
...@@ -165,6 +165,8 @@ extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev, ...@@ -165,6 +165,8 @@ extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
unsigned int action); unsigned int action);
extern void ata_eh_done(struct ata_link *link, struct ata_device *dev, extern void ata_eh_done(struct ata_link *link, struct ata_device *dev,
unsigned int action); unsigned int action);
extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
u8 page, void *buf, unsigned int sectors);
extern void ata_eh_autopsy(struct ata_port *ap); extern void ata_eh_autopsy(struct ata_port *ap);
const char *ata_get_cmd_descript(u8 command); const char *ata_get_cmd_descript(u8 command);
extern void ata_eh_report(struct ata_port *ap); extern void ata_eh_report(struct ata_port *ap);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/pata_arasan_cf_data.h> #include <linux/pata_arasan_cf_data.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
...@@ -310,7 +311,7 @@ static int cf_init(struct arasan_cf_dev *acdev) ...@@ -310,7 +311,7 @@ static int cf_init(struct arasan_cf_dev *acdev)
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
ret = clk_enable(acdev->clk); ret = clk_prepare_enable(acdev->clk);
if (ret) { if (ret) {
dev_dbg(acdev->host->dev, "clock enable failed"); dev_dbg(acdev->host->dev, "clock enable failed");
return ret; return ret;
...@@ -340,7 +341,7 @@ static void cf_exit(struct arasan_cf_dev *acdev) ...@@ -340,7 +341,7 @@ static void cf_exit(struct arasan_cf_dev *acdev)
writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB, writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB,
acdev->vbase + OP_MODE); acdev->vbase + OP_MODE);
spin_unlock_irqrestore(&acdev->host->lock, flags); spin_unlock_irqrestore(&acdev->host->lock, flags);
clk_disable(acdev->clk); clk_disable_unprepare(acdev->clk);
} }
static void dma_callback(void *dev) static void dma_callback(void *dev)
...@@ -935,6 +936,14 @@ static int arasan_cf_resume(struct device *dev) ...@@ -935,6 +936,14 @@ static int arasan_cf_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(arasan_cf_pm_ops, arasan_cf_suspend, arasan_cf_resume); static SIMPLE_DEV_PM_OPS(arasan_cf_pm_ops, arasan_cf_suspend, arasan_cf_resume);
#ifdef CONFIG_OF
static const struct of_device_id arasan_cf_id_table[] = {
{ .compatible = "arasan,cf-spear1340" },
{}
};
MODULE_DEVICE_TABLE(of, arasan_cf_id_table);
#endif
static struct platform_driver arasan_cf_driver = { static struct platform_driver arasan_cf_driver = {
.probe = arasan_cf_probe, .probe = arasan_cf_probe,
.remove = __devexit_p(arasan_cf_remove), .remove = __devexit_p(arasan_cf_remove),
...@@ -942,6 +951,7 @@ static struct platform_driver arasan_cf_driver = { ...@@ -942,6 +951,7 @@ static struct platform_driver arasan_cf_driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &arasan_cf_pm_ops, .pm = &arasan_cf_pm_ops,
.of_match_table = of_match_ptr(arasan_cf_id_table),
}, },
}; };
......
...@@ -123,6 +123,7 @@ enum { ...@@ -123,6 +123,7 @@ enum {
ONLINE = (1 << 31), ONLINE = (1 << 31),
GOING_OFFLINE = (1 << 30), GOING_OFFLINE = (1 << 30),
BIST_ERR = (1 << 29), BIST_ERR = (1 << 29),
CLEAR_ERROR = (1 << 27),
FATAL_ERR_HC_MASTER_ERR = (1 << 18), FATAL_ERR_HC_MASTER_ERR = (1 << 18),
FATAL_ERR_PARITY_ERR_TX = (1 << 17), FATAL_ERR_PARITY_ERR_TX = (1 << 17),
...@@ -143,6 +144,7 @@ enum { ...@@ -143,6 +144,7 @@ enum {
FATAL_ERR_CRC_ERR_RX | FATAL_ERR_CRC_ERR_RX |
FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX, FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX,
INT_ON_DATA_LENGTH_MISMATCH = (1 << 12),
INT_ON_FATAL_ERR = (1 << 5), INT_ON_FATAL_ERR = (1 << 5),
INT_ON_PHYRDY_CHG = (1 << 4), INT_ON_PHYRDY_CHG = (1 << 4),
...@@ -1181,25 +1183,54 @@ static void sata_fsl_host_intr(struct ata_port *ap) ...@@ -1181,25 +1183,54 @@ static void sata_fsl_host_intr(struct ata_port *ap)
u32 hstatus, done_mask = 0; u32 hstatus, done_mask = 0;
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
u32 SError; u32 SError;
u32 tag;
u32 status_mask = INT_ON_ERROR;
hstatus = ioread32(hcr_base + HSTATUS); hstatus = ioread32(hcr_base + HSTATUS);
sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError); sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError);
/* Read command completed register */
done_mask = ioread32(hcr_base + CC);
/* Workaround for data length mismatch errata */
if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) {
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
qc = ata_qc_from_tag(ap, tag);
if (qc && ata_is_atapi(qc->tf.protocol)) {
u32 hcontrol;
/* Set HControl[27] to clear error registers */
hcontrol = ioread32(hcr_base + HCONTROL);
iowrite32(hcontrol | CLEAR_ERROR,
hcr_base + HCONTROL);
/* Clear HControl[27] */
iowrite32(hcontrol & ~CLEAR_ERROR,
hcr_base + HCONTROL);
/* Clear SError[E] bit */
sata_fsl_scr_write(&ap->link, SCR_ERROR,
SError);
/* Ignore fatal error and device error */
status_mask &= ~(INT_ON_SINGL_DEVICE_ERR
| INT_ON_FATAL_ERR);
break;
}
}
}
if (unlikely(SError & 0xFFFF0000)) { if (unlikely(SError & 0xFFFF0000)) {
DPRINTK("serror @host_intr : 0x%x\n", SError); DPRINTK("serror @host_intr : 0x%x\n", SError);
sata_fsl_error_intr(ap); sata_fsl_error_intr(ap);
} }
if (unlikely(hstatus & INT_ON_ERROR)) { if (unlikely(hstatus & status_mask)) {
DPRINTK("error interrupt!!\n"); DPRINTK("error interrupt!!\n");
sata_fsl_error_intr(ap); sata_fsl_error_intr(ap);
return; return;
} }
/* Read command completed register */
done_mask = ioread32(hcr_base + CC);
VPRINTK("Status of all queues :\n"); VPRINTK("Status of all queues :\n");
VPRINTK("done_mask/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n", VPRINTK("done_mask/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n",
done_mask, done_mask,
......
This diff is collapsed.
...@@ -79,8 +79,8 @@ ...@@ -79,8 +79,8 @@
* module options * module options
*/ */
static int msi;
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static int msi;
module_param(msi, int, S_IRUGO); module_param(msi, int, S_IRUGO);
MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
#endif #endif
...@@ -652,12 +652,13 @@ static u8 mv_sff_check_status(struct ata_port *ap); ...@@ -652,12 +652,13 @@ static u8 mv_sff_check_status(struct ata_port *ap);
* because we have to allow room for worst case splitting of * because we have to allow room for worst case splitting of
* PRDs for 64K boundaries in mv_fill_sg(). * PRDs for 64K boundaries in mv_fill_sg().
*/ */
#ifdef CONFIG_PCI
static struct scsi_host_template mv5_sht = { static struct scsi_host_template mv5_sht = {
ATA_BASE_SHT(DRV_NAME), ATA_BASE_SHT(DRV_NAME),
.sg_tablesize = MV_MAX_SG_CT / 2, .sg_tablesize = MV_MAX_SG_CT / 2,
.dma_boundary = MV_DMA_BOUNDARY, .dma_boundary = MV_DMA_BOUNDARY,
}; };
#endif
static struct scsi_host_template mv6_sht = { static struct scsi_host_template mv6_sht = {
ATA_NCQ_SHT(DRV_NAME), ATA_NCQ_SHT(DRV_NAME),
.can_queue = MV_MAX_Q_DEPTH - 1, .can_queue = MV_MAX_Q_DEPTH - 1,
...@@ -1252,7 +1253,7 @@ static void mv_dump_mem(void __iomem *start, unsigned bytes) ...@@ -1252,7 +1253,7 @@ static void mv_dump_mem(void __iomem *start, unsigned bytes)
} }
} }
#endif #endif
#if defined(ATA_DEBUG) || defined(CONFIG_PCI)
static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes) static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
{ {
#ifdef ATA_DEBUG #ifdef ATA_DEBUG
...@@ -1269,6 +1270,7 @@ static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes) ...@@ -1269,6 +1270,7 @@ static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
} }
#endif #endif
} }
#endif
static void mv_dump_all_regs(void __iomem *mmio_base, int port, static void mv_dump_all_regs(void __iomem *mmio_base, int port,
struct pci_dev *pdev) struct pci_dev *pdev)
{ {
......
...@@ -77,6 +77,9 @@ enum { ...@@ -77,6 +77,9 @@ enum {
ATA_ID_EIDE_PIO_IORDY = 68, ATA_ID_EIDE_PIO_IORDY = 68,
ATA_ID_ADDITIONAL_SUPP = 69, ATA_ID_ADDITIONAL_SUPP = 69,
ATA_ID_QUEUE_DEPTH = 75, ATA_ID_QUEUE_DEPTH = 75,
ATA_ID_SATA_CAPABILITY = 76,
ATA_ID_SATA_CAPABILITY_2 = 77,
ATA_ID_FEATURE_SUPP = 78,
ATA_ID_MAJOR_VER = 80, ATA_ID_MAJOR_VER = 80,
ATA_ID_COMMAND_SET_1 = 82, ATA_ID_COMMAND_SET_1 = 82,
ATA_ID_COMMAND_SET_2 = 83, ATA_ID_COMMAND_SET_2 = 83,
...@@ -292,6 +295,13 @@ enum { ...@@ -292,6 +295,13 @@ enum {
/* READ_LOG_EXT pages */ /* READ_LOG_EXT pages */
ATA_LOG_SATA_NCQ = 0x10, ATA_LOG_SATA_NCQ = 0x10,
ATA_LOG_SATA_ID_DEV_DATA = 0x30,
ATA_LOG_SATA_SETTINGS = 0x08,
ATA_LOG_DEVSLP_MDAT = 0x30,
ATA_LOG_DEVSLP_MDAT_MASK = 0x1F,
ATA_LOG_DEVSLP_DETO = 0x31,
ATA_LOG_DEVSLP_VALID = 0x37,
ATA_LOG_DEVSLP_VALID_MASK = 0x80,
/* READ/WRITE LONG (obsolete) */ /* READ/WRITE LONG (obsolete) */
ATA_CMD_READ_LONG = 0x22, ATA_CMD_READ_LONG = 0x22,
...@@ -345,6 +355,7 @@ enum { ...@@ -345,6 +355,7 @@ enum {
SATA_FPDMA_IN_ORDER = 0x04, /* FPDMA in-order data delivery */ SATA_FPDMA_IN_ORDER = 0x04, /* FPDMA in-order data delivery */
SATA_AN = 0x05, /* Asynchronous Notification */ SATA_AN = 0x05, /* Asynchronous Notification */
SATA_SSP = 0x06, /* Software Settings Preservation */ SATA_SSP = 0x06, /* Software Settings Preservation */
SATA_DEVSLP = 0x09, /* Device Sleep */
/* feature values for SET_MAX */ /* feature values for SET_MAX */
ATA_SET_MAX_ADDR = 0x00, ATA_SET_MAX_ADDR = 0x00,
...@@ -558,15 +569,17 @@ static inline int ata_is_data(u8 prot) ...@@ -558,15 +569,17 @@ static inline int ata_is_data(u8 prot)
#define ata_id_is_ata(id) (((id)[ATA_ID_CONFIG] & (1 << 15)) == 0) #define ata_id_is_ata(id) (((id)[ATA_ID_CONFIG] & (1 << 15)) == 0)
#define ata_id_has_lba(id) ((id)[ATA_ID_CAPABILITY] & (1 << 9)) #define ata_id_has_lba(id) ((id)[ATA_ID_CAPABILITY] & (1 << 9))
#define ata_id_has_dma(id) ((id)[ATA_ID_CAPABILITY] & (1 << 8)) #define ata_id_has_dma(id) ((id)[ATA_ID_CAPABILITY] & (1 << 8))
#define ata_id_has_ncq(id) ((id)[76] & (1 << 8)) #define ata_id_has_ncq(id) ((id)[ATA_ID_SATA_CAPABILITY] & (1 << 8))
#define ata_id_queue_depth(id) (((id)[ATA_ID_QUEUE_DEPTH] & 0x1f) + 1) #define ata_id_queue_depth(id) (((id)[ATA_ID_QUEUE_DEPTH] & 0x1f) + 1)
#define ata_id_removeable(id) ((id)[ATA_ID_CONFIG] & (1 << 7)) #define ata_id_removeable(id) ((id)[ATA_ID_CONFIG] & (1 << 7))
#define ata_id_has_atapi_AN(id) \ #define ata_id_has_atapi_AN(id) \
( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \ ((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \
((id)[78] & (1 << 5)) ) ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \
((id)[ATA_ID_FEATURE_SUPP] & (1 << 5)))
#define ata_id_has_fpdma_aa(id) \ #define ata_id_has_fpdma_aa(id) \
( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \ ((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \
((id)[78] & (1 << 2)) ) ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \
((id)[ATA_ID_FEATURE_SUPP] & (1 << 2)))
#define ata_id_iordy_disable(id) ((id)[ATA_ID_CAPABILITY] & (1 << 10)) #define ata_id_iordy_disable(id) ((id)[ATA_ID_CAPABILITY] & (1 << 10))
#define ata_id_has_iordy(id) ((id)[ATA_ID_CAPABILITY] & (1 << 11)) #define ata_id_has_iordy(id) ((id)[ATA_ID_CAPABILITY] & (1 << 11))
#define ata_id_u32(id,n) \ #define ata_id_u32(id,n) \
...@@ -578,11 +591,12 @@ static inline int ata_is_data(u8 prot) ...@@ -578,11 +591,12 @@ static inline int ata_is_data(u8 prot)
((u64) (id)[(n) + 0]) ) ((u64) (id)[(n) + 0]) )
#define ata_id_cdb_intr(id) (((id)[ATA_ID_CONFIG] & 0x60) == 0x20) #define ata_id_cdb_intr(id) (((id)[ATA_ID_CONFIG] & 0x60) == 0x20)
#define ata_id_has_da(id) ((id)[77] & (1 << 4)) #define ata_id_has_da(id) ((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4))
#define ata_id_has_devslp(id) ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8))
static inline bool ata_id_has_hipm(const u16 *id) static inline bool ata_id_has_hipm(const u16 *id)
{ {
u16 val = id[76]; u16 val = id[ATA_ID_SATA_CAPABILITY];
if (val == 0 || val == 0xffff) if (val == 0 || val == 0xffff)
return false; return false;
...@@ -592,7 +606,7 @@ static inline bool ata_id_has_hipm(const u16 *id) ...@@ -592,7 +606,7 @@ static inline bool ata_id_has_hipm(const u16 *id)
static inline bool ata_id_has_dipm(const u16 *id) static inline bool ata_id_has_dipm(const u16 *id)
{ {
u16 val = id[78]; u16 val = id[ATA_ID_FEATURE_SUPP];
if (val == 0 || val == 0xffff) if (val == 0 || val == 0xffff)
return false; return false;
......
...@@ -162,6 +162,7 @@ enum { ...@@ -162,6 +162,7 @@ enum {
ATA_DFLAG_DETACHED = (1 << 25), ATA_DFLAG_DETACHED = (1 << 25),
ATA_DFLAG_DA = (1 << 26), /* device supports Device Attention */ ATA_DFLAG_DA = (1 << 26), /* device supports Device Attention */
ATA_DFLAG_DEVSLP = (1 << 27), /* device supports Device Sleep */
ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_UNKNOWN = 0, /* unknown device */
ATA_DEV_ATA = 1, /* ATA device */ ATA_DEV_ATA = 1, /* ATA device */
...@@ -649,6 +650,9 @@ struct ata_device { ...@@ -649,6 +650,9 @@ struct ata_device {
u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
}; };
/* Identify Device Data Log (30h), SATA Settings (page 08h) */
u8 sata_settings[ATA_SECT_SIZE];
/* error history */ /* error history */
int spdn_cnt; int spdn_cnt;
/* ering is CLEAR_END, read comment above CLEAR_END */ /* ering is CLEAR_END, read comment above CLEAR_END */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment