Commit b6d69282 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ata-6.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux

Pull ata fixes from Niklas Cassel:

 - Do not try to set a sleeping device to standby. Sleep is a deeper
   sleep state than standby, and needs a reset to wake up the drive. A
   system resume will reset the port. Sending a command other than reset
   to a sleeping device is not wise, as the command will timeout (Damien
   Le Moal)

 - Do not try to put a device to standby twice during system shutdown.
   ata_dev_power_set_standby() is currently called twice during
   shutdown, once after the scsi device is removed, and another when
   ata_pci_shutdown_one() executes. Modify ata_dev_power_set_standby()
   to do nothing if the device is already in standby (Damien Le Moal)

 - Add a quirk for ASM1064 to fixup the number of implemented ports. We
   probe all ports that the hardware reports to be implemented. Probing
   ports that are not implemented causes significantly increased boot
   time (Andrey Jr. Melnikov)

 - Fix error handling for the ahci_ceva driver. Ensure that the
   ahci_ceva driver does a proper cleanup of its resources in the error
   path (Radhey Shyam Pandey)

* tag 'ata-6.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: libata-core: Do not call ata_dev_power_set_standby() twice
  ata: ahci_ceva: fix error handling for Xilinx GT PHY support
  ahci: asm1064: correct count of reported ports
  ata: libata-core: Do not try to set sleeping devices to standby
parents 9cd42be8 9cec467d
......@@ -671,9 +671,17 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
static void ahci_pci_save_initial_config(struct pci_dev *pdev,
struct ahci_host_priv *hpriv)
{
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1166) {
dev_info(&pdev->dev, "ASM1166 has only six ports\n");
hpriv->saved_port_map = 0x3f;
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA) {
switch (pdev->device) {
case 0x1166:
dev_info(&pdev->dev, "ASM1166 has only six ports\n");
hpriv->saved_port_map = 0x3f;
break;
case 0x1064:
dev_info(&pdev->dev, "ASM1064 has only four ports\n");
hpriv->saved_port_map = 0xf;
break;
}
}
if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
......
......@@ -88,7 +88,6 @@ struct ceva_ahci_priv {
u32 axicc;
bool is_cci_enabled;
int flags;
struct reset_control *rst;
};
static unsigned int ceva_ahci_read_id(struct ata_device *dev,
......@@ -189,6 +188,60 @@ static const struct scsi_host_template ahci_platform_sht = {
AHCI_SHT(DRV_NAME),
};
static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
{
int rc, i;
rc = ahci_platform_enable_regulators(hpriv);
if (rc)
return rc;
rc = ahci_platform_enable_clks(hpriv);
if (rc)
goto disable_regulator;
/* Assert the controller reset */
rc = ahci_platform_assert_rsts(hpriv);
if (rc)
goto disable_clks;
for (i = 0; i < hpriv->nports; i++) {
rc = phy_init(hpriv->phys[i]);
if (rc)
goto disable_rsts;
}
/* De-assert the controller reset */
ahci_platform_deassert_rsts(hpriv);
for (i = 0; i < hpriv->nports; i++) {
rc = phy_power_on(hpriv->phys[i]);
if (rc) {
phy_exit(hpriv->phys[i]);
goto disable_phys;
}
}
return 0;
disable_rsts:
ahci_platform_deassert_rsts(hpriv);
disable_phys:
while (--i >= 0) {
phy_power_off(hpriv->phys[i]);
phy_exit(hpriv->phys[i]);
}
disable_clks:
ahci_platform_disable_clks(hpriv);
disable_regulator:
ahci_platform_disable_regulators(hpriv);
return rc;
}
static int ceva_ahci_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
......@@ -203,47 +256,19 @@ static int ceva_ahci_probe(struct platform_device *pdev)
return -ENOMEM;
cevapriv->ahci_pdev = pdev;
cevapriv->rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
NULL);
if (IS_ERR(cevapriv->rst))
dev_err_probe(&pdev->dev, PTR_ERR(cevapriv->rst),
"failed to get reset\n");
hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
if (!cevapriv->rst) {
rc = ahci_platform_enable_resources(hpriv);
if (rc)
return rc;
} else {
int i;
hpriv->rsts = devm_reset_control_get_optional_exclusive(&pdev->dev,
NULL);
if (IS_ERR(hpriv->rsts))
return dev_err_probe(&pdev->dev, PTR_ERR(hpriv->rsts),
"failed to get reset\n");
rc = ahci_platform_enable_clks(hpriv);
if (rc)
return rc;
/* Assert the controller reset */
reset_control_assert(cevapriv->rst);
for (i = 0; i < hpriv->nports; i++) {
rc = phy_init(hpriv->phys[i]);
if (rc)
return rc;
}
/* De-assert the controller reset */
reset_control_deassert(cevapriv->rst);
for (i = 0; i < hpriv->nports; i++) {
rc = phy_power_on(hpriv->phys[i]);
if (rc) {
phy_exit(hpriv->phys[i]);
return rc;
}
}
}
rc = ceva_ahci_platform_enable_resources(hpriv);
if (rc)
return rc;
if (of_property_read_bool(np, "ceva,broken-gen2"))
cevapriv->flags = CEVA_FLAG_BROKEN_GEN2;
......@@ -252,52 +277,60 @@ static int ceva_ahci_probe(struct platform_device *pdev)
if (of_property_read_u8_array(np, "ceva,p0-cominit-params",
(u8 *)&cevapriv->pp2c[0], 4) < 0) {
dev_warn(dev, "ceva,p0-cominit-params property not defined\n");
return -EINVAL;
rc = -EINVAL;
goto disable_resources;
}
if (of_property_read_u8_array(np, "ceva,p1-cominit-params",
(u8 *)&cevapriv->pp2c[1], 4) < 0) {
dev_warn(dev, "ceva,p1-cominit-params property not defined\n");
return -EINVAL;
rc = -EINVAL;
goto disable_resources;
}
/* Read OOB timing value for COMWAKE from device-tree*/
if (of_property_read_u8_array(np, "ceva,p0-comwake-params",
(u8 *)&cevapriv->pp3c[0], 4) < 0) {
dev_warn(dev, "ceva,p0-comwake-params property not defined\n");
return -EINVAL;
rc = -EINVAL;
goto disable_resources;
}
if (of_property_read_u8_array(np, "ceva,p1-comwake-params",
(u8 *)&cevapriv->pp3c[1], 4) < 0) {
dev_warn(dev, "ceva,p1-comwake-params property not defined\n");
return -EINVAL;
rc = -EINVAL;
goto disable_resources;
}
/* Read phy BURST timing value from device-tree */
if (of_property_read_u8_array(np, "ceva,p0-burst-params",
(u8 *)&cevapriv->pp4c[0], 4) < 0) {
dev_warn(dev, "ceva,p0-burst-params property not defined\n");
return -EINVAL;
rc = -EINVAL;
goto disable_resources;
}
if (of_property_read_u8_array(np, "ceva,p1-burst-params",
(u8 *)&cevapriv->pp4c[1], 4) < 0) {
dev_warn(dev, "ceva,p1-burst-params property not defined\n");
return -EINVAL;
rc = -EINVAL;
goto disable_resources;
}
/* Read phy RETRY interval timing value from device-tree */
if (of_property_read_u16_array(np, "ceva,p0-retry-params",
(u16 *)&cevapriv->pp5c[0], 2) < 0) {
dev_warn(dev, "ceva,p0-retry-params property not defined\n");
return -EINVAL;
rc = -EINVAL;
goto disable_resources;
}
if (of_property_read_u16_array(np, "ceva,p1-retry-params",
(u16 *)&cevapriv->pp5c[1], 2) < 0) {
dev_warn(dev, "ceva,p1-retry-params property not defined\n");
return -EINVAL;
rc = -EINVAL;
goto disable_resources;
}
/*
......@@ -335,7 +368,7 @@ static int __maybe_unused ceva_ahci_resume(struct device *dev)
struct ahci_host_priv *hpriv = host->private_data;
int rc;
rc = ahci_platform_enable_resources(hpriv);
rc = ceva_ahci_platform_enable_resources(hpriv);
if (rc)
return rc;
......
......@@ -2001,6 +2001,33 @@ bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf,
return true;
}
static bool ata_dev_power_is_active(struct ata_device *dev)
{
struct ata_taskfile tf;
unsigned int err_mask;
ata_tf_init(dev, &tf);
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
tf.protocol = ATA_PROT_NODATA;
tf.command = ATA_CMD_CHK_POWER;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
if (err_mask) {
ata_dev_err(dev, "Check power mode failed (err_mask=0x%x)\n",
err_mask);
/*
* Assume we are in standby mode so that we always force a
* spinup in ata_dev_power_set_active().
*/
return false;
}
ata_dev_dbg(dev, "Power mode: 0x%02x\n", tf.nsect);
/* Active or idle */
return tf.nsect == 0xff;
}
/**
* ata_dev_power_set_standby - Set a device power mode to standby
* @dev: target device
......@@ -2017,6 +2044,11 @@ void ata_dev_power_set_standby(struct ata_device *dev)
struct ata_taskfile tf;
unsigned int err_mask;
/* If the device is already sleeping or in standby, do nothing. */
if ((dev->flags & ATA_DFLAG_SLEEPING) ||
!ata_dev_power_is_active(dev))
return;
/*
* Some odd clown BIOSes issue spindown on power off (ACPI S4 or S5)
* causing some drives to spin up and down again. For these, do nothing
......@@ -2042,33 +2074,6 @@ void ata_dev_power_set_standby(struct ata_device *dev)
err_mask);
}
static bool ata_dev_power_is_active(struct ata_device *dev)
{
struct ata_taskfile tf;
unsigned int err_mask;
ata_tf_init(dev, &tf);
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
tf.protocol = ATA_PROT_NODATA;
tf.command = ATA_CMD_CHK_POWER;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
if (err_mask) {
ata_dev_err(dev, "Check power mode failed (err_mask=0x%x)\n",
err_mask);
/*
* Assume we are in standby mode so that we always force a
* spinup in ata_dev_power_set_active().
*/
return false;
}
ata_dev_dbg(dev, "Power mode: 0x%02x\n", tf.nsect);
/* Active or idle */
return tf.nsect == 0xff;
}
/**
* ata_dev_power_set_active - Set a device power mode to active
* @dev: target device
......
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