Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52a84ec2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents b1792e36 9062712f
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -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);
@@ -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);
+72 −24
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -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;
@@ -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)
@@ -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);
		}
	}
@@ -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;
@@ -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;
@@ -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.
@@ -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",
@@ -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 */
	{ }
};
@@ -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.
@@ -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;
}
@@ -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;
}
@@ -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;
+79 −8
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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;
		}
@@ -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;
@@ -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:
@@ -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)))
@@ -2962,6 +3009,25 @@ 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;
}

@@ -2969,6 +3035,10 @@ 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) {
@@ -2979,11 +3049,12 @@ 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));
			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);
		}
	}
+1 −1
Original line number Diff line number Diff line
@@ -729,7 +729,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
		if (tries) {
			/* consecutive revalidation failures? speed down */
			if (reval_failed)
				sata_down_spd_limit(link);
				sata_down_spd_limit(link, 0);
			else
				reval_failed = 1;

+1 −0
Original line number Diff line number Diff line
@@ -415,6 +415,7 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,

/**
 *	ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
 *	@ap: target port
 *	@sdev: SCSI device to get identify data for
 *	@arg: User buffer area for identify data
 *
Loading