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

Commit 88e6c949 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: (28 commits)
  drivers/ata: trim trailing whitespace
  Fixups to ATA ACPI hotplug
  libata: ignore SIMG4726 config pseudo device
  sata_sil24: don't use NCQ if marvell 4140 PMP is attached
  libata: don't schedule LPM action seperately during probing
  libata: make sure PMP notification is turned off during recovery
  libata: increase PMP register access timeout to 3s
  libata: ignore recovered PHY errors
  libata: kill hotplug related race condition
  libata: move reset freeze/thaw handling into ata_eh_reset()
  libata: reorganize ata_eh_reset() no reset method path
  libata: fix sata_link_hardreset() @online out parameter handling
  sata_promise: other cleanups
  sata_promise: mmio access cleanups
  sata_promise: fix irq clearing buglets
  ata: remove FIT() macro
  sata_mv: ensure empty request queue for FBS-NCQ EH
  sata_mv: cache main_irq_mask register in hpriv
  sata_mv: disregard masked irqs
  sata_mv: fix pmp drives not found
  ...
parents 8c4bab3a c85665ff
Loading
Loading
Loading
Loading
+49 −26
Original line number Diff line number Diff line
@@ -118,8 +118,8 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
}

static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
				    u32 event)
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device
				    *dev, u32 event)
{
	char event_string[12];
	char *envp[] = { event_string, NULL };
@@ -127,6 +127,9 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
	struct kobject *kobj = NULL;
	int wait = 0;
	unsigned long flags;
	acpi_handle handle, tmphandle;
	unsigned long sta;
	acpi_status status;

	if (!ap)
		ap = dev->link->ap;
@@ -134,31 +137,56 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,

	spin_lock_irqsave(ap->lock, flags);

	if (dev)
		handle = dev->acpi_handle;
	else
		handle = ap->acpi_handle;

	status = acpi_get_handle(handle, "_EJ0", &tmphandle);
	if (ACPI_FAILURE(status)) {
		/* This device is not ejectable */
		spin_unlock_irqrestore(ap->lock, flags);
		return;
	}

	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
	if (ACPI_FAILURE(status)) {
		printk ("Unable to determine bay status\n");
		spin_unlock_irqrestore(ap->lock, flags);
		return;
	}

	switch (event) {
	case ACPI_NOTIFY_BUS_CHECK:
	case ACPI_NOTIFY_DEVICE_CHECK:
		ata_ehi_push_desc(ehi, "ACPI event");
		ata_ehi_hotplugged(ehi);
		ata_port_freeze(ap);
		break;

	case ACPI_NOTIFY_EJECT_REQUEST:
		ata_ehi_push_desc(ehi, "ACPI event");
		if (!sta) {
                /* Device has been unplugged */
			if (dev)
				dev->flags |= ATA_DFLAG_DETACH;
			else {
				struct ata_link *tlink;
				struct ata_device *tdev;

			ata_port_for_each_link(tlink, ap)
				ata_link_for_each_dev(tdev, tlink)
					tdev->flags |= ATA_DFLAG_DETACH;
				ata_port_for_each_link(tlink, ap) {
					ata_link_for_each_dev(tdev, tlink) {
						tdev->flags |=
							ATA_DFLAG_DETACH;
					}
				}
			}

			ata_port_schedule_eh(ap);
			wait = 1;
		break;
		} else {
			ata_ehi_hotplugged(ehi);
			ata_port_freeze(ap);
		}
	}

	spin_unlock_irqrestore(ap->lock, flags);

	if (wait)
		ata_port_wait_eh(ap);

	if (dev) {
		if (dev->sdev)
@@ -170,11 +198,6 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
		sprintf(event_string, "BAY_EVENT=%d", event);
		kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
	}

	spin_unlock_irqrestore(ap->lock, flags);

	if (wait)
		ata_port_wait_eh(ap);
}

static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
+22 −18
Original line number Diff line number Diff line
@@ -2126,6 +2126,13 @@ int ata_dev_configure(struct ata_device *dev)
	dev->horkage |= ata_dev_blacklisted(dev);
	ata_force_horkage(dev);

	if (dev->horkage & ATA_HORKAGE_DISABLE) {
		ata_dev_printk(dev, KERN_INFO,
			       "unsupported device, disabling\n");
		ata_dev_disable(dev);
		return 0;
	}

	/* let ACPI work its magic */
	rc = ata_acpi_on_devcfg(dev);
	if (rc)
@@ -3490,22 +3497,11 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
	if ((rc = sata_link_debounce(link, params, deadline)))
		return rc;

	/* Clear SError.  PMP and some host PHYs require this to
	 * operate and clearing should be done before checking PHY
	 * online status to avoid race condition (hotplugging between
	 * link resume and status check).
	 */
	/* clear SError, some PHYs require this even for SRST to work */
	if (!(rc = sata_scr_read(link, SCR_ERROR, &serror)))
		rc = sata_scr_write(link, SCR_ERROR, serror);
	if (rc == 0 || rc == -EINVAL) {
		unsigned long flags;

		spin_lock_irqsave(link->ap->lock, flags);
		link->eh_info.serror = 0;
		spin_unlock_irqrestore(link->ap->lock, flags);
		rc = 0;
	}
	return rc;
	return rc != -EINVAL ? rc : 0;
}

/**
@@ -3653,9 +3649,13 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
	if (check_ready)
		rc = ata_wait_ready(link, deadline, check_ready);
 out:
	if (rc && rc != -EAGAIN)
	if (rc && rc != -EAGAIN) {
		/* online is set iff link is online && reset succeeded */
		if (online)
			*online = false;
		ata_link_printk(link, KERN_ERR,
				"COMRESET failed (errno=%d)\n", rc);
	}
	DPRINTK("EXIT, rc=%d\n", rc);
	return rc;
}
@@ -3700,8 +3700,14 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
 */
void ata_std_postreset(struct ata_link *link, unsigned int *classes)
{
	u32 serror;

	DPRINTK("ENTER\n");

	/* reset complete, clear SError */
	if (!sata_scr_read(link, SCR_ERROR, &serror))
		sata_scr_write(link, SCR_ERROR, serror);

	/* print link status */
	sata_print_link_status(link);

@@ -3894,8 +3900,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
	{ "SAMSUNG CD-ROM SN-124", "N001",	ATA_HORKAGE_NODMA },
	{ "Seagate STT20000A", NULL,		ATA_HORKAGE_NODMA },
	/* Odd clown on sil3726/4726 PMPs */
	{ "Config  Disk",	NULL,		ATA_HORKAGE_NODMA |
						ATA_HORKAGE_SKIP_PM },
	{ "Config  Disk",	NULL,		ATA_HORKAGE_DISABLE },

	/* Weird ATAPI devices */
	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },
@@ -5616,7 +5621,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
			spin_lock_irqsave(ap->lock, flags);

			ehi->probe_mask |= ATA_ALL_DEVICES;
			ehi->action |= ATA_EH_RESET;
			ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
			ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;

			ap->pflags &= ~ATA_PFLAG_INITIALIZING;
@@ -5649,7 +5654,6 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
		struct ata_port *ap = host->ports[i];

		ata_scsi_scan_host(ap, 1);
		ata_lpm_schedule(ap, ap->pm_policy);
	}

	return 0;
+113 −94
Original line number Diff line number Diff line
@@ -1308,12 +1308,7 @@ static void ata_eh_analyze_serror(struct ata_link *link)
	unsigned int err_mask = 0, action = 0;
	u32 hotplug_mask;

	if (serror & SERR_PERSISTENT) {
		err_mask |= AC_ERR_ATA_BUS;
		action |= ATA_EH_RESET;
	}
	if (serror &
	    (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
	if (serror & (SERR_PERSISTENT | SERR_DATA)) {
		err_mask |= AC_ERR_ATA_BUS;
		action |= ATA_EH_RESET;
	}
@@ -2047,19 +2042,11 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
			unsigned int *classes, unsigned long deadline)
{
	struct ata_device *dev;
	int rc;

	ata_link_for_each_dev(dev, link)
		classes[dev->devno] = ATA_DEV_UNKNOWN;

	rc = reset(link, classes, deadline);

	/* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
	ata_link_for_each_dev(dev, link)
		if (classes[dev->devno] == ATA_DEV_UNKNOWN)
			classes[dev->devno] = ATA_DEV_NONE;

	return rc;
	return reset(link, classes, deadline);
}

static int ata_eh_followup_srst_needed(struct ata_link *link,
@@ -2096,9 +2083,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
	ata_reset_fn_t reset;
	unsigned long flags;
	u32 sstatus;
	int rc;
	int nr_known, rc;

	/* about to reset */
	/*
	 * Prepare to reset
	 */
	spin_lock_irqsave(ap->lock, flags);
	ap->pflags |= ATA_PFLAG_RESETTING;
	spin_unlock_irqrestore(ap->lock, flags);
@@ -2124,16 +2113,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
			ap->ops->set_piomode(ap, dev);
	}

	if (!softreset && !hardreset) {
		if (verbose)
			ata_link_printk(link, KERN_INFO, "no reset method "
					"available, skipping reset\n");
		if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
			lflags |= ATA_LFLAG_ASSUME_ATA;
		goto done;
	}

	/* prefer hardreset */
	reset = NULL;
	ehc->i.action &= ~ATA_EH_RESET;
	if (hardreset) {
		reset = hardreset;
@@ -2141,11 +2122,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
	} else if (softreset) {
		reset = softreset;
		ehc->i.action = ATA_EH_SOFTRESET;
	} else {
		ata_link_printk(link, KERN_ERR, "BUG: no reset method, "
				"please report to linux-ide@vger.kernel.org\n");
		dump_stack();
		return -EINVAL;
	}

	if (prereset) {
@@ -2165,21 +2141,28 @@ int ata_eh_reset(struct ata_link *link, int classify,
					"prereset failed (errno=%d)\n", rc);
			goto out;
		}
	}

	/* prereset() might have cleared ATA_EH_RESET */
	if (!(ehc->i.action & ATA_EH_RESET)) {
		/* prereset told us not to reset, bang classes and return */
		/* prereset() might have cleared ATA_EH_RESET.  If so,
		 * bang classes and return.
		 */
		if (reset && !(ehc->i.action & ATA_EH_RESET)) {
			ata_link_for_each_dev(dev, link)
				classes[dev->devno] = ATA_DEV_NONE;
			rc = 0;
			goto out;
		}
	}

 retry:
	/*
	 * Perform reset
	 */
	if (ata_is_host_link(link))
		ata_eh_freeze_port(ap);

	deadline = jiffies + ata_eh_reset_timeouts[try++];

	/* shut up during boot probing */
	if (reset) {
		if (verbose)
			ata_link_printk(link, KERN_INFO, "%s resetting link\n",
					reset == softreset ? "soft" : "hard");
@@ -2212,8 +2195,17 @@ int ata_eh_reset(struct ata_link *link, int classify,
		/* -EAGAIN can happen if we skipped followup SRST */
		if (rc && rc != -EAGAIN)
			goto fail;
	} else {
		if (verbose)
			ata_link_printk(link, KERN_INFO, "no reset method "
					"available, skipping reset\n");
		if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
			lflags |= ATA_LFLAG_ASSUME_ATA;
	}

 done:
	/*
	 * Post-reset processing
	 */
	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
@@ -2236,9 +2228,53 @@ int ata_eh_reset(struct ata_link *link, int classify,
	if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
		link->sata_spd = (sstatus >> 4) & 0xf;

	/* 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);

	/* clear cached SError */
	spin_lock_irqsave(link->ap->lock, flags);
	link->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 onlineness and classification result, those conditions
	 * can be reliably detected and retried.
	 */
	nr_known = 0;
	ata_link_for_each_dev(dev, link) {
		/* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
		if (classes[dev->devno] == ATA_DEV_UNKNOWN)
			classes[dev->devno] = ATA_DEV_NONE;
		else
			nr_known++;
	}

	if (classify && !nr_known && ata_link_online(link)) {
		if (try < max_tries) {
			ata_link_printk(link, KERN_WARNING, "link online but "
				       "device misclassified, retrying\n");
			rc = -EAGAIN;
			goto fail;
		}
		ata_link_printk(link, KERN_WARNING,
			       "link online but device misclassified, "
			       "device detection might fail\n");
	}

	/* reset successful, schedule revalidation */
	ata_eh_done(link, NULL, ATA_EH_RESET);
	ehc->i.action |= ATA_EH_REVALIDATE;
@@ -2587,7 +2623,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
	struct ata_link *link;
	struct ata_device *dev;
	int nr_failed_devs, nr_disabled_devs;
	int reset, rc;
	int rc;
	unsigned long flags;

	DPRINTK("ENTER\n");
@@ -2630,7 +2666,6 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
	rc = 0;
	nr_failed_devs = 0;
	nr_disabled_devs = 0;
	reset = 0;

	/* if UNLOADING, finish immediately */
	if (ap->pflags & ATA_PFLAG_UNLOADING)
@@ -2644,22 +2679,11 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
		if (ata_eh_skip_recovery(link))
			ehc->i.action = 0;

		/* do we need to reset? */
		if (ehc->i.action & ATA_EH_RESET)
			reset = 1;

		ata_link_for_each_dev(dev, link)
			ehc->classes[dev->devno] = ATA_DEV_UNKNOWN;
	}

	/* reset */
	if (reset) {
		/* if PMP is attached, this function only deals with
		 * downstream links, port should stay thawed.
		 */
		if (!sata_pmp_attached(ap))
			ata_eh_freeze_port(ap);

	ata_port_for_each_link(link, ap) {
		struct ata_eh_context *ehc = &link->eh_context;

@@ -2667,8 +2691,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
			continue;

		rc = ata_eh_reset(link, ata_link_nr_vacant(link),
					  prereset, softreset, hardreset,
					  postreset);
				  prereset, softreset, hardreset, postreset);
		if (rc) {
			ata_link_printk(link, KERN_ERR,
					"reset failed, giving up\n");
@@ -2676,10 +2699,6 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
		}
	}

		if (!sata_pmp_attached(ap))
			ata_eh_thaw_port(ap);
	}

	/* the rest */
	ata_port_for_each_link(link, ap) {
		struct ata_eh_context *ehc = &link->eh_context;
+22 −22
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ static unsigned int sata_pmp_read(struct ata_link *link, int reg, u32 *r_val)
	tf.device = link->pmp;

	err_mask = ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0,
				     SATA_PMP_SCR_TIMEOUT);
				     SATA_PMP_RW_TIMEOUT);
	if (err_mask)
		return err_mask;

@@ -88,7 +88,7 @@ static unsigned int sata_pmp_write(struct ata_link *link, int reg, u32 val)
	tf.lbah = (val >> 24) & 0xff;

	return ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0,
				 SATA_PMP_SCR_TIMEOUT);
				 SATA_PMP_RW_TIMEOUT);
}

/**
@@ -257,19 +257,6 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
		goto fail;
	}

	/* turn off notification till fan-out ports are reset and configured */
	if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) {
		gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY;

		err_mask = sata_pmp_write(dev->link, SATA_PMP_GSCR_FEAT_EN,
					  gscr[SATA_PMP_GSCR_FEAT_EN]);
		if (err_mask) {
			rc = -EIO;
			reason = "failed to write GSCR_FEAT_EN";
			goto fail;
		}
	}

	if (print_info) {
		ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
			       "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
@@ -700,8 +687,6 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
	if (ehc->i.action & ATA_EH_RESET) {
		struct ata_link *tlink;

		ata_eh_freeze_port(ap);

		/* reset */
		rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
				  postreset);
@@ -711,8 +696,6 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
			goto fail;
		}

		ata_eh_thaw_port(ap);

		/* PMP is reset, SErrors cannot be trusted, scan all */
		ata_port_for_each_link(tlink, ap) {
			struct ata_eh_context *ehc = &tlink->eh_context;
@@ -864,6 +847,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
	struct ata_link *pmp_link = &ap->link;
	struct ata_device *pmp_dev = pmp_link->device;
	struct ata_eh_context *pmp_ehc = &pmp_link->eh_context;
	u32 *gscr = pmp_dev->gscr;
	struct ata_link *link;
	struct ata_device *dev;
	unsigned int err_mask;
@@ -901,6 +885,22 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
	if (rc)
		goto pmp_fail;

	/* PHY event notification can disturb reset and other recovery
	 * operations.  Turn it off.
	 */
	if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) {
		gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY;

		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
					  gscr[SATA_PMP_GSCR_FEAT_EN]);
		if (err_mask) {
			ata_link_printk(pmp_link, KERN_WARNING,
				"failed to disable NOTIFY (err_mask=0x%x)\n",
				err_mask);
			goto pmp_fail;
		}
	}

	/* handle disabled links */
	rc = sata_pmp_eh_handle_disabled_links(ap);
	if (rc)
@@ -923,10 +923,10 @@ static int sata_pmp_eh_recover(struct ata_port *ap)

	/* enable notification */
	if (pmp_dev->flags & ATA_DFLAG_AN) {
		pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;
		gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;

		err_mask = sata_pmp_write(pmp_dev->link, SATA_PMP_GSCR_FEAT_EN,
					  pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN]);
		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
					  gscr[SATA_PMP_GSCR_FEAT_EN]);
		if (err_mask) {
			ata_dev_printk(pmp_dev, KERN_ERR, "failed to write "
				       "PMP_FEAT_EN (Emask=0x%x)\n", err_mask);
+0 −6
Original line number Diff line number Diff line
@@ -1082,12 +1082,6 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
	if (((cdb[4] >> 4) & 0xf) != 0)
		goto invalid_fld;       /* power conditions not supported */

	if (qc->dev->horkage & ATA_HORKAGE_SKIP_PM) {
		/* the device lacks PM support, finish without doing anything */
		scmd->result = SAM_STAT_GOOD;
		return 1;
	}

	if (cdb[4] & 0x1) {
		tf->nsect = 1;	/* 1 sector, lba=0 */

Loading