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

Pull ata fixes from Damien Le Moal:

 - Fix PCI resource initialization in the sata_mv driver to keep legacy
   Marvell boards functional (Rosen)

 - Fix ahci_ceva driver initialization error path (Radhey)

 - Fix libata header file to remove a kernel doc compilation warning
   (Randy)

 - Increase the timeout for the STANDBY IMMEDIATE command to avoid
   suspend failures with drives that are slow to respond to this command
   (Matt)

 - Fixes for the handling of timed out commands in the presence of
   deferred non-NCQ commands, to avoid excessive delays in executing the
   error handler (me)

 - Disable link power management for a couple of WD drives that have
   been identified as not functioning properly when power management is
   used (Niklas)

 - Fix the device iteration loop when checking for link power management
   support to correctly handle port multiplier setups (Niklas)

* tag 'ata-7.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: libata-sata: fix ata_scsi_lpm_supported() iteration
  ata: libata-core: Disable LPM on WD Green 2.5 480GB
  ata: libata-core: Disable LPM on some WD drives
  scsi: libsas: terminate deferred commands on time out
  ata: libata-scsi: schedule deferred atapi command
  ata: libata-scsi: terminate deferred commands on time out
  ata: libata-eh: Increase STANDBY IMMEDIATE timeout
  ata: libata: avoid kernel-doc warnings
  ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()
  ata: sata_mv: accept 1 or 2 resources in platform probe
This commit is contained in:
Linus Torvalds
2026-07-31 17:05:13 -07:00
11 changed files with 173 additions and 46 deletions
+14 -4
View File
@@ -211,7 +211,7 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
rc = phy_init(hpriv->phys[i]);
if (rc)
goto disable_rsts;
goto exit_phys;
}
/* De-assert the controller reset */
@@ -230,14 +230,24 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
return 0;
disable_rsts:
ahci_platform_deassert_rsts(hpriv);
disable_phys:
while (--i >= 0) {
if (ahci_ignore_port(hpriv, i))
continue;
phy_power_off(hpriv->phys[i]);
phy_exit(hpriv->phys[i]);
}
ahci_platform_assert_rsts(hpriv);
goto disable_clks;
exit_phys:
while (--i >= 0) {
if (ahci_ignore_port(hpriv, i))
continue;
phy_exit(hpriv->phys[i]);
}
disable_clks:
ahci_platform_disable_clks(hpriv);
+9
View File
@@ -4413,6 +4413,15 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
{ "WDC WD3000JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM },
{ "WDC WD3200JD-*", NULL, ATA_QUIRK_WD_BROKEN_LPM },
/*
* WD drives with LPM issues (irrespective of supported SATA speeds).
* (Unlike ATA_QUIRK_WD_BROKEN_LPM, which is only applied if the drive
* exposes SATA Gen1 speed support, and SATA Gen1 speed support only.)
*/
{ "WDC WD100EFGX-68CPLN0", NULL, ATA_QUIRK_NOLPM },
{ "WDC WD102KFBX-68M95N0", NULL, ATA_QUIRK_NOLPM },
{ "WD Green 2.5 480GB", NULL, ATA_QUIRK_NOLPM },
/*
* This sata dom device goes on a walkabout when the ATA_LOG_DIRECTORY
* log page is accessed. Ensure we never ask for this log page with
+14 -23
View File
@@ -106,6 +106,12 @@ static const unsigned int ata_eh_flush_timeouts[] = {
UINT_MAX,
};
static const unsigned int ata_eh_standby_timeouts[] = {
15000, /* Some drives may be slow to standby */
/* but don't hold up a suspend too long waiting for them */
UINT_MAX,
};
static const unsigned int ata_eh_other_timeouts[] = {
5000, /* same rationale as identify timeout */
10000, /* ditto */
@@ -147,6 +153,8 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = {
.timeouts = ata_eh_other_timeouts, },
{ .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT),
.timeouts = ata_eh_flush_timeouts },
{ .commands = CMDS(ATA_CMD_STANDBYNOW1),
.timeouts = ata_eh_standby_timeouts },
{ .commands = CMDS(ATA_CMD_VERIFY),
.timeouts = ata_eh_reset_timeouts },
};
@@ -650,29 +658,12 @@ int ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
set_host_byte(scmd, DID_OK);
ata_qc_for_each_raw(ap, qc, i) {
if (qc->scsicmd != scmd)
continue;
if ((qc->flags & ATA_QCFLAG_ACTIVE) ||
qc == qc->dev->link->deferred_qc)
if (qc->scsicmd == scmd &&
qc->flags & ATA_QCFLAG_ACTIVE)
break;
}
if (i < ATA_MAX_QUEUE && qc == qc->dev->link->deferred_qc) {
/*
* This is a deferred command that timed out while
* waiting for the command queue to drain. Since the qc
* is not active yet (deferred_qc is still set, so the
* deferred qc work has not issued the command yet),
* simply signal the timeout by finishing the SCSI
* command and clear the deferred qc to prevent the
* deferred qc work from issuing this qc.
*/
WARN_ON_ONCE(qc->flags & ATA_QCFLAG_ACTIVE);
qc->dev->link->deferred_qc = NULL;
cancel_work(&qc->dev->link->deferred_qc_work);
set_host_byte(scmd, DID_TIME_OUT);
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
} else if (i < ATA_MAX_QUEUE) {
if (i < ATA_MAX_QUEUE) {
/* the scmd has an associated qc */
if (!(qc->flags & ATA_QCFLAG_EH)) {
/* which hasn't failed yet, timeout */
@@ -948,10 +939,10 @@ static void ata_eh_set_pending(struct ata_port *ap, bool fastdrain)
ap->pflags |= ATA_PFLAG_EH_PENDING;
/*
* If we have a deferred qc, requeue it so that it is retried once EH
* completes.
* If we have deferred QCs, requeue them so that the SCSI EH task can
* run.
*/
ata_scsi_requeue_deferred_qc(ap);
ata_scsi_requeue_deferred_qc(ap, NULL);
if (!fastdrain)
return;
+1 -1
View File
@@ -913,7 +913,7 @@ static bool ata_scsi_lpm_supported(struct ata_port *ap)
return false;
ata_for_each_link(link, ap, EDGE) {
ata_for_each_dev(dev, &ap->link, ENABLED) {
ata_for_each_dev(dev, link, ENABLED) {
if (dev->quirks & ATA_QUIRK_NOLPM)
return false;
}
+107 -12
View File
@@ -1685,26 +1685,80 @@ void ata_scsi_deferred_qc_work(struct work_struct *work)
spin_unlock_irqrestore(ap->lock, flags);
}
void ata_scsi_requeue_deferred_qc(struct ata_port *ap)
enum scsi_timeout_action ata_scsi_requeue_deferred_qc(struct ata_port *ap,
struct scsi_cmnd *timedout_scmd)
{
enum scsi_timeout_action action = SCSI_EH_NOT_HANDLED;
struct ata_queued_cmd *qc;
struct ata_link *link;
u32 host_byte;
lockdep_assert_held(ap->lock);
/*
* If we have a deferred qc when a reset occurs or NCQ commands fail,
* do not try to be smart about what to do with this deferred command
* and simply requeue it by completing it with DID_REQUEUE.
* If we have deferred QCs when a reset, a timeout or an NCQ command
* fails, do not try to be smart about what to do with the deferred
* commands and simply terminate them and let the SCSI layer decide
* what to do.
*/
ata_for_each_link(link, ap, PMP_FIRST) {
struct ata_queued_cmd *qc = link->deferred_qc;
qc = link->deferred_qc;
if (!qc)
continue;
if (qc) {
link->deferred_qc = NULL;
cancel_work(&link->deferred_qc_work);
ata_scsi_qc_done(qc, true, DID_REQUEUE << 16);
/*
* Clear the deferred QC so that the deferred work does not try
* to issue it.
*/
link->deferred_qc = NULL;
cancel_work(&link->deferred_qc_work);
/*
* We are going to complete some scsi command, either with
* DID_TIME_OUT if the command timed out while waiting for being
* issued, or with DID_REQUEUE if another command timed out or
* we had a failed command. However, the block layer may re-issue
* these commands immediately, keeping the scsi host busy and
* thus preventing the SCSI EH task from running.
* So schedule EH on the port to prevent accepting new commands
* until everything is sorted out with the error or timeout that
* got us here in the first place. Note that we set EH pending
* on the port before calling ata_port_schedule_eh() so that we
* do not reenter this function from ata_eh_set_pending() with
* timedout_scmd being NULL and erroneously retry deferred QCs
* that have timed out on other links.
*/
if (!ata_port_eh_scheduled(ap)) {
ap->pflags |= ATA_PFLAG_EH_PENDING;
ata_port_schedule_eh(ap);
}
/*
* If we are being called from scsi_timeout(), then we have a
* non-NULL timedout_scmd. If the timed out command is for a
* deferred QC, terminate that deferred QC with DID_TIME_OUT and
* requeue all other deferred QCs. In this case we need to
* return SCSI_EH_DONE, because the timed out command was
* handled.
* If the timed out command is not for a deferred QC, we need to
* requeue all deferred QCs, and return SCSI_EH_NOT_HANDLED so
* that the timed out command gets added to the EH work queue
* with scsi_eh_scmd_add(), for later handling with libata EH
* ata_scsi_cmd_error_handler().
* If timedout_scmd is NULL, we simply need to requeue all
* deferred QCs and the return value does not matter as we were
* not called from scsi_timeout().
*/
if (timedout_scmd && qc->scsicmd == timedout_scmd) {
host_byte = DID_TIME_OUT;
action = SCSI_EH_DONE;
} else {
host_byte = DID_REQUEUE;
}
ata_scsi_qc_done(qc, true, host_byte << 16);
}
return action;
}
static void ata_scsi_schedule_deferred_qc(struct ata_link *link)
@@ -1723,13 +1777,42 @@ static void ata_scsi_schedule_deferred_qc(struct ata_link *link)
return;
if (ata_port_eh_scheduled(ap)) {
ata_scsi_requeue_deferred_qc(ap);
ata_scsi_requeue_deferred_qc(ap, NULL);
return;
}
if (!ap->ops->qc_defer(qc))
queue_work(system_highpri_wq, &link->deferred_qc_work);
}
enum scsi_timeout_action ata_scsi_retry_deferred_qc(struct ata_port *ap,
struct scsi_cmnd *scmd)
{
enum scsi_timeout_action action;
unsigned long flags;
spin_lock_irqsave(ap->lock, flags);
action = ata_scsi_requeue_deferred_qc(ap, scmd);
spin_unlock_irqrestore(ap->lock, flags);
return action;
}
EXPORT_SYMBOL_GPL(ata_scsi_retry_deferred_qc);
enum scsi_timeout_action ata_scsi_eh_timed_out(struct scsi_cmnd *scmd)
{
struct ata_port *ap = ata_shost_to_port(scmd->device->host);
/*
* ata_scsi_cmd_error_handler() takes care of commands that timed out
* while executing. However, if we have deferred QCs while a timeout
* triggers, we must requeue these commands for retry so that we do not
* unnecessarily delay starting the SCSI EH task until these deferred
* commands also time out.
*/
return ata_scsi_retry_deferred_qc(ap, scmd);
}
EXPORT_SYMBOL_GPL(ata_scsi_eh_timed_out);
static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_link *link = qc->dev->link;
@@ -2911,6 +2994,7 @@ static void atapi_fixup_inquiry(struct scsi_cmnd *cmd)
static void atapi_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_link *link = qc->dev->link;
struct scsi_cmnd *cmd = qc->scsicmd;
unsigned int err_mask = qc->err_mask;
@@ -2936,8 +3020,16 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev)
qc->dev->sdev->locked = 0;
ata_scsi_qc_done(qc, true, SAM_STAT_CHECK_CONDITION);
return;
if (cmd->result)
ata_scsi_qc_done(qc, false, 0);
else
ata_scsi_qc_done(qc, true, SAM_STAT_CHECK_CONDITION);
goto schedule_deferred;
}
if (cmd->result) {
ata_scsi_qc_done(qc, false, 0);
goto schedule_deferred;
}
/* successful completion path */
@@ -2945,6 +3037,9 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
atapi_fixup_inquiry(cmd);
ata_scsi_qc_done(qc, true, SAM_STAT_GOOD);
schedule_deferred:
ata_scsi_schedule_deferred_qc(link);
}
/**
* atapi_xlat - Initialize PACKET taskfile
+2 -1
View File
@@ -180,7 +180,8 @@ enum scsi_qc_status __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
struct ata_port *ap)
__must_hold(ap->lock);
void ata_scsi_deferred_qc_work(struct work_struct *work);
void ata_scsi_requeue_deferred_qc(struct ata_port *ap);
enum scsi_timeout_action ata_scsi_requeue_deferred_qc(struct ata_port *ap,
struct scsi_cmnd *scmd);
/* libata-eh.c */
extern unsigned int ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
+1 -1
View File
@@ -4027,7 +4027,7 @@ static int mv_platform_probe(struct platform_device *pdev)
/*
* Simple resource validation ..
*/
if (unlikely(pdev->num_resources != 1)) {
if (unlikely(pdev->num_resources != 1 && pdev->num_resources != 2)) {
dev_err(&pdev->dev, "invalid number of resources\n");
return -EINVAL;
}
+15
View File
@@ -502,6 +502,21 @@ int sas_eh_target_reset_handler(struct scsi_cmnd *cmd)
}
EXPORT_SYMBOL_GPL(sas_eh_target_reset_handler);
/*
* Handle deferred QCs in case of a command timeout.
* See ata_scsi_eh_timed_out() for details.
*/
enum scsi_timeout_action sas_eh_timed_out(struct scsi_cmnd *cmd)
{
struct domain_device *dev = cmd_to_domain_dev(cmd);
if (dev_is_sata(dev))
return ata_scsi_retry_deferred_qc(dev->sata_dev.ap, cmd);
return SCSI_EH_NOT_HANDLED;
}
EXPORT_SYMBOL_GPL(sas_eh_timed_out);
/* Try to reset a device */
static int try_to_reset_cmd_device(struct scsi_cmnd *cmd)
{
+3 -3
View File
@@ -762,8 +762,7 @@ static inline bool ata_id_sense_reporting_enabled(const u16 *id)
return id[ATA_ID_COMMAND_SET_4] & BIT(6);
}
/**
*
/*
* Word: 206 - SCT Command Transport
* 15:12 - Vendor Specific
* 11:6 - Reserved
@@ -810,8 +809,9 @@ static inline bool ata_id_sct_supported(const u16 *id)
*
* The practical impact of this is that ata_id_major_version cannot
* reliably report on drives below ATA3.
*
* Returns: major version of ATA drive level or %0 if unknown
*/
static inline unsigned int ata_id_major_version(const u16 *id)
{
unsigned int mver;
+5 -1
View File
@@ -425,7 +425,7 @@ enum {
/* This should match the actual table size of
* ata_eh_cmd_timeout_table in libata-eh.c.
*/
ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 8,
ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 9,
/* User visible DMA mask for DMA control. DO NOT renumber. */
ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */
@@ -1153,6 +1153,9 @@ extern int ata_scsi_ioctl(struct scsi_device *dev, unsigned int cmd,
#endif
extern enum scsi_qc_status ata_scsi_queuecmd(struct Scsi_Host *h,
struct scsi_cmnd *cmd);
enum scsi_timeout_action ata_scsi_retry_deferred_qc(struct ata_port *ap,
struct scsi_cmnd *scmd);
enum scsi_timeout_action ata_scsi_eh_timed_out(struct scsi_cmnd *cmd);
#if IS_REACHABLE(CONFIG_ATA)
bool ata_scsi_dma_need_drain(struct request *rq);
#else
@@ -1464,6 +1467,7 @@ extern const struct attribute_group *ata_common_sdev_groups[];
.ioctl = ata_scsi_ioctl, \
ATA_SCSI_COMPAT_IOCTL \
.queuecommand = ata_scsi_queuecmd, \
.eh_timed_out = ata_scsi_eh_timed_out, \
.dma_need_drain = ata_scsi_dma_need_drain, \
.this_id = ATA_SHT_THIS_ID, \
.emulated = ATA_SHT_EMULATED, \
+2
View File
@@ -705,6 +705,7 @@ void sas_task_abort(struct sas_task *);
int sas_eh_abort_handler(struct scsi_cmnd *cmd);
int sas_eh_device_reset_handler(struct scsi_cmnd *cmd);
int sas_eh_target_reset_handler(struct scsi_cmnd *cmd);
enum scsi_timeout_action sas_eh_timed_out(struct scsi_cmnd *cmd);
extern void sas_target_destroy(struct scsi_target *);
extern int sas_sdev_init(struct scsi_device *);
@@ -743,6 +744,7 @@ void sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
.this_id = -1, \
.eh_device_reset_handler = sas_eh_device_reset_handler, \
.eh_target_reset_handler = sas_eh_target_reset_handler, \
.eh_timed_out = sas_eh_timed_out, \
.target_destroy = sas_target_destroy, \
.ioctl = sas_ioctl, \