mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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:
+14
-4
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -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, \
|
||||
|
||||
|
||||
Reference in New Issue
Block a user