All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@us.ibm.com>
To: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: alexisb@us.ibm.com
Subject: [PATCH 14/15] libsas: Provide a generic SATL registration function
Date: Fri, 17 Nov 2006 13:08:30 -0800	[thread overview]
Message-ID: <20061117210830.17052.40552.stgit@localhost.localdomain> (raw)
In-Reply-To: <20061117210737.17052.67041.stgit@localhost.localdomain>


Decouple libsas and sas_ata so that the latter can be provided as a
plug-in module for the former.  Any module wishing to provide SATL
services registers itself with libsas; when SATA devices are
discovered, libsas will module_get/put as necessary to ensure that
the module cannot go away accidentally.  At this time, the ability
to start a SAS HBA without a SATL, load a SATL later, and then
rerun device discovery; that may be addressed in a later patch.

Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
---

 drivers/scsi/libsas/Kconfig         |   11 +++
 drivers/scsi/libsas/sas_discover.c  |    6 --
 drivers/scsi/libsas/sas_scsi_host.c |  134 ++++++++++++++++++++++++++++++++---
 include/scsi/libsas.h               |   30 +-------
 include/scsi/sas_ata.h              |   37 +++++++++-
 5 files changed, 174 insertions(+), 44 deletions(-)

diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
index b64e391..9c06eec 100644
--- a/drivers/scsi/libsas/Kconfig
+++ b/drivers/scsi/libsas/Kconfig
@@ -24,12 +24,21 @@ #
 
 config SCSI_SAS_LIBSAS
 	tristate "SAS Domain Transport Attributes"
-	depends on SCSI && ATA
+	depends on SCSI
 	select SCSI_SAS_ATTRS
 	help
 	  This provides transport specific helpers for SAS drivers which
 	  use the domain device construct (like the aic94xxx).
 
+config SCSI_SAS_SATL
+	tristate "Serial ATA Translation Layer (SATL) on SAS controllers"
+	depends on SCSI_SAS_LIBSAS && ATA
+	default y
+	help
+	  This provides an ATA translation layer between libsas and
+	  libata to load SATA devices that are connected to SAS
+	  controllers.
+
 config SCSI_SAS_LIBSAS_DEBUG
 	bool "Compile the SAS Domain Transport Attributes in debug mode"
 	default y
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 758b153..01ff15c 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -476,12 +476,6 @@ cont1:
 	if (!dev->parent)
 		sas_sata_propagate_sas_addr(dev);
 
-	/* XXX Hint: register this SATA device with SATL.
-	   When this returns, dev->sata_dev->lu is alive and
-	   present.
-	sas_satl_register_dev(dev);
-	*/
-
 	sas_fill_in_rphy(dev, dev->rphy);
 
 	return 0;
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 59409be..c1a1e06 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -46,6 +46,9 @@ #include <linux/libata.h>
 #define TO_SAS_TASK(_scsi_cmd)  ((void *)(_scsi_cmd)->host_scribble)
 #define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0)
 
+static DEFINE_SPINLOCK(satl_ops_lock);
+static struct satl_operations *satl_ops;
+
 static void sas_scsi_task_done(struct sas_task *task)
 {
 	struct task_status_struct *ts = &task->task_status;
@@ -215,8 +218,8 @@ int sas_queuecommand(struct scsi_cmnd *c
 			unsigned long flags;
 
 			spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
-			res = ata_sas_queuecmd(cmd, scsi_done,
-					       dev->sata_dev.ap);
+			res = satl_ops->queuecommand(cmd, scsi_done,
+						     dev->sata_dev.ap);
 			spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
 			goto out;
 		}
@@ -574,8 +577,9 @@ int sas_ioctl(struct scsi_device *sdev, 
 {
 	struct domain_device *dev = sdev_to_domain_dev(sdev);
 
-	if (dev_is_sata(dev))
-		return ata_scsi_ioctl(sdev, cmd, arg);
+	if (dev_is_sata(dev)) {
+		return satl_ops->ioctl(sdev, cmd, arg);
+	}
 
 	return -EINVAL;
 }
@@ -615,6 +619,29 @@ static inline struct domain_device *sas_
 	return sas_find_dev_by_rphy(rphy);
 }
 
+static int sas_target_alloc_sata(struct domain_device *dev,
+				 struct scsi_target *starget)
+{
+	int res = -ENODEV;
+
+	/* Do we have a SATL available? */
+	if (!get_satl())
+		goto satl_found;
+
+	request_module("sas_ata");
+	if (!get_satl())
+		goto satl_found;
+
+	SAS_DPRINTK("sas_ata not loaded, ignoring SATA devices\n");
+	goto no_satl;
+
+satl_found:
+	res = satl_ops->init_target(dev, starget);
+
+no_satl:
+	return res;
+}
+
 int sas_target_alloc(struct scsi_target *starget)
 {
 	struct domain_device *found_dev = sas_find_target(starget);
@@ -624,7 +651,7 @@ int sas_target_alloc(struct scsi_target 
 		return -ENODEV;
 
 	if (dev_is_sata(found_dev)) {
-		res = sas_ata_init_host_and_port(found_dev, starget);
+		res = sas_target_alloc_sata(found_dev, starget);
 		if (res)
 			return res;
 	}
@@ -644,7 +671,7 @@ int sas_slave_configure(struct scsi_devi
 	BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE);
 
 	if (dev_is_sata(dev)) {
-		ata_sas_slave_configure(scsi_dev, dev->sata_dev.ap);
+		satl_ops->configure_port(scsi_dev, dev->sata_dev.ap);
 		return 0;
 	}
 
@@ -672,7 +699,7 @@ void sas_slave_destroy(struct scsi_devic
 	struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
 
 	if (dev_is_sata(dev))
-		ata_port_disable(dev->sata_dev.ap);
+		satl_ops->deactivate_port(dev->sata_dev.ap);
 }
 
 int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth)
@@ -849,7 +876,7 @@ int sas_slave_alloc(struct scsi_device *
 	struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
 
 	if (dev_is_sata(dev))
-		return ata_sas_port_init(dev->sata_dev.ap);
+		return satl_ops->init_port(dev->sata_dev.ap);
 
 	return 0;
 }
@@ -861,8 +888,11 @@ void sas_target_destroy(struct scsi_targ
 	if (!found_dev)
 		return;
 
-	if (dev_is_sata(found_dev))
-		ata_sas_port_destroy(found_dev->sata_dev.ap);
+	if (dev_is_sata(found_dev)) {
+		if (found_dev->sata_dev.ap)
+			satl_ops->destroy_port(found_dev->sata_dev.ap);
+		put_satl();
+	}
 
 	return;
 }
@@ -925,6 +955,85 @@ void sas_task_abort(struct sas_task *tas
 	SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__);
 }
 
+struct sas_task *sas_alloc_task(gfp_t flags)
+{
+	extern kmem_cache_t *sas_task_cache;
+	struct sas_task *task = kmem_cache_alloc(sas_task_cache, flags);
+
+	if (task) {
+		memset(task, 0, sizeof(*task));
+		INIT_LIST_HEAD(&task->list);
+		spin_lock_init(&task->task_state_lock);
+		task->task_state_flags = SAS_TASK_STATE_PENDING;
+		init_timer(&task->timer);
+		init_completion(&task->completion);
+	}
+
+	return task;
+}
+
+void sas_free_task(struct sas_task *task)
+{
+	if (task) {
+		extern kmem_cache_t *sas_task_cache;
+		BUG_ON(!list_empty(&task->list));
+		kmem_cache_free(sas_task_cache, task);
+	}
+}
+
+/* Jump table to ATA translation layer functions */
+int sas_register_satl(struct satl_operations *ops)
+{
+	int res = -ENODEV;
+
+	spin_lock(&satl_ops_lock);
+	if (satl_ops)
+		goto out;
+	satl_ops = ops;
+	res = 0;
+out:
+	spin_unlock(&satl_ops_lock);
+	return res;
+}
+
+int sas_unregister_satl(struct satl_operations *ops)
+{
+	int res = -ENODEV;
+
+	spin_lock(&satl_ops_lock);
+	if (satl_ops != ops)
+		goto out;
+	satl_ops = NULL;
+	res = 0;
+out:
+	spin_unlock(&satl_ops_lock);
+	return res;
+}
+
+int get_satl(void)
+{
+	int res = -ENODEV;
+
+	spin_lock(&satl_ops_lock);
+
+	if (!satl_ops)
+		goto out;
+	if (!try_module_get(satl_ops->owner))
+		goto out;
+	res = 0;
+
+out:
+	spin_unlock(&satl_ops_lock);
+	return res;
+}
+
+void put_satl(void)
+{
+	spin_lock(&satl_ops_lock);
+	module_put(satl_ops->owner);
+	spin_unlock(&satl_ops_lock);
+}
+
 EXPORT_SYMBOL_GPL(sas_queuecommand);
 EXPORT_SYMBOL_GPL(sas_target_alloc);
 EXPORT_SYMBOL_GPL(sas_slave_configure);
@@ -939,3 +1048,8 @@ EXPORT_SYMBOL_GPL(sas_task_abort);
 EXPORT_SYMBOL_GPL(sas_phy_reset);
 EXPORT_SYMBOL_GPL(sas_phy_enable);
 EXPORT_SYMBOL_GPL(sas_set_phy_speed);
+EXPORT_SYMBOL_GPL(sas_register_satl);
+EXPORT_SYMBOL_GPL(sas_unregister_satl);
+EXPORT_SYMBOL_GPL(sas_queue_up);
+EXPORT_SYMBOL_GPL(sas_alloc_task);
+EXPORT_SYMBOL_GPL(sas_free_task);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 7dcf593..90748ce 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -549,31 +549,8 @@ #define SAS_TASK_STATE_ABORTED      4
 #define SAS_TASK_INITIATOR_ABORTED  8
 #define SAS_TASK_AT_INITIATOR       16
 
-static inline struct sas_task *sas_alloc_task(gfp_t flags)
-{
-	extern kmem_cache_t *sas_task_cache;
-	struct sas_task *task = kmem_cache_alloc(sas_task_cache, flags);
-
-	if (task) {
-		memset(task, 0, sizeof(*task));
-		INIT_LIST_HEAD(&task->list);
-		spin_lock_init(&task->task_state_lock);
-		task->task_state_flags = SAS_TASK_STATE_PENDING;
-		init_timer(&task->timer);
-		init_completion(&task->completion);
-	}
-
-	return task;
-}
-
-static inline void sas_free_task(struct sas_task *task)
-{
-	if (task) {
-		extern kmem_cache_t *sas_task_cache;
-		BUG_ON(!list_empty(&task->list));
-		kmem_cache_free(sas_task_cache, task);
-	}
-}
+struct sas_task *sas_alloc_task(gfp_t flags);
+void sas_free_task(struct sas_task *task);
 
 struct sas_domain_function_template {
 	/* The class calls these to notify the LLDD of an event. */
@@ -649,4 +626,7 @@ extern int sas_slave_alloc(struct scsi_d
 extern int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg);
 void sas_task_abort(struct sas_task *task);
 
+int get_satl(void);
+void put_satl(void);
+
 #endif /* _SASLIB_H_ */
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index 72a1904..bb4a1cb 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -28,12 +28,45 @@ #define _SAS_ATA_H_
 #include <linux/libata.h>
 #include <scsi/libsas.h>
 
+struct satl_operations {
+	struct module *owner;
+
+	int (*init_target) (struct domain_device *found_dev,
+			    struct scsi_target *starget);
+	int  (*queuecommand) (struct scsi_cmnd *cmd,
+			      void (*done)(struct scsi_cmnd *),
+			      struct ata_port *ap);
+	int  (*ioctl) (struct scsi_device *dev, int cmd,
+		       void __user *arg);
+	int  (*configure_port) (struct scsi_device *,
+				struct ata_port *);
+	void (*deactivate_port) (struct ata_port *);
+	void (*destroy_port) (struct ata_port *);
+	int  (*init_port) (struct ata_port *);
+};
+
+int sas_register_satl(struct satl_operations *satl_ops);
+int sas_unregister_satl(struct satl_operations *satl_ops);
+
+#ifdef CONFIG_SCSI_SAS_SATL_MODULE
+# define SAS_ATA_AVAILABLE
+#endif
+
+#ifdef CONFIG_SCSI_SAS_SATL
+# define SAS_ATA_AVAILABLE
+#endif
+
+#ifdef SAS_ATA_AVAILABLE
+
 static inline int dev_is_sata(struct domain_device *dev)
 {
 	return (dev->rphy->identify.target_port_protocols & SAS_PROTOCOL_SATA);
 }
 
-int sas_ata_init_host_and_port(struct domain_device *found_dev,
-			       struct scsi_target *starget);
+#else
+
+#define dev_is_sata(x) (0)
+
+#endif /* SAS_ATA_AVAILABLE */
 
 #endif /* _SAS_ATA_H_ */

  parent reply	other threads:[~2006-11-17 21:02 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-11-17 21:07 [PATCH 00/15] Roll-up of my libsas, aic94xx and sas_ata patches Darrick J. Wong
2006-11-17 21:07 ` [PATCH 01/15] aic94xx: Handle REQ_DEVICE_RESET Darrick J. Wong
2006-11-17 21:07 ` [PATCH 02/15] libsas: Clean up rphys/port dev list after a discovery error Darrick J. Wong
2006-11-17 21:07 ` [PATCH 03/15] aic94xx: Delete ascb timers when freeing queues Darrick J. Wong
2006-11-17 21:07 ` [PATCH 04/15] libsas: Don't give scsi_cmnds to the EH if they never made it to the SAS LLDD or have already returned Darrick J. Wong
2006-11-25  6:58   ` [PATCH v2] " Darrick J. Wong
2006-11-25 19:02     ` James Bottomley
2006-11-17 21:07 ` [PATCH 05/15] libsas: Add a sysfs knob to enable/disable a phy Darrick J. Wong
2006-11-17 21:07 ` [PATCH 06/15] sas_ata: Require CONFIG_ATA in Kconfig Darrick J. Wong
2006-11-17 21:08 ` [PATCH 07/15] sas_ata: Satisfy libata qc function locking requirements Darrick J. Wong
2006-11-17 21:08 ` [PATCH 08/15] sas_ata: sas_ata_qc_issue should return AC_ERR_* Darrick J. Wong
2006-11-17 21:08 ` [PATCH 09/15] sas_ata: ata_post_internal should abort the sas_task Darrick J. Wong
2006-11-17 21:08 ` [PATCH 10/15] aic94xx: Don't call pci_map_sg for already-mapped scatterlists Darrick J. Wong
2006-11-17 21:08 ` [PATCH 11/15] sas_ata: Don't copy aic94xx's sactive to ata_port Darrick J. Wong
2006-11-17 21:08 ` [PATCH 12/15] sas_ata: Implement sata phy control Darrick J. Wong
2006-11-17 21:08 ` [PATCH 13/15] sas_ata: Implement a libata error handler Darrick J. Wong
2006-11-17 21:08 ` Darrick J. Wong [this message]
2006-11-17 21:08 ` [PATCH 15/15] sas_ata: Make this a module separate from libsas Darrick J. Wong
2006-11-21  1:16 ` [PATCH 00/15] Roll-up of my libsas, aic94xx and sas_ata patches Darrick J. Wong

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=20061117210830.17052.40552.stgit@localhost.localdomain \
    --to=djwong@us.ibm.com \
    --cc=alexisb@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.