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

Commit baa1e78a authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik
Browse files

[PATCH] libata: implement ATA_EHI_SETMODE and ATA_EHI_POST_SETMODE



libata EH used to perform ata_set_mode() iff the EH session performed
reset as indicated by ATA_EHI_DID_RESET.  This is incorrect because
->dev_config() called by revalidation is allowed to modify transfer
mode which ata_set_mode() should take care of.  This patch implements
the following two flags.

* ATA_EHI_SETMODE: set during EH to schedule ata_set_mode().  Both new
  device attachment and revalidation set this flag.

* ATA_EHI_POST_SETMODE: set while the device is revalidated after
  ata_set_mode().  Post-setmode revalidation is different from initial
  configuaration and EH revalidation in that ->dev_config() is not
  allowed tune transfer mode.  LLD can use this flag to determine
  whether it's allowed to tune transfer mode.  Note that POST_SETMODE
  ->dev_config() is guaranteed to be preceded by non-POST_SETMODE
  ->dev_config().

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent efdaedc4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2158,6 +2158,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)

static int ata_dev_set_mode(struct ata_device *dev)
{
	struct ata_eh_context *ehc = &dev->ap->eh_context;
	unsigned int err_mask;
	int rc;

@@ -2172,7 +2173,9 @@ static int ata_dev_set_mode(struct ata_device *dev)
		return -EIO;
	}

	ehc->i.flags |= ATA_EHI_POST_SETMODE;
	rc = ata_dev_revalidate(dev, 0);
	ehc->i.flags &= ~ATA_EHI_POST_SETMODE;
	if (rc)
		return rc;

+11 −2
Original line number Diff line number Diff line
@@ -1653,6 +1653,11 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,

			ata_eh_done(ap, dev, ATA_EH_REVALIDATE);

			/* Configuration may have changed, reconfigure
			 * transfer mode.
			 */
			ehc->i.flags |= ATA_EHI_SETMODE;

			/* schedule the scsi_rescan_device() here */
			queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
		} else if (dev->class == ATA_DEV_UNKNOWN &&
@@ -1675,6 +1680,9 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
			spin_lock_irqsave(ap->lock, flags);
			ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
			spin_unlock_irqrestore(ap->lock, flags);

			/* new device discovered, configure transfer mode */
			ehc->i.flags |= ATA_EHI_SETMODE;
		}
	}

@@ -1990,13 +1998,14 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
	if (rc)
		goto dev_fail;

	/* configure transfer mode if the port has been reset */
	if (ehc->i.flags & ATA_EHI_DID_RESET) {
	/* configure transfer mode if necessary */
	if (ehc->i.flags & ATA_EHI_SETMODE) {
		rc = ata_set_mode(ap, &dev);
		if (rc) {
			down_xfermask = 1;
			goto dev_fail;
		}
		ehc->i.flags &= ~ATA_EHI_SETMODE;
	}

	/* suspend devices */
+2 −0
Original line number Diff line number Diff line
@@ -284,6 +284,8 @@ enum {

	ATA_EHI_DID_RESET	= (1 << 16), /* already reset this port */
	ATA_EHI_PRINTINFO	= (1 << 17), /* print configuration info */
	ATA_EHI_SETMODE		= (1 << 18), /* configure transfer mode */
	ATA_EHI_POST_SETMODE	= (1 << 19), /* revaildating after setmode */

	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,