linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tejun Heo <htejun@gmail.com>
To: jgarzik@pobox.com, alan@lxorguk.ukuu.org.uk, mlord@pobox.com,
	albertcc@tw.ibm.com, uchang@tw.ibm.com, forrest.zhao@intel.com,
	brking@us.ibm.com, linux-ide@vger.kernel.org
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 2/20] libata: implement ata_host_start/stop()
Date: Sat, 19 Aug 2006 17:59:30 +0900	[thread overview]
Message-ID: <1155977970528-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <11559778241753-git-send-email-htejun@gmail.com>

Implement [de-]init helpers ata_host_start/stop().  start() will start
all ports in the host while stop() does the opposite.  These helpers
use ATA_PFLAG_STARTED to track whether a port is started or not and
thus can be called without side effect.

ata_host_stop() replaces half of ata_scsi_release() and the other half
is merged into ata_host_detach().

This patch introduces the follwing behavior changes.

* ->port_start/stop() can be omitted.  This will be used to simplify
  port initialization.

* ->port_disable() callback is reordered w.r.t. freeing IRQs.  The
  callback's roll and usefulness are questionable.  All LLDs use
  ata_port_disable() and libata-core directly calls ata_port_disable()
  in several places.  ->port_disable() invocation during port deinit
  doesn't provide any feature.  All are already done by EH.  The
  relocation doesn't cause any real behavior change.

This is a part of efforts to improve [de-]init paths and simplify
LLDs.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 drivers/ata/ahci.c        |    9 +--
 drivers/ata/libata-core.c |  129 +++++++++++++++++++++++++++++----------------
 include/linux/libata.h    |    5 +-
 3 files changed, 91 insertions(+), 52 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 3f1106f..eb6ceb3 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1643,13 +1643,10 @@ static void ahci_remove_one (struct pci_
 	have_msi = hpriv->flags & AHCI_FLAG_MSI;
 	free_irq(host->irq, host);
 
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-
-		ata_scsi_release(ap->scsi_host);
-		scsi_host_put(ap->scsi_host);
-	}
+	ata_host_stop(host);
 
+	for (i = 0; i < host->n_ports; i++)
+		scsi_host_put(host->ports[i]->scsi_host);
 	kfree(hpriv);
 	pci_iounmap(pdev, host->mmio_base);
 	kfree(host);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index e8bbbaa..8472ec9 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5394,6 +5394,42 @@ void ata_host_init(struct ata_host *host
 }
 
 /**
+ *	ata_host_start - start ports of an ATA host
+ *	@host: ATA host to start ports for
+ *
+ *	Start ports of @host.  Port started status is recorded in
+ *	ap->pflags, so this function can be called multiple times.
+ *	Ports are guaranteed to get started only once.
+ *
+ *	LOCKING:
+ *	Inherited from calling layer (may sleep).
+ *
+ *	RETURNS:
+ *	0 if all ports are started successfully, -errno otherwise.
+ */
+int ata_host_start(struct ata_host *host)
+{
+	int i, rc;
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		if (ap->pflags & ATA_PFLAG_STARTED)
+			continue;
+
+		if (ap->ops->port_start) {
+			rc = ap->ops->port_start(ap);
+			if (rc)
+				return rc;
+		}
+
+		ap->pflags |= ATA_PFLAG_STARTED;
+	}
+
+	return 0;
+}
+
+/**
  *	ata_device_add - Register hardware device with ATA and SCSI layers
  *	@ent: Probe information describing hardware device to be registered
  *
@@ -5451,14 +5487,6 @@ int ata_device_add(const struct ata_prob
 			continue;
 		}
 
-		/* start port */
-		rc = ap->ops->port_start(ap);
-		if (rc) {
-			host->ports[i] = NULL;
-			scsi_host_put(ap->scsi_host);
-			goto err_out;
-		}
-
 		/* Report the secondary IRQ for second channel legacy */
 		if (i == 1 && ent->irq2)
 			irq_line = ent->irq2;
@@ -5476,6 +5504,16 @@ int ata_device_add(const struct ata_prob
 				ap->ioaddr.ctl_addr,
 				ap->ioaddr.bmdma_addr,
 				irq_line);
+	}
+
+	/* start ports */
+	rc = ata_host_start(host);
+	if (rc)
+		goto err_out;
+
+	/* freeze */
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
 
 		ata_chk_status(ap);
 		host->ops->irq_clear(ap);
@@ -5582,14 +5620,10 @@ int ata_device_add(const struct ata_prob
 err_out_free_irq:
 	free_irq(ent->irq, host);
 err_out:
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-		if (ap) {
-			ap->ops->port_stop(ap);
-			scsi_host_put(ap->scsi_host);
-		}
-	}
+	ata_host_stop(host);
 
+	for (i = 0; i < host->n_ports; i++)
+		scsi_host_put(host->ports[i]->scsi_host);
 	kfree(host);
 	VPRINTK("EXIT, returning 0\n");
 	return 0;
@@ -5651,6 +5685,37 @@ void ata_port_detach(struct ata_port *ap
  skip_eh:
 	/* remove the associated SCSI host */
 	scsi_remove_host(ap->scsi_host);
+
+	/* disable port */
+	ap->ops->port_disable(ap);
+}
+
+/**
+ *	ata_host_stop - stop ports of an ATA host
+ *	@host: ATA host to stop
+ *
+ *	Stop ports of @host.  Port started status is recorded in
+ *	ap->pflags, so this functio can be called multiple times.
+ *	Started ports are guranteed to be stopped only once.
+ *
+ *	LOCKING:
+ *	Inherited from calling layer (may sleep).
+ */
+void ata_host_stop(struct ata_host *host)
+{
+	int i;
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		if (!ap || !(ap->pflags & ATA_PFLAG_STARTED))
+			continue;
+
+		if (ap->ops->port_stop)
+			ap->ops->port_stop(ap);
+
+		ap->pflags &= ~ATA_PFLAG_STARTED;
+	}
 }
 
 /**
@@ -5675,11 +5740,11 @@ void ata_host_remove(struct ata_host *ho
 	if (host->irq2)
 		free_irq(host->irq2, host);
 
+	ata_host_stop(host);
+
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
 
-		ata_scsi_release(ap->scsi_host);
-
 		if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
 			struct ata_ioports *ioaddr = &ap->ioaddr;
 
@@ -5699,33 +5764,6 @@ void ata_host_remove(struct ata_host *ho
 	kfree(host);
 }
 
-/**
- *	ata_scsi_release - SCSI layer callback hook for host unload
- *	@host: libata host to be unloaded
- *
- *	Performs all duties necessary to shut down a libata port...
- *	Kill port kthread, disable port, and release resources.
- *
- *	LOCKING:
- *	Inherited from SCSI layer.
- *
- *	RETURNS:
- *	One.
- */
-
-int ata_scsi_release(struct Scsi_Host *shost)
-{
-	struct ata_port *ap = ata_shost_to_port(shost);
-
-	DPRINTK("ENTER\n");
-
-	ap->ops->port_disable(ap);
-	ap->ops->port_stop(ap);
-
-	DPRINTK("EXIT\n");
-	return 1;
-}
-
 struct ata_probe_ent *
 ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
 {
@@ -6030,8 +6068,10 @@ EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_host_init);
+EXPORT_SYMBOL_GPL(ata_host_start);
 EXPORT_SYMBOL_GPL(ata_device_add);
 EXPORT_SYMBOL_GPL(ata_port_detach);
+EXPORT_SYMBOL_GPL(ata_host_stop);
 EXPORT_SYMBOL_GPL(ata_host_remove);
 EXPORT_SYMBOL_GPL(ata_sg_init);
 EXPORT_SYMBOL_GPL(ata_sg_init_one);
@@ -6090,7 +6130,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
 EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
-EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
 EXPORT_SYMBOL_GPL(sata_scr_valid);
 EXPORT_SYMBOL_GPL(sata_scr_read);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 8fd8851..e098d32 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -184,6 +184,8 @@ enum {
 	ATA_PFLAG_SUSPENDED	= (1 << 17), /* port is suspended (power) */
 	ATA_PFLAG_PM_PENDING	= (1 << 18), /* PM operation pending */
 
+	ATA_PFLAG_STARTED	= (1 << 24), /* port has been started */
+
 	/* struct ata_queued_cmd flags */
 	ATA_QCFLAG_ACTIVE	= (1 << 0), /* cmd not yet ack'd to scsi lyer */
 	ATA_QCFLAG_SG		= (1 << 1), /* have s/g table? */
@@ -688,15 +690,16 @@ extern int ata_pci_device_suspend(struct
 extern int ata_pci_device_resume(struct pci_dev *pdev);
 extern int ata_pci_clear_simplex(struct pci_dev *pdev);
 #endif /* CONFIG_PCI */
+extern int ata_host_start(struct ata_host *host);
 extern int ata_device_add(const struct ata_probe_ent *ent);
 extern void ata_port_detach(struct ata_port *ap);
+extern void ata_host_stop(struct ata_host *host);
 extern void ata_host_init(struct ata_host *, struct device *,
 			  unsigned long, const struct ata_port_operations *);
 extern void ata_host_remove(struct ata_host *host);
 extern int ata_scsi_detect(struct scsi_host_template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
-extern int ata_scsi_release(struct Scsi_Host *host);
 extern void ata_sas_port_destroy(struct ata_port *);
 extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
 					   struct ata_port_info *, struct Scsi_Host *);
-- 
1.4.1.1



  parent reply	other threads:[~2006-08-19  8:59 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-19  8:57 [PATCHSET] libata: implement new initialization model w/ iomap support, take 2 Tejun Heo
2006-08-19  8:59 ` [PATCH 1/20] libata: kill ata_host_stop() Tejun Heo
2006-08-19 14:51   ` Jeff Garzik
2006-08-19 15:29     ` Tejun Heo
2006-09-19  4:46   ` Jeff Garzik
2006-09-19  4:50     ` Tejun Heo
2006-08-19  8:59 ` Tejun Heo [this message]
2006-08-19  8:59 ` [PATCH 4/20] libata: separate out ata_host_alloc() and ata_host_attach() Tejun Heo
2006-09-19  5:08   ` Jeff Garzik
2006-09-19  5:48     ` Tejun Heo
2006-08-19  8:59 ` [PATCH 7/20] libata: implement PCI ATA init helpers Tejun Heo
2006-09-19  5:29   ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 6/20] libata: implement legacy " Tejun Heo
2006-09-19  5:26   ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 5/20] libata: implement several LLD " Tejun Heo
2006-08-22 22:11   ` Brian King
2006-08-27  9:52     ` Tejun Heo
2006-08-30 21:16       ` Brian King
2006-09-19  5:16   ` Jeff Garzik
2006-09-19  5:57     ` Tejun Heo
2006-08-19  8:59 ` [PATCH 3/20] libata: implement ata_host_detach() and ata_host_free() Tejun Heo
2006-09-19  4:59   ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 12/20] libata: kill old init helpers Tejun Heo
2006-08-19  8:59 ` [PATCH 11/20] libata: use remove_one() for deinit instead of ->host_stop() Tejun Heo
2006-09-19  5:42   ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 8/20] libata: reimplement ata_pci_init_one() using new init helpers Tejun Heo
2006-09-19  5:32   ` Jeff Garzik
2006-09-19  6:04     ` Tejun Heo
2006-09-19  6:09       ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 13/20] libata: kill unused ->host_stop() operation and related functions Tejun Heo
2006-09-19  5:42   ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 10/20] libata: reimplement ata_pci_remove_one() using new PCI init helpers Tejun Heo
2006-08-19  8:59 ` [PATCH 17/20] libata: make ata_pci_acquire_resources() handle iomap Tejun Heo
2006-09-19  5:47   ` Jeff Garzik
2006-09-19  6:27     ` Tejun Heo
2006-09-19  6:32       ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 14/20] libata: use LLD name where possible Tejun Heo
2006-09-19  5:43   ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 15/20] libata: move ->irq_handler from port_ops to port_info Tejun Heo
2006-09-19  5:43   ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 16/20] libata: make ata_host_alloc() take care of hpriv alloc/free Tejun Heo
2006-09-19  5:45   ` Jeff Garzik
2006-08-19  8:59 ` [PATCH 19/20] libata: kill unused ATA_FLAG_MMIO Tejun Heo
2006-08-19  8:59 ` [PATCH 20/20] libata: move scattered PCI ATA functions into liata-pci.c Tejun Heo
2006-09-19  5:50   ` Jeff Garzik
2006-08-22 22:10 ` [PATCHSET] libata: implement new initialization model w/ iomap support, take 2 Brian King
2006-08-27 10:12   ` Tejun Heo
2006-08-30 20:58     ` Brian King
2006-09-01 13:45       ` Tejun Heo
2006-09-07 13:22         ` Brian King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1155977970528-git-send-email-htejun@gmail.com \
    --to=htejun@gmail.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=albertcc@tw.ibm.com \
    --cc=brking@us.ibm.com \
    --cc=forrest.zhao@intel.com \
    --cc=jgarzik@pobox.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=mlord@pobox.com \
    --cc=uchang@tw.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).