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

Commit 4750def5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'reset-seq' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'reset-seq' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  [libata reset-seq] build and merge fixes
  libata: reimplement reset sequencing
  libata: improve ata_std_prereset()
  libata: improve 0xff status handling
  libata: add deadline support to prereset and reset methods
parents 9028780a 27c78b37
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
@@ -874,7 +874,8 @@ static int ahci_clo(struct ata_port *ap)
	return 0;
}

static int ahci_softreset(struct ata_port *ap, unsigned int *class)
static int ahci_softreset(struct ata_port *ap, unsigned int *class,
			  unsigned long deadline)
{
	struct ahci_port_priv *pp = ap->private_data;
	void __iomem *port_mmio = ahci_port_base(ap);
@@ -959,15 +960,13 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
	 */
	msleep(150);

	*class = ATA_DEV_NONE;
	if (ata_port_online(ap)) {
		if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
			rc = -EIO;
	rc = ata_wait_ready(ap, deadline);
	/* link occupied, -ENODEV too is an error */
	if (rc) {
		reason = "device not ready";
		goto fail;
	}
	*class = ahci_dev_classify(ap);
	}

	DPRINTK("EXIT, class=%u\n", *class);
	return 0;
@@ -979,7 +978,8 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
	return rc;
}

static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
static int ahci_hardreset(struct ata_port *ap, unsigned int *class,
			  unsigned long deadline)
{
	struct ahci_port_priv *pp = ap->private_data;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
@@ -995,7 +995,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
	tf.command = 0x80;
	ata_tf_to_fis(&tf, d2h_fis, 0);

	rc = sata_std_hardreset(ap, class);
	rc = sata_std_hardreset(ap, class, deadline);

	ahci_start_engine(ap);

@@ -1008,7 +1008,8 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
	return rc;
}

static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class,
				 unsigned long deadline)
{
	int rc;

@@ -1016,7 +1017,8 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)

	ahci_stop_engine(ap);

	rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
	rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context),
				 deadline);

	/* vt8251 needs SError cleared for the port to operate */
	ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
+3 −3
Original line number Diff line number Diff line
@@ -625,17 +625,18 @@ static int ich_pata_cable_detect(struct ata_port *ap)
/**
 *	piix_pata_prereset - prereset for PATA host controller
 *	@ap: Target port
 *	@deadline: deadline jiffies for the operation
 *
 *	LOCKING:
 *	None (inherited from caller).
 */
static int piix_pata_prereset(struct ata_port *ap)
static int piix_pata_prereset(struct ata_port *ap, unsigned long deadline)
{
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);

	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
		return -ENOENT;
	return ata_std_prereset(ap);
	return ata_std_prereset(ap, deadline);
}

static void piix_pata_error_handler(struct ata_port *ap)
@@ -644,7 +645,6 @@ static void piix_pata_error_handler(struct ata_port *ap)
			   ata_std_postreset);
}


static void piix_sata_error_handler(struct ata_port *ap)
{
	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+138 −87
Original line number Diff line number Diff line
@@ -2979,23 +2979,71 @@ int ata_busy_sleep(struct ata_port *ap,
	return 0;
}

static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
/**
 *	ata_wait_ready - sleep until BSY clears, or timeout
 *	@ap: port containing status register to be polled
 *	@deadline: deadline jiffies for the operation
 *
 *	Sleep until ATA Status register bit BSY clears, or timeout
 *	occurs.
 *
 *	LOCKING:
 *	Kernel thread context (may sleep).
 *
 *	RETURNS:
 *	0 on success, -errno otherwise.
 */
int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
{
	unsigned long start = jiffies;
	int warned = 0;

	while (1) {
		u8 status = ata_chk_status(ap);
		unsigned long now = jiffies;

		if (!(status & ATA_BUSY))
			return 0;
		if (status == 0xff)
			return -ENODEV;
		if (time_after(now, deadline))
			return -EBUSY;

		if (!warned && time_after(now, start + 5 * HZ) &&
		    (deadline - now > 3 * HZ)) {
			ata_port_printk(ap, KERN_WARNING,
				"port is slow to respond, please be patient "
				"(Status 0x%x)\n", status);
			warned = 1;
		}

		msleep(50);
	}
}

static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
			      unsigned long deadline)
{
	struct ata_ioports *ioaddr = &ap->ioaddr;
	unsigned int dev0 = devmask & (1 << 0);
	unsigned int dev1 = devmask & (1 << 1);
	unsigned long timeout;
	int rc, ret = 0;

	/* if device 0 was found in ata_devchk, wait for its
	 * BSY bit to clear
	 */
	if (dev0)
		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
	if (dev0) {
		rc = ata_wait_ready(ap, deadline);
		if (rc) {
			if (rc != -ENODEV)
				return rc;
			ret = rc;
		}
	}

	/* if device 1 was found in ata_devchk, wait for
	 * register access, then wait for BSY to clear
	 */
	timeout = jiffies + ATA_TMOUT_BOOT;
	while (dev1) {
		u8 nsect, lbal;

@@ -3004,14 +3052,18 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
		lbal = ioread8(ioaddr->lbal_addr);
		if ((nsect == 1) && (lbal == 1))
			break;
		if (time_after(jiffies, timeout)) {
			dev1 = 0;
			break;
		}
		if (time_after(jiffies, deadline))
			return -EBUSY;
		msleep(50);	/* give drive a breather */
	}
	if (dev1)
		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
	if (dev1) {
		rc = ata_wait_ready(ap, deadline);
		if (rc) {
			if (rc != -ENODEV)
				return rc;
			ret = rc;
		}
	}

	/* is all this really necessary? */
	ap->ops->dev_select(ap, 0);
@@ -3019,10 +3071,12 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
		ap->ops->dev_select(ap, 1);
	if (dev0)
		ap->ops->dev_select(ap, 0);

	return ret;
}

static unsigned int ata_bus_softreset(struct ata_port *ap,
				      unsigned int devmask)
static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
			     unsigned long deadline)
{
	struct ata_ioports *ioaddr = &ap->ioaddr;

@@ -3052,11 +3106,9 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
	 * pulldown resistor.
	 */
	if (ata_check_status(ap) == 0xFF)
		return 0;

	ata_bus_post_reset(ap, devmask);
		return -ENODEV;

	return 0;
	return ata_bus_post_reset(ap, devmask, deadline);
}

/**
@@ -3085,6 +3137,7 @@ void ata_bus_reset(struct ata_port *ap)
	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
	u8 err;
	unsigned int dev0, dev1 = 0, devmask = 0;
	int rc;

	DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);

@@ -3106,9 +3159,11 @@ void ata_bus_reset(struct ata_port *ap)
	ap->ops->dev_select(ap, 0);

	/* issue bus reset */
	if (ap->flags & ATA_FLAG_SRST)
		if (ata_bus_softreset(ap, devmask))
	if (ap->flags & ATA_FLAG_SRST) {
		rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
		if (rc && rc != -ENODEV)
			goto err_out;
	}

	/*
	 * determine by signature whether we have ATA or ATAPI devices
@@ -3150,29 +3205,37 @@ void ata_bus_reset(struct ata_port *ap)
 *	sata_phy_debounce - debounce SATA phy status
 *	@ap: ATA port to debounce SATA phy status for
 *	@params: timing parameters { interval, duratinon, timeout } in msec
 *	@deadline: deadline jiffies for the operation
 *
 *	Make sure SStatus of @ap reaches stable state, determined by
 *	holding the same value where DET is not 1 for @duration polled
 *	every @interval, before @timeout.  Timeout constraints the
 *	beginning of the stable state.  Because, after hot unplugging,
 *	DET gets stuck at 1 on some controllers, this functions waits
 *	beginning of the stable state.  Because DET gets stuck at 1 on
 *	some controllers after hot unplugging, this functions waits
 *	until timeout then returns 0 if DET is stable at 1.
 *
 *	@timeout is further limited by @deadline.  The sooner of the
 *	two is used.
 *
 *	LOCKING:
 *	Kernel thread context (may sleep)
 *
 *	RETURNS:
 *	0 on success, -errno on failure.
 */
int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
int sata_phy_debounce(struct ata_port *ap, const unsigned long *params,
		      unsigned long deadline)
{
	unsigned long interval_msec = params[0];
	unsigned long duration = params[1] * HZ / 1000;
	unsigned long timeout = jiffies + params[2] * HZ / 1000;
	unsigned long last_jiffies;
	unsigned long duration = msecs_to_jiffies(params[1]);
	unsigned long last_jiffies, t;
	u32 last, cur;
	int rc;

	t = jiffies + msecs_to_jiffies(params[2]);
	if (time_before(t, deadline))
		deadline = t;

	if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
		return rc;
	cur &= 0xf;
@@ -3188,7 +3251,7 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)

		/* DET stable? */
		if (cur == last) {
			if (cur == 1 && time_before(jiffies, timeout))
			if (cur == 1 && time_before(jiffies, deadline))
				continue;
			if (time_after(jiffies, last_jiffies + duration))
				return 0;
@@ -3199,8 +3262,8 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
		last = cur;
		last_jiffies = jiffies;

		/* check timeout */
		if (time_after(jiffies, timeout))
		/* check deadline */
		if (time_after(jiffies, deadline))
			return -EBUSY;
	}
}
@@ -3209,6 +3272,7 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
 *	sata_phy_resume - resume SATA phy
 *	@ap: ATA port to resume SATA phy for
 *	@params: timing parameters { interval, duratinon, timeout } in msec
 *	@deadline: deadline jiffies for the operation
 *
 *	Resume SATA phy of @ap and debounce it.
 *
@@ -3218,7 +3282,8 @@ int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
 *	RETURNS:
 *	0 on success, -errno on failure.
 */
int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
int sata_phy_resume(struct ata_port *ap, const unsigned long *params,
		    unsigned long deadline)
{
	u32 scontrol;
	int rc;
@@ -3236,43 +3301,19 @@ int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
	 */
	msleep(200);

	return sata_phy_debounce(ap, params);
}

static void ata_wait_spinup(struct ata_port *ap)
{
	struct ata_eh_context *ehc = &ap->eh_context;
	unsigned long end, secs;
	int rc;

	/* first, debounce phy if SATA */
	if (ap->cbl == ATA_CBL_SATA) {
		rc = sata_phy_debounce(ap, sata_deb_timing_hotplug);

		/* if debounced successfully and offline, no need to wait */
		if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
			return;
	}

	/* okay, let's give the drive time to spin up */
	end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000;
	secs = ((end - jiffies) + HZ - 1) / HZ;

	if (time_after(jiffies, end))
		return;

	if (secs > 5)
		ata_port_printk(ap, KERN_INFO, "waiting for device to spin up "
				"(%lu secs)\n", secs);

	schedule_timeout_uninterruptible(end - jiffies);
	return sata_phy_debounce(ap, params, deadline);
}

/**
 *	ata_std_prereset - prepare for reset
 *	@ap: ATA port to be reset
 *	@deadline: deadline jiffies for the operation
 *
 *	@ap is about to be reset.  Initialize it.
 *	@ap is about to be reset.  Initialize it.  Failure from
 *	prereset makes libata abort whole reset sequence and give up
 *	that port, so prereset should be best-effort.  It does its
 *	best to prepare for reset sequence but if things go wrong, it
 *	should just whine, not fail.
 *
 *	LOCKING:
 *	Kernel thread context (may sleep)
@@ -3280,41 +3321,41 @@ static void ata_wait_spinup(struct ata_port *ap)
 *	RETURNS:
 *	0 on success, -errno otherwise.
 */
int ata_std_prereset(struct ata_port *ap)
int ata_std_prereset(struct ata_port *ap, unsigned long deadline)
{
	struct ata_eh_context *ehc = &ap->eh_context;
	const unsigned long *timing = sata_ehc_deb_timing(ehc);
	int rc;

	/* handle link resume & hotplug spinup */
	/* handle link resume */
	if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
	    (ap->flags & ATA_FLAG_HRST_TO_RESUME))
		ehc->i.action |= ATA_EH_HARDRESET;

	if ((ehc->i.flags & ATA_EHI_HOTPLUGGED) &&
	    (ap->flags & ATA_FLAG_SKIP_D2H_BSY))
		ata_wait_spinup(ap);

	/* if we're about to do hardreset, nothing more to do */
	if (ehc->i.action & ATA_EH_HARDRESET)
		return 0;

	/* if SATA, resume phy */
	if (ap->cbl == ATA_CBL_SATA) {
		rc = sata_phy_resume(ap, timing);
		if (rc && rc != -EOPNOTSUPP) {
			/* phy resume failed */
		rc = sata_phy_resume(ap, timing, deadline);
		/* whine about phy resume failure but proceed */
		if (rc && rc != -EOPNOTSUPP)
			ata_port_printk(ap, KERN_WARNING, "failed to resume "
					"link for reset (errno=%d)\n", rc);
			return rc;
		}
	}

	/* Wait for !BSY if the controller can wait for the first D2H
	 * Reg FIS and we don't know that no device is attached.
	 */
	if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap))
		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
	if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap)) {
		rc = ata_wait_ready(ap, deadline);
		if (rc) {
			ata_port_printk(ap, KERN_WARNING, "device not ready "
					"(errno=%d), forcing hardreset\n", rc);
			ehc->i.action |= ATA_EH_HARDRESET;
		}
	}

	return 0;
}
@@ -3323,6 +3364,7 @@ int ata_std_prereset(struct ata_port *ap)
 *	ata_std_softreset - reset host port via ATA SRST
 *	@ap: port to reset
 *	@classes: resulting classes of attached devices
 *	@deadline: deadline jiffies for the operation
 *
 *	Reset host port using ATA SRST.
 *
@@ -3332,10 +3374,12 @@ int ata_std_prereset(struct ata_port *ap)
 *	RETURNS:
 *	0 on success, -errno otherwise.
 */
int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
int ata_std_softreset(struct ata_port *ap, unsigned int *classes,
		      unsigned long deadline)
{
	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
	unsigned int devmask = 0, err_mask;
	unsigned int devmask = 0;
	int rc;
	u8 err;

	DPRINTK("ENTER\n");
@@ -3356,11 +3400,11 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)

	/* issue bus reset */
	DPRINTK("about to softreset, devmask=%x\n", devmask);
	err_mask = ata_bus_softreset(ap, devmask);
	if (err_mask) {
		ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
				err_mask);
		return -EIO;
	rc = ata_bus_softreset(ap, devmask, deadline);
	/* if link is occupied, -ENODEV too is an error */
	if (rc && (rc != -ENODEV || sata_scr_valid(ap))) {
		ata_port_printk(ap, KERN_ERR, "SRST failed (errno=%d)\n", rc);
		return rc;
	}

	/* determine by signature whether we have ATA or ATAPI devices */
@@ -3377,6 +3421,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
 *	sata_port_hardreset - reset port via SATA phy reset
 *	@ap: port to reset
 *	@timing: timing parameters { interval, duratinon, timeout } in msec
 *	@deadline: deadline jiffies for the operation
 *
 *	SATA phy-reset host port using DET bits of SControl register.
 *
@@ -3386,7 +3431,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
 *	RETURNS:
 *	0 on success, -errno otherwise.
 */
int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing,
			unsigned long deadline)
{
	u32 scontrol;
	int rc;
@@ -3425,7 +3471,7 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
	msleep(1);

	/* bring phy back */
	rc = sata_phy_resume(ap, timing);
	rc = sata_phy_resume(ap, timing, deadline);
 out:
	DPRINTK("EXIT, rc=%d\n", rc);
	return rc;
@@ -3435,6 +3481,7 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
 *	sata_std_hardreset - reset host port via SATA phy reset
 *	@ap: port to reset
 *	@class: resulting class of attached device
 *	@deadline: deadline jiffies for the operation
 *
 *	SATA phy-reset host port using DET bits of SControl register,
 *	wait for !BSY and classify the attached device.
@@ -3445,7 +3492,8 @@ int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing)
 *	RETURNS:
 *	0 on success, -errno otherwise.
 */
int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
int sata_std_hardreset(struct ata_port *ap, unsigned int *class,
		       unsigned long deadline)
{
	const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context);
	int rc;
@@ -3453,7 +3501,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
	DPRINTK("ENTER\n");

	/* do hardreset */
	rc = sata_port_hardreset(ap, timing);
	rc = sata_port_hardreset(ap, timing, deadline);
	if (rc) {
		ata_port_printk(ap, KERN_ERR,
				"COMRESET failed (errno=%d)\n", rc);
@@ -3470,10 +3518,12 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
	/* wait a while before checking status, see SRST for more info */
	msleep(150);

	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
	rc = ata_wait_ready(ap, deadline);
	/* link occupied, -ENODEV too is an error */
	if (rc) {
		ata_port_printk(ap, KERN_ERR,
				"COMRESET failed (device not ready)\n");
		return -EIO;
				"COMRESET failed (errno=%d)\n", rc);
		return rc;
	}

	ap->ops->dev_select(ap, 0);	/* probably unnecessary */
@@ -6793,6 +6843,7 @@ EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_wait_register);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
EXPORT_SYMBOL_GPL(ata_wait_ready);
EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
+43 −19
Original line number Diff line number Diff line
@@ -50,6 +50,28 @@ enum {
	ATA_EH_SPDN_FALLBACK_TO_PIO	= (1 << 2),
};

/* 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.
 */
enum {
	ATA_EH_PRERESET_TIMEOUT		= 10 * HZ,
};

/* 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/ 10sec timeout should succeed.  Following entries
 * are mostly for error handling, hotplug and retarded devices.
 */
static const unsigned long ata_eh_reset_timeouts[] = {
	10 * HZ,	/* most drives spin up by 10sec */
	10 * HZ,	/* > 99% working drives spin up before 20sec */
	35 * HZ,	/* give > 30 secs of idleness for retarded devices */
	5 * HZ,		/* and sweet one last chance */
	/* > 1 min has elapsed, give up */
};

static void __ata_port_freeze(struct ata_port *ap);
static void ata_eh_finish(struct ata_port *ap);
#ifdef CONFIG_PM
@@ -1558,14 +1580,14 @@ static void ata_eh_report(struct ata_port *ap)
}

static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
			unsigned int *classes)
			unsigned int *classes, unsigned long deadline)
{
	int i, rc;

	for (i = 0; i < ATA_MAX_DEVICES; i++)
		classes[i] = ATA_DEV_UNKNOWN;

	rc = reset(ap, classes);
	rc = reset(ap, classes, deadline);
	if (rc)
		return rc;

@@ -1603,8 +1625,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
{
	struct ata_eh_context *ehc = &ap->eh_context;
	unsigned int *classes = ehc->classes;
	int tries = ATA_EH_RESET_TRIES;
	int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
	int try = 0;
	unsigned long deadline;
	unsigned int action;
	ata_reset_fn_t reset;
	int i, did_followup_srst, rc;
@@ -1624,7 +1647,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
		ehc->i.action |= ATA_EH_HARDRESET;

	if (prereset) {
		rc = prereset(ap);
		rc = prereset(ap, jiffies + ATA_EH_PRERESET_TIMEOUT);
		if (rc) {
			if (rc == -ENOENT) {
				ata_port_printk(ap, KERN_DEBUG,
@@ -1665,6 +1688,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
	}

 retry:
	deadline = jiffies + ata_eh_reset_timeouts[try++];

	/* shut up during boot probing */
	if (verbose)
		ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
@@ -1676,7 +1701,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
	else
		ehc->i.flags |= ATA_EHI_DID_SOFTRESET;

	rc = ata_do_reset(ap, reset, classes);
	rc = ata_do_reset(ap, reset, classes, deadline);

	did_followup_srst = 0;
	if (reset == hardreset &&
@@ -1693,7 +1718,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
		}

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

		if (rc == 0 && classify &&
		    classes[0] == ATA_DEV_UNKNOWN) {
@@ -1703,22 +1728,21 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
		}
	}

	if (rc && --tries) {
		const char *type;
	if (rc && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
		unsigned long now = jiffies;

		if (reset == softreset) {
			if (did_followup_srst)
				type = "follow-up soft";
			else
				type = "soft";
		} else
			type = "hard";
		if (time_before(now, deadline)) {
			unsigned long delta = deadline - jiffies;

		ata_port_printk(ap, KERN_WARNING,
				"%sreset failed, retrying in 5 secs\n", type);
		ssleep(5);
			ata_port_printk(ap, KERN_WARNING, "reset failed "
				"(errno=%d), retrying in %u secs\n",
				rc, (jiffies_to_msecs(delta) + 999) / 1000);

		if (reset == hardreset)
			schedule_timeout_uninterruptible(delta);
		}

		if (reset == hardreset &&
		    try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1)
			sata_down_spd_limit(ap);
		if (hardreset)
			reset = hardreset;
+6 −5
Original line number Diff line number Diff line
@@ -121,12 +121,13 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
/**
 *	amd_probe_init		-	perform reset handling
 *	@ap: ATA port
 *	@deadline: deadline jiffies for the operation
 *
 *	Reset sequence checking enable bits to see which ports are
 *	active.
 */

static int amd_pre_reset(struct ata_port *ap)
static int amd_pre_reset(struct ata_port *ap, unsigned long deadline)
{
	static const struct pci_bits amd_enable_bits[] = {
		{ 0x40, 1, 0x02, 0x02 },
@@ -138,8 +139,7 @@ static int amd_pre_reset(struct ata_port *ap)
	if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
		return -ENOENT;

	return ata_std_prereset(ap);

	return ata_std_prereset(ap, deadline);
}

static void amd_error_handler(struct ata_port *ap)
@@ -227,7 +227,8 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 *	space for us.
 */

static int nv_pre_reset(struct ata_port *ap) {
static int nv_pre_reset(struct ata_port *ap, unsigned long deadline)
{
	static const struct pci_bits nv_enable_bits[] = {
		{ 0x50, 1, 0x02, 0x02 },
		{ 0x50, 1, 0x01, 0x01 }
@@ -238,7 +239,7 @@ static int nv_pre_reset(struct ata_port *ap) {
	if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no]))
		return -ENOENT;

	return ata_std_prereset(ap);
	return ata_std_prereset(ap, deadline);
}

static void nv_error_handler(struct ata_port *ap)
Loading