Re: [ANNOUNCE] new revision of PMP support patchsets are about to be posted

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Git tree has been updated to reflect two EH fixes just posted [1][2].

* Link resume handling in the previous version was broken causing
  libata to ignore hotplug event after a link has been hot-unplugged.
  Fixed.

* A few other hotplug related problems are fixed. 

Git trees are updated and available in the following git trees.

  http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=link
  git://htj.dyndns.org/libata-tj link

  http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=pmp-prep
  git://htj.dyndns.org/libata-tj pmp-prep

  http://htj.dyndns.org/git/?p=libata-tj.git;a=shortlog;h=pmp
  git://htj.dyndns.org/libata-tj pmp

Diff from the last post [3] is at the end of this mail.

Thanks.

--
tejun

[1] http://article.gmane.org/gmane.linux.ide/12001
[2] http://article.gmane.org/gmane.linux.ide/12002
[3] http://article.gmane.org/gmane.linux.ide/11967

 drivers/scsi/libata-eh.c  |   48 +++++++++++++++++++++++++++++++++++-----------
 drivers/scsi/libata-pmp.c |    3 +-
 drivers/scsi/sata_sil24.c |   19 ++++++++++++++++++
 include/linux/libata.h    |    4 ++-
 4 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index bdfea33..be956fc 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -814,13 +814,28 @@ void ata_eh_about_to_do(struct ata_link 
 			unsigned int action)
 {
 	struct ata_port *ap = link->ap;
+	struct ata_eh_info *ehi = &link->eh_info;
+	struct ata_eh_context *ehc = &link->eh_context;
 	unsigned long flags;
 
 	spin_lock_irqsave(ap->lock, flags);
 
-	ata_eh_clear_action(link, dev, &link->eh_info, action);
+	/* Reset is represented by combination of actions and EHI
+	 * flags.  Suck in all related bits before clearing eh_info to
+	 * avoid losing requested action.
+	 */
+	if (action & ATA_EH_RESET_MASK) {
+		ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
+		ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
+
+		/* make sure all reset actions are cleared & clear EHI flags */
+		action |= ATA_EH_RESET_MASK;
+		ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+	}
+
+	ata_eh_clear_action(link, dev, ehi, action);
 
-	if (!(link->eh_context.i.flags & ATA_EHI_QUIET))
+	if (!(ehc->i.flags & ATA_EHI_QUIET))
 		ap->pflags |= ATA_PFLAG_RECOVERED;
 
 	spin_unlock_irqrestore(ap->lock, flags);
@@ -828,7 +843,7 @@ void ata_eh_about_to_do(struct ata_link 
 
 /**
  *	ata_eh_done - EH action complete
- *	@link: target ATA link
+*	@ap: target ATA port
  *	@dev: target ATA dev for per-dev action (can be NULL)
  *	@action: action just completed
  *
@@ -841,7 +856,15 @@ void ata_eh_about_to_do(struct ata_link 
 void ata_eh_done(struct ata_link *link, struct ata_device *dev,
 		 unsigned int action)
 {
-	ata_eh_clear_action(link, dev, &link->eh_context.i, action);
+	struct ata_eh_context *ehc = &link->eh_context;
+
+	/* if reset is complete, clear all reset actions & reset modifier */
+	if (action & ATA_EH_RESET_MASK) {
+		action |= ATA_EH_RESET_MASK;
+		ehc->i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+	}
+
+	ata_eh_clear_action(link, dev, &ehc->i, action);
 }
 
 /**
@@ -1591,6 +1614,9 @@ int ata_eh_reset(struct ata_link *link, 
 	ata_reset_fn_t reset;
 	int did_followup_srst, rc;
 
+	/* about to reset */
+	ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
+
 	/* Determine which reset to use and record in ehc->i.action.
 	 * prereset() may examine and modify it.
 	 */
@@ -1639,8 +1665,7 @@ int ata_eh_reset(struct ata_link *link, 
 		ata_link_printk(link, KERN_INFO, "%s resetting port\n",
 				reset == softreset ? "soft" : "hard");
 
-	/* reset */
-	ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
+	/* mark that this EH session started with reset */
 	ehc->i.flags |= ATA_EHI_DID_RESET;
 
 	rc = ata_do_reset(link, reset, classes);
@@ -1703,7 +1728,7 @@ int ata_eh_reset(struct ata_link *link, 
 			postreset(link, classes);
 
 		/* reset successful, schedule revalidation */
-		ata_eh_done(link, NULL, ATA_EH_RESET_MASK);
+		ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
 		ehc->i.action |= ATA_EH_REVALIDATE;
 	}
 
@@ -1974,15 +1999,16 @@ static int ata_eh_skip_recovery(struct a
 
 	/* skip if all possible devices are suspended */
 	ata_link_for_each_dev(dev, link) {
-		if (ata_dev_absent(dev) || ata_dev_ready(dev))
+		if (!(dev->flags & ATA_DFLAG_SUSPENDED))
 			break;
 	}
 
 	if (dev == NULL)
 		return 1;
 
-	/* always thaw frozen port and recover failed devices */
-	if (link->ap->pflags & ATA_PFLAG_FROZEN || ata_link_nr_enabled(link))
+	/* thaw frozen port, resume link and recover failed devices */
+	if ((link->ap->pflags & ATA_PFLAG_FROZEN) ||
+	    (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link))
 		return 0;
 
 	/* skip if class codes for all vacant slots are ATA_DEV_NONE */
@@ -2194,7 +2220,7 @@ int ata_eh_recover(struct ata_port *ap, 
 			goto dev_fail;
 
 		/* this link is okay now */
-		ehc->i.flags &= ~ATA_EHI_DID_RESET;
+		ehc->i.flags = 0;
 		continue;
 
 	dev_fail:
diff --git a/drivers/scsi/libata-pmp.c b/drivers/scsi/libata-pmp.c
index c0bf4c1..f4e4ece 100644
--- a/drivers/scsi/libata-pmp.c
+++ b/drivers/scsi/libata-pmp.c
@@ -435,6 +435,7 @@ static int sata_pmp_init_links(struct at
 		struct ata_link *link = &pmp_link[i];
 		struct ata_eh_context *ehc = &link->eh_context;
 
+		link->flags = 0;
 		link->reset_tries = ATA_EH_PMP_RESET_TRIES;
 		ehc->i.probe_mask |= 1;
 		ehc->i.action |= ATA_EH_SOFTRESET;
@@ -807,7 +808,7 @@ static int sata_pmp_eh_recover_pmp(struc
 	}
 
 	/* okay, PMP resurrected */
-	ehc->i.flags &= ~ATA_EHI_DID_RESET;
+	ehc->i.flags = 0;
 
 	DPRINTK("EXIT, rc=0\n");
 	return 0;
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 3757701..399bd1e 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -320,6 +320,7 @@ struct sil24_port_priv {
 	union sil24_cmd_block *cmd_block;	/* 32 cmd blocks */
 	dma_addr_t cmd_block_dma;		/* DMA base addr for them */
 	struct ata_taskfile tf;			/* Cached taskfile registers */
+	int sdb_notify;
 	int do_port_rst;
 };
 
@@ -1035,6 +1036,7 @@ static void sil24_error_intr(struct ata_
 		ehi->err_mask |= AC_ERR_OTHER;
 		ata_ehi_push_desc(ehi, ", SDB notify");
 		ata_port_schedule_eh(ap);
+		pp->sdb_notify = 1;
 	}
 
 	/* deal with command error */
@@ -1207,12 +1209,29 @@ static void sil24_error_handler(struct a
 	if (sil24_init_port(ap))
 		ata_eh_freeze_port(ap);
 
+	/* SDB_NOTIFY often hangs the controller resulting in port
+	 * reset.  If PORT_RST is scheduled or pmp_read doesn't work
+	 * after SDB_NOTIFY, unconditionally generate hotplug events
+	 * on all PMP links.
+	 */
+	if (ap->nr_pmp_links && pp->sdb_notify) {
+		struct ata_device *pmp_dev = ap->link.device;
+		u32 tmp;
+
+		if (sil24_pmp_read(pmp_dev, SATA_PMP_CTRL_PORT, 0, &tmp)) {
+			struct ata_link *tlink;
+			ata_port_for_each_link(tlink, ap)
+				ata_ehi_hotplugged(&tlink->eh_context.i);
+		}
+	}
+
 	/* perform recovery */
 	sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
 		       ata_std_postreset, sata_pmp_std_prereset,
 		       sil24_pmp_softreset, sil24_pmp_hardreset,
 		       sata_pmp_std_postreset);
 
+	pp->sdb_notify = 0;
 	pp->do_port_rst = 0;
 }
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a90135f..e8fc080 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -279,13 +279,15 @@ enum {
 				  ATA_EH_RESUME | ATA_EH_PM_FREEZE,
 
 	/* ata_eh_info->flags */
-	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* hotplugged (reset modifier) */
+	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* could have been hotplugged */
 	ATA_EHI_RESUME_LINK	= (1 << 1),  /* resume link (reset modifier) */
 	ATA_EHI_NO_AUTOPSY	= (1 << 2),  /* no autopsy */
 	ATA_EHI_QUIET		= (1 << 3),  /* be quiet */
 
 	ATA_EHI_DID_RESET	= (1 << 16), /* already reset this port */
 
+	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
 	/* max repeat if error condition is still set after ->error_handler */
 	ATA_EH_MAX_REPEAT	= 5,
 
-
: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux