mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 05:24:12 +08:00
ata changes for 6.8-rc6
- 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) -----BEGIN PGP SIGNATURE----- iIgEABYKADAWIQRN+ES/c4tHlMch3DzJZDGjmcZNcgUCZdjJthIcY2Fzc2VsQGtl cm5lbC5vcmcACgkQyWQxo5nGTXKjKQEAw4J68mFTAjJuM0JxerDG1MMNBRWTtfS3 sWtjpbkC6H8A/0PBFhgedSTy9w2eewspDlUR44SMTaKykNyPwBEF6Q0C =gpJt -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
b6d69282db
@ -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,47 +2001,6 @@ bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf,
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_standby - Set a device power mode to standby
|
||||
* @dev: target device
|
||||
*
|
||||
* Issue a STANDBY IMMEDIATE command to set a device power mode to standby.
|
||||
* For an HDD device, this spins down the disks.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep).
|
||||
*/
|
||||
void ata_dev_power_set_standby(struct ata_device *dev)
|
||||
{
|
||||
unsigned long ap_flags = dev->link->ap->flags;
|
||||
struct ata_taskfile tf;
|
||||
unsigned int err_mask;
|
||||
|
||||
/*
|
||||
* 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
|
||||
* if we are being called on shutdown.
|
||||
*/
|
||||
if ((ap_flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
|
||||
system_state == SYSTEM_POWER_OFF)
|
||||
return;
|
||||
|
||||
if ((ap_flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
|
||||
system_entering_hibernation())
|
||||
return;
|
||||
|
||||
/* Issue STANDBY IMMEDIATE command only if supported by the device */
|
||||
if (!ata_dev_power_init_tf(dev, &tf, false))
|
||||
return;
|
||||
|
||||
ata_dev_notice(dev, "Entering standby power mode\n");
|
||||
|
||||
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
|
||||
if (err_mask)
|
||||
ata_dev_err(dev, "STANDBY IMMEDIATE failed (err_mask=0x%x)\n",
|
||||
err_mask);
|
||||
}
|
||||
|
||||
static bool ata_dev_power_is_active(struct ata_device *dev)
|
||||
{
|
||||
struct ata_taskfile tf;
|
||||
@ -2069,6 +2028,52 @@ static bool ata_dev_power_is_active(struct ata_device *dev)
|
||||
return tf.nsect == 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_standby - Set a device power mode to standby
|
||||
* @dev: target device
|
||||
*
|
||||
* Issue a STANDBY IMMEDIATE command to set a device power mode to standby.
|
||||
* For an HDD device, this spins down the disks.
|
||||
*
|
||||
* LOCKING:
|
||||
* Kernel thread context (may sleep).
|
||||
*/
|
||||
void ata_dev_power_set_standby(struct ata_device *dev)
|
||||
{
|
||||
unsigned long ap_flags = dev->link->ap->flags;
|
||||
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
|
||||
* if we are being called on shutdown.
|
||||
*/
|
||||
if ((ap_flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
|
||||
system_state == SYSTEM_POWER_OFF)
|
||||
return;
|
||||
|
||||
if ((ap_flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
|
||||
system_entering_hibernation())
|
||||
return;
|
||||
|
||||
/* Issue STANDBY IMMEDIATE command only if supported by the device */
|
||||
if (!ata_dev_power_init_tf(dev, &tf, false))
|
||||
return;
|
||||
|
||||
ata_dev_notice(dev, "Entering standby power mode\n");
|
||||
|
||||
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
|
||||
if (err_mask)
|
||||
ata_dev_err(dev, "STANDBY IMMEDIATE failed (err_mask=0x%x)\n",
|
||||
err_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_active - Set a device power mode to active
|
||||
* @dev: target device
|
||||
|
Loading…
Reference in New Issue
Block a user