Skip to content

Commit

Permalink
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (23 commits)
  libata: don't configure downstream links faster than the upstream link
  libata: request PHY speed configuration on SControl access failure
  libata: consider errors not associated with commands for speed down
  libata: more robust reset failure handling
  libata: cosmetic clean up / reorganization of ata_eh_reset()
  libata: fix timing computation in ata_eh_reset()
  libata: increase 128 KB / cmd limit for ATAPI tape drives
  sata_promise: fix endianess bug in ASIC PRD bug workaround
  libata: fix docbook
  make ata_scsi_lpm_get() static
  libata: suppress two warnings
  ata/sata_fsl: Remove ata_scsi_suspend/resume callbacks
  ata/sata_fsl: Remove sending LOG EXT command in sata_fsl_softreset()
  ata/sata_fsl: Move MPC8315DS link speed limit workaround to specific ifdef
  ata/sata_fsl: cleanup style problem
  ata/sata_fsl: remove unneeded sata_fsl_hardreset()
  ata/sata_fsl: remove unneeded on-stack copy of FIS
  ata/sata_fsl: cleanup needless casts to/from void __iomem *
  ata/sata_fsl: Remove unnecessary SCR cases
  ata/sata_fsl: Kill ata_sg_is_last()
  ...
  • Loading branch information
Linus Torvalds committed Nov 3, 2007
2 parents ebab899 + 5270222 commit 468f8af
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 206 deletions.
38 changes: 28 additions & 10 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,8 +704,8 @@ static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)

/**
* ata_dev_enable_pm - enable SATA interface power management
* @device - device to enable ipm for
* @policy - the link power management policy
* @dev: device to enable power management
* @policy: the link power management policy
*
* Enable SATA Interface power management. This will enable
* Device Interface Power Management (DIPM) for min_power
Expand Down Expand Up @@ -735,9 +735,10 @@ void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy)
return /* rc */; /* hopefully we can use 'rc' eventually */
}

#ifdef CONFIG_PM
/**
* ata_dev_disable_pm - disable SATA interface power management
* @device - device to enable ipm for
* @dev: device to disable power management
*
* Disable SATA Interface power management. This will disable
* Device Interface Power Management (DIPM) without changing
Expand All @@ -755,6 +756,7 @@ static void ata_dev_disable_pm(struct ata_device *dev)
if (ap->ops->disable_pm)
ap->ops->disable_pm(ap);
}
#endif /* CONFIG_PM */

void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy)
{
Expand All @@ -764,6 +766,7 @@ void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy)
ata_port_schedule_eh(ap);
}

#ifdef CONFIG_PM
static void ata_lpm_enable(struct ata_host *host)
{
struct ata_link *link;
Expand All @@ -789,6 +792,7 @@ static void ata_lpm_disable(struct ata_host *host)
ata_lpm_schedule(ap, ap->pm_policy);
}
}
#endif /* CONFIG_PM */


/**
Expand Down Expand Up @@ -2300,6 +2304,10 @@ int ata_dev_configure(struct ata_device *dev)
dev->max_sectors = ATA_MAX_SECTORS;
}

if ((dev->class == ATA_DEV_ATAPI) &&
(atapi_command_packet_set(id) == TYPE_TAPE))
dev->max_sectors = ATA_MAX_SECTORS_TAPE;

if (dev->horkage & ATA_HORKAGE_MAX_SEC_128)
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);
Expand Down Expand Up @@ -2743,17 +2751,27 @@ int sata_down_spd_limit(struct ata_link *link)

static int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol)
{
u32 spd, limit;
struct ata_link *host_link = &link->ap->link;
u32 limit, target, spd;

limit = link->sata_spd_limit;

if (link->sata_spd_limit == UINT_MAX)
limit = 0;
/* Don't configure downstream link faster than upstream link.
* It doesn't speed up anything and some PMPs choke on such
* configuration.
*/
if (!ata_is_host_link(link) && host_link->sata_spd)
limit &= (1 << host_link->sata_spd) - 1;

if (limit == UINT_MAX)
target = 0;
else
limit = fls(link->sata_spd_limit);
target = fls(limit);

spd = (*scontrol >> 4) & 0xf;
*scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4);
*scontrol = (*scontrol & ~0xf0) | ((target & 0xf) << 4);

return spd != limit;
return spd != target;
}

/**
Expand All @@ -2776,7 +2794,7 @@ int sata_set_spd_needed(struct ata_link *link)
u32 scontrol;

if (sata_scr_read(link, SCR_CONTROL, &scontrol))
return 0;
return 1;

return __sata_set_spd_needed(link, &scontrol);
}
Expand Down
148 changes: 81 additions & 67 deletions drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1747,6 +1747,7 @@ 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_device *dev;
unsigned int all_err_mask = 0;
int tag, is_io = 0;
u32 serror;
Expand Down Expand Up @@ -1818,18 +1819,24 @@ static void ata_eh_link_autopsy(struct ata_link *link)
(!is_io && (all_err_mask & ~AC_ERR_DEV)))
ehc->i.action |= ATA_EH_REVALIDATE;

/* if we have offending qcs and the associated failed device */
/* If we have offending qcs and the associated failed device,
* perform per-dev EH action only on the offending device.
*/
if (ehc->i.dev) {
/* speed down */
ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io,
all_err_mask);

/* perform per-dev EH action only on the offending device */
ehc->i.dev_action[ehc->i.dev->devno] |=
ehc->i.action & ATA_EH_PERDEV_MASK;
ehc->i.action &= ~ATA_EH_PERDEV_MASK;
}

/* 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)
ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask);

DPRINTK("EXIT\n");
}

Expand Down Expand Up @@ -2065,16 +2072,19 @@ int ata_eh_reset(struct ata_link *link, int classify,
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
{
const int max_tries = ARRAY_SIZE(ata_eh_reset_timeouts);
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
unsigned int *classes = ehc->classes;
unsigned int lflags = link->flags;
int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
int try = 0;
struct ata_device *dev;
unsigned long deadline;
unsigned long deadline, now;
unsigned int tmp_action;
ata_reset_fn_t reset;
unsigned long flags;
u32 sstatus;
int rc;

/* about to reset */
Expand Down Expand Up @@ -2106,7 +2116,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
/* Determine which reset to use and record in ehc->i.action.
* prereset() may examine and modify it.
*/
if (softreset && (!hardreset || (!(link->flags & ATA_LFLAG_NO_SRST) &&
if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) &&
!sata_set_spd_needed(link) &&
!(ehc->i.action & ATA_EH_HARDRESET))))
tmp_action = ATA_EH_SOFTRESET;
Expand Down Expand Up @@ -2181,82 +2191,64 @@ int ata_eh_reset(struct ata_link *link, int classify,
"follow-up softreset required "
"but no softreset avaliable\n");
rc = -EINVAL;
goto out;
goto fail;
}

ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
rc = ata_do_reset(link, reset, classes, deadline);

if (rc == 0 && classify && classes[0] == ATA_DEV_UNKNOWN &&
!(link->flags & ATA_LFLAG_ASSUME_CLASS)) {
ata_link_printk(link, KERN_ERR,
"classification failed\n");
rc = -EINVAL;
goto out;
}
}

/* if we skipped follow-up srst, clear rc */
if (rc == -EAGAIN)
rc = 0;

if (rc && rc != -ERESTART && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
unsigned long now = jiffies;

if (time_before(now, deadline)) {
unsigned long delta = deadline - jiffies;

ata_link_printk(link, KERN_WARNING, "reset failed "
"(errno=%d), retrying in %u secs\n",
rc, (jiffies_to_msecs(delta) + 999) / 1000);
/* -EAGAIN can happen if we skipped followup SRST */
if (rc && rc != -EAGAIN)
goto fail;

while (delta)
delta = schedule_timeout_uninterruptible(delta);
/* was classification successful? */
if (classify && classes[0] == ATA_DEV_UNKNOWN &&
!(lflags & ATA_LFLAG_ASSUME_CLASS)) {
if (try < max_tries) {
ata_link_printk(link, KERN_WARNING,
"classification failed\n");
rc = -EINVAL;
goto fail;
}

if (rc == -EPIPE ||
try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1)
sata_down_spd_limit(link);
if (hardreset)
reset = hardreset;
goto retry;
ata_link_printk(link, KERN_WARNING,
"classfication failed, assuming ATA\n");
lflags |= ATA_LFLAG_ASSUME_ATA;
}

if (rc == 0) {
u32 sstatus;
ata_link_for_each_dev(dev, link) {
/* 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;

ata_link_for_each_dev(dev, link) {
/* 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_link_offline(link))
continue;

if (ata_link_offline(link))
continue;
/* apply class override and convert UNKNOWN to NONE */
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; /* not yet */
else if (classes[dev->devno] == ATA_DEV_UNKNOWN)
classes[dev->devno] = ATA_DEV_NONE;
}

/* apply class override and convert UNKNOWN to NONE */
if (link->flags & ATA_LFLAG_ASSUME_ATA)
classes[dev->devno] = ATA_DEV_ATA;
else if (link->flags & ATA_LFLAG_ASSUME_SEMB)
classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */
else if (classes[dev->devno] == ATA_DEV_UNKNOWN)
classes[dev->devno] = ATA_DEV_NONE;
}
/* record current link speed */
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
link->sata_spd = (sstatus >> 4) & 0xf;

/* record current link speed */
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
link->sata_spd = (sstatus >> 4) & 0xf;
if (postreset)
postreset(link, classes);

if (postreset)
postreset(link, classes);
/* reset successful, schedule revalidation */
ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
ehc->i.action |= ATA_EH_REVALIDATE;

/* reset successful, schedule revalidation */
ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
ehc->i.action |= ATA_EH_REVALIDATE;
}
rc = 0;
out:
/* clear hotplug flag */
ehc->i.flags &= ~ATA_EHI_HOTPLUGGED;
Expand All @@ -2266,6 +2258,28 @@ int ata_eh_reset(struct ata_link *link, int classify,
spin_unlock_irqrestore(ap->lock, flags);

return rc;

fail:
if (rc == -ERESTART || try >= max_tries)
goto out;

now = jiffies;
if (time_before(now, deadline)) {
unsigned long delta = deadline - now;

ata_link_printk(link, KERN_WARNING, "reset failed "
"(errno=%d), retrying in %u secs\n",
rc, (jiffies_to_msecs(delta) + 999) / 1000);

while (delta)
delta = schedule_timeout_uninterruptible(delta);
}

if (rc == -EPIPE || try == max_tries - 1)
sata_down_spd_limit(link);
if (hardreset)
reset = hardreset;
goto retry;
}

static int ata_eh_revalidate_and_attach(struct ata_link *link,
Expand Down
2 changes: 1 addition & 1 deletion drivers/ata/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ static const struct {
{ MEDIUM_POWER, "medium_power" },
};

const char *ata_scsi_lpm_get(enum link_pm policy)
static const char *ata_scsi_lpm_get(enum link_pm policy)
{
int i;

Expand Down
Loading

0 comments on commit 468f8af

Please sign in to comment.