Skip to content

Commit

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

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  libata: implement HORKAGE_1_5_GBPS and apply it to WD My Book
  libata: add no penalty retry request for EH device handling routines
  libata: improve probe failure handling
  libata: add @spd_limit to sata_down_spd_limit()
  libata: clear dev->ering in smarter way
  libata: check onlineness before using SPD in sata_down_spd_limit()
  libata: move ata_dev_disable() to libata-eh.c
  libata: fix EH device failure handling
  sata_nv: ck804 has borked hardreset too
  ide/libata: fix ata_id_is_cfa() (take 4)
  libata: fix kernel-doc warnings
  ahci: add a module parameter to ignore the SSS flags for async scanning
  sata_mv: Fix chip type for Hightpoint RocketRaid 1740/1742
  [libata] sata_sil: Fix compilation error with libata debugging enabled
  • Loading branch information
Linus Torvalds committed Feb 3, 2009
2 parents b1792e3 + 9062712 commit 52a84ec
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 53 deletions.
9 changes: 8 additions & 1 deletion drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,14 @@
#define EM_MSG_LED_VALUE_ON 0x00010000

static int ahci_skip_host_reset;
static int ahci_ignore_sss;

module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");

module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");

static int ahci_enable_alpm(struct ata_port *ap,
enum link_pm policy);
static void ahci_disable_alpm(struct ata_port *ap);
Expand Down Expand Up @@ -2692,8 +2697,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
host->iomap = pcim_iomap_table(pdev);
host->private_data = hpriv;

if (!(hpriv->cap & HOST_CAP_SSS))
if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
host->flags |= ATA_HOST_PARALLEL_SCAN;
else
printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");

if (pi.flags & ATA_FLAG_EM)
ahci_reset_em(host);
Expand Down
96 changes: 72 additions & 24 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);


static bool ata_sstatus_online(u32 sstatus)
{
return (sstatus & 0xf) == 0x3;
}

/**
* ata_link_next - link iteration helper
* @link: the previous link, NULL to start
Expand Down Expand Up @@ -1015,18 +1020,6 @@ static const char *sata_spd_string(unsigned int spd)
return spd_str[spd - 1];
}

void ata_dev_disable(struct ata_device *dev)
{
if (ata_dev_enabled(dev)) {
if (ata_msg_drv(dev->link->ap))
ata_dev_printk(dev, KERN_WARNING, "disabled\n");
ata_acpi_on_disable(dev);
ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 |
ATA_DNXFER_QUIET);
dev->class++;
}
}

static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
{
struct ata_link *link = dev->link;
Expand Down Expand Up @@ -2239,6 +2232,40 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
return rc;
}

static int ata_do_link_spd_horkage(struct ata_device *dev)
{
struct ata_link *plink = ata_dev_phys_link(dev);
u32 target, target_limit;

if (!sata_scr_valid(plink))
return 0;

if (dev->horkage & ATA_HORKAGE_1_5_GBPS)
target = 1;
else
return 0;

target_limit = (1 << target) - 1;

/* if already on stricter limit, no need to push further */
if (plink->sata_spd_limit <= target_limit)
return 0;

plink->sata_spd_limit = target_limit;

/* Request another EH round by returning -EAGAIN if link is
* going faster than the target speed. Forward progress is
* guaranteed by setting sata_spd_limit to target_limit above.
*/
if (plink->sata_spd > target) {
ata_dev_printk(dev, KERN_INFO,
"applying link speed limit horkage to %s\n",
sata_spd_string(target));
return -EAGAIN;
}
return 0;
}

static inline u8 ata_dev_knobble(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
Expand Down Expand Up @@ -2329,6 +2356,10 @@ int ata_dev_configure(struct ata_device *dev)
return 0;
}

rc = ata_do_link_spd_horkage(dev);
if (rc)
return rc;

/* let ACPI work its magic */
rc = ata_acpi_on_devcfg(dev);
if (rc)
Expand Down Expand Up @@ -2784,7 +2815,7 @@ int ata_bus_probe(struct ata_port *ap)
/* This is the last chance, better to slow
* down than lose it.
*/
sata_down_spd_limit(&ap->link);
sata_down_spd_limit(&ap->link, 0);
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
Expand Down Expand Up @@ -2880,21 +2911,27 @@ void ata_port_disable(struct ata_port *ap)
/**
* sata_down_spd_limit - adjust SATA spd limit downward
* @link: Link to adjust SATA spd limit for
* @spd_limit: Additional limit
*
* Adjust SATA spd limit of @link downward. Note that this
* function only adjusts the limit. The change must be applied
* using sata_set_spd().
*
* If @spd_limit is non-zero, the speed is limited to equal to or
* lower than @spd_limit if such speed is supported. If
* @spd_limit is slower than any supported speed, only the lowest
* supported speed is allowed.
*
* LOCKING:
* Inherited from caller.
*
* RETURNS:
* 0 on success, negative errno on failure
*/
int sata_down_spd_limit(struct ata_link *link)
int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
{
u32 sstatus, spd, mask;
int rc, highbit;
int rc, bit;

if (!sata_scr_valid(link))
return -EOPNOTSUPP;
Expand All @@ -2903,7 +2940,7 @@ int sata_down_spd_limit(struct ata_link *link)
* If not, use cached value in link->sata_spd.
*/
rc = sata_scr_read(link, SCR_STATUS, &sstatus);
if (rc == 0)
if (rc == 0 && ata_sstatus_online(sstatus))
spd = (sstatus >> 4) & 0xf;
else
spd = link->sata_spd;
Expand All @@ -2913,8 +2950,8 @@ int sata_down_spd_limit(struct ata_link *link)
return -EINVAL;

/* unconditionally mask off the highest bit */
highbit = fls(mask) - 1;
mask &= ~(1 << highbit);
bit = fls(mask) - 1;
mask &= ~(1 << bit);

/* Mask off all speeds higher than or equal to the current
* one. Force 1.5Gbps if current SPD is not available.
Expand All @@ -2928,6 +2965,15 @@ int sata_down_spd_limit(struct ata_link *link)
if (!mask)
return -EINVAL;

if (spd_limit) {
if (mask & ((1 << spd_limit) - 1))
mask &= (1 << spd_limit) - 1;
else {
bit = ffs(mask) - 1;
mask = 1 << bit;
}
}

link->sata_spd_limit = mask;

ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n",
Expand Down Expand Up @@ -4215,6 +4261,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices that do not need bridging limits applied */
{ "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, },

/* Devices which aren't very happy with higher link speeds */
{ "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },

/* End Marker */
{ }
};
Expand Down Expand Up @@ -4709,8 +4758,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)

/**
* ata_qc_new - Request an available ATA command, for queueing
* @ap: Port associated with device @dev
* @dev: Device from whom we request an available command structure
* @ap: target port
*
* LOCKING:
* None.
Expand Down Expand Up @@ -5175,7 +5223,7 @@ bool ata_phys_link_online(struct ata_link *link)
u32 sstatus;

if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
(sstatus & 0xf) == 0x3)
ata_sstatus_online(sstatus))
return true;
return false;
}
Expand All @@ -5199,7 +5247,7 @@ bool ata_phys_link_offline(struct ata_link *link)
u32 sstatus;

if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
(sstatus & 0xf) != 0x3)
!ata_sstatus_online(sstatus))
return true;
return false;
}
Expand Down Expand Up @@ -5412,8 +5460,8 @@ void ata_dev_init(struct ata_device *dev)
dev->horkage = 0;
spin_unlock_irqrestore(ap->lock, flags);

memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0,
sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET);
memset((void *)dev + ATA_DEVICE_CLEAR_BEGIN, 0,
ATA_DEVICE_CLEAR_END - ATA_DEVICE_CLEAR_BEGIN);
dev->pio_mask = UINT_MAX;
dev->mwdma_mask = UINT_MAX;
dev->udma_mask = UINT_MAX;
Expand Down
87 changes: 79 additions & 8 deletions drivers/ata/libata-eh.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ enum {
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
Expand Down Expand Up @@ -1175,6 +1179,32 @@ void ata_eh_qc_retry(struct ata_queued_cmd *qc)
__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;

if (ata_msg_drv(dev->link->ap))
ata_dev_printk(dev, KERN_WARNING, "disabled\n");
ata_acpi_on_disable(dev);
ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
dev->class++;

/* From now till the next successful probe, ering is used to
* track probe failures. Clear accumulated device error info.
*/
ata_ering_clear(&dev->ering);
}

/**
* ata_eh_detach_dev - detach ATA device
* @dev: ATA device to detach
Expand Down Expand Up @@ -1849,7 +1879,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
/* speed down? */
if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
/* speed down SATA link speed if possible */
if (sata_down_spd_limit(link) == 0) {
if (sata_down_spd_limit(link, 0) == 0) {
action |= ATA_EH_RESET;
goto done;
}
Expand Down Expand Up @@ -2601,11 +2631,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
}

if (try == max_tries - 1) {
sata_down_spd_limit(link);
sata_down_spd_limit(link, 0);
if (slave)
sata_down_spd_limit(slave);
sata_down_spd_limit(slave, 0);
} else if (rc == -EPIPE)
sata_down_spd_limit(failed_link);
sata_down_spd_limit(failed_link, 0);

if (hardreset)
reset = hardreset;
Expand Down Expand Up @@ -2744,6 +2774,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
readid_flags, dev->id);
switch (rc) {
case 0:
/* clear error info accumulated during probe */
ata_ering_clear(&dev->ering);
new_mask |= 1 << dev->devno;
break;
case -ENOENT:
Expand Down Expand Up @@ -2947,9 +2979,24 @@ static int ata_eh_skip_recovery(struct ata_link *link)
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->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)))
Expand All @@ -2962,14 +3009,37 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
ehc->saved_xfer_mode[dev->devno] = 0;
ehc->saved_ncq_enabled &= ~(1 << dev->devno);

/* 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.5Gbps.
*
* 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;

ehc->tries[dev->devno]--;
/* -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:
Expand All @@ -2979,12 +3049,13 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
/* give it just one more chance */
ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
case -EIO:
if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) {
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));
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
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);
}
}

Expand Down
Loading

0 comments on commit 52a84ec

Please sign in to comment.