ATA changes for 6.7-rc1
- Modify the AHCI driver to print the link power management policy used on scan, to help with debugging issues (Niklas). - Add support for the ASM2116 series adapters to the AHCI driver (Szuying). - Prepare libata for the coming gcc and Clang __counted_by attribute (Kees). - Following the recent estensive fixing of libata suspend/resume handling, several patches further cleanup and improve disk power state management (from me). - Reduce the verbosity of some error messages for non-fatal temporary errors, e.g. slow response to device reset when scanning a port, and warning messages that are in fact normal, e.g. disabling a device on suspend or when removing it (from me). - Cleanup DMA helper functions (from me). - Fix sata_mv drive handling of potential errors durring probe (Ma). - Cleanup the xgene and imx drivers using the functions of_device_get_match_data() and device_get_match_data() (Rob). - Improve the tegra driver device tree (Rob). -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQSRPv8tYSvhwAzJdzjdoc3SxdoYdgUCZT9PtwAKCRDdoc3SxdoY diCGAQCbSOB3PCpsm1cCMevZeEbt+zUSx+sj6twR12RohtQK6wEA1rEytQllZyqa Pk/jIH2UYZaf+lVuV3Vbey4rwDYXTQs= =V53T -----END PGP SIGNATURE----- Merge tag 'ata-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata Pull ATA updates from Damien Le Moal: - Modify the AHCI driver to print the link power management policy used on scan, to help with debugging issues (Niklas) - Add support for the ASM2116 series adapters to the AHCI driver (Szuying) - Prepare libata for the coming gcc and Clang __counted_by attribute (Kees) - Following the recent estensive fixing of libata suspend/resume handling, several patches further cleanup and improve disk power state management (me) - Reduce the verbosity of some error messages for non-fatal temporary errors, e.g. slow response to device reset when scanning a port, and warning messages that are in fact normal, e.g. disabling a device on suspend or when removing it (me) - Cleanup DMA helper functions (me) - Fix sata_mv drive handling of potential errors durring probe (Ma) - Cleanup the xgene and imx drivers using the functions of_device_get_match_data() and device_get_match_data() (Rob) - Improve the tegra driver device tree (Rob) * tag 'ata-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata: (22 commits) dt-bindings: ata: tegra: Disallow undefined properties ata: libata-core: Improve ata_dev_power_set_active() ata: libata-eh: Spinup disk on resume after revalidation ata: imx: Use device_get_match_data() ata: xgene: Use of_device_get_match_data() ata: sata_mv: aspeed: fix value check in mv_platform_probe() ata: ahci: Add Intel Alder Lake-P AHCI controller to low power chipsets list ata: libata: Cleanup inline DMA helper functions ata: libata-eh: Reduce "disable device" message verbosity ata: libata-eh: Improve reset error messages ata: libata-sata: Improve ata_sas_slave_configure() ata: libata-core: Do not resume runtime suspended ports ata: libata-core: Do not poweroff runtime suspended ports ata: libata-core: Remove ata_port_resume_async() ata: libata-core: Remove ata_port_suspend_async() ata: libata-core: Detach a port devices on shutdown ata: libata-core: Synchronize ata_port_detach() with hotplug ata: libata-scsi: Cleanup ata_scsi_start_stop_xlat() scsi: Remove scsi device no_start_on_resume flag ata: libata: Annotate struct ata_cpr_log with __counted_by ...
This commit is contained in:
commit
39714efc23
@ -151,7 +151,7 @@ allOf:
|
||||
- interconnects
|
||||
- power-domains
|
||||
|
||||
additionalProperties: true
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -423,6 +423,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x02d7), board_ahci_low_power }, /* Comet Lake PCH RAID */
|
||||
/* Elkhart Lake IDs 0x4b60 & 0x4b62 https://sata-io.org/product/8803 not tested yet */
|
||||
{ PCI_VDEVICE(INTEL, 0x4b63), board_ahci_low_power }, /* Elkhart Lake AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x7ae2), board_ahci_low_power }, /* Alder Lake-P AHCI */
|
||||
|
||||
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
|
||||
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
@ -604,6 +605,11 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci }, /* ASM1062+JMB575 */
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci }, /* ASM1062A */
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci }, /* ASM1064 */
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci }, /* ASM1164 */
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x1165), board_ahci }, /* ASM1165 */
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x1166), board_ahci }, /* ASM1166 */
|
||||
|
||||
/*
|
||||
* Samsung SSDs found on some macbooks. NCQ times out if MSI is
|
||||
|
@ -9,10 +9,11 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/ahci_platform.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
|
||||
#include <linux/libata.h>
|
||||
@ -1050,16 +1051,11 @@ static int imx8_sata_probe(struct device *dev, struct imx_ahci_priv *imxpriv)
|
||||
static int imx_ahci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *of_id;
|
||||
struct ahci_host_priv *hpriv;
|
||||
struct imx_ahci_priv *imxpriv;
|
||||
unsigned int reg_val;
|
||||
int ret;
|
||||
|
||||
of_id = of_match_device(imx_ahci_of_match, dev);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
|
||||
if (!imxpriv)
|
||||
return -ENOMEM;
|
||||
@ -1067,7 +1063,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
|
||||
imxpriv->ahci_pdev = pdev;
|
||||
imxpriv->no_device = false;
|
||||
imxpriv->first_time = true;
|
||||
imxpriv->type = (unsigned long)of_id->data;
|
||||
imxpriv->type = (enum ahci_imx_type)device_get_match_data(dev);
|
||||
|
||||
imxpriv->sata_clk = devm_clk_get(dev, "sata");
|
||||
if (IS_ERR(imxpriv->sata_clk)) {
|
||||
|
@ -13,9 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ahci_platform.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include "ahci.h"
|
||||
|
||||
@ -735,7 +733,6 @@ static int xgene_ahci_probe(struct platform_device *pdev)
|
||||
struct ahci_host_priv *hpriv;
|
||||
struct xgene_ahci_context *ctx;
|
||||
struct resource *res;
|
||||
const struct of_device_id *of_devid;
|
||||
enum xgene_ahci_version version = XGENE_AHCI_V1;
|
||||
const struct ata_port_info *ppi[] = { &xgene_ahci_v1_port_info,
|
||||
&xgene_ahci_v2_port_info };
|
||||
@ -778,10 +775,8 @@ static int xgene_ahci_probe(struct platform_device *pdev)
|
||||
ctx->csr_mux = csr;
|
||||
}
|
||||
|
||||
of_devid = of_match_device(xgene_ahci_of_match, dev);
|
||||
if (of_devid) {
|
||||
if (of_devid->data)
|
||||
version = (unsigned long) of_devid->data;
|
||||
if (dev->of_node) {
|
||||
version = (enum xgene_ahci_version)of_device_get_match_data(dev);
|
||||
}
|
||||
#ifdef CONFIG_ACPI
|
||||
else {
|
||||
|
@ -2730,7 +2730,7 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host,
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
ata_port_desc(host->ports[i], "irq %d", irq);
|
||||
ata_port_desc_misc(host->ports[i], irq);
|
||||
}
|
||||
|
||||
return ata_host_register(host, sht);
|
||||
|
@ -1972,6 +1972,35 @@ retry:
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool ata_dev_power_init_tf(struct ata_device *dev, struct ata_taskfile *tf,
|
||||
bool set_active)
|
||||
{
|
||||
/* Only applies to ATA and ZAC devices */
|
||||
if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
|
||||
return false;
|
||||
|
||||
ata_tf_init(dev, tf);
|
||||
tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
|
||||
tf->protocol = ATA_PROT_NODATA;
|
||||
|
||||
if (set_active) {
|
||||
/* VERIFY for 1 sector at lba=0 */
|
||||
tf->command = ATA_CMD_VERIFY;
|
||||
tf->nsect = 1;
|
||||
if (dev->flags & ATA_DFLAG_LBA) {
|
||||
tf->flags |= ATA_TFLAG_LBA;
|
||||
tf->device |= ATA_LBA;
|
||||
} else {
|
||||
/* CHS */
|
||||
tf->lbal = 0x1; /* sect */
|
||||
}
|
||||
} else {
|
||||
tf->command = ATA_CMD_STANDBYNOW1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_dev_power_set_standby - Set a device power mode to standby
|
||||
* @dev: target device
|
||||
@ -1988,10 +2017,6 @@ void ata_dev_power_set_standby(struct ata_device *dev)
|
||||
struct ata_taskfile tf;
|
||||
unsigned int err_mask;
|
||||
|
||||
/* Issue STANDBY IMMEDIATE command only if supported by the device */
|
||||
if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
|
||||
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
|
||||
@ -2005,10 +2030,9 @@ void ata_dev_power_set_standby(struct ata_device *dev)
|
||||
system_entering_hibernation())
|
||||
return;
|
||||
|
||||
ata_tf_init(dev, &tf);
|
||||
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
|
||||
tf.protocol = ATA_PROT_NODATA;
|
||||
tf.command = ATA_CMD_STANDBYNOW1;
|
||||
/* 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");
|
||||
|
||||
@ -2018,6 +2042,33 @@ 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
|
||||
@ -2038,21 +2089,15 @@ void ata_dev_power_set_active(struct ata_device *dev)
|
||||
* Issue READ VERIFY SECTORS command for 1 sector at lba=0 only
|
||||
* if supported by the device.
|
||||
*/
|
||||
if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC)
|
||||
if (!ata_dev_power_init_tf(dev, &tf, true))
|
||||
return;
|
||||
|
||||
ata_tf_init(dev, &tf);
|
||||
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
|
||||
tf.protocol = ATA_PROT_NODATA;
|
||||
tf.command = ATA_CMD_VERIFY;
|
||||
tf.nsect = 1;
|
||||
if (dev->flags & ATA_DFLAG_LBA) {
|
||||
tf.flags |= ATA_TFLAG_LBA;
|
||||
tf.device |= ATA_LBA;
|
||||
} else {
|
||||
/* CHS */
|
||||
tf.lbal = 0x1; /* sect */
|
||||
}
|
||||
/*
|
||||
* Check the device power state & condition and force a spinup with
|
||||
* VERIFY command only if the drive is not already ACTIVE or IDLE.
|
||||
*/
|
||||
if (ata_dev_power_is_active(dev))
|
||||
return;
|
||||
|
||||
ata_dev_notice(dev, "Entering active power mode\n");
|
||||
|
||||
@ -5155,41 +5200,29 @@ static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
|
||||
ata_port_wait_eh(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* On some hardware, device fails to respond after spun down for suspend. As
|
||||
* the device won't be used before being resumed, we don't need to touch the
|
||||
* device. Ask EH to skip the usual stuff and proceed directly to suspend.
|
||||
static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg,
|
||||
bool async)
|
||||
{
|
||||
/*
|
||||
* We are about to suspend the port, so we do not care about
|
||||
* scsi_rescan_device() calls scheduled by previous resume operations.
|
||||
* The next resume will schedule the rescan again. So cancel any rescan
|
||||
* that is not done yet.
|
||||
*/
|
||||
cancel_delayed_work_sync(&ap->scsi_rescan_task);
|
||||
|
||||
/*
|
||||
* On some hardware, device fails to respond after spun down for
|
||||
* suspend. As the device will not be used until being resumed, we
|
||||
* do not need to touch the device. Ask EH to skip the usual stuff
|
||||
* and proceed directly to suspend.
|
||||
*
|
||||
* http://thread.gmane.org/gmane.linux.ide/46764
|
||||
*/
|
||||
static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET
|
||||
| ATA_EHI_NO_AUTOPSY
|
||||
| ATA_EHI_NO_RECOVERY;
|
||||
|
||||
static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg)
|
||||
{
|
||||
/*
|
||||
* We are about to suspend the port, so we do not care about
|
||||
* scsi_rescan_device() calls scheduled by previous resume operations.
|
||||
* The next resume will schedule the rescan again. So cancel any rescan
|
||||
* that is not done yet.
|
||||
*/
|
||||
cancel_delayed_work_sync(&ap->scsi_rescan_task);
|
||||
|
||||
ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false);
|
||||
}
|
||||
|
||||
static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg)
|
||||
{
|
||||
/*
|
||||
* We are about to suspend the port, so we do not care about
|
||||
* scsi_rescan_device() calls scheduled by previous resume operations.
|
||||
* The next resume will schedule the rescan again. So cancel any rescan
|
||||
* that is not done yet.
|
||||
*/
|
||||
cancel_delayed_work_sync(&ap->scsi_rescan_task);
|
||||
|
||||
ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true);
|
||||
ata_port_request_pm(ap, mesg, 0,
|
||||
ATA_EHI_QUIET | ATA_EHI_NO_AUTOPSY |
|
||||
ATA_EHI_NO_RECOVERY,
|
||||
async);
|
||||
}
|
||||
|
||||
static int ata_port_pm_suspend(struct device *dev)
|
||||
@ -5199,7 +5232,7 @@ static int ata_port_pm_suspend(struct device *dev)
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
ata_port_suspend(ap, PMSG_SUSPEND);
|
||||
ata_port_suspend(ap, PMSG_SUSPEND, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5210,35 +5243,29 @@ static int ata_port_pm_freeze(struct device *dev)
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
ata_port_suspend(ap, PMSG_FREEZE);
|
||||
ata_port_suspend(ap, PMSG_FREEZE, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ata_port_pm_poweroff(struct device *dev)
|
||||
{
|
||||
ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE);
|
||||
if (!pm_runtime_suspended(dev))
|
||||
ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const unsigned int ata_port_resume_ehi = ATA_EHI_NO_AUTOPSY
|
||||
| ATA_EHI_QUIET;
|
||||
|
||||
static void ata_port_resume(struct ata_port *ap, pm_message_t mesg)
|
||||
static void ata_port_resume(struct ata_port *ap, pm_message_t mesg,
|
||||
bool async)
|
||||
{
|
||||
ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, false);
|
||||
}
|
||||
|
||||
static void ata_port_resume_async(struct ata_port *ap, pm_message_t mesg)
|
||||
{
|
||||
ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, true);
|
||||
ata_port_request_pm(ap, mesg, ATA_EH_RESET,
|
||||
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET,
|
||||
async);
|
||||
}
|
||||
|
||||
static int ata_port_pm_resume(struct device *dev)
|
||||
{
|
||||
ata_port_resume_async(to_ata_port(dev), PMSG_RESUME);
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
if (!pm_runtime_suspended(dev))
|
||||
ata_port_resume(to_ata_port(dev), PMSG_RESUME, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5268,13 +5295,13 @@ static int ata_port_runtime_idle(struct device *dev)
|
||||
|
||||
static int ata_port_runtime_suspend(struct device *dev)
|
||||
{
|
||||
ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND);
|
||||
ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ata_port_runtime_resume(struct device *dev)
|
||||
{
|
||||
ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME);
|
||||
ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5298,13 +5325,13 @@ static const struct dev_pm_ops ata_port_pm_ops = {
|
||||
*/
|
||||
void ata_sas_port_suspend(struct ata_port *ap)
|
||||
{
|
||||
ata_port_suspend_async(ap, PMSG_SUSPEND);
|
||||
ata_port_suspend(ap, PMSG_SUSPEND, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_sas_port_suspend);
|
||||
|
||||
void ata_sas_port_resume(struct ata_port *ap)
|
||||
{
|
||||
ata_port_resume_async(ap, PMSG_RESUME);
|
||||
ata_port_resume(ap, PMSG_RESUME, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_sas_port_resume);
|
||||
|
||||
@ -6026,7 +6053,7 @@ int ata_host_activate(struct ata_host *host, int irq,
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < host->n_ports; i++)
|
||||
ata_port_desc(host->ports[i], "irq %d", irq);
|
||||
ata_port_desc_misc(host->ports[i], irq);
|
||||
|
||||
rc = ata_host_register(host, sht);
|
||||
/* if failed, just free the IRQ and leave ports alone */
|
||||
@ -6054,6 +6081,9 @@ static void ata_port_detach(struct ata_port *ap)
|
||||
struct ata_link *link;
|
||||
struct ata_device *dev;
|
||||
|
||||
/* Ensure ata_port probe has completed */
|
||||
async_synchronize_cookie(ap->cookie + 1);
|
||||
|
||||
/* Wait for any ongoing EH */
|
||||
ata_port_wait_eh(ap);
|
||||
|
||||
@ -6118,11 +6148,8 @@ void ata_host_detach(struct ata_host *host)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
/* Ensure ata_port probe has completed */
|
||||
async_synchronize_cookie(host->ports[i]->cookie + 1);
|
||||
for (i = 0; i < host->n_ports; i++)
|
||||
ata_port_detach(host->ports[i]);
|
||||
}
|
||||
|
||||
/* the host is dead now, dissociate ACPI */
|
||||
ata_acpi_dissociate(host);
|
||||
@ -6153,10 +6180,24 @@ EXPORT_SYMBOL_GPL(ata_pci_remove_one);
|
||||
void ata_pci_shutdown_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct ata_host *host = pci_get_drvdata(pdev);
|
||||
struct ata_port *ap;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
/* Tell EH to disable all devices */
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_port *ap = host->ports[i];
|
||||
ap = host->ports[i];
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
ap->pflags |= ATA_PFLAG_UNLOADING;
|
||||
ata_port_schedule_eh(ap);
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
}
|
||||
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
ap = host->ports[i];
|
||||
|
||||
/* Wait for EH to complete before freezing the port */
|
||||
ata_port_wait_eh(ap);
|
||||
|
||||
ap->pflags |= ATA_PFLAG_FROZEN;
|
||||
|
||||
|
@ -494,6 +494,18 @@ void ata_eh_release(struct ata_port *ap)
|
||||
mutex_unlock(&ap->host->eh_mutex);
|
||||
}
|
||||
|
||||
static void ata_eh_dev_disable(struct ata_device *dev)
|
||||
{
|
||||
ata_acpi_on_disable(dev);
|
||||
ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
|
||||
dev->class++;
|
||||
|
||||
/* From now till the next successful probe, ering is used to
|
||||
* track probe failures. Clear accumulated device error info.
|
||||
*/
|
||||
ata_ering_clear(&dev->ering);
|
||||
}
|
||||
|
||||
static void ata_eh_unload(struct ata_port *ap)
|
||||
{
|
||||
struct ata_link *link;
|
||||
@ -517,8 +529,8 @@ static void ata_eh_unload(struct ata_port *ap)
|
||||
*/
|
||||
ata_for_each_link(link, ap, PMP_FIRST) {
|
||||
sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0);
|
||||
ata_for_each_dev(dev, link, ALL)
|
||||
ata_dev_disable(dev);
|
||||
ata_for_each_dev(dev, link, ENABLED)
|
||||
ata_eh_dev_disable(dev);
|
||||
}
|
||||
|
||||
/* freeze and set UNLOADED */
|
||||
@ -1211,14 +1223,8 @@ void ata_dev_disable(struct ata_device *dev)
|
||||
return;
|
||||
|
||||
ata_dev_warn(dev, "disable device\n");
|
||||
ata_acpi_on_disable(dev);
|
||||
ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
|
||||
dev->class++;
|
||||
|
||||
/* From now till the next successful probe, ering is used to
|
||||
* track probe failures. Clear accumulated device error info.
|
||||
*/
|
||||
ata_ering_clear(&dev->ering);
|
||||
ata_eh_dev_disable(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_dev_disable);
|
||||
|
||||
@ -1240,12 +1246,12 @@ void ata_eh_detach_dev(struct ata_device *dev)
|
||||
|
||||
/*
|
||||
* If the device is still enabled, transition it to standby power mode
|
||||
* (i.e. spin down HDDs).
|
||||
* (i.e. spin down HDDs) and disable it.
|
||||
*/
|
||||
if (ata_dev_enabled(dev))
|
||||
if (ata_dev_enabled(dev)) {
|
||||
ata_dev_power_set_standby(dev);
|
||||
|
||||
ata_dev_disable(dev);
|
||||
ata_eh_dev_disable(dev);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
@ -2909,6 +2915,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
|
||||
*/
|
||||
if (ata_is_host_link(link))
|
||||
ata_eh_thaw_port(ap);
|
||||
ata_link_warn(link, "%s failed\n",
|
||||
reset == hardreset ? "hardreset" : "softreset");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -3043,15 +3051,6 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
|
||||
if (ehc->i.flags & ATA_EHI_DID_RESET)
|
||||
readid_flags |= ATA_READID_POSTRESET;
|
||||
|
||||
/*
|
||||
* When resuming, before executing any command, make sure to
|
||||
* transition the device to the active power mode.
|
||||
*/
|
||||
if ((action & ATA_EH_SET_ACTIVE) && ata_dev_enabled(dev)) {
|
||||
ata_dev_power_set_active(dev);
|
||||
ata_eh_done(link, dev, ATA_EH_SET_ACTIVE);
|
||||
}
|
||||
|
||||
if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
|
||||
WARN_ON(dev->class == ATA_DEV_PMP);
|
||||
|
||||
@ -3848,6 +3847,17 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure to transition devices to the active power mode
|
||||
* if needed (e.g. if we were scheduled on system resume).
|
||||
*/
|
||||
ata_for_each_dev(dev, link, ENABLED) {
|
||||
if (ehc->i.dev_action[dev->devno] & ATA_EH_SET_ACTIVE) {
|
||||
ata_dev_power_set_active(dev);
|
||||
ata_eh_done(link, dev, ATA_EH_SET_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
/* retry flush if necessary */
|
||||
ata_for_each_dev(dev, link, ALL) {
|
||||
if (dev->class != ATA_DEV_ATA &&
|
||||
|
@ -621,7 +621,6 @@ int sata_link_hardreset(struct ata_link *link, const unsigned int *timing,
|
||||
/* online is set iff link is online && reset succeeded */
|
||||
if (online)
|
||||
*online = false;
|
||||
ata_link_err(link, "COMRESET failed (errno=%d)\n", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -1182,8 +1181,8 @@ EXPORT_SYMBOL_GPL(ata_sas_tport_delete);
|
||||
int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap)
|
||||
{
|
||||
ata_scsi_sdev_config(sdev);
|
||||
ata_scsi_dev_config(sdev, ap->link.device);
|
||||
return 0;
|
||||
|
||||
return ata_scsi_dev_config(sdev, ap->link.device);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_sas_slave_configure);
|
||||
|
||||
|
@ -1203,7 +1203,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
|
||||
static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct scsi_cmnd *scmd = qc->scsicmd;
|
||||
struct ata_taskfile *tf = &qc->tf;
|
||||
const u8 *cdb = scmd->cmnd;
|
||||
u16 fp;
|
||||
u8 bp = 0xff;
|
||||
@ -1213,54 +1212,24 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
|
||||
goto invalid_fld;
|
||||
}
|
||||
|
||||
tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
|
||||
tf->protocol = ATA_PROT_NODATA;
|
||||
if (cdb[1] & 0x1) {
|
||||
; /* ignore IMMED bit, violates sat-r05 */
|
||||
}
|
||||
/* LOEJ bit set not supported */
|
||||
if (cdb[4] & 0x2) {
|
||||
fp = 4;
|
||||
bp = 1;
|
||||
goto invalid_fld; /* LOEJ bit set not supported */
|
||||
goto invalid_fld;
|
||||
}
|
||||
|
||||
/* Power conditions not supported */
|
||||
if (((cdb[4] >> 4) & 0xf) != 0) {
|
||||
fp = 4;
|
||||
bp = 3;
|
||||
goto invalid_fld; /* power conditions not supported */
|
||||
goto invalid_fld;
|
||||
}
|
||||
|
||||
if (cdb[4] & 0x1) {
|
||||
tf->nsect = 1; /* 1 sector, lba=0 */
|
||||
|
||||
if (qc->dev->flags & ATA_DFLAG_LBA) {
|
||||
tf->flags |= ATA_TFLAG_LBA;
|
||||
|
||||
tf->lbah = 0x0;
|
||||
tf->lbam = 0x0;
|
||||
tf->lbal = 0x0;
|
||||
tf->device |= ATA_LBA;
|
||||
} else {
|
||||
/* CHS */
|
||||
tf->lbal = 0x1; /* sect */
|
||||
tf->lbam = 0x0; /* cyl low */
|
||||
tf->lbah = 0x0; /* cyl high */
|
||||
}
|
||||
|
||||
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
|
||||
} else {
|
||||
/* Some odd clown BIOSen issue spindown on power off (ACPI S4
|
||||
* or S5) causing some drives to spin up and down again.
|
||||
*/
|
||||
if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
|
||||
system_state == SYSTEM_POWER_OFF)
|
||||
goto skip;
|
||||
|
||||
if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
|
||||
system_entering_hibernation())
|
||||
goto skip;
|
||||
|
||||
/* Issue ATA STANDBY IMMEDIATE command */
|
||||
tf->command = ATA_CMD_STANDBYNOW1;
|
||||
/* Ignore IMMED bit (cdb[1] & 0x1), violates sat-r05 */
|
||||
if (!ata_dev_power_init_tf(qc->dev, &qc->tf, cdb[4] & 0x1)) {
|
||||
ata_scsi_set_sense(qc->dev, scmd, ABORTED_COMMAND, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1275,12 +1244,8 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
|
||||
invalid_fld:
|
||||
ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp);
|
||||
return 1;
|
||||
skip:
|
||||
scmd->result = SAM_STAT_GOOD;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
|
||||
* @qc: Storage for translated ATA taskfile
|
||||
|
@ -2316,7 +2316,7 @@ int ata_pci_sff_activate_host(struct ata_host *host,
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (ata_port_is_dummy(host->ports[i]))
|
||||
continue;
|
||||
ata_port_desc(host->ports[i], "irq %d", pdev->irq);
|
||||
ata_port_desc_misc(host->ports[i], pdev->irq);
|
||||
}
|
||||
} else if (legacy_mode) {
|
||||
if (!ata_port_is_dummy(host->ports[0])) {
|
||||
@ -2326,7 +2326,7 @@ int ata_pci_sff_activate_host(struct ata_host *host,
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ata_port_desc(host->ports[0], "irq %d",
|
||||
ata_port_desc_misc(host->ports[0],
|
||||
ATA_PRIMARY_IRQ(pdev));
|
||||
}
|
||||
|
||||
@ -2337,7 +2337,7 @@ int ata_pci_sff_activate_host(struct ata_host *host,
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ata_port_desc(host->ports[1], "irq %d",
|
||||
ata_port_desc_misc(host->ports[1],
|
||||
ATA_SECONDARY_IRQ(pdev));
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,8 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
|
||||
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
|
||||
unsigned int readid_flags);
|
||||
extern int ata_dev_configure(struct ata_device *dev);
|
||||
extern bool ata_dev_power_init_tf(struct ata_device *dev,
|
||||
struct ata_taskfile *tf, bool set_active);
|
||||
extern void ata_dev_power_set_standby(struct ata_device *dev);
|
||||
extern void ata_dev_power_set_active(struct ata_device *dev);
|
||||
extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
|
||||
|
@ -212,7 +212,7 @@ static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ata_port_desc(ap, "irq %d", irq[i]);
|
||||
ata_port_desc_misc(ap, irq[i]);
|
||||
}
|
||||
|
||||
return ata_host_register(host, &cs5520_sht);
|
||||
|
@ -4123,10 +4123,13 @@ static int mv_platform_probe(struct platform_device *pdev)
|
||||
hpriv->base -= SATAHC0_REG_BASE;
|
||||
|
||||
hpriv->clk = clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(hpriv->clk))
|
||||
if (IS_ERR(hpriv->clk)) {
|
||||
dev_notice(&pdev->dev, "cannot get optional clkdev\n");
|
||||
else
|
||||
clk_prepare_enable(hpriv->clk);
|
||||
} else {
|
||||
rc = clk_prepare_enable(hpriv->clk);
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (port = 0; port < n_ports; port++) {
|
||||
char port_number[16];
|
||||
|
@ -3928,7 +3928,7 @@ static int sd_suspend_runtime(struct device *dev)
|
||||
static int sd_resume(struct device *dev, bool runtime)
|
||||
{
|
||||
struct scsi_disk *sdkp = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
|
||||
return 0;
|
||||
@ -3938,11 +3938,8 @@ static int sd_resume(struct device *dev, bool runtime)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sdkp->device->no_start_on_resume) {
|
||||
sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
|
||||
ret = sd_start_stop_device(sdkp, 1);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
opal_unlock_from_suspend(sdkp->opal_dev);
|
||||
sdkp->suspended = false;
|
||||
|
@ -656,7 +656,7 @@ struct ata_cpr {
|
||||
|
||||
struct ata_cpr_log {
|
||||
u8 nr_cpr;
|
||||
struct ata_cpr cpr[];
|
||||
struct ata_cpr cpr[] __counted_by(nr_cpr);
|
||||
};
|
||||
|
||||
struct ata_device {
|
||||
@ -1561,6 +1561,11 @@ void ata_port_desc(struct ata_port *ap, const char *fmt, ...);
|
||||
extern void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
|
||||
const char *name);
|
||||
#endif
|
||||
static inline void ata_port_desc_misc(struct ata_port *ap, int irq)
|
||||
{
|
||||
ata_port_desc(ap, "irq %d", irq);
|
||||
ata_port_desc(ap, "lpm-pol %d", ap->target_lpm_policy);
|
||||
}
|
||||
|
||||
static inline bool ata_tag_internal(unsigned int tag)
|
||||
{
|
||||
@ -1881,23 +1886,21 @@ static inline unsigned long ata_deadline(unsigned long from_jiffies,
|
||||
change in future hardware and specs, secondly 0xFF means 'no DMA' but is
|
||||
> UDMA_0. Dyma ddreigiau */
|
||||
|
||||
static inline int ata_using_mwdma(struct ata_device *adev)
|
||||
static inline bool ata_using_mwdma(struct ata_device *adev)
|
||||
{
|
||||
if (adev->dma_mode >= XFER_MW_DMA_0 && adev->dma_mode <= XFER_MW_DMA_4)
|
||||
return 1;
|
||||
return 0;
|
||||
return adev->dma_mode >= XFER_MW_DMA_0 &&
|
||||
adev->dma_mode <= XFER_MW_DMA_4;
|
||||
}
|
||||
|
||||
static inline int ata_using_udma(struct ata_device *adev)
|
||||
static inline bool ata_using_udma(struct ata_device *adev)
|
||||
{
|
||||
if (adev->dma_mode >= XFER_UDMA_0 && adev->dma_mode <= XFER_UDMA_7)
|
||||
return 1;
|
||||
return 0;
|
||||
return adev->dma_mode >= XFER_UDMA_0 &&
|
||||
adev->dma_mode <= XFER_UDMA_7;
|
||||
}
|
||||
|
||||
static inline int ata_dma_enabled(struct ata_device *adev)
|
||||
static inline bool ata_dma_enabled(struct ata_device *adev)
|
||||
{
|
||||
return (adev->dma_mode == 0xFF ? 0 : 1);
|
||||
return adev->dma_mode != 0xFF;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -213,7 +213,6 @@ struct scsi_device {
|
||||
unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
|
||||
unsigned no_start_on_add:1; /* do not issue start on add */
|
||||
unsigned allow_restart:1; /* issue START_UNIT in error handler */
|
||||
unsigned no_start_on_resume:1; /* Do not issue START_STOP_UNIT on resume */
|
||||
unsigned start_stop_pwr_cond:1; /* Set power cond. in START_STOP_UNIT */
|
||||
unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
|
||||
unsigned select_no_atn:1;
|
||||
|
Loading…
Reference in New Issue
Block a user