// SPDX-License-Identifier: GPL-2.0-or-later
/*
* libata - eh . c - libata error handling
*
* Copyright 2006 Tejun Heo < htejun @ gmail . com >
*
* libata documentation is available via ' make { ps | pdf } docs ' ,
* as Documentation / driver - api / libata . rst
*
* Hardware documentation available from http : //www.t13.org/ and
* http : //www.sata-io.org/
*/
#include <linux/kernel.h>
#include <linux/blkdev.h>
#include <linux/export.h>
#include <linux/pci.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_dbg.h>
#include "../scsi/scsi_transport_api.h"
#include <linux/libata.h>
#include <trace/events/libata.h>
#include "libata.h"
enum {
/* speed down verdicts */
ATA_EH_SPDN_NCQ_OFF = (1 << 0 ),
ATA_EH_SPDN_SPEED_DOWN = (1 << 1 ),
ATA_EH_SPDN_FALLBACK_TO_PIO = (1 << 2 ),
ATA_EH_SPDN_KEEP_ERRORS = (1 << 3 ),
/* error flags */
ATA_EFLAG_IS_IO = (1 << 0 ),
ATA_EFLAG_DUBIOUS_XFER = (1 << 1 ),
ATA_EFLAG_OLD_ER = (1 << 31 ),
/* error categories */
ATA_ECAT_NONE = 0 ,
ATA_ECAT_ATA_BUS = 1 ,
ATA_ECAT_TOUT_HSM = 2 ,
ATA_ECAT_UNK_DEV = 3 ,
ATA_ECAT_DUBIOUS_NONE = 4 ,
ATA_ECAT_DUBIOUS_ATA_BUS = 5 ,
ATA_ECAT_DUBIOUS_TOUT_HSM = 6 ,
ATA_ECAT_DUBIOUS_UNK_DEV = 7 ,
ATA_ECAT_NR = 8 ,
ATA_EH_CMD_DFL_TIMEOUT = 5000 ,
/* always put at least this amount of time between resets */
ATA_EH_RESET_COOL_DOWN = 5000 ,
/* Waiting in ->prereset can never be reliable. It's
* sometimes nice to wait there but it can ' t be depended upon ;
* otherwise , we wouldn ' t be resetting . Just give it enough
* time for most drives to spin up .
*/
ATA_EH_PRERESET_TIMEOUT = 10000 ,
ATA_EH_FASTDRAIN_INTERVAL = 3000 ,
ATA_EH_UA_TRIES = 5 ,
/* probe speed down parameters, see ata_eh_schedule_probe() */
ATA_EH_PROBE_TRIAL_INTERVAL = 60000 , /* 1 min */
ATA_EH_PROBE_TRIALS = 2 ,
};
/* The following table determines how we sequence resets. Each entry
* represents timeout for that try . The first try can be soft or
* hardreset . All others are hardreset if available . In most cases
* the first reset w / 10 sec timeout should succeed . Following entries
* are mostly for error handling , hotplug and those outlier devices that
* take an exceptionally long time to recover from reset .
*/
static const unsigned int ata_eh_reset_timeouts[] = {
10000 , /* most drives spin up by 10sec */
10000 , /* > 99% working drives spin up before 20sec */
35000 , /* give > 30 secs of idleness for outlier devices */
5000 , /* and sweet one last chance */
UINT_MAX, /* > 1 min has elapsed, give up */
};
static const unsigned int ata_eh_identify_timeouts[] = {
5000 , /* covers > 99% of successes and not too boring on failures */
10000 , /* combined time till here is enough even for media access */
30000 , /* for true idiots */
UINT_MAX,
};
static const unsigned int ata_eh_revalidate_timeouts[] = {
15000 , /* Some drives are slow to read log pages when waking-up */
15000 , /* combined time till here is enough even for media access */
UINT_MAX,
};
static const unsigned int ata_eh_flush_timeouts[] = {
15000 , /* be generous with flush */
15000 , /* ditto */
30000 , /* and even more generous */
UINT_MAX,
};
static const unsigned int ata_eh_other_timeouts[] = {
5000 , /* same rationale as identify timeout */
10000 , /* ditto */
/* but no merciful 30sec for other commands, it just isn't worth it */
UINT_MAX,
};
struct ata_eh_cmd_timeout_ent {
const u8 *commands;
const unsigned int *timeouts;
};
/* The following table determines timeouts to use for EH internal
* commands . Each table entry is a command class and matches the
* commands the entry applies to and the timeout table to use .
*
* On the retry after a command timed out , the next timeout value from
* the table is used . If the table doesn ' t contain further entries ,
* the last value is used .
*
* ehc - > cmd_timeout_idx keeps track of which timeout to use per
* command class , so if SET_FEATURES times out on the first try , the
* next try will use the second timeout value only for that class .
*/
#define CMDS(cmds...) (const u8 []){ cmds, 0 }
static const struct ata_eh_cmd_timeout_ent
ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = {
{ .commands = CMDS(ATA_CMD_ID_ATA, ATA_CMD_ID_ATAPI),
.timeouts = ata_eh_identify_timeouts, },
{ .commands = CMDS(ATA_CMD_READ_LOG_EXT, ATA_CMD_READ_LOG_DMA_EXT),
.timeouts = ata_eh_revalidate_timeouts, },
{ .commands = CMDS(ATA_CMD_READ_NATIVE_MAX, ATA_CMD_READ_NATIVE_MAX_EXT),
.timeouts = ata_eh_other_timeouts, },
{ .commands = CMDS(ATA_CMD_SET_MAX, ATA_CMD_SET_MAX_EXT),
.timeouts = ata_eh_other_timeouts, },
{ .commands = CMDS(ATA_CMD_SET_FEATURES),
.timeouts = ata_eh_other_timeouts, },
{ .commands = CMDS(ATA_CMD_INIT_DEV_PARAMS),
.timeouts = ata_eh_other_timeouts, },
{ .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT),
.timeouts = ata_eh_flush_timeouts },
{ .commands = CMDS(ATA_CMD_VERIFY),
.timeouts = ata_eh_reset_timeouts },
};
#undef CMDS
static void __ata_port_freeze(struct ata_port *ap);
#ifdef CONFIG_PM
static void ata_eh_handle_port_suspend(struct ata_port *ap);
static void ata_eh_handle_port_resume(struct ata_port *ap);
#else /* CONFIG_PM */
static void ata_eh_handle_port_suspend(struct ata_port *ap)
{ }
static void ata_eh_handle_port_resume(struct ata_port *ap)
{ }
#endif /* CONFIG_PM */
static __printf(2 , 0 ) void __ata_ehi_pushv_desc(struct ata_eh_info *ehi,
const char *fmt, va_list args)
{
ehi->desc_len += vscnprintf(ehi->desc + ehi->desc_len,
ATA_EH_DESC_LEN - ehi->desc_len,
fmt, args);
}
/**
* _ _ ata_ehi_push_desc - push error description without adding separator
* @ ehi : target EHI
* @ fmt : printf format string
*
* Format string according to @ fmt and append it to @ ehi - > desc .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*/
void __ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
__ata_ehi_pushv_desc(ehi, fmt, args);
va_end(args);
}
EXPORT_SYMBOL_GPL(__ata_ehi_push_desc);
/**
* ata_ehi_push_desc - push error description with separator
* @ ehi : target EHI
* @ fmt : printf format string
*
* Format string according to @ fmt and append it to @ ehi - > desc .
* If @ ehi - > desc is not empty , " , " is added in - between .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*/
void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...)
{
va_list args;
if (ehi->desc_len)
__ata_ehi_push_desc(ehi, ", " );
va_start(args, fmt);
__ata_ehi_pushv_desc(ehi, fmt, args);
va_end(args);
}
EXPORT_SYMBOL_GPL(ata_ehi_push_desc);
/**
* ata_ehi_clear_desc - clean error description
* @ ehi : target EHI
*
* Clear @ ehi - > desc .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*/
void ata_ehi_clear_desc(struct ata_eh_info *ehi)
{
ehi->desc[0 ] = '\0' ;
ehi->desc_len = 0 ;
}
EXPORT_SYMBOL_GPL(ata_ehi_clear_desc);
/**
* ata_port_desc - append port description
* @ ap : target ATA port
* @ fmt : printf format string
*
* Format string according to @ fmt and append it to port
* description . If port description is not empty , " " is added
* in - between . This function is to be used while initializing
* ata_host . The description is printed on host registration .
*
* LOCKING :
* None .
*/
void ata_port_desc(struct ata_port *ap, const char *fmt, ...)
{
va_list args;
WARN_ON(!(ap->pflags & ATA_PFLAG_INITIALIZING));
if (ap->link.eh_info.desc_len)
__ata_ehi_push_desc(&ap->link.eh_info, " " );
va_start(args, fmt);
__ata_ehi_pushv_desc(&ap->link.eh_info, fmt, args);
va_end(args);
}
EXPORT_SYMBOL_GPL(ata_port_desc);
#ifdef CONFIG_PCI
/**
* ata_port_pbar_desc - append PCI BAR description
* @ ap : target ATA port
* @ bar : target PCI BAR
* @ offset : offset into PCI BAR
* @ name : name of the area
*
* If @ offset is negative , this function formats a string which
* contains the name , address , size and type of the BAR and
* appends it to the port description . If @ offset is zero or
* positive , only name and offsetted address is appended .
*
* LOCKING :
* None .
*/
void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
const char *name)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
char *type = "" ;
unsigned long long start, len;
if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM)
type = "m" ;
else if (pci_resource_flags(pdev, bar) & IORESOURCE_IO)
type = "i" ;
start = (unsigned long long )pci_resource_start(pdev, bar);
len = (unsigned long long )pci_resource_len(pdev, bar);
if (offset < 0 )
ata_port_desc(ap, "%s %s%llu@0x%llx" , name, type, len, start);
else
ata_port_desc(ap, "%s 0x%llx" , name,
start + (unsigned long long )offset);
}
EXPORT_SYMBOL_GPL(ata_port_pbar_desc);
#endif /* CONFIG_PCI */
static int ata_lookup_timeout_table(u8 cmd)
{
int i;
for (i = 0 ; i < ATA_EH_CMD_TIMEOUT_TABLE_SIZE; i++) {
const u8 *cur;
for (cur = ata_eh_cmd_timeout_table[i].commands; *cur; cur++)
if (*cur == cmd)
return i;
}
return -1 ;
}
/**
* ata_internal_cmd_timeout - determine timeout for an internal command
* @ dev : target device
* @ cmd : internal command to be issued
*
* Determine timeout for internal command @ cmd for @ dev .
*
* LOCKING :
* EH context .
*
* RETURNS :
* Determined timeout .
*/
unsigned int ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
int ent = ata_lookup_timeout_table(cmd);
int idx;
if (ent < 0 )
return ATA_EH_CMD_DFL_TIMEOUT;
idx = ehc->cmd_timeout_idx[dev->devno][ent];
return ata_eh_cmd_timeout_table[ent].timeouts[idx];
}
/**
* ata_internal_cmd_timed_out - notification for internal command timeout
* @ dev : target device
* @ cmd : internal command which timed out
*
* Notify EH that internal command @ cmd for @ dev timed out . This
* function should be called only for commands whose timeouts are
* determined using ata_internal_cmd_timeout ( ) .
*
* LOCKING :
* EH context .
*/
void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
int ent = ata_lookup_timeout_table(cmd);
int idx;
if (ent < 0 )
return ;
idx = ehc->cmd_timeout_idx[dev->devno][ent];
if (ata_eh_cmd_timeout_table[ent].timeouts[idx + 1 ] != UINT_MAX)
ehc->cmd_timeout_idx[dev->devno][ent]++;
}
static void ata_ering_record(struct ata_ering *ering, unsigned int eflags,
unsigned int err_mask)
{
struct ata_ering_entry *ent;
WARN_ON(!err_mask);
ering->cursor++;
ering->cursor %= ATA_ERING_SIZE;
ent = &ering->ring[ering->cursor];
ent->eflags = eflags;
ent->err_mask = err_mask;
ent->timestamp = get_jiffies_64();
}
static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
{
struct ata_ering_entry *ent = &ering->ring[ering->cursor];
if (ent->err_mask)
return ent;
return NULL;
}
int ata_ering_map(struct ata_ering *ering,
int (*map_fn)(struct ata_ering_entry *, void *),
void *arg)
{
int idx, rc = 0 ;
struct ata_ering_entry *ent;
idx = ering->cursor;
do {
ent = &ering->ring[idx];
if (!ent->err_mask)
break ;
rc = map_fn(ent, arg);
if (rc)
break ;
idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE;
} while (idx != ering->cursor);
return rc;
}
static int ata_ering_clear_cb(struct ata_ering_entry *ent, void *void_arg)
{
ent->eflags |= ATA_EFLAG_OLD_ER;
return 0 ;
}
static void ata_ering_clear(struct ata_ering *ering)
{
ata_ering_map(ering, ata_ering_clear_cb, NULL);
}
static unsigned int ata_eh_dev_action(struct ata_device *dev)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
return ehc->i.action | ehc->i.dev_action[dev->devno];
}
static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev,
struct ata_eh_info *ehi, unsigned int action)
{
struct ata_device *tdev;
if (!dev) {
ehi->action &= ~action;
ata_for_each_dev(tdev, link, ALL)
ehi->dev_action[tdev->devno] &= ~action;
} else {
/* doesn't make sense for port-wide EH actions */
WARN_ON(!(action & ATA_EH_PERDEV_MASK));
/* break ehi->action into ehi->dev_action */
if (ehi->action & action) {
ata_for_each_dev(tdev, link, ALL)
ehi->dev_action[tdev->devno] |=
ehi->action & action;
ehi->action &= ~action;
}
/* turn off the specified per-dev action */
ehi->dev_action[dev->devno] &= ~action;
}
}
/**
* ata_eh_acquire - acquire EH ownership
* @ ap : ATA port to acquire EH ownership for
*
* Acquire EH ownership for @ ap . This is the basic exclusion
* mechanism for ports sharing a host . Only one port hanging off
* the same host can claim the ownership of EH .
*
* LOCKING :
* EH context .
*/
void ata_eh_acquire(struct ata_port *ap)
{
mutex_lock(&ap->host->eh_mutex);
WARN_ON_ONCE(ap->host->eh_owner);
ap->host->eh_owner = current;
}
/**
* ata_eh_release - release EH ownership
* @ ap : ATA port to release EH ownership for
*
* Release EH ownership for @ ap if the caller . The caller must
* have acquired EH ownership using ata_eh_acquire ( ) previously .
*
* LOCKING :
* EH context .
*/
void ata_eh_release(struct ata_port *ap)
{
WARN_ON_ONCE(ap->host->eh_owner != current);
ap->host->eh_owner = NULL;
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);
ata_dev_free_resources(dev);
}
static void ata_eh_unload(struct ata_port *ap)
{
struct ata_link *link;
struct ata_device *dev;
unsigned long flags;
/*
* Unless we are restarting , transition all enabled devices to
* standby power mode .
*/
if (system_state != SYSTEM_RESTART) {
ata_for_each_link(link, ap, PMP_FIRST) {
ata_for_each_dev(dev, link, ENABLED)
ata_dev_power_set_standby(dev);
}
}
/*
* Restore SControl IPM and SPD for the next driver and
* disable attached devices .
*/
ata_for_each_link(link, ap, PMP_FIRST) {
sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0 xff0);
ata_for_each_dev(dev, link, ENABLED)
ata_eh_dev_disable(dev);
}
/* freeze and set UNLOADED */
spin_lock_irqsave(ap->lock, flags);
ata_port_freeze(ap); /* won't be thawed */
ap->pflags &= ~ATA_PFLAG_EH_PENDING; /* clear pending from freeze */
ap->pflags |= ATA_PFLAG_UNLOADED;
spin_unlock_irqrestore(ap->lock, flags);
}
/**
* ata_scsi_error - SCSI layer error handler callback
* @ host : SCSI host on which error occurred
*
* Handles SCSI - layer - thrown error events .
*
* LOCKING :
* Inherited from SCSI layer ( none , can sleep )
*
* RETURNS :
* Zero .
*/
void ata_scsi_error(struct Scsi_Host *host)
{
struct ata_port *ap = ata_shost_to_port(host);
unsigned long flags;
LIST_HEAD(eh_work_q);
spin_lock_irqsave(host->host_lock, flags);
list_splice_init(&host->eh_cmd_q, &eh_work_q);
spin_unlock_irqrestore(host->host_lock, flags);
ata_scsi_cmd_error_handler(host, ap, &eh_work_q);
/* If we timed raced normal completion and there is nothing to
recover nr_timedout == 0 why exactly are we doing error recovery ? */
ata_scsi_port_error_handler(host, ap);
/* finish or retry handled scmd's and clean up */
WARN_ON(!list_empty(&eh_work_q));
}
/**
* ata_scsi_cmd_error_handler - error callback for a list of commands
* @ host : scsi host containing the port
* @ ap : ATA port within the host
* @ eh_work_q : list of commands to process
*
* process the given list of commands and return those finished to the
* ap - > eh_done_q . This function is the first part of the libata error
* handler which processes a given list of failed commands .
*/
void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
struct list_head *eh_work_q)
{
int i;
unsigned long flags;
struct scsi_cmnd *scmd, *tmp;
int nr_timedout = 0 ;
/* make sure sff pio task is not running */
ata_sff_flush_pio_task(ap);
/* synchronize with host lock and sort out timeouts */
/*
* For EH , all qcs are finished in one of three ways -
* normal completion , error completion , and SCSI timeout .
* Both completions can race against SCSI timeout . When normal
* completion wins , the qc never reaches EH . When error
* completion wins , the qc has ATA_QCFLAG_EH set .
*
* When SCSI timeout wins , things are a bit more complex .
* Normal or error completion can occur after the timeout but
* before this point . In such cases , both types of
* completions are honored . A scmd is determined to have
* timed out iff its associated qc is active and not failed .
*/
spin_lock_irqsave(ap->lock, flags);
/*
* This must occur under the ap - > lock as we don ' t want
* a polled recovery to race the real interrupt handler
*
* The lost_interrupt handler checks for any completed but
* non - notified command and completes much like an IRQ handler .
*
* We then fall into the error recovery code which will treat
* this as if normal completion won the race
*/
if (ap->ops->lost_interrupt)
ap->ops->lost_interrupt(ap);
list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) {
struct ata_queued_cmd *qc;
/*
* If the scmd was added to EH , via ata_qc_schedule_eh ( ) - >
* scsi_timeout ( ) - > scsi_eh_scmd_add ( ) , scsi_timeout ( ) will
* have set DID_TIME_OUT ( since libata does not have an abort
* handler ) . Thus , to clear DID_TIME_OUT , clear the host byte .
*/
set_host_byte(scmd, DID_OK);
ata_qc_for_each_raw(ap, qc, i) {
if (qc->flags & ATA_QCFLAG_ACTIVE &&
qc->scsicmd == scmd)
break ;
}
if (i < ATA_MAX_QUEUE) {
/* the scmd has an associated qc */
if (!(qc->flags & ATA_QCFLAG_EH)) {
/* which hasn't failed yet, timeout */
set_host_byte(scmd, DID_TIME_OUT);
qc->err_mask |= AC_ERR_TIMEOUT;
qc->flags |= ATA_QCFLAG_EH;
nr_timedout++;
}
} else {
/* Normal completion occurred after
* SCSI timeout but before this point .
* Successfully complete it .
*/
scmd->retries = scmd->allowed;
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
}
}
/*
* If we have timed out qcs . They belong to EH from
* this point but the state of the controller is
* unknown . Freeze the port to make sure the IRQ
* handler doesn ' t diddle with those qcs . This must
* be done atomically w . r . t . setting ATA_QCFLAG_EH .
*/
if (nr_timedout)
__ata_port_freeze(ap);
/* initialize eh_tries */
ap->eh_tries = ATA_EH_MAX_TRIES;
spin_unlock_irqrestore(ap->lock, flags);
}
EXPORT_SYMBOL(ata_scsi_cmd_error_handler);
/**
* ata_scsi_port_error_handler - recover the port after the commands
* @ host : SCSI host containing the port
* @ ap : the ATA port
*
* Handle the recovery of the port @ ap after all the commands
* have been recovered .
*/
void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
{
unsigned long flags;
struct ata_link *link;
/* acquire EH ownership */
ata_eh_acquire(ap);
repeat:
/* kill fast drain timer */
timer_delete_sync(&ap->fastdrain_timer);
/* process port resume request */
ata_eh_handle_port_resume(ap);
/* fetch & clear EH info */
spin_lock_irqsave(ap->lock, flags);
ata_for_each_link(link, ap, HOST_FIRST) {
struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev;
memset(&link->eh_context, 0 , sizeof (link->eh_context));
link->eh_context.i = link->eh_info;
memset(&link->eh_info, 0 , sizeof (link->eh_info));
ata_for_each_dev(dev, link, ENABLED) {
int devno = dev->devno;
ehc->saved_xfer_mode[devno] = dev->xfer_mode;
if (ata_ncq_enabled(dev))
ehc->saved_ncq_enabled |= 1 << devno;
/* If we are resuming, wake up the device */
if (ap->pflags & ATA_PFLAG_RESUMING) {
dev->flags |= ATA_DFLAG_RESUMING;
ehc->i.dev_action[devno] |= ATA_EH_SET_ACTIVE;
}
}
}
ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
ap->pflags &= ~ATA_PFLAG_EH_PENDING;
ap->excl_link = NULL; /* don't maintain exclusion over EH */
spin_unlock_irqrestore(ap->lock, flags);
/* invoke EH, skip if unloading or suspended */
if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)))
ap->ops->error_handler(ap);
else {
/* if unloading, commence suicide */
if ((ap->pflags & ATA_PFLAG_UNLOADING) &&
!(ap->pflags & ATA_PFLAG_UNLOADED))
ata_eh_unload(ap);
ata_eh_finish(ap);
}
/* process port suspend request */
ata_eh_handle_port_suspend(ap);
/*
* Exception might have happened after - > error_handler recovered the
* port but before this point . Repeat EH in such case .
*/
spin_lock_irqsave(ap->lock, flags);
if (ap->pflags & ATA_PFLAG_EH_PENDING) {
if (--ap->eh_tries) {
spin_unlock_irqrestore(ap->lock, flags);
goto repeat;
}
ata_port_err(ap,
"EH pending after %d tries, giving up\n" ,
ATA_EH_MAX_TRIES);
ap->pflags &= ~ATA_PFLAG_EH_PENDING;
}
/* this run is complete, make sure EH info is clear */
ata_for_each_link(link, ap, HOST_FIRST)
memset(&link->eh_info, 0 , sizeof (link->eh_info));
/*
* end eh ( clear host_eh_scheduled ) while holding ap - > lock such that if
* exception occurs after this point but before EH completion , SCSI
* midlayer will re - initiate EH .
*/
ap->ops->end_eh(ap);
spin_unlock_irqrestore(ap->lock, flags);
ata_eh_release(ap);
scsi_eh_flush_done_q(&ap->eh_done_q);
/* clean up */
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_RESUMING;
if (ap->pflags & ATA_PFLAG_LOADING)
ap->pflags &= ~ATA_PFLAG_LOADING;
else if ((ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) &&
!(ap->flags & ATA_FLAG_SAS_HOST))
schedule_delayed_work(&ap->hotplug_task, 0 );
if (ap->pflags & ATA_PFLAG_RECOVERED)
ata_port_info(ap, "EH complete\n" );
ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
/* tell wait_eh that we're done */
ap->pflags &= ~ATA_PFLAG_EH_IN_PROGRESS;
wake_up_all(&ap->eh_wait_q);
spin_unlock_irqrestore(ap->lock, flags);
}
EXPORT_SYMBOL_GPL(ata_scsi_port_error_handler);
/**
* ata_port_wait_eh - Wait for the currently pending EH to complete
* @ ap : Port to wait EH for
*
* Wait until the currently pending EH is complete .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*/
void ata_port_wait_eh(struct ata_port *ap)
{
unsigned long flags;
DEFINE_WAIT(wait);
retry:
spin_lock_irqsave(ap->lock, flags);
while (ata_port_eh_scheduled(ap)) {
prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE);
spin_unlock_irqrestore(ap->lock, flags);
schedule();
spin_lock_irqsave(ap->lock, flags);
}
finish_wait(&ap->eh_wait_q, &wait);
spin_unlock_irqrestore(ap->lock, flags);
/* make sure SCSI EH is complete */
if (scsi_host_in_recovery(ap->scsi_host)) {
ata_msleep(ap, 10 );
goto retry;
}
}
EXPORT_SYMBOL_GPL(ata_port_wait_eh);
static unsigned int ata_eh_nr_in_flight(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
unsigned int tag;
unsigned int nr = 0 ;
/* count only non-internal commands */
ata_qc_for_each(ap, qc, tag) {
if (qc)
nr++;
}
return nr;
}
void ata_eh_fastdrain_timerfn(struct timer_list *t)
{
struct ata_port *ap = timer_container_of(ap, t, fastdrain_timer);
unsigned long flags;
unsigned int cnt;
spin_lock_irqsave(ap->lock, flags);
cnt = ata_eh_nr_in_flight(ap);
/* are we done? */
if (!cnt)
goto out_unlock;
if (cnt == ap->fastdrain_cnt) {
struct ata_queued_cmd *qc;
unsigned int tag;
/* No progress during the last interval, tag all
* in - flight qcs as timed out and freeze the port .
*/
ata_qc_for_each(ap, qc, tag) {
if (qc)
qc->err_mask |= AC_ERR_TIMEOUT;
}
ata_port_freeze(ap);
} else {
/* some qcs have finished, give it another chance */
ap->fastdrain_cnt = cnt;
ap->fastdrain_timer.expires =
ata_deadline(jiffies, ATA_EH_FASTDRAIN_INTERVAL);
add_timer(&ap->fastdrain_timer);
}
out_unlock:
spin_unlock_irqrestore(ap->lock, flags);
}
/**
* ata_eh_set_pending - set ATA_PFLAG_EH_PENDING and activate fast drain
* @ ap : target ATA port
* @ fastdrain : activate fast drain
*
* Set ATA_PFLAG_EH_PENDING and activate fast drain if @ fastdrain
* is non - zero and EH wasn ' t pending before . Fast drain ensures
* that EH kicks in in timely manner .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*/
static void ata_eh_set_pending(struct ata_port *ap, bool fastdrain)
{
unsigned int cnt;
/* already scheduled? */
if (ap->pflags & ATA_PFLAG_EH_PENDING)
return ;
ap->pflags |= ATA_PFLAG_EH_PENDING;
if (!fastdrain)
return ;
/* do we have in-flight qcs? */
cnt = ata_eh_nr_in_flight(ap);
if (!cnt)
return ;
/* activate fast drain */
ap->fastdrain_cnt = cnt;
ap->fastdrain_timer.expires =
ata_deadline(jiffies, ATA_EH_FASTDRAIN_INTERVAL);
add_timer(&ap->fastdrain_timer);
}
/**
* ata_qc_schedule_eh - schedule qc for error handling
* @ qc : command to schedule error handling for
*
* Schedule error handling for @ qc . EH will kick in as soon as
* other commands are drained .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*/
void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
qc->flags |= ATA_QCFLAG_EH;
ata_eh_set_pending(ap, true );
/* The following will fail if timeout has already expired.
* ata_scsi_error ( ) takes care of such scmds on EH entry .
* Note that ATA_QCFLAG_EH is unconditionally set after
* this function completes .
*/
blk_abort_request(scsi_cmd_to_rq(qc->scsicmd));
}
/**
* ata_std_sched_eh - non - libsas ata_ports issue eh with this common routine
* @ ap : ATA port to schedule EH for
*
* LOCKING : inherited from ata_port_schedule_eh
* spin_lock_irqsave ( host lock )
*/
void ata_std_sched_eh(struct ata_port *ap)
{
if (ap->pflags & ATA_PFLAG_INITIALIZING)
return ;
ata_eh_set_pending(ap, true );
scsi_schedule_eh(ap->scsi_host);
trace_ata_std_sched_eh(ap);
}
EXPORT_SYMBOL_GPL(ata_std_sched_eh);
/**
* ata_std_end_eh - non - libsas ata_ports complete eh with this common routine
* @ ap : ATA port to end EH for
*
* In the libata object model there is a 1 : 1 mapping of ata_port to
* shost , so host fields can be directly manipulated under ap - > lock , in
* the libsas case we need to hold a lock at the ha - > level to coordinate
* these events .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*/
void ata_std_end_eh(struct ata_port *ap)
{
struct Scsi_Host *host = ap->scsi_host;
host->host_eh_scheduled = 0 ;
}
EXPORT_SYMBOL(ata_std_end_eh);
/**
* ata_port_schedule_eh - schedule error handling without a qc
* @ ap : ATA port to schedule EH for
*
* Schedule error handling for @ ap . EH will kick in as soon as
* all commands are drained .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*/
void ata_port_schedule_eh(struct ata_port *ap)
{
/* see: ata_std_sched_eh, unless you know better */
ap->ops->sched_eh(ap);
}
EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
{
struct ata_queued_cmd *qc;
int tag, nr_aborted = 0 ;
/* we're gonna abort all commands, no need for fast drain */
ata_eh_set_pending(ap, false );
/* include internal tag in iteration */
ata_qc_for_each_with_internal(ap, qc, tag) {
if (qc && (!link || qc->dev->link == link)) {
qc->flags |= ATA_QCFLAG_EH;
ata_qc_complete(qc);
nr_aborted++;
}
}
if (!nr_aborted)
ata_port_schedule_eh(ap);
return nr_aborted;
}
/**
* ata_link_abort - abort all qc ' s on the link
* @ link : ATA link to abort qc ' s for
*
* Abort all active qc ' s active on @ link and schedule EH .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*
* RETURNS :
* Number of aborted qc ' s .
*/
int ata_link_abort(struct ata_link *link)
{
return ata_do_link_abort(link->ap, link);
}
EXPORT_SYMBOL_GPL(ata_link_abort);
/**
* ata_port_abort - abort all qc ' s on the port
* @ ap : ATA port to abort qc ' s for
*
* Abort all active qc ' s of @ ap and schedule EH .
*
* LOCKING :
* spin_lock_irqsave ( host_set lock )
*
* RETURNS :
* Number of aborted qc ' s .
*/
int ata_port_abort(struct ata_port *ap)
{
return ata_do_link_abort(ap, NULL);
}
EXPORT_SYMBOL_GPL(ata_port_abort);
/**
* _ _ ata_port_freeze - freeze port
* @ ap : ATA port to freeze
*
* This function is called when HSM violation or some other
* condition disrupts normal operation of the port . Frozen port
* is not allowed to perform any operation until the port is
* thawed , which usually follows a successful reset .
*
* ap - > ops - > freeze ( ) callback can be used for freezing the port
* hardware - wise ( e . g . mask interrupt and stop DMA engine ) . If a
* port cannot be frozen hardware - wise , the interrupt handler
* must ack and clear interrupts unconditionally while the port
* is frozen .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*/
static void __ata_port_freeze(struct ata_port *ap)
{
if (ap->ops->freeze)
ap->ops->freeze(ap);
ap->pflags |= ATA_PFLAG_FROZEN;
trace_ata_port_freeze(ap);
}
/**
* ata_port_freeze - abort & freeze port
* @ ap : ATA port to freeze
*
* Abort and freeze @ ap . The freeze operation must be called
* first , because some hardware requires special operations
* before the taskfile registers are accessible .
*
* LOCKING :
* spin_lock_irqsave ( host lock )
*
* RETURNS :
* Number of aborted commands .
*/
int ata_port_freeze(struct ata_port *ap)
{
__ata_port_freeze(ap);
return ata_port_abort(ap);
}
EXPORT_SYMBOL_GPL(ata_port_freeze);
/**
* ata_eh_freeze_port - EH helper to freeze port
* @ ap : ATA port to freeze
*
* Freeze @ ap .
*
* LOCKING :
* None .
*/
void ata_eh_freeze_port(struct ata_port *ap)
{
unsigned long flags;
spin_lock_irqsave(ap->lock, flags);
__ata_port_freeze(ap);
spin_unlock_irqrestore(ap->lock, flags);
}
EXPORT_SYMBOL_GPL(ata_eh_freeze_port);
/**
* ata_eh_thaw_port - EH helper to thaw port
* @ ap : ATA port to thaw
*
* Thaw frozen port @ ap .
*
* LOCKING :
* None .
*/
void ata_eh_thaw_port(struct ata_port *ap)
{
unsigned long flags;
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_FROZEN;
if (ap->ops->thaw)
ap->ops->thaw(ap);
spin_unlock_irqrestore(ap->lock, flags);
trace_ata_port_thaw(ap);
}
static void ata_eh_scsidone(struct scsi_cmnd *scmd)
{
/* nada */
}
static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scsi_cmnd *scmd = qc->scsicmd;
unsigned long flags;
spin_lock_irqsave(ap->lock, flags);
qc->scsidone = ata_eh_scsidone;
__ata_qc_complete(qc);
WARN_ON(ata_tag_valid(qc->tag));
spin_unlock_irqrestore(ap->lock, flags);
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
}
/**
* ata_eh_qc_complete - Complete an active ATA command from EH
* @ qc : Command to complete
*
* Indicate to the mid and upper layers that an ATA command has
* completed . To be used from EH .
*/
void ata_eh_qc_complete(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
scmd->retries = scmd->allowed;
__ata_eh_qc_complete(qc);
}
/**
* ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
* @ qc : Command to retry
*
* Indicate to the mid and upper layers that an ATA command
* should be retried . To be used from EH .
*
* SCSI midlayer limits the number of retries to scmd - > allowed .
* scmd - > allowed is incremented for commands which get retried
* due to unrelated failures ( qc - > err_mask is zero ) .
*/
void ata_eh_qc_retry(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
if (!qc->err_mask)
scmd->allowed++;
__ata_eh_qc_complete(qc);
}
/**
* ata_dev_disable - disable ATA device
* @ dev : ATA device to disable
*
* Disable @ dev .
*
* Locking :
* EH context .
*/
void ata_dev_disable(struct ata_device *dev)
{
if (!ata_dev_enabled(dev))
return ;
ata_dev_warn(dev, "disable device\n" );
ata_eh_dev_disable(dev);
}
EXPORT_SYMBOL_GPL(ata_dev_disable);
/**
* ata_eh_detach_dev - detach ATA device
* @ dev : ATA device to detach
*
* Detach @ dev .
*
* LOCKING :
* None .
*/
void ata_eh_detach_dev(struct ata_device *dev)
{
struct ata_link *link = dev->link;
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
unsigned long flags;
/*
* If the device is still enabled , transition it to standby power mode
* ( i . e . spin down HDDs ) and disable it .
*/
if (ata_dev_enabled(dev)) {
ata_dev_power_set_standby(dev);
ata_eh_dev_disable(dev);
}
spin_lock_irqsave(ap->lock, flags);
dev->flags &= ~ATA_DFLAG_DETACH;
if (ata_scsi_offline_dev(dev)) {
dev->flags |= ATA_DFLAG_DETACHED;
ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
}
/* clear per-dev EH info */
ata_eh_clear_action(link, dev, &link->eh_info, ATA_EH_PERDEV_MASK);
ata_eh_clear_action(link, dev, &link->eh_context.i, ATA_EH_PERDEV_MASK);
ehc->saved_xfer_mode[dev->devno] = 0 ;
ehc->saved_ncq_enabled &= ~(1 << dev->devno);
spin_unlock_irqrestore(ap->lock, flags);
}
/**
* ata_eh_about_to_do - about to perform eh_action
* @ link : target ATA link
* @ dev : target ATA dev for per - dev action ( can be NULL )
* @ action : action about to be performed
*
* Called just before performing EH actions to clear related bits
* in @ link - > eh_info such that eh actions are not unnecessarily
* repeated .
*
* LOCKING :
* None .
*/
void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
unsigned int action)
{
struct ata_port *ap = link->ap;
struct ata_eh_info *ehi = &link->eh_info;
struct ata_eh_context *ehc = &link->eh_context;
unsigned long flags;
trace_ata_eh_about_to_do(link, dev ? dev->devno : 0 , action);
spin_lock_irqsave(ap->lock, flags);
ata_eh_clear_action(link, dev, ehi, action);
/* About to take EH action, set RECOVERED. Ignore actions on
* slave links as master will do them again .
*/
if (!(ehc->i.flags & ATA_EHI_QUIET) && link != ap->slave_link)
ap->pflags |= ATA_PFLAG_RECOVERED;
spin_unlock_irqrestore(ap->lock, flags);
}
/**
* ata_eh_done - EH action complete
* @ link : ATA link for which EH actions are complete
* @ dev : target ATA dev for per - dev action ( can be NULL )
* @ action : action just completed
*
* Called right after performing EH actions to clear related bits
* in @ link - > eh_context .
*
* LOCKING :
* None .
*/
void ata_eh_done(struct ata_link *link, struct ata_device *dev,
unsigned int action)
{
struct ata_eh_context *ehc = &link->eh_context;
trace_ata_eh_done(link, dev ? dev->devno : 0 , action);
ata_eh_clear_action(link, dev, &ehc->i, action);
}
/**
* ata_err_string - convert err_mask to descriptive string
* @ err_mask : error mask to convert to string
*
* Convert @ err_mask to descriptive string . Errors are
* prioritized according to severity and only the most severe
* error is reported .
*
* LOCKING :
* None .
*
* RETURNS :
* Descriptive string for @ err_mask
*/
static const char *ata_err_string(unsigned int err_mask)
{
if (err_mask & AC_ERR_HOST_BUS)
return "host bus error" ;
if (err_mask & AC_ERR_ATA_BUS)
return "ATA bus error" ;
if (err_mask & AC_ERR_TIMEOUT)
return "timeout" ;
if (err_mask & AC_ERR_HSM)
return "HSM violation" ;
if (err_mask & AC_ERR_SYSTEM)
return "internal error" ;
if (err_mask & AC_ERR_MEDIA)
return "media error" ;
if (err_mask & AC_ERR_INVALID)
return "invalid argument" ;
if (err_mask & AC_ERR_DEV)
return "device error" ;
if (err_mask & AC_ERR_NCQ)
return "NCQ error" ;
if (err_mask & AC_ERR_NODEV_HINT)
return "Polling detection error" ;
return "unknown error" ;
}
/**
* atapi_eh_tur - perform ATAPI TEST_UNIT_READY
* @ dev : target ATAPI device
* @ r_sense_key : out parameter for sense_key
*
* Perform ATAPI TEST_UNIT_READY .
*
* LOCKING :
* EH context ( may sleep ) .
*
* RETURNS :
* 0 on success , AC_ERR_ * mask on failure .
*/
unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)
{
u8 cdb[ATAPI_CDB_LEN] = { TEST_UNIT_READY, 0 , 0 , 0 , 0 , 0 };
struct ata_taskfile tf;
unsigned int err_mask;
ata_tf_init(dev, &tf);
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf.command = ATA_CMD_PACKET;
tf.protocol = ATAPI_PROT_NODATA;
err_mask = ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0 , 0 );
if (err_mask == AC_ERR_DEV)
*r_sense_key = tf.error >> 4 ;
return err_mask;
}
/**
* ata_eh_decide_disposition - Disposition a qc based on sense data
* @ qc : qc to examine
*
* For a regular SCSI command , the SCSI completion callback ( scsi_done ( ) )
* will call scsi_complete ( ) , which will call scsi_decide_disposition ( ) ,
* which will call scsi_check_sense ( ) . scsi_complete ( ) finally calls
* scsi_finish_command ( ) . This is fine for SCSI , since any eventual sense
* data is usually returned in the completion itself ( without invoking SCSI
* EH ) . However , for a QC , we always need to fetch the sense data
* explicitly using SCSI EH .
*
* A command that is completed via SCSI EH will instead be completed using
* scsi_eh_flush_done_q ( ) , which will call scsi_finish_command ( ) directly
* ( without ever calling scsi_check_sense ( ) ) .
*
* For a command that went through SCSI EH , it is the responsibility of the
* SCSI EH strategy handler to call scsi_decide_disposition ( ) , see e . g . how
* scsi_eh_get_sense ( ) calls scsi_decide_disposition ( ) for SCSI LLDDs that
* do not get the sense data as part of the completion .
*
* Thus , for QC commands that went via SCSI EH , we need to call
* scsi_check_sense ( ) ourselves , similar to how scsi_eh_get_sense ( ) calls
* scsi_decide_disposition ( ) , which calls scsi_check_sense ( ) , in order to
* set the correct SCSI ML byte ( if any ) .
*
* LOCKING :
* EH context .
*
* RETURNS :
* SUCCESS or FAILED or NEEDS_RETRY or ADD_TO_MLQUEUE
*/
enum scsi_disposition ata_eh_decide_disposition(struct ata_queued_cmd *qc)
{
return scsi_check_sense(qc->scsicmd);
}
/**
* ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT
* @ qc : qc to perform REQUEST_SENSE_SENSE_DATA_EXT to
*
* Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK
* SENSE . This function is an EH helper .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*
* RETURNS :
* true if sense data could be fetched , false otherwise .
*/
static bool ata_eh_request_sense(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *cmd = qc->scsicmd;
struct ata_device *dev = qc->dev;
struct ata_taskfile tf;
unsigned int err_mask;
if (ata_port_is_frozen(qc->ap)) {
ata_dev_warn(dev, "sense data available but port frozen\n" );
return false ;
}
if (!ata_id_sense_reporting_enabled(dev->id)) {
ata_dev_warn(qc->dev, "sense data reporting disabled\n" );
return false ;
}
ata_tf_init(dev, &tf);
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
tf.command = ATA_CMD_REQ_SENSE_DATA;
tf.protocol = ATA_PROT_NODATA;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0 , 0 );
/* Ignore err_mask; ATA_ERR might be set */
if (tf.status & ATA_SENSE) {
if (ata_scsi_sense_is_valid(tf.lbah, tf.lbam, tf.lbal)) {
/* Set sense without also setting scsicmd->result */
scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE,
cmd->sense_buffer, tf.lbah,
tf.lbam, tf.lbal);
qc->flags |= ATA_QCFLAG_SENSE_VALID;
return true ;
}
} else {
ata_dev_warn(dev, "request sense failed stat %02x emask %x\n" ,
tf.status, err_mask);
}
return false ;
}
/**
* atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
* @ dev : device to perform REQUEST_SENSE to
* @ sense_buf : result sense data buffer ( SCSI_SENSE_BUFFERSIZE bytes long )
* @ dfl_sense_key : default sense key to use
*
* Perform ATAPI REQUEST_SENSE after the device reported CHECK
* SENSE . This function is EH helper .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*
* RETURNS :
* 0 on success , AC_ERR_ * mask on failure
*/
unsigned int atapi_eh_request_sense(struct ata_device *dev,
u8 *sense_buf, u8 dfl_sense_key)
{
u8 cdb[ATAPI_CDB_LEN] =
{ REQUEST_SENSE, 0 , 0 , 0 , SCSI_SENSE_BUFFERSIZE, 0 };
struct ata_port *ap = dev->link->ap;
struct ata_taskfile tf;
memset(sense_buf, 0 , SCSI_SENSE_BUFFERSIZE);
/* initialize sense_buf with the error register,
* for the case where they are - not - overwritten
*/
sense_buf[0 ] = 0 x70;
sense_buf[2 ] = dfl_sense_key;
/* some devices time out if garbage left in tf */
ata_tf_init(dev, &tf);
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf.command = ATA_CMD_PACKET;
/*
* Do not use DMA if the connected device only supports PIO , even if the
* port prefers PIO commands via DMA .
*
* Ideally , we should call atapi_check_dma ( ) to check if it is safe for
* the LLD to use DMA for REQUEST_SENSE , but we don ' t have a qc .
* Since we can ' t check the command , perhaps we should only use pio ?
*/
if ((ap->flags & ATA_FLAG_PIO_DMA) && !(dev->flags & ATA_DFLAG_PIO)) {
tf.protocol = ATAPI_PROT_DMA;
tf.feature |= ATAPI_PKT_DMA;
} else {
tf.protocol = ATAPI_PROT_PIO;
tf.lbam = SCSI_SENSE_BUFFERSIZE;
tf.lbah = 0 ;
}
return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
sense_buf, SCSI_SENSE_BUFFERSIZE, 0 );
}
/**
* ata_eh_analyze_serror - analyze SError for a failed port
* @ link : ATA link to analyze SError for
*
* Analyze SError if available and further determine cause of
* failure .
*
* LOCKING :
* None .
*/
static void ata_eh_analyze_serror(struct ata_link *link)
{
struct ata_eh_context *ehc = &link->eh_context;
u32 serror = ehc->i.serror;
unsigned int err_mask = 0 , action = 0 ;
u32 hotplug_mask;
if (serror & (SERR_PERSISTENT | SERR_DATA)) {
err_mask |= AC_ERR_ATA_BUS;
action |= ATA_EH_RESET;
}
if (serror & SERR_PROTOCOL) {
err_mask |= AC_ERR_HSM;
action |= ATA_EH_RESET;
}
if (serror & SERR_INTERNAL) {
err_mask |= AC_ERR_SYSTEM;
action |= ATA_EH_RESET;
}
/* Determine whether a hotplug event has occurred. Both
* SError . N / X are considered hotplug events for enabled or
* host links . For disabled PMP links , only N bit is
* considered as X bit is left at 1 for link plugging .
*/
if (link->lpm_policy > ATA_LPM_MAX_POWER)
hotplug_mask = 0 ; /* hotplug doesn't work w/ LPM */
else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG;
else
hotplug_mask = SERR_PHYRDY_CHG;
if (serror & hotplug_mask)
ata_ehi_hotplugged(&ehc->i);
ehc->i.err_mask |= err_mask;
ehc->i.action |= action;
}
/**
* ata_eh_analyze_tf - analyze taskfile of a failed qc
* @ qc : qc to analyze
*
* Analyze taskfile of @ qc and further determine cause of
* failure . This function also requests ATAPI sense data if
* available .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*
* RETURNS :
* Determined recovery action
*/
static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc)
{
const struct ata_taskfile *tf = &qc->result_tf;
unsigned int tmp, action = 0 ;
u8 stat = tf->status, err = tf->error;
if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
qc->err_mask |= AC_ERR_HSM;
return ATA_EH_RESET;
}
if (stat & (ATA_ERR | ATA_DF)) {
qc->err_mask |= AC_ERR_DEV;
/*
* Sense data reporting does not work if the
* device fault bit is set .
*/
if (stat & ATA_DF)
stat &= ~ATA_SENSE;
} else {
return 0 ;
}
switch (qc->dev->class ) {
case ATA_DEV_ATA:
case ATA_DEV_ZAC:
/*
* Fetch the sense data explicitly if :
* - It was a non - NCQ command that failed , or
* - It was a NCQ command that failed , but the sense data
* was not included in the NCQ command error log
* ( i . e . NCQ autosense is not supported by the device ) .
*/
if (!(qc->flags & ATA_QCFLAG_SENSE_VALID) &&
(stat & ATA_SENSE) && ata_eh_request_sense(qc))
set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION);
if (err & ATA_ICRC)
qc->err_mask |= AC_ERR_ATA_BUS;
if (err & (ATA_UNC | ATA_AMNF))
qc->err_mask |= AC_ERR_MEDIA;
if (err & ATA_IDNF)
qc->err_mask |= AC_ERR_INVALID;
break ;
case ATA_DEV_ATAPI:
if (!ata_port_is_frozen(qc->ap)) {
tmp = atapi_eh_request_sense(qc->dev,
qc->scsicmd->sense_buffer,
qc->result_tf.error >> 4 );
if (!tmp)
qc->flags |= ATA_QCFLAG_SENSE_VALID;
else
qc->err_mask |= tmp;
}
}
if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
enum scsi_disposition ret = ata_eh_decide_disposition(qc);
/*
* SUCCESS here means that the sense code could be
* evaluated and should be passed to the upper layers
* for correct evaluation .
* FAILED means the sense code could not be interpreted
* and the device would need to be reset .
* NEEDS_RETRY and ADD_TO_MLQUEUE means that the
* command would need to be retried .
*/
if (ret == NEEDS_RETRY || ret == ADD_TO_MLQUEUE) {
qc->flags |= ATA_QCFLAG_RETRY;
qc->err_mask |= AC_ERR_OTHER;
} else if (ret != SUCCESS) {
qc->err_mask |= AC_ERR_HSM;
}
}
if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
action |= ATA_EH_RESET;
return action;
}
static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask,
int *xfer_ok)
{
int base = 0 ;
if (!(eflags & ATA_EFLAG_DUBIOUS_XFER))
*xfer_ok = 1 ;
if (!*xfer_ok)
base = ATA_ECAT_DUBIOUS_NONE;
if (err_mask & AC_ERR_ATA_BUS)
return base + ATA_ECAT_ATA_BUS;
if (err_mask & AC_ERR_TIMEOUT)
return base + ATA_ECAT_TOUT_HSM;
if (eflags & ATA_EFLAG_IS_IO) {
if (err_mask & AC_ERR_HSM)
return base + ATA_ECAT_TOUT_HSM;
if ((err_mask &
(AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
return base + ATA_ECAT_UNK_DEV;
}
return 0 ;
}
struct speed_down_verdict_arg {
u64 since;
int xfer_ok;
int nr_errors[ATA_ECAT_NR];
};
static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
{
struct speed_down_verdict_arg *arg = void_arg;
int cat;
if ((ent->eflags & ATA_EFLAG_OLD_ER) || (ent->timestamp < arg->since))
return -1 ;
cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
&arg->xfer_ok);
arg->nr_errors[cat]++;
return 0 ;
}
/**
* ata_eh_speed_down_verdict - Determine speed down verdict
* @ dev : Device of interest
*
* This function examines error ring of @ dev and determines
* whether NCQ needs to be turned off , transfer speed should be
* stepped down , or falling back to PIO is necessary .
*
* ECAT_ATA_BUS : ATA_BUS error for any command
*
* ECAT_TOUT_HSM : TIMEOUT for any command or HSM violation for
* IO commands
*
* ECAT_UNK_DEV : Unknown DEV error for IO commands
*
* ECAT_DUBIOUS_ * : Identical to above three but occurred while
* data transfer hasn ' t been verified .
*
* Verdicts are
*
* NCQ_OFF : Turn off NCQ .
*
* SPEED_DOWN : Speed down transfer speed but don ' t fall back
* to PIO .
*
* FALLBACK_TO_PIO : Fall back to PIO .
*
* Even if multiple verdicts are returned , only one action is
* taken per error . An action triggered by non - DUBIOUS errors
* clears ering , while one triggered by DUBIOUS_ * errors doesn ' t .
* This is to expedite speed down decisions right after device is
* initially configured .
*
* The following are speed down rules . # 1 and # 2 deal with
* DUBIOUS errors .
*
* 1 . If more than one DUBIOUS_ATA_BUS or DUBIOUS_TOUT_HSM errors
* occurred during last 5 mins , SPEED_DOWN and FALLBACK_TO_PIO .
*
* 2 . If more than one DUBIOUS_TOUT_HSM or DUBIOUS_UNK_DEV errors
* occurred during last 5 mins , NCQ_OFF .
*
* 3 . If more than 8 ATA_BUS , TOUT_HSM or UNK_DEV errors
* occurred during last 5 mins , FALLBACK_TO_PIO
*
* 4 . If more than 3 TOUT_HSM or UNK_DEV errors occurred
* during last 10 mins , NCQ_OFF .
*
* 5 . If more than 3 ATA_BUS or TOUT_HSM errors , or more than 6
* UNK_DEV errors occurred during last 10 mins , SPEED_DOWN .
*
* LOCKING :
* Inherited from caller .
*
* RETURNS :
* OR of ATA_EH_SPDN_ * flags .
*/
static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
{
const u64 j5mins = 5 LLU * 60 * HZ, j10mins = 10 LLU * 60 * HZ;
u64 j64 = get_jiffies_64();
struct speed_down_verdict_arg arg;
unsigned int verdict = 0 ;
/* scan past 5 mins of error history */
memset(&arg, 0 , sizeof (arg));
arg.since = j64 - min(j64, j5mins);
ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
if (arg.nr_errors[ATA_ECAT_DUBIOUS_ATA_BUS] +
arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] > 1 )
verdict |= ATA_EH_SPDN_SPEED_DOWN |
ATA_EH_SPDN_FALLBACK_TO_PIO | ATA_EH_SPDN_KEEP_ERRORS;
if (arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] +
arg.nr_errors[ATA_ECAT_DUBIOUS_UNK_DEV] > 1 )
verdict |= ATA_EH_SPDN_NCQ_OFF | ATA_EH_SPDN_KEEP_ERRORS;
if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
arg.nr_errors[ATA_ECAT_TOUT_HSM] +
arg.nr_errors[ATA_ECAT_UNK_DEV] > 6 )
verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
/* scan past 10 mins of error history */
memset(&arg, 0 , sizeof (arg));
arg.since = j64 - min(j64, j10mins);
ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
if (arg.nr_errors[ATA_ECAT_TOUT_HSM] +
arg.nr_errors[ATA_ECAT_UNK_DEV] > 3 )
verdict |= ATA_EH_SPDN_NCQ_OFF;
if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
arg.nr_errors[ATA_ECAT_TOUT_HSM] > 3 ||
arg.nr_errors[ATA_ECAT_UNK_DEV] > 6 )
verdict |= ATA_EH_SPDN_SPEED_DOWN;
return verdict;
}
/**
* ata_eh_speed_down - record error and speed down if necessary
* @ dev : Failed device
* @ eflags : mask of ATA_EFLAG_ * flags
* @ err_mask : err_mask of the error
*
* Record error and examine error history to determine whether
* adjusting transmission speed is necessary . It also sets
* transmission limits appropriately if such adjustment is
* necessary .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*
* RETURNS :
* Determined recovery action .
*/
static unsigned int ata_eh_speed_down(struct ata_device *dev,
unsigned int eflags, unsigned int err_mask)
{
struct ata_link *link = ata_dev_phys_link(dev);
int xfer_ok = 0 ;
unsigned int verdict;
unsigned int action = 0 ;
/* don't bother if Cat-0 error */
if (ata_eh_categorize_error(eflags, err_mask, &xfer_ok) == 0 )
return 0 ;
/* record error and determine whether speed down is necessary */
ata_ering_record(&dev->ering, eflags, err_mask);
verdict = ata_eh_speed_down_verdict(dev);
/* turn off NCQ? */
if ((verdict & ATA_EH_SPDN_NCQ_OFF) && ata_ncq_enabled(dev)) {
dev->flags |= ATA_DFLAG_NCQ_OFF;
ata_dev_warn(dev, "NCQ disabled due to excessive errors\n" );
goto done;
}
/* speed down? */
if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
/* speed down SATA link speed if possible */
if (sata_down_spd_limit(link, 0 ) == 0 ) {
action |= ATA_EH_RESET;
goto done;
}
/* lower transfer mode */
if (dev->spdn_cnt < 2 ) {
static const int dma_dnxfer_sel[] =
{ ATA_DNXFER_DMA, ATA_DNXFER_40C };
static const int pio_dnxfer_sel[] =
{ ATA_DNXFER_PIO, ATA_DNXFER_FORCE_PIO0 };
int sel;
if (dev->xfer_shift != ATA_SHIFT_PIO)
sel = dma_dnxfer_sel[dev->spdn_cnt];
else
sel = pio_dnxfer_sel[dev->spdn_cnt];
dev->spdn_cnt++;
if (ata_down_xfermask_limit(dev, sel) == 0 ) {
action |= ATA_EH_RESET;
goto done;
}
}
}
/* Fall back to PIO? Slowing down to PIO is meaningless for
* SATA ATA devices . Consider it only for PATA and SATAPI .
*/
if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2 ) &&
(link->ap->cbl != ATA_CBL_SATA || dev->class == ATA_DEV_ATAPI) &&
(dev->xfer_shift != ATA_SHIFT_PIO)) {
if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0 ) {
dev->spdn_cnt = 0 ;
action |= ATA_EH_RESET;
goto done;
}
}
return 0 ;
done:
/* device has been slowed down, blow error history */
if (!(verdict & ATA_EH_SPDN_KEEP_ERRORS))
ata_ering_clear(&dev->ering);
return action;
}
/**
* ata_eh_worth_retry - analyze error and decide whether to retry
* @ qc : qc to possibly retry
*
* Look at the cause of the error and decide if a retry
* might be useful or not . We don ' t want to retry media errors
* because the drive itself has probably already taken 10 - 30 seconds
* doing its own internal retries before reporting the failure .
*/
static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc)
{
if (qc->err_mask & AC_ERR_MEDIA)
return 0 ; /* don't retry media errors */
if (qc->flags & ATA_QCFLAG_IO)
return 1 ; /* otherwise retry anything from fs stack */
if (qc->err_mask & AC_ERR_INVALID)
return 0 ; /* don't retry these */
return qc->err_mask != AC_ERR_DEV; /* retry if not dev error */
}
/**
* ata_eh_quiet - check if we need to be quiet about a command error
* @ qc : qc to check
*
* Look at the qc flags anbd its scsi command request flags to determine
* if we need to be quiet about the command failure .
*/
static inline bool ata_eh_quiet(struct ata_queued_cmd *qc)
{
if (qc->scsicmd && scsi_cmd_to_rq(qc->scsicmd)->rq_flags & RQF_QUIET)
qc->flags |= ATA_QCFLAG_QUIET;
return qc->flags & ATA_QCFLAG_QUIET;
}
static int ata_eh_get_non_ncq_success_sense(struct ata_link *link)
{
struct ata_port *ap = link->ap;
struct ata_queued_cmd *qc;
qc = __ata_qc_from_tag(ap, link->active_tag);
if (!qc)
return -EIO;
if (!(qc->flags & ATA_QCFLAG_EH) ||
!(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) ||
qc->err_mask)
return -EIO;
if (!ata_eh_request_sense(qc))
return -EIO;
/*
* No point in checking the return value , since the command has already
* completed successfully .
*/
ata_eh_decide_disposition(qc);
return 0 ;
}
static void ata_eh_get_success_sense(struct ata_link *link)
{
struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev = link->device;
struct ata_port *ap = link->ap;
struct ata_queued_cmd *qc;
int tag, ret = 0 ;
if (!(ehc->i.dev_action[dev->devno] & ATA_EH_GET_SUCCESS_SENSE))
return ;
/* if frozen, we can't do much */
if (ata_port_is_frozen(ap)) {
ata_dev_warn(dev,
"successful sense data available but port frozen\n" );
goto out;
}
/*
* If the link has sactive set , then we have outstanding NCQ commands
* and have to read the Successful NCQ Commands log to get the sense
* data . Otherwise , we are dealing with a non - NCQ command and use
* request sense ext command to retrieve the sense data .
*/
if (link->sactive)
ret = ata_eh_get_ncq_success_sense(link);
else
ret = ata_eh_get_non_ncq_success_sense(link);
if (ret)
goto out;
ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE);
return ;
out:
/*
* If we failed to get sense data for a successful command that ought to
* have sense data , we cannot simply return BLK_STS_OK to user space .
* This is because we can ' t know if the sense data that we couldn ' t get
* was actually " DATA CURRENTLY UNAVAILABLE " . Reporting such a command
* as success to user space would result in a silent data corruption .
* Thus , add a bogus ABORTED_COMMAND sense data to such commands , such
* that SCSI will report these commands as BLK_STS_IOERR to user space .
*/
ata_qc_for_each_raw(ap, qc, tag) {
if (!(qc->flags & ATA_QCFLAG_EH) ||
!(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) ||
qc->err_mask ||
ata_dev_phys_link(qc->dev) != link)
continue ;
/* We managed to get sense for this success command, skip. */
if (qc->flags & ATA_QCFLAG_SENSE_VALID)
continue ;
/* This success command did not have any sense data, skip. */
if (!(qc->result_tf.status & ATA_SENSE))
continue ;
/* This success command had sense data, but we failed to get. */
ata_scsi_set_sense(dev, qc->scsicmd, ABORTED_COMMAND, 0 , 0 );
qc->flags |= ATA_QCFLAG_SENSE_VALID;
}
ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE);
}
/*
* Check if a link is established . This is a relaxed version of
* ata_phys_link_online ( ) which accounts for the fact that this is potentially
* called after changing the link power management policy , which may not be
* reflected immediately in the SStatus register ( e . g . , we may still be seeing
* the PHY in partial , slumber or devsleep Partial power management state .
* So check that :
* - A device is still present , that is , DET is 1 h ( Device presence detected
* but Phy communication not established ) or 3 h ( Device presence detected and
* Phy communication established )
* - Communication is established , that is , IPM is not 0 h , indicating that PHY
* is online or in a low power state .
*/
static bool ata_eh_link_established(struct ata_link *link)
{
u32 sstatus;
u8 det, ipm;
/*
* For old IDE / PATA adapters that do not have a valid scr_read method ,
* or if reading the SStatus register fails , assume that the device is
* present . Device probe will determine if that is really the case .
*/
if (sata_scr_read(link, SCR_STATUS, &sstatus))
return true ;
det = sstatus & 0 x0f;
ipm = (sstatus >> 8 ) & 0 x0f;
return (det & 0 x01) && ipm;
}
/**
* ata_eh_link_set_lpm - configure SATA interface power management
* @ link : link to configure
* @ policy : the link power management policy
* @ r_failed_dev : out parameter for failed device
*
* Enable SATA Interface power management . This will enable
* Device Interface Power Management ( DIPM ) for min_power and
* medium_power_with_dipm policies , and then call driver specific
* callbacks for enabling Host Initiated Power management .
*
* LOCKING :
* EH context .
*
* RETURNS :
* 0 on success , - errno on failure .
*/
static int ata_eh_link_set_lpm(struct ata_link *link,
enum ata_lpm_policy policy,
struct ata_device **r_failed_dev)
{
struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
enum ata_lpm_policy old_policy = link->lpm_policy;
bool host_has_dipm = !(link->ap->flags & ATA_FLAG_NO_DIPM);
unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
unsigned int err_mask;
int rc;
/* if the link or host doesn't do LPM, noop */
if (!IS_ENABLED(CONFIG_SATA_HOST) ||
(link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm))
return 0 ;
/*
* This function currently assumes that it will never be supplied policy
* ATA_LPM_UNKNOWN .
*/
if (WARN_ON_ONCE(policy == ATA_LPM_UNKNOWN))
return 0 ;
ata_link_dbg(link, "Set LPM policy: %d -> %d\n" , old_policy, policy);
/*
* DIPM is enabled only for ATA_LPM_MIN_POWER ,
* ATA_LPM_MIN_POWER_WITH_PARTIAL , and ATA_LPM_MED_POWER_WITH_DIPM , as
* some devices misbehave when the host NACKs transition to SLUMBER .
*/
ata_for_each_dev(dev, link, ENABLED) {
bool dev_has_hipm = ata_id_has_hipm(dev->id);
bool dev_has_dipm = ata_id_has_dipm(dev->id);
/* find the first enabled and LPM enabled devices */
if (!link_dev)
link_dev = dev;
if (!lpm_dev &&
(dev_has_hipm || (dev_has_dipm && host_has_dipm)))
lpm_dev = dev;
hints &= ~ATA_LPM_EMPTY;
if (!dev_has_hipm)
hints &= ~ATA_LPM_HIPM;
/* disable DIPM before changing link config */
if (dev_has_dipm) {
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_DISABLE, SATA_DIPM);
if (err_mask && err_mask != AC_ERR_DEV) {
ata_dev_warn(dev,
"failed to disable DIPM, Emask 0x%x\n" ,
err_mask);
rc = -EIO;
goto fail;
}
}
}
if (ap) {
rc = ap->ops->set_lpm(link, policy, hints);
if (!rc && ap->slave_link)
rc = ap->ops->set_lpm(ap->slave_link, policy, hints);
} else
rc = sata_pmp_set_lpm(link, policy, hints);
/*
* Attribute link config failure to the first ( LPM ) enabled
* device on the link .
*/
if (rc) {
if (rc == -EOPNOTSUPP) {
link->flags |= ATA_LFLAG_NO_LPM;
return 0 ;
}
dev = lpm_dev ? lpm_dev : link_dev;
goto fail;
}
/*
* Low level driver acked the transition . Issue DIPM command
* with the new policy set .
*/
link->lpm_policy = policy;
if (ap && ap->slave_link)
ap->slave_link->lpm_policy = policy;
/*
* Host config updated , enable DIPM if transitioning to
* ATA_LPM_MIN_POWER , ATA_LPM_MIN_POWER_WITH_PARTIAL , or
* ATA_LPM_MED_POWER_WITH_DIPM .
*/
ata_for_each_dev(dev, link, ENABLED) {
bool dev_has_dipm = ata_id_has_dipm(dev->id);
if (policy >= ATA_LPM_MED_POWER_WITH_DIPM && host_has_dipm &&
dev_has_dipm) {
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_ENABLE, SATA_DIPM);
if (err_mask && err_mask != AC_ERR_DEV) {
ata_dev_warn(dev,
"failed to enable DIPM, Emask 0x%x\n" ,
err_mask);
rc = -EIO;
goto fail;
}
}
}
link->last_lpm_change = jiffies;
link->flags |= ATA_LFLAG_CHANGED;
return 0 ;
fail:
/* restore the old policy */
link->lpm_policy = old_policy;
if (ap && ap->slave_link)
ap->slave_link->lpm_policy = old_policy;
/* if no device or only one more chance is left, disable LPM */
if (!dev || ehc->tries[dev->devno] <= 2 ) {
ata_link_warn(link, "disabling LPM on the link\n" );
link->flags |= ATA_LFLAG_NO_LPM;
}
if (r_failed_dev)
*r_failed_dev = dev;
return rc;
}
/**
* ata_eh_link_autopsy - analyze error and determine recovery action
* @ link : host link to perform autopsy on
*
* Analyze why @ link failed and determine which recovery actions
* are needed . This function also sets more detailed AC_ERR_ *
* values and fills sense data for ATAPI CHECK SENSE .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*/
static void ata_eh_link_autopsy(struct ata_link *link)
{
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
struct ata_queued_cmd *qc;
struct ata_device *dev;
unsigned int all_err_mask = 0 , eflags = 0 ;
int tag, nr_failed = 0 , nr_quiet = 0 ;
u32 serror;
int rc;
if (ehc->i.flags & ATA_EHI_NO_AUTOPSY)
return ;
/* obtain and analyze SError */
rc = sata_scr_read(link, SCR_ERROR, &serror);
if (rc == 0 ) {
ehc->i.serror |= serror;
ata_eh_analyze_serror(link);
} else if (rc != -EOPNOTSUPP) {
/* SError read failed, force reset and probing */
ehc->i.probe_mask |= ATA_ALL_DEVICES;
ehc->i.action |= ATA_EH_RESET;
ehc->i.err_mask |= AC_ERR_OTHER;
}
/* analyze NCQ failure */
ata_eh_analyze_ncq_error(link);
/*
* Check if this was a successful command that simply needs sense data .
* Since the sense data is not part of the completion , we need to fetch
* it using an additional command . Since this can ' t be done from irq
* context , the sense data for successful commands are fetched by EH .
*/
ata_eh_get_success_sense(link);
/* any real error trumps AC_ERR_OTHER */
if (ehc->i.err_mask & ~AC_ERR_OTHER)
ehc->i.err_mask &= ~AC_ERR_OTHER;
all_err_mask |= ehc->i.err_mask;
ata_qc_for_each_raw(ap, qc, tag) {
if (!(qc->flags & ATA_QCFLAG_EH) ||
qc->flags & ATA_QCFLAG_RETRY ||
qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD ||
ata_dev_phys_link(qc->dev) != link)
continue ;
/* inherit upper level err_mask */
qc->err_mask |= ehc->i.err_mask;
/* analyze TF */
ehc->i.action |= ata_eh_analyze_tf(qc);
/* DEV errors are probably spurious in case of ATA_BUS error */
if (qc->err_mask & AC_ERR_ATA_BUS)
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA |
AC_ERR_INVALID);
/* any real error trumps unknown error */
if (qc->err_mask & ~AC_ERR_OTHER)
qc->err_mask &= ~AC_ERR_OTHER;
/*
* SENSE_VALID trumps dev / unknown error and revalidation . Upper
* layers will determine whether the command is worth retrying
* based on the sense data and device class / type . Otherwise ,
* determine directly if the command is worth retrying using its
* error mask and flags .
*/
if (qc->flags & ATA_QCFLAG_SENSE_VALID)
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
else if (ata_eh_worth_retry(qc))
qc->flags |= ATA_QCFLAG_RETRY;
/* accumulate error info */
ehc->i.dev = qc->dev;
all_err_mask |= qc->err_mask;
if (qc->flags & ATA_QCFLAG_IO)
eflags |= ATA_EFLAG_IS_IO;
trace_ata_eh_link_autopsy_qc(qc);
/* Count quiet errors */
if (ata_eh_quiet(qc))
nr_quiet++;
nr_failed++;
}
/* If all failed commands requested silence, then be quiet */
if (nr_quiet == nr_failed)
ehc->i.flags |= ATA_EHI_QUIET;
/* enforce default EH actions */
if (ata_port_is_frozen(ap) ||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
ehc->i.action |= ATA_EH_RESET;
else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
(!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV)))
ehc->i.action |= ATA_EH_REVALIDATE;
/* If we have offending qcs and the associated failed device,
* perform per - dev EH action only on the offending device .
*/
if (ehc->i.dev) {
ehc->i.dev_action[ehc->i.dev->devno] |=
ehc->i.action & ATA_EH_PERDEV_MASK;
ehc->i.action &= ~ATA_EH_PERDEV_MASK;
}
/* propagate timeout to host link */
if ((all_err_mask & AC_ERR_TIMEOUT) && !ata_is_host_link(link))
ap->link.eh_context.i.err_mask |= AC_ERR_TIMEOUT;
/* record error and consider speeding down */
dev = ehc->i.dev;
if (!dev && ((ata_link_max_devices(link) == 1 &&
ata_dev_enabled(link->device))))
dev = link->device;
if (dev) {
if (dev->flags & ATA_DFLAG_DUBIOUS_XFER)
eflags |= ATA_EFLAG_DUBIOUS_XFER;
ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask);
trace_ata_eh_link_autopsy(dev, ehc->i.action, all_err_mask);
}
}
/**
* ata_eh_autopsy - analyze error and determine recovery action
* @ ap : host port to perform autopsy on
*
* Analyze all links of @ ap and determine why they failed and
* which recovery actions are needed .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*/
void ata_eh_autopsy(struct ata_port *ap)
{
struct ata_link *link;
ata_for_each_link(link, ap, EDGE)
ata_eh_link_autopsy(link);
/* Handle the frigging slave link. Autopsy is done similarly
* but actions and flags are transferred over to the master
* link and handled from there .
*/
if (ap->slave_link) {
struct ata_eh_context *mehc = &ap->link.eh_context;
struct ata_eh_context *sehc = &ap->slave_link->eh_context;
/* transfer control flags from master to slave */
sehc->i.flags |= mehc->i.flags & ATA_EHI_TO_SLAVE_MASK;
/* perform autopsy on the slave link */
ata_eh_link_autopsy(ap->slave_link);
/* transfer actions from slave to master and clear slave */
ata_eh_about_to_do(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS);
mehc->i.action |= sehc->i.action;
mehc->i.dev_action[1 ] |= sehc->i.dev_action[1 ];
mehc->i.flags |= sehc->i.flags;
ata_eh_done(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS);
}
/* Autopsy of fanout ports can affect host link autopsy.
* Perform host link autopsy last .
*/
if (sata_pmp_attached(ap))
ata_eh_link_autopsy(&ap->link);
}
/**
* ata_get_cmd_name - get name for ATA command
* @ command : ATA command code to get name for
*
* Return a textual name of the given command or " unknown "
*
* LOCKING :
* None
*/
const char *ata_get_cmd_name(u8 command)
{
#ifdef CONFIG_ATA_VERBOSE_ERROR
static const struct
{
u8 command;
const char *text;
} cmd_descr[] = {
{ ATA_CMD_DEV_RESET, "DEVICE RESET" },
{ ATA_CMD_CHK_POWER, "CHECK POWER MODE" },
{ ATA_CMD_STANDBY, "STANDBY" },
{ ATA_CMD_IDLE, "IDLE" },
{ ATA_CMD_EDD, "EXECUTE DEVICE DIAGNOSTIC" },
{ ATA_CMD_DOWNLOAD_MICRO, "DOWNLOAD MICROCODE" },
{ ATA_CMD_DOWNLOAD_MICRO_DMA, "DOWNLOAD MICROCODE DMA" },
{ ATA_CMD_NOP, "NOP" },
{ ATA_CMD_FLUSH, "FLUSH CACHE" },
{ ATA_CMD_FLUSH_EXT, "FLUSH CACHE EXT" },
{ ATA_CMD_ID_ATA, "IDENTIFY DEVICE" },
{ ATA_CMD_ID_ATAPI, "IDENTIFY PACKET DEVICE" },
{ ATA_CMD_SERVICE, "SERVICE" },
{ ATA_CMD_READ, "READ DMA" },
{ ATA_CMD_READ_EXT, "READ DMA EXT" },
{ ATA_CMD_READ_QUEUED, "READ DMA QUEUED" },
{ ATA_CMD_READ_STREAM_EXT, "READ STREAM EXT" },
{ ATA_CMD_READ_STREAM_DMA_EXT, "READ STREAM DMA EXT" },
{ ATA_CMD_WRITE, "WRITE DMA" },
{ ATA_CMD_WRITE_EXT, "WRITE DMA EXT" },
{ ATA_CMD_WRITE_QUEUED, "WRITE DMA QUEUED EXT" },
{ ATA_CMD_WRITE_STREAM_EXT, "WRITE STREAM EXT" },
{ ATA_CMD_WRITE_STREAM_DMA_EXT, "WRITE STREAM DMA EXT" },
{ ATA_CMD_WRITE_FUA_EXT, "WRITE DMA FUA EXT" },
{ ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" },
{ ATA_CMD_FPDMA_READ, "READ FPDMA QUEUED" },
{ ATA_CMD_FPDMA_WRITE, "WRITE FPDMA QUEUED" },
{ ATA_CMD_NCQ_NON_DATA, "NCQ NON-DATA" },
{ ATA_CMD_FPDMA_SEND, "SEND FPDMA QUEUED" },
{ ATA_CMD_FPDMA_RECV, "RECEIVE FPDMA QUEUED" },
{ ATA_CMD_PIO_READ, "READ SECTOR(S)" },
{ ATA_CMD_PIO_READ_EXT, "READ SECTOR(S) EXT" },
{ ATA_CMD_PIO_WRITE, "WRITE SECTOR(S)" },
{ ATA_CMD_PIO_WRITE_EXT, "WRITE SECTOR(S) EXT" },
{ ATA_CMD_READ_MULTI, "READ MULTIPLE" },
{ ATA_CMD_READ_MULTI_EXT, "READ MULTIPLE EXT" },
{ ATA_CMD_WRITE_MULTI, "WRITE MULTIPLE" },
{ ATA_CMD_WRITE_MULTI_EXT, "WRITE MULTIPLE EXT" },
{ ATA_CMD_WRITE_MULTI_FUA_EXT, "WRITE MULTIPLE FUA EXT" },
{ ATA_CMD_SET_FEATURES, "SET FEATURES" },
{ ATA_CMD_SET_MULTI, "SET MULTIPLE MODE" },
{ ATA_CMD_VERIFY, "READ VERIFY SECTOR(S)" },
{ ATA_CMD_VERIFY_EXT, "READ VERIFY SECTOR(S) EXT" },
{ ATA_CMD_WRITE_UNCORR_EXT, "WRITE UNCORRECTABLE EXT" },
{ ATA_CMD_STANDBYNOW1, "STANDBY IMMEDIATE" },
{ ATA_CMD_IDLEIMMEDIATE, "IDLE IMMEDIATE" },
{ ATA_CMD_SLEEP, "SLEEP" },
{ ATA_CMD_INIT_DEV_PARAMS, "INITIALIZE DEVICE PARAMETERS" },
{ ATA_CMD_READ_NATIVE_MAX, "READ NATIVE MAX ADDRESS" },
{ ATA_CMD_READ_NATIVE_MAX_EXT, "READ NATIVE MAX ADDRESS EXT" },
{ ATA_CMD_SET_MAX, "SET MAX ADDRESS" },
{ ATA_CMD_SET_MAX_EXT, "SET MAX ADDRESS EXT" },
{ ATA_CMD_READ_LOG_EXT, "READ LOG EXT" },
{ ATA_CMD_WRITE_LOG_EXT, "WRITE LOG EXT" },
{ ATA_CMD_READ_LOG_DMA_EXT, "READ LOG DMA EXT" },
{ ATA_CMD_WRITE_LOG_DMA_EXT, "WRITE LOG DMA EXT" },
{ ATA_CMD_TRUSTED_NONDATA, "TRUSTED NON-DATA" },
{ ATA_CMD_TRUSTED_RCV, "TRUSTED RECEIVE" },
{ ATA_CMD_TRUSTED_RCV_DMA, "TRUSTED RECEIVE DMA" },
{ ATA_CMD_TRUSTED_SND, "TRUSTED SEND" },
{ ATA_CMD_TRUSTED_SND_DMA, "TRUSTED SEND DMA" },
{ ATA_CMD_PMP_READ, "READ BUFFER" },
{ ATA_CMD_PMP_READ_DMA, "READ BUFFER DMA" },
{ ATA_CMD_PMP_WRITE, "WRITE BUFFER" },
{ ATA_CMD_PMP_WRITE_DMA, "WRITE BUFFER DMA" },
{ ATA_CMD_CONF_OVERLAY, "DEVICE CONFIGURATION OVERLAY" },
{ ATA_CMD_SEC_SET_PASS, "SECURITY SET PASSWORD" },
{ ATA_CMD_SEC_UNLOCK, "SECURITY UNLOCK" },
{ ATA_CMD_SEC_ERASE_PREP, "SECURITY ERASE PREPARE" },
{ ATA_CMD_SEC_ERASE_UNIT, "SECURITY ERASE UNIT" },
{ ATA_CMD_SEC_FREEZE_LOCK, "SECURITY FREEZE LOCK" },
{ ATA_CMD_SEC_DISABLE_PASS, "SECURITY DISABLE PASSWORD" },
{ ATA_CMD_CONFIG_STREAM, "CONFIGURE STREAM" },
{ ATA_CMD_SMART, "SMART" },
{ ATA_CMD_MEDIA_LOCK, "DOOR LOCK" },
{ ATA_CMD_MEDIA_UNLOCK, "DOOR UNLOCK" },
{ ATA_CMD_DSM, "DATA SET MANAGEMENT" },
{ ATA_CMD_CHK_MED_CRD_TYP, "CHECK MEDIA CARD TYPE" },
{ ATA_CMD_CFA_REQ_EXT_ERR, "CFA REQUEST EXTENDED ERROR" },
{ ATA_CMD_CFA_WRITE_NE, "CFA WRITE SECTORS WITHOUT ERASE" },
{ ATA_CMD_CFA_TRANS_SECT, "CFA TRANSLATE SECTOR" },
{ ATA_CMD_CFA_ERASE, "CFA ERASE SECTORS" },
{ ATA_CMD_CFA_WRITE_MULT_NE, "CFA WRITE MULTIPLE WITHOUT ERASE" },
{ ATA_CMD_REQ_SENSE_DATA, "REQUEST SENSE DATA EXT" },
{ ATA_CMD_SANITIZE_DEVICE, "SANITIZE DEVICE" },
{ ATA_CMD_ZAC_MGMT_IN, "ZAC MANAGEMENT IN" },
{ ATA_CMD_ZAC_MGMT_OUT, "ZAC MANAGEMENT OUT" },
{ ATA_CMD_READ_LONG, "READ LONG (with retries)" },
{ ATA_CMD_READ_LONG_ONCE, "READ LONG (without retries)" },
{ ATA_CMD_WRITE_LONG, "WRITE LONG (with retries)" },
{ ATA_CMD_WRITE_LONG_ONCE, "WRITE LONG (without retries)" },
{ ATA_CMD_RESTORE, "RECALIBRATE" },
{ 0 , NULL } /* terminate list */
};
unsigned int i;
for (i = 0 ; cmd_descr[i].text; i++)
if (cmd_descr[i].command == command)
return cmd_descr[i].text;
#endif
return "unknown" ;
}
EXPORT_SYMBOL_GPL(ata_get_cmd_name);
/**
* ata_eh_link_report - report error handling to user
* @ link : ATA link EH is going on
*
* Report EH to user .
*
* LOCKING :
* None .
*/
static void ata_eh_link_report(struct ata_link *link)
{
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
struct ata_queued_cmd *qc;
const char *frozen, *desc;
char tries_buf[16 ] = "" ;
int tag, nr_failed = 0 ;
if (ehc->i.flags & ATA_EHI_QUIET)
return ;
desc = NULL;
if (ehc->i.desc[0 ] != '\0' )
desc = ehc->i.desc;
ata_qc_for_each_raw(ap, qc, tag) {
if (!(qc->flags & ATA_QCFLAG_EH) ||
ata_dev_phys_link(qc->dev) != link ||
((qc->flags & ATA_QCFLAG_QUIET) &&
qc->err_mask == AC_ERR_DEV))
continue ;
if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
continue ;
nr_failed++;
}
if (!nr_failed && !ehc->i.err_mask)
return ;
frozen = "" ;
if (ata_port_is_frozen(ap))
frozen = " frozen" ;
if (ap->eh_tries < ATA_EH_MAX_TRIES)
snprintf(tries_buf, sizeof (tries_buf), " t%d" ,
ap->eh_tries);
if (ehc->i.dev) {
ata_dev_err(ehc->i.dev, "exception Emask 0x%x "
"SAct 0x%x SErr 0x%x action 0x%x%s%s\n" ,
ehc->i.err_mask, link->sactive, ehc->i.serror,
ehc->i.action, frozen, tries_buf);
if (desc)
ata_dev_err(ehc->i.dev, "%s\n" , desc);
} else {
ata_link_err(link, "exception Emask 0x%x "
"SAct 0x%x SErr 0x%x action 0x%x%s%s\n" ,
ehc->i.err_mask, link->sactive, ehc->i.serror,
ehc->i.action, frozen, tries_buf);
if (desc)
ata_link_err(link, "%s\n" , desc);
}
#ifdef CONFIG_ATA_VERBOSE_ERROR
if (ehc->i.serror)
ata_link_err(link,
"SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n" ,
ehc->i.serror & SERR_DATA_RECOVERED ? "RecovData " : "" ,
ehc->i.serror & SERR_COMM_RECOVERED ? "RecovComm " : "" ,
ehc->i.serror & SERR_DATA ? "UnrecovData " : "" ,
ehc->i.serror & SERR_PERSISTENT ? "Persist " : "" ,
ehc->i.serror & SERR_PROTOCOL ? "Proto " : "" ,
ehc->i.serror & SERR_INTERNAL ? "HostInt " : "" ,
ehc->i.serror & SERR_PHYRDY_CHG ? "PHYRdyChg " : "" ,
ehc->i.serror & SERR_PHY_INT_ERR ? "PHYInt " : "" ,
ehc->i.serror & SERR_COMM_WAKE ? "CommWake " : "" ,
ehc->i.serror & SERR_10B_8B_ERR ? "10B8B " : "" ,
ehc->i.serror & SERR_DISPARITY ? "Dispar " : "" ,
ehc->i.serror & SERR_CRC ? "BadCRC " : "" ,
ehc->i.serror & SERR_HANDSHAKE ? "Handshk " : "" ,
ehc->i.serror & SERR_LINK_SEQ_ERR ? "LinkSeq " : "" ,
ehc->i.serror & SERR_TRANS_ST_ERROR ? "TrStaTrns " : "" ,
ehc->i.serror & SERR_UNRECOG_FIS ? "UnrecFIS " : "" ,
ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "" );
#endif
ata_qc_for_each_raw(ap, qc, tag) {
struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf;
char data_buf[20 ] = "" ;
char cdb_buf[70 ] = "" ;
if (!(qc->flags & ATA_QCFLAG_EH) ||
ata_dev_phys_link(qc->dev) != link || !qc->err_mask)
continue ;
if (qc->dma_dir != DMA_NONE) {
static const char *dma_str[] = {
[DMA_BIDIRECTIONAL] = "bidi" ,
[DMA_TO_DEVICE] = "out" ,
[DMA_FROM_DEVICE] = "in" ,
};
const char *prot_str = NULL;
switch (qc->tf.protocol) {
case ATA_PROT_UNKNOWN:
prot_str = "unknown" ;
break ;
case ATA_PROT_NODATA:
prot_str = "nodata" ;
break ;
case ATA_PROT_PIO:
prot_str = "pio" ;
break ;
case ATA_PROT_DMA:
prot_str = "dma" ;
break ;
case ATA_PROT_NCQ:
prot_str = "ncq dma" ;
break ;
case ATA_PROT_NCQ_NODATA:
prot_str = "ncq nodata" ;
break ;
case ATAPI_PROT_NODATA:
prot_str = "nodata" ;
break ;
case ATAPI_PROT_PIO:
prot_str = "pio" ;
break ;
case ATAPI_PROT_DMA:
prot_str = "dma" ;
break ;
}
snprintf(data_buf, sizeof (data_buf), " %s %u %s" ,
prot_str, qc->nbytes, dma_str[qc->dma_dir]);
}
if (ata_is_atapi(qc->tf.protocol)) {
const u8 *cdb = qc->cdb;
size_t cdb_len = qc->dev->cdb_len;
if (qc->scsicmd) {
cdb = qc->scsicmd->cmnd;
cdb_len = qc->scsicmd->cmd_len;
}
__scsi_format_command(cdb_buf, sizeof (cdb_buf),
cdb, cdb_len);
} else
ata_dev_err(qc->dev, "failed command: %s\n" ,
ata_get_cmd_name(cmd->command));
ata_dev_err(qc->dev,
"cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
"tag %d%s\n %s"
"res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "
"Emask 0x%x (%s)%s\n" ,
cmd->command, cmd->feature, cmd->nsect,
cmd->lbal, cmd->lbam, cmd->lbah,
cmd->hob_feature, cmd->hob_nsect,
cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah,
cmd->device, qc->tag, data_buf, cdb_buf,
res->status, res->error, res->nsect,
res->lbal, res->lbam, res->lbah,
res->hob_feature, res->hob_nsect,
res->hob_lbal, res->hob_lbam, res->hob_lbah,
res->device, qc->err_mask, ata_err_string(qc->err_mask),
qc->err_mask & AC_ERR_NCQ ? " <F>" : "" );
#ifdef CONFIG_ATA_VERBOSE_ERROR
if (res->status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
ATA_SENSE | ATA_ERR)) {
if (res->status & ATA_BUSY)
ata_dev_err(qc->dev, "status: { Busy }\n" );
else
ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n" ,
res->status & ATA_DRDY ? "DRDY " : "" ,
res->status & ATA_DF ? "DF " : "" ,
res->status & ATA_DRQ ? "DRQ " : "" ,
res->status & ATA_SENSE ? "SENSE " : "" ,
res->status & ATA_ERR ? "ERR " : "" );
}
if (cmd->command != ATA_CMD_PACKET &&
(res->error & (ATA_ICRC | ATA_UNC | ATA_AMNF | ATA_IDNF |
ATA_ABORTED)))
ata_dev_err(qc->dev, "error: { %s%s%s%s%s}\n" ,
res->error & ATA_ICRC ? "ICRC " : "" ,
res->error & ATA_UNC ? "UNC " : "" ,
res->error & ATA_AMNF ? "AMNF " : "" ,
res->error & ATA_IDNF ? "IDNF " : "" ,
res->error & ATA_ABORTED ? "ABRT " : "" );
#endif
}
}
/**
* ata_eh_report - report error handling to user
* @ ap : ATA port to report EH about
*
* Report EH to user .
*
* LOCKING :
* None .
*/
void ata_eh_report(struct ata_port *ap)
{
struct ata_link *link;
ata_for_each_link(link, ap, HOST_FIRST)
ata_eh_link_report(link);
}
static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
unsigned int *classes, unsigned long deadline,
bool clear_classes)
{
struct ata_device *dev;
if (clear_classes)
ata_for_each_dev(dev, link, ALL)
classes[dev->devno] = ATA_DEV_UNKNOWN;
return reset(link, classes, deadline);
}
static bool ata_eh_followup_srst_needed(struct ata_link *link, int rc)
{
if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link))
return false ;
if (rc == -EAGAIN)
return true ;
if (sata_pmp_supported(link->ap) && ata_is_host_link(link))
return true ;
return false ;
}
int ata_eh_reset(struct ata_link *link, int classify,
struct ata_reset_operations *reset_ops)
{
struct ata_port *ap = link->ap;
struct ata_link *slave = ap->slave_link;
struct ata_eh_context *ehc = &link->eh_context;
struct ata_eh_context *sehc = slave ? &slave->eh_context : NULL;
ata_reset_fn_t hardreset = reset_ops->hardreset;
ata_reset_fn_t softreset = reset_ops->softreset;
ata_prereset_fn_t prereset = reset_ops->prereset;
ata_postreset_fn_t postreset = reset_ops->postreset;
unsigned int *classes = ehc->classes;
unsigned int lflags = link->flags;
int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
int max_tries = 0 , try = 0 ;
struct ata_link *failed_link;
struct ata_device *dev;
unsigned long deadline, now;
ata_reset_fn_t reset;
unsigned long flags;
u32 sstatus;
int nr_unknown, rc;
/*
* Prepare to reset
*/
while (ata_eh_reset_timeouts[max_tries] != UINT_MAX)
max_tries++;
if (link->flags & ATA_LFLAG_RST_ONCE)
max_tries = 1 ;
if (link->flags & ATA_LFLAG_NO_HRST)
hardreset = NULL;
if (link->flags & ATA_LFLAG_NO_SRST)
softreset = NULL;
/* make sure each reset attempt is at least COOL_DOWN apart */
if (ehc->i.flags & ATA_EHI_DID_RESET) {
now = jiffies;
WARN_ON(time_after(ehc->last_reset, now));
deadline = ata_deadline(ehc->last_reset,
ATA_EH_RESET_COOL_DOWN);
if (time_before(now, deadline))
schedule_timeout_uninterruptible(deadline - now);
}
spin_lock_irqsave(ap->lock, flags);
ap->pflags |= ATA_PFLAG_RESETTING;
spin_unlock_irqrestore(ap->lock, flags);
ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
ata_for_each_dev(dev, link, ALL) {
/* If we issue an SRST then an ATA drive (not ATAPI)
* may change configuration and be in PIO0 timing . If
* we do a hard reset ( or are coming from power on )
* this is true for ATA or ATAPI . Until we ' ve set a
* suitable controller mode we should not touch the
* bus as we may be talking too fast .
*/
dev->pio_mode = XFER_PIO_0;
dev->dma_mode = 0 xff;
/* If the controller has a pio mode setup function
* then use it to set the chipset to rights . Don ' t
* touch the DMA setup as that will be dealt with when
* configuring devices .
*/
if (ap->ops->set_piomode)
ap->ops->set_piomode(ap, dev);
}
/* prefer hardreset */
reset = NULL;
ehc->i.action &= ~ATA_EH_RESET;
if (hardreset) {
reset = hardreset;
ehc->i.action |= ATA_EH_HARDRESET;
} else if (softreset) {
reset = softreset;
ehc->i.action |= ATA_EH_SOFTRESET;
}
if (prereset) {
unsigned long deadline = ata_deadline(jiffies,
ATA_EH_PRERESET_TIMEOUT);
if (slave) {
sehc->i.action &= ~ATA_EH_RESET;
sehc->i.action |= ehc->i.action;
}
rc = prereset(link, deadline);
/* If present, do prereset on slave link too. Reset
* is skipped iff both master and slave links report
* - ENOENT or clear ATA_EH_RESET .
*/
if (slave && (rc == 0 || rc == -ENOENT)) {
int tmp;
tmp = prereset(slave, deadline);
if (tmp != -ENOENT)
rc = tmp;
ehc->i.action |= sehc->i.action;
}
if (rc) {
if (rc == -ENOENT) {
ata_link_dbg(link, "port disabled--ignoring\n" );
ehc->i.action &= ~ATA_EH_RESET;
ata_for_each_dev(dev, link, ALL)
classes[dev->devno] = ATA_DEV_NONE;
rc = 0 ;
} else
ata_link_err(link,
"prereset failed (errno=%d)\n" ,
rc);
goto out;
}
/* prereset() might have cleared ATA_EH_RESET. If so,
* bang classes , thaw and return .
*/
if (reset && !(ehc->i.action & ATA_EH_RESET)) {
ata_for_each_dev(dev, link, ALL)
classes[dev->devno] = ATA_DEV_NONE;
if (ata_port_is_frozen(ap) && ata_is_host_link(link))
ata_eh_thaw_port(ap);
rc = 0 ;
goto out;
}
}
retry:
/*
* Perform reset
*/
if (ata_is_host_link(link))
ata_eh_freeze_port(ap);
deadline = ata_deadline(jiffies, ata_eh_reset_timeouts[try ++]);
if (reset) {
if (verbose)
ata_link_info(link, "%s resetting link\n" ,
reset == softreset ? "soft" : "hard" );
/* mark that this EH session started with reset */
ehc->last_reset = jiffies;
if (reset == hardreset) {
ehc->i.flags |= ATA_EHI_DID_HARDRESET;
trace_ata_link_hardreset_begin(link, classes, deadline);
} else {
ehc->i.flags |= ATA_EHI_DID_SOFTRESET;
trace_ata_link_softreset_begin(link, classes, deadline);
}
rc = ata_do_reset(link, reset, classes, deadline, true );
if (reset == hardreset)
trace_ata_link_hardreset_end(link, classes, rc);
else
trace_ata_link_softreset_end(link, classes, rc);
if (rc && rc != -EAGAIN) {
failed_link = link;
goto fail;
}
/* hardreset slave link if existent */
if (slave && reset == hardreset) {
int tmp;
if (verbose)
ata_link_info(slave, "hard resetting link\n" );
ata_eh_about_to_do(slave, NULL, ATA_EH_RESET);
trace_ata_slave_hardreset_begin(slave, classes,
deadline);
tmp = ata_do_reset(slave, reset, classes, deadline,
false );
trace_ata_slave_hardreset_end(slave, classes, tmp);
switch (tmp) {
case -EAGAIN:
rc = -EAGAIN;
break ;
case 0 :
break ;
default :
failed_link = slave;
rc = tmp;
goto fail;
}
}
/* perform follow-up SRST if necessary */
if (reset == hardreset &&
ata_eh_followup_srst_needed(link, rc)) {
reset = softreset;
if (!reset) {
ata_link_err(link,
"follow-up softreset required but no softreset available\n" );
failed_link = link;
rc = -EINVAL;
goto fail;
}
ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
trace_ata_link_softreset_begin(link, classes, deadline);
rc = ata_do_reset(link, reset, classes, deadline, true );
trace_ata_link_softreset_end(link, classes, rc);
if (rc) {
failed_link = link;
goto fail;
}
}
} else {
if (verbose)
ata_link_info(link,
"no reset method available, skipping reset\n" );
if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
lflags |= ATA_LFLAG_ASSUME_ATA;
}
/*
* Post - reset processing
*/
ata_for_each_dev(dev, link, ALL) {
/* After the reset, the device state is PIO 0 and the
* controller state is undefined . Reset also wakes up
* drives from sleeping mode .
*/
dev->pio_mode = XFER_PIO_0;
dev->flags &= ~ATA_DFLAG_SLEEPING;
if (ata_phys_link_offline(ata_dev_phys_link(dev)))
continue ;
/* apply class override */
if (lflags & ATA_LFLAG_ASSUME_ATA)
classes[dev->devno] = ATA_DEV_ATA;
else if (lflags & ATA_LFLAG_ASSUME_SEMB)
classes[dev->devno] = ATA_DEV_SEMB_UNSUP;
}
/* record current link speed */
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 )
link->sata_spd = (sstatus >> 4 ) & 0 xf;
if (slave && sata_scr_read(slave, SCR_STATUS, &sstatus) == 0 )
slave->sata_spd = (sstatus >> 4 ) & 0 xf;
/* thaw the port */
if (ata_is_host_link(link))
ata_eh_thaw_port(ap);
/* postreset() should clear hardware SError. Although SError
* is cleared during link resume , clearing SError here is
* necessary as some PHYs raise hotplug events after SRST .
* This introduces race condition where hotplug occurs between
* reset and here . This race is mediated by cross checking
* link onlineness and classification result later .
*/
if (postreset) {
postreset(link, classes);
trace_ata_link_postreset(link, classes, rc);
if (slave) {
postreset(slave, classes);
trace_ata_slave_postreset(slave, classes, rc);
}
}
/* clear cached SError */
spin_lock_irqsave(link->ap->lock, flags);
link->eh_info.serror = 0 ;
if (slave)
slave->eh_info.serror = 0 ;
spin_unlock_irqrestore(link->ap->lock, flags);
/*
* Make sure onlineness and classification result correspond .
* Hotplug could have happened during reset and some
* controllers fail to wait while a drive is spinning up after
* being hotplugged causing misdetection . By cross checking
* link on / offlineness and classification result , those
* conditions can be reliably detected and retried .
*/
nr_unknown = 0 ;
ata_for_each_dev(dev, link, ALL) {
if (ata_phys_link_online(ata_dev_phys_link(dev))) {
if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
ata_dev_dbg(dev, "link online but device misclassified\n" );
classes[dev->devno] = ATA_DEV_NONE;
nr_unknown++;
}
} else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {
if (ata_class_enabled(classes[dev->devno]))
ata_dev_dbg(dev,
"link offline, clearing class %d to NONE\n" ,
classes[dev->devno]);
classes[dev->devno] = ATA_DEV_NONE;
} else if (classes[dev->devno] == ATA_DEV_UNKNOWN) {
ata_dev_dbg(dev,
"link status unknown, clearing UNKNOWN to NONE\n" );
classes[dev->devno] = ATA_DEV_NONE;
}
}
if (classify && nr_unknown) {
if (try < max_tries) {
ata_link_warn(link,
"link online but %d devices misclassified, retrying\n" ,
nr_unknown);
failed_link = link;
rc = -EAGAIN;
goto fail;
}
ata_link_warn(link,
"link online but %d devices misclassified, "
"device detection might fail\n" , nr_unknown);
}
/* reset successful, schedule revalidation */
ata_eh_done(link, NULL, ATA_EH_RESET);
if (slave)
ata_eh_done(slave, NULL, ATA_EH_RESET);
ehc->last_reset = jiffies; /* update to completion time */
ehc->i.action |= ATA_EH_REVALIDATE;
link->lpm_policy = ATA_LPM_UNKNOWN; /* reset LPM state */
rc = 0 ;
out:
/* clear hotplug flag */
ehc->i.flags &= ~ATA_EHI_HOTPLUGGED;
if (slave)
sehc->i.flags &= ~ATA_EHI_HOTPLUGGED;
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_RESETTING;
spin_unlock_irqrestore(ap->lock, flags);
return rc;
fail:
/* if SCR isn't accessible on a fan-out port, PMP needs to be reset */
if (!ata_is_host_link(link) &&
sata_scr_read(link, SCR_STATUS, &sstatus))
rc = -ERESTART;
if (try >= max_tries) {
/*
* Thaw host port even if reset failed , so that the port
* can be retried on the next phy event . This risks
* repeated EH runs but seems to be a better tradeoff than
* shutting down a port after a botched hotplug attempt .
*/
if (ata_is_host_link(link))
ata_eh_thaw_port(ap);
ata_link_warn(link, "%s failed\n" ,
reset == hardreset ? "hardreset" : "softreset" );
goto out;
}
now = jiffies;
if (time_before(now, deadline)) {
unsigned long delta = deadline - now;
ata_link_warn(failed_link,
"reset failed (errno=%d), retrying in %u secs\n" ,
rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000 ));
ata_eh_release(ap);
while (delta)
delta = schedule_timeout_uninterruptible(delta);
ata_eh_acquire(ap);
}
/*
* While disks spinup behind PMP , some controllers fail sending SRST .
* They need to be reset - as well as the PMP - before retrying .
*/
if (rc == -ERESTART) {
if (ata_is_host_link(link))
ata_eh_thaw_port(ap);
goto out;
}
if (try == max_tries - 1 ) {
sata_down_spd_limit(link, 0 );
if (slave)
sata_down_spd_limit(slave, 0 );
} else if (rc == -EPIPE)
sata_down_spd_limit(failed_link, 0 );
if (hardreset)
reset = hardreset;
goto retry;
}
static inline void ata_eh_pull_park_action(struct ata_port *ap)
{
struct ata_link *link;
struct ata_device *dev;
unsigned long flags;
/*
* This function can be thought of as an extended version of
* ata_eh_about_to_do ( ) specially crafted to accommodate the
* requirements of ATA_EH_PARK handling . Since the EH thread
* does not leave the do { } while ( ) loop in ata_eh_recover as
* long as the timeout for a park request to * one * device on
* the port has not expired , and since we still want to pick
* up park requests to other devices on the same port or
* timeout updates for the same device , we have to pull
* ATA_EH_PARK actions from eh_info into eh_context . i
* ourselves at the beginning of each pass over the loop .
*
* Additionally , all write accesses to & ap - > park_req_pending
* through reinit_completion ( ) ( see below ) or complete_all ( )
* ( see ata_scsi_park_store ( ) ) are protected by the host lock .
* As a result we have that park_req_pending . done is zero on
* exit from this function , i . e . when ATA_EH_PARK actions for
* * all * devices on port ap have been pulled into the
* respective eh_context structs . If , and only if ,
* park_req_pending . done is non - zero by the time we reach
* wait_for_completion_timeout ( ) , another ATA_EH_PARK action
* has been scheduled for at least one of the devices on port
* ap and we have to cycle over the do { } while ( ) loop in
* ata_eh_recover ( ) again .
*/
spin_lock_irqsave(ap->lock, flags);
reinit_completion(&ap->park_req_pending);
ata_for_each_link(link, ap, EDGE) {
ata_for_each_dev(dev, link, ALL) {
struct ata_eh_info *ehi = &link->eh_info;
link->eh_context.i.dev_action[dev->devno] |=
ehi->dev_action[dev->devno] & ATA_EH_PARK;
ata_eh_clear_action(link, dev, ehi, ATA_EH_PARK);
}
}
spin_unlock_irqrestore(ap->lock, flags);
}
static void ata_eh_park_issue_cmd(struct ata_device *dev, int park)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
struct ata_taskfile tf;
unsigned int err_mask;
ata_tf_init(dev, &tf);
if (park) {
ehc->unloaded_mask |= 1 << dev->devno;
tf.command = ATA_CMD_IDLEIMMEDIATE;
tf.feature = 0 x44;
tf.lbal = 0 x4c;
tf.lbam = 0 x4e;
tf.lbah = 0 x55;
} else {
ehc->unloaded_mask &= ~(1 << dev->devno);
tf.command = ATA_CMD_CHK_POWER;
}
tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
tf.protocol = ATA_PROT_NODATA;
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0 , 0 );
if (park && (err_mask || tf.lbal != 0 xc4)) {
ata_dev_err(dev, "head unload failed!\n" );
ehc->unloaded_mask &= ~(1 << dev->devno);
}
}
static int ata_eh_revalidate_and_attach(struct ata_link *link,
struct ata_device **r_failed_dev)
{
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev;
unsigned int new_mask = 0 ;
unsigned long flags;
int rc = 0 ;
/* For PATA drive side cable detection to work, IDENTIFY must
* be done backwards such that PDIAG - is released by the slave
* device before the master device is identified .
*/
ata_for_each_dev(dev, link, ALL_REVERSE) {
unsigned int action = ata_eh_dev_action(dev);
unsigned int readid_flags = 0 ;
if (ehc->i.flags & ATA_EHI_DID_RESET)
readid_flags |= ATA_READID_POSTRESET;
if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
WARN_ON(dev->class == ATA_DEV_PMP);
/*
* The link may be in a deep sleep , wake it up .
*
* If the link is in deep sleep , ata_phys_link_offline ( )
* will return true , causing the revalidation to fail ,
* which leads to a ( potentially ) needless hard reset .
*
* ata_eh_recover ( ) will later restore the link policy
* to ap - > target_lpm_policy after revalidation is done .
*/
if (link->lpm_policy > ATA_LPM_MAX_POWER) {
rc = ata_eh_link_set_lpm(link, ATA_LPM_MAX_POWER,
r_failed_dev);
if (rc)
goto err;
}
if (!ata_eh_link_established(ata_dev_phys_link(dev))) {
rc = -EIO;
goto err;
}
ata_eh_about_to_do(link, dev, ATA_EH_REVALIDATE);
rc = ata_dev_revalidate(dev, ehc->classes[dev->devno],
readid_flags);
if (rc)
goto err;
ata_eh_done(link, dev, ATA_EH_REVALIDATE);
/* Configuration may have changed, reconfigure
* transfer mode .
*/
ehc->i.flags |= ATA_EHI_SETMODE;
/* schedule the scsi_rescan_device() here */
schedule_delayed_work(&ap->scsi_rescan_task, 0 );
} else if (dev->class == ATA_DEV_UNKNOWN &&
ehc->tries[dev->devno] &&
ata_class_enabled(ehc->classes[dev->devno])) {
/* Temporarily set dev->class, it will be
* permanently set once all configurations are
* complete . This is necessary because new
* device configuration is done in two
* separate loops .
*/
dev->class = ehc->classes[dev->devno];
if (dev->class == ATA_DEV_PMP)
rc = sata_pmp_attach(dev);
else
rc = ata_dev_read_id(dev, &dev->class ,
readid_flags, dev->id);
/* read_id might have changed class, store and reset */
ehc->classes[dev->devno] = dev->class ;
dev->class = ATA_DEV_UNKNOWN;
switch (rc) {
case 0 :
/* clear error info accumulated during probe */
ata_ering_clear(&dev->ering);
new_mask |= 1 << dev->devno;
break ;
case -ENOENT:
/* IDENTIFY was issued to non-existent
* device . No need to reset . Just
* thaw and ignore the device .
*/
ata_eh_thaw_port(ap);
break ;
default :
goto err;
}
}
}
/* PDIAG- should have been released, ask cable type if post-reset */
if ((ehc->i.flags & ATA_EHI_DID_RESET) && ata_is_host_link(link)) {
if (ap->ops->cable_detect)
ap->cbl = ap->ops->cable_detect(ap);
ata_force_cbl(ap);
}
/* Configure new devices forward such that user doesn't see
* device detection messages backwards .
*/
ata_for_each_dev(dev, link, ALL) {
if (!(new_mask & (1 << dev->devno)))
continue ;
dev->class = ehc->classes[dev->devno];
if (dev->class == ATA_DEV_PMP)
continue ;
ehc->i.flags |= ATA_EHI_PRINTINFO;
rc = ata_dev_configure(dev);
ehc->i.flags &= ~ATA_EHI_PRINTINFO;
if (rc) {
dev->class = ATA_DEV_UNKNOWN;
goto err;
}
spin_lock_irqsave(ap->lock, flags);
ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
spin_unlock_irqrestore(ap->lock, flags);
/* new device discovered, configure xfermode */
ehc->i.flags |= ATA_EHI_SETMODE;
}
return 0 ;
err:
dev->flags &= ~ATA_DFLAG_RESUMING;
*r_failed_dev = dev;
return rc;
}
/**
* ata_eh_set_mode - Program timings and issue SET FEATURES - XFER
* @ link : link on which timings will be programmed
* @ r_failed_dev : out parameter for failed device
*
* Set ATA device disk transfer mode ( PIO3 , UDMA6 , etc . ) . If
* ata_eh_set_mode ( ) fails , pointer to the failing device is
* returned in @ r_failed_dev .
*
* LOCKING :
* PCI / etc . bus probe sem .
*
* RETURNS :
* 0 on success , negative errno otherwise
*/
static int ata_eh_set_mode(struct ata_link *link,
struct ata_device **r_failed_dev)
{
struct ata_port *ap = link->ap;
struct ata_device *dev;
int rc;
/* if data transfer is verified, clear DUBIOUS_XFER on ering top */
ata_for_each_dev(dev, link, ENABLED) {
if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) {
struct ata_ering_entry *ent;
ent = ata_ering_top(&dev->ering);
if (ent)
ent->eflags &= ~ATA_EFLAG_DUBIOUS_XFER;
}
}
/* has private set_mode? */
if (ap->ops->set_mode)
rc = ap->ops->set_mode(link, r_failed_dev);
else
rc = ata_set_mode(link, r_failed_dev);
/* if transfer mode has changed, set DUBIOUS_XFER on device */
ata_for_each_dev(dev, link, ENABLED) {
struct ata_eh_context *ehc = &link->eh_context;
u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno];
u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno));
if (dev->xfer_mode != saved_xfer_mode ||
ata_ncq_enabled(dev) != saved_ncq)
dev->flags |= ATA_DFLAG_DUBIOUS_XFER;
}
return rc;
}
/**
* atapi_eh_clear_ua - Clear ATAPI UNIT ATTENTION after reset
* @ dev : ATAPI device to clear UA for
*
* Resets and other operations can make an ATAPI device raise
* UNIT ATTENTION which causes the next operation to fail . This
* function clears UA .
*
* LOCKING :
* EH context ( may sleep ) .
*
* RETURNS :
* 0 on success , - errno on failure .
*/
static int atapi_eh_clear_ua(struct ata_device *dev)
{
int i;
for (i = 0 ; i < ATA_EH_UA_TRIES; i++) {
u8 *sense_buffer = dev->sector_buf;
u8 sense_key = 0 ;
unsigned int err_mask;
err_mask = atapi_eh_tur(dev, &sense_key);
if (err_mask != 0 && err_mask != AC_ERR_DEV) {
ata_dev_warn(dev,
"TEST_UNIT_READY failed (err_mask=0x%x)\n" ,
err_mask);
return -EIO;
}
if (!err_mask || sense_key != UNIT_ATTENTION)
return 0 ;
err_mask = atapi_eh_request_sense(dev, sense_buffer, sense_key);
if (err_mask) {
ata_dev_warn(dev, "failed to clear "
"UNIT ATTENTION (err_mask=0x%x)\n" , err_mask);
return -EIO;
}
}
ata_dev_warn(dev, "UNIT ATTENTION persists after %d tries\n" ,
ATA_EH_UA_TRIES);
return 0 ;
}
/**
* ata_eh_maybe_retry_flush - Retry FLUSH if necessary
* @ dev : ATA device which may need FLUSH retry
*
* If @ dev failed FLUSH , it needs to be reported upper layer
* immediately as it means that @ dev failed to remap and already
* lost at least a sector and further FLUSH retrials won ' t make
* any difference to the lost sector . However , if FLUSH failed
* for other reasons , for example transmission error , FLUSH needs
* to be retried .
*
* This function determines whether FLUSH failure retry is
* necessary and performs it if so .
*
* RETURNS :
* 0 if EH can continue , - errno if EH needs to be repeated .
*/
static int ata_eh_maybe_retry_flush(struct ata_device *dev)
{
struct ata_link *link = dev->link;
struct ata_port *ap = link->ap;
struct ata_queued_cmd *qc;
struct ata_taskfile tf;
unsigned int err_mask;
int rc = 0 ;
/* did flush fail for this device? */
if (!ata_tag_valid(link->active_tag))
return 0 ;
qc = __ata_qc_from_tag(ap, link->active_tag);
if (qc->dev != dev || (qc->tf.command != ATA_CMD_FLUSH_EXT &&
qc->tf.command != ATA_CMD_FLUSH))
return 0 ;
/* if the device failed it, it should be reported to upper layers */
if (qc->err_mask & AC_ERR_DEV)
return 0 ;
/* flush failed for some other reason, give it another shot */
ata_tf_init(dev, &tf);
tf.command = qc->tf.command;
tf.flags |= ATA_TFLAG_DEVICE;
tf.protocol = ATA_PROT_NODATA;
ata_dev_warn(dev, "retrying FLUSH 0x%x Emask 0x%x\n" ,
tf.command, qc->err_mask);
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0 , 0 );
if (!err_mask) {
/*
* FLUSH is complete but there ' s no way to
* successfully complete a failed command from EH .
* Making sure retry is allowed at least once and
* retrying it should do the trick - whatever was in
* the cache is already on the platter and this won ' t
* cause infinite loop .
*/
qc->scsicmd->allowed = max(qc->scsicmd->allowed, 1 );
} else {
ata_dev_warn(dev, "FLUSH failed Emask 0x%x\n" ,
err_mask);
rc = -EIO;
/* if device failed it, report it to upper layers */
if (err_mask & AC_ERR_DEV) {
qc->err_mask |= AC_ERR_DEV;
qc->result_tf = tf;
if (!ata_port_is_frozen(ap))
rc = 0 ;
}
}
return rc;
}
int ata_link_nr_enabled(struct ata_link *link)
{
struct ata_device *dev;
int cnt = 0 ;
ata_for_each_dev(dev, link, ENABLED)
cnt++;
return cnt;
}
static int ata_link_nr_vacant(struct ata_link *link)
{
struct ata_device *dev;
int cnt = 0 ;
ata_for_each_dev(dev, link, ALL)
if (dev->class == ATA_DEV_UNKNOWN)
cnt++;
return cnt;
}
static int ata_eh_skip_recovery(struct ata_link *link)
{
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
struct ata_device *dev;
/* skip disabled links */
if (link->flags & ATA_LFLAG_DISABLED)
return 1 ;
/* skip if explicitly requested */
if (ehc->i.flags & ATA_EHI_NO_RECOVERY)
return 1 ;
/* thaw frozen port and recover failed devices */
if (ata_port_is_frozen(ap) || ata_link_nr_enabled(link))
return 0 ;
/* reset at least once if reset is requested */
if ((ehc->i.action & ATA_EH_RESET) &&
!(ehc->i.flags & ATA_EHI_DID_RESET))
return 0 ;
/* skip if class codes for all vacant slots are ATA_DEV_NONE */
ata_for_each_dev(dev, link, ALL) {
if (dev->class == ATA_DEV_UNKNOWN &&
ehc->classes[dev->devno] != ATA_DEV_NONE)
return 0 ;
}
return 1 ;
}
static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg)
{
u64 interval = msecs_to_jiffies(ATA_EH_PROBE_TRIAL_INTERVAL);
u64 now = get_jiffies_64();
int *trials = void_arg;
if ((ent->eflags & ATA_EFLAG_OLD_ER) ||
(ent->timestamp < now - min(now, interval)))
return -1 ;
(*trials)++;
return 0 ;
}
static int ata_eh_schedule_probe(struct ata_device *dev)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
struct ata_link *link = ata_dev_phys_link(dev);
int trials = 0 ;
if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
(ehc->did_probe_mask & (1 << dev->devno)))
return 0 ;
ata_eh_detach_dev(dev);
ata_dev_init(dev);
ehc->did_probe_mask |= (1 << dev->devno);
ehc->i.action |= ATA_EH_RESET;
ehc->saved_xfer_mode[dev->devno] = 0 ;
ehc->saved_ncq_enabled &= ~(1 << dev->devno);
/* the link maybe in a deep sleep, wake it up */
if (link->lpm_policy > ATA_LPM_MAX_POWER) {
if (ata_is_host_link(link))
link->ap->ops->set_lpm(link, ATA_LPM_MAX_POWER,
ATA_LPM_EMPTY);
else
sata_pmp_set_lpm(link, ATA_LPM_MAX_POWER,
ATA_LPM_EMPTY);
}
/* Record and count probe trials on the ering. The specific
* error mask used is irrelevant . Because a successful device
* detection clears the ering , this count accumulates only if
* there are consecutive failed probes .
*
* If the count is equal to or higher than ATA_EH_PROBE_TRIALS
* in the last ATA_EH_PROBE_TRIAL_INTERVAL , link speed is
* forced to 1 . 5 Gbps .
*
* This is to work around cases where failed link speed
* negotiation results in device misdetection leading to
* infinite DEVXCHG or PHRDY CHG events .
*/
ata_ering_record(&dev->ering, 0 , AC_ERR_OTHER);
ata_ering_map(&dev->ering, ata_count_probe_trials_cb, &trials);
if (trials > ATA_EH_PROBE_TRIALS)
sata_down_spd_limit(link, 1 );
return 1 ;
}
static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
/* -EAGAIN from EH routine indicates retry without prejudice.
* The requester is responsible for ensuring forward progress .
*/
if (err != -EAGAIN)
ehc->tries[dev->devno]--;
switch (err) {
case -ENODEV:
/* device missing or wrong IDENTIFY data, schedule probing */
ehc->i.probe_mask |= (1 << dev->devno);
fallthrough;
case -EINVAL:
/* give it just one more chance */
ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1 );
fallthrough;
case -EIO:
if (ehc->tries[dev->devno] == 1 ) {
/* This is the last chance, better to slow
* down than lose it .
*/
sata_down_spd_limit(ata_dev_phys_link(dev), 0 );
if (dev->pio_mode > XFER_PIO_0)
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
/* disable device if it has used up all its chances */
ata_dev_disable(dev);
/* detach if offline */
if (ata_phys_link_offline(ata_dev_phys_link(dev)))
ata_eh_detach_dev(dev);
/* schedule probe if necessary */
if (ata_eh_schedule_probe(dev)) {
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
memset(ehc->cmd_timeout_idx[dev->devno], 0 ,
sizeof (ehc->cmd_timeout_idx[dev->devno]));
}
return 1 ;
} else {
ehc->i.action |= ATA_EH_RESET;
return 0 ;
}
}
/**
* ata_eh_recover - recover host port after error
* @ ap : host port to recover
* @ reset_ops : The set of reset operations to use
* @ r_failed_link : out parameter for failed link
*
* This is the alpha and omega , eum and yang , heart and soul of
* libata exception handling . On entry , actions required to
* recover each link and hotplug requests are recorded in the
* link ' s eh_context . This function executes all the operations
* with appropriate retrials and fallbacks to resurrect failed
* devices , detach goners and greet newcomers .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*
* RETURNS :
* 0 on success , - errno on failure .
*/
int ata_eh_recover(struct ata_port *ap, struct ata_reset_operations *reset_ops,
struct ata_link **r_failed_link)
{
struct ata_link *link;
struct ata_device *dev;
int rc, nr_fails;
unsigned long flags, deadline;
/* prep for recovery */
ata_for_each_link(link, ap, EDGE) {
struct ata_eh_context *ehc = &link->eh_context;
/* re-enable link? */
if (ehc->i.action & ATA_EH_ENABLE_LINK) {
ata_eh_about_to_do(link, NULL, ATA_EH_ENABLE_LINK);
spin_lock_irqsave(ap->lock, flags);
link->flags &= ~ATA_LFLAG_DISABLED;
spin_unlock_irqrestore(ap->lock, flags);
ata_eh_done(link, NULL, ATA_EH_ENABLE_LINK);
}
ata_for_each_dev(dev, link, ALL) {
if (link->flags & ATA_LFLAG_NO_RETRY)
ehc->tries[dev->devno] = 1 ;
else
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
/* collect port action mask recorded in dev actions */
ehc->i.action |= ehc->i.dev_action[dev->devno] &
~ATA_EH_PERDEV_MASK;
ehc->i.dev_action[dev->devno] &= ATA_EH_PERDEV_MASK;
/* process hotplug request */
if (dev->flags & ATA_DFLAG_DETACH)
ata_eh_detach_dev(dev);
/* schedule probe if necessary */
if (!ata_dev_enabled(dev))
ata_eh_schedule_probe(dev);
}
}
retry:
rc = 0 ;
/* if UNLOADING, finish immediately */
if (ap->pflags & ATA_PFLAG_UNLOADING)
goto out;
/* prep for EH */
ata_for_each_link(link, ap, EDGE) {
struct ata_eh_context *ehc = &link->eh_context;
/* skip EH if possible. */
if (ata_eh_skip_recovery(link))
ehc->i.action = 0 ;
ata_for_each_dev(dev, link, ALL)
ehc->classes[dev->devno] = ATA_DEV_UNKNOWN;
}
/* reset */
ata_for_each_link(link, ap, EDGE) {
struct ata_eh_context *ehc = &link->eh_context;
if (!(ehc->i.action & ATA_EH_RESET))
continue ;
rc = ata_eh_reset(link, ata_link_nr_vacant(link), reset_ops);
if (rc) {
ata_link_err(link, "reset failed, giving up\n" );
goto out;
}
}
do {
unsigned long now;
/*
* clears ATA_EH_PARK in eh_info and resets
* ap - > park_req_pending
*/
ata_eh_pull_park_action(ap);
deadline = jiffies;
ata_for_each_link(link, ap, EDGE) {
ata_for_each_dev(dev, link, ALL) {
struct ata_eh_context *ehc = &link->eh_context;
unsigned long tmp;
if (dev->class != ATA_DEV_ATA &&
dev->class != ATA_DEV_ZAC)
continue ;
if (!(ehc->i.dev_action[dev->devno] &
ATA_EH_PARK))
continue ;
tmp = dev->unpark_deadline;
if (time_before(deadline, tmp))
deadline = tmp;
else if (time_before_eq(tmp, jiffies))
continue ;
if (ehc->unloaded_mask & (1 << dev->devno))
continue ;
ata_eh_park_issue_cmd(dev, 1 );
}
}
now = jiffies;
if (time_before_eq(deadline, now))
break ;
ata_eh_release(ap);
deadline = wait_for_completion_timeout(&ap->park_req_pending,
deadline - now);
ata_eh_acquire(ap);
} while (deadline);
ata_for_each_link(link, ap, EDGE) {
ata_for_each_dev(dev, link, ALL) {
if (!(link->eh_context.unloaded_mask &
(1 << dev->devno)))
continue ;
ata_eh_park_issue_cmd(dev, 0 );
ata_eh_done(link, dev, ATA_EH_PARK);
}
}
/* the rest */
nr_fails = 0 ;
ata_for_each_link(link, ap, PMP_FIRST) {
struct ata_eh_context *ehc = &link->eh_context;
if (sata_pmp_attached(ap) && ata_is_host_link(link))
goto config_lpm;
/* revalidate existing devices and attach new ones */
rc = ata_eh_revalidate_and_attach(link, &dev);
if (rc)
goto rest_fail;
/* if PMP got attached, return, pmp EH will take care of it */
if (link->device->class == ATA_DEV_PMP) {
ehc->i.action = 0 ;
return 0 ;
}
/* configure transfer mode if necessary */
if (ehc->i.flags & ATA_EHI_SETMODE) {
rc = ata_eh_set_mode(link, &dev);
if (rc)
goto rest_fail;
ehc->i.flags &= ~ATA_EHI_SETMODE;
}
/* If reset has been issued, clear UA to avoid
* disrupting the current users of the device .
*/
if (ehc->i.flags & ATA_EHI_DID_RESET) {
ata_for_each_dev(dev, link, ALL) {
if (dev->class != ATA_DEV_ATAPI)
continue ;
rc = atapi_eh_clear_ua(dev);
if (rc)
goto rest_fail;
if (zpodd_dev_enabled(dev))
zpodd_post_poweron(dev);
}
}
/*
* 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 &&
dev->class != ATA_DEV_ZAC)
continue ;
rc = ata_eh_maybe_retry_flush(dev);
if (rc)
goto rest_fail;
}
config_lpm:
/* configure link power saving */
if (link->lpm_policy != ap->target_lpm_policy) {
rc = ata_eh_link_set_lpm(link, ap->target_lpm_policy,
&dev);
if (rc)
goto rest_fail;
}
/* this link is okay now */
ehc->i.flags = 0 ;
continue ;
rest_fail:
nr_fails++;
if (dev)
ata_eh_handle_dev_fail(dev, rc);
if (ata_port_is_frozen(ap)) {
/* PMP reset requires working host port.
* Can ' t retry if it ' s frozen .
*/
if (sata_pmp_attached(ap))
goto out;
break ;
}
}
if (nr_fails)
goto retry;
out:
if (rc && r_failed_link)
*r_failed_link = link;
return rc;
}
/**
* ata_eh_finish - finish up EH
* @ ap : host port to finish EH for
*
* Recovery is complete . Clean up EH states and retry or finish
* failed qcs .
*
* LOCKING :
* None .
*/
void ata_eh_finish(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
int tag;
/* retry or finish qcs */
ata_qc_for_each_raw(ap, qc, tag) {
if (!(qc->flags & ATA_QCFLAG_EH))
continue ;
if (qc->err_mask) {
/* FIXME: Once EH migration is complete,
* generate sense data in this function ,
* considering both err_mask and tf .
*/
if (qc->flags & ATA_QCFLAG_RETRY) {
/*
* Since qc - > err_mask is set , ata_eh_qc_retry ( )
* will not increment scmd - > allowed , so upper
* layer will only retry the command if it has
* not already been retried too many times .
*/
ata_eh_qc_retry(qc);
} else {
ata_eh_qc_complete(qc);
}
} else {
if (qc->flags & ATA_QCFLAG_SENSE_VALID ||
qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) {
ata_eh_qc_complete(qc);
} else {
/* feed zero TF to sense generation */
memset(&qc->result_tf, 0 , sizeof (qc->result_tf));
/*
* Since qc - > err_mask is not set ,
* ata_eh_qc_retry ( ) will increment
* scmd - > allowed , so upper layer is guaranteed
* to retry the command .
*/
ata_eh_qc_retry(qc);
}
}
}
/* make sure nr_active_links is zero after EH */
WARN_ON(ap->nr_active_links);
ap->nr_active_links = 0 ;
}
/**
* ata_std_error_handler - standard error handler
* @ ap : host port to handle error for
*
* Perform standard error handling sequence .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*/
void ata_std_error_handler(struct ata_port *ap)
{
struct ata_reset_operations *reset_ops = &ap->ops->reset;
struct ata_link *link = &ap->link;
int rc;
/* Ignore built-in hardresets if SCR access is not available */
if ((reset_ops->hardreset == sata_std_hardreset ||
reset_ops->hardreset == sata_sff_hardreset) &&
!sata_scr_valid(link))
link->flags |= ATA_LFLAG_NO_HRST;
ata_eh_autopsy(ap);
ata_eh_report(ap);
rc = ata_eh_recover(ap, reset_ops, NULL);
if (rc) {
struct ata_device *dev;
ata_for_each_dev(dev, link, ALL)
ata_dev_disable(dev);
}
ata_eh_finish(ap);
}
EXPORT_SYMBOL_GPL(ata_std_error_handler);
#ifdef CONFIG_PM
/**
* ata_eh_handle_port_suspend - perform port suspend operation
* @ ap : port to suspend
*
* Suspend @ ap .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*/
static void ata_eh_handle_port_suspend(struct ata_port *ap)
{
unsigned long flags;
int rc = 0 ;
struct ata_device *dev;
struct ata_link *link;
/* are we suspending? */
spin_lock_irqsave(ap->lock, flags);
if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
ap->pm_mesg.event & PM_EVENT_RESUME) {
spin_unlock_irqrestore(ap->lock, flags);
return ;
}
spin_unlock_irqrestore(ap->lock, flags);
WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
/*
* We will reach this point for all of the PM events :
* PM_EVENT_SUSPEND ( if runtime pm , PM_EVENT_AUTO will also be set )
* PM_EVENT_FREEZE , and PM_EVENT_HIBERNATE .
*
* We do not want to perform disk spin down for PM_EVENT_FREEZE .
* ( Spin down will be performed by the subsequent PM_EVENT_HIBERNATE . )
*/
if (!(ap->pm_mesg.event & PM_EVENT_FREEZE)) {
/* Set all devices attached to the port in standby mode */
ata_for_each_link(link, ap, HOST_FIRST) {
ata_for_each_dev(dev, link, ENABLED)
ata_dev_power_set_standby(dev);
}
}
/*
* If we have a ZPODD attached , check its zero
* power ready status before the port is frozen .
* Only needed for runtime suspend .
*/
if (PMSG_IS_AUTO(ap->pm_mesg)) {
ata_for_each_dev(dev, &ap->link, ENABLED) {
if (zpodd_dev_enabled(dev))
zpodd_on_suspend(dev);
}
}
/* suspend */
ata_eh_freeze_port(ap);
if (ap->ops->port_suspend)
rc = ap->ops->port_suspend(ap, ap->pm_mesg);
ata_acpi_set_state(ap, ap->pm_mesg);
/* update the flags */
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_PM_PENDING;
if (rc == 0 )
ap->pflags |= ATA_PFLAG_SUSPENDED;
else if (ata_port_is_frozen(ap))
ata_port_schedule_eh(ap);
spin_unlock_irqrestore(ap->lock, flags);
return ;
}
/**
* ata_eh_handle_port_resume - perform port resume operation
* @ ap : port to resume
*
* Resume @ ap .
*
* LOCKING :
* Kernel thread context ( may sleep ) .
*/
static void ata_eh_handle_port_resume(struct ata_port *ap)
{
struct ata_link *link;
struct ata_device *dev;
unsigned long flags;
/* are we resuming? */
spin_lock_irqsave(ap->lock, flags);
if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
!(ap->pm_mesg.event & PM_EVENT_RESUME)) {
spin_unlock_irqrestore(ap->lock, flags);
return ;
}
spin_unlock_irqrestore(ap->lock, flags);
WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED));
/*
* Error timestamps are in jiffies which doesn ' t run while
* suspended and PHY events during resume isn ' t too uncommon .
* When the two are combined , it can lead to unnecessary speed
* downs if the machine is suspended and resumed repeatedly .
* Clear error history .
*/
ata_for_each_link(link, ap, HOST_FIRST)
ata_for_each_dev(dev, link, ALL)
ata_ering_clear(&dev->ering);
ata_acpi_set_state(ap, ap->pm_mesg);
if (ap->ops->port_resume)
ap->ops->port_resume(ap);
/* tell ACPI that we're resuming */
ata_acpi_on_resume(ap);
/* update the flags */
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
ap->pflags |= ATA_PFLAG_RESUMING;
spin_unlock_irqrestore(ap->lock, flags);
}
#endif /* CONFIG_PM */
Messung V0.5 in Prozent C=96 H=96 G=95
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.153Angebot
¤
*Bot Zugriff