public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
From: Dan Williams <dan.j.williams@intel.com>
To: linux-scsi@vger.kernel.org
Cc: linux-ide@vger.kernel.org
Subject: [PATCH v3 05/14] libsas: perform sas-transport resets in shost->workq context
Date: Thu, 05 Jan 2012 16:59:26 -0800	[thread overview]
Message-ID: <20120106005925.11464.3339.stgit@localhost6.localdomain6> (raw)
In-Reply-To: <20120106005634.11464.64030.stgit@localhost6.localdomain6>

Extend the sas transport class to allow transport users to attach extra
data to a sas_phy (->hostdata).  Use this area in libsas to move resets
to workq context in preparation for scheduling ata device resets through
libata-eh.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/scsi/libsas/sas_event.c    |    2 +
 drivers/scsi/libsas/sas_init.c     |   59 +++++++++++++++++++++++++++++++++++-
 drivers/scsi/libsas/sas_internal.h |   10 ++++++
 drivers/scsi/scsi_transport_sas.c  |   18 ++++++++++-
 include/scsi/scsi_transport_sas.h  |    5 ++-
 5 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 933d757..dbfacee 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -27,7 +27,7 @@
 #include "sas_internal.h"
 #include "sas_dump.h"
 
-static void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work)
+void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work)
 {
 	if (!test_bit(SAS_HA_REGISTERED, &ha->state))
 		return;
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index e17fe35..cb65adf 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -290,9 +290,66 @@ int sas_set_phy_speed(struct sas_phy *phy,
 	return ret;
 }
 
+static void sas_phy_release(struct sas_phy *phy)
+{
+	kfree(phy->hostdata);
+	phy->hostdata = NULL;
+}
+
+static void phy_reset_work(struct work_struct *work)
+{
+	struct sas_phy_data *d = container_of(work, typeof(*d), reset_work);
+
+	d->reset_result = sas_phy_reset(d->phy, d->hard_reset);
+}
+
+static int sas_phy_setup(struct sas_phy *phy)
+{
+	struct sas_phy_data *d = kzalloc(sizeof(*d), GFP_KERNEL);
+
+	if (!d)
+		return -ENOMEM;
+
+	mutex_init(&d->event_lock);
+	INIT_WORK(&d->reset_work, phy_reset_work);
+	d->phy = phy;
+	phy->hostdata = d;
+
+	return 0;
+}
+
+static int queue_phy_reset(struct sas_phy *phy, int hard_reset)
+{
+	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
+	struct sas_phy_data *d = phy->hostdata;
+	int rc;
+
+	if (!d)
+		return -ENOMEM;
+
+	/* libsas workqueue coordinates ata-eh reset with discovery */
+	mutex_lock(&d->event_lock);
+	d->reset_result = 0;
+	d->hard_reset = hard_reset;
+
+	spin_lock_irq(&ha->state_lock);
+	sas_queue_work(ha, &d->reset_work);
+	spin_unlock_irq(&ha->state_lock);
+
+	rc = sas_drain_work(ha);
+	if (rc == 0)
+		rc = d->reset_result;
+	mutex_unlock(&d->event_lock);
+
+	return rc;
+}
+
 static struct sas_function_template sft = {
 	.phy_enable = sas_phy_enable,
-	.phy_reset = sas_phy_reset,
+	.phy_reset = queue_phy_reset,
+	.phy_setup = sas_phy_setup,
+	.phy_release = sas_phy_release,
 	.set_phy_speed = sas_set_phy_speed,
 	.get_linkerrors = sas_get_linkerrors,
 	.smp_handler = sas_smp_handler,
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 662ffcb..9ba65e0 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -38,6 +38,15 @@
 #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)
 
+struct sas_phy_data {
+	/* let reset be performed in sas_queue_work() context */
+	struct sas_phy *phy;
+	struct mutex event_lock;
+	int hard_reset;
+	int reset_result;
+	struct work_struct reset_work;
+};
+
 void sas_scsi_recover_host(struct Scsi_Host *shost);
 
 int sas_show_class(enum sas_class class, char *buf);
@@ -66,6 +75,7 @@ void sas_porte_broadcast_rcvd(struct work_struct *work);
 void sas_porte_link_reset_err(struct work_struct *work);
 void sas_porte_timer_event(struct work_struct *work);
 void sas_porte_hard_reset(struct work_struct *work);
+void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work);
 
 int sas_notify_lldd_dev_found(struct domain_device *);
 void sas_notify_lldd_dev_gone(struct domain_device *);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 9421bae..ab3bd0b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -652,9 +652,21 @@ sas_phy_linkerror_attr(running_disparity_error_count);
 sas_phy_linkerror_attr(loss_of_dword_sync_count);
 sas_phy_linkerror_attr(phy_reset_problem_count);
 
+static int sas_phy_setup(struct transport_container *tc, struct device *dev,
+			 struct device *cdev)
+{
+	struct sas_phy *phy = dev_to_phy(dev);
+	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+	struct sas_internal *i = to_sas_internal(shost->transportt);
+
+	if (i->f->phy_setup)
+		i->f->phy_setup(phy);
+
+	return 0;
+}
 
 static DECLARE_TRANSPORT_CLASS(sas_phy_class,
-		"sas_phy", NULL, NULL, NULL);
+		"sas_phy", sas_phy_setup, NULL, NULL);
 
 static int sas_phy_match(struct attribute_container *cont, struct device *dev)
 {
@@ -678,7 +690,11 @@ static int sas_phy_match(struct attribute_container *cont, struct device *dev)
 static void sas_phy_release(struct device *dev)
 {
 	struct sas_phy *phy = dev_to_phy(dev);
+	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+	struct sas_internal *i = to_sas_internal(shost->transportt);
 
+	if (i->f->phy_release)
+		i->f->phy_release(phy);
 	put_device(dev->parent);
 	kfree(phy);
 }
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 6d14daa..42817fa 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -75,7 +75,8 @@ struct sas_phy {
 	/* for the list of phys belonging to a port */
 	struct list_head	port_siblings;
 
-	struct work_struct      reset_work;
+	/* available to the lldd */
+	void			*hostdata;
 };
 
 #define dev_to_phy(d) \
@@ -169,6 +170,8 @@ struct sas_function_template {
 	int (*get_bay_identifier)(struct sas_rphy *);
 	int (*phy_reset)(struct sas_phy *, int);
 	int (*phy_enable)(struct sas_phy *, int);
+	int (*phy_setup)(struct sas_phy *);
+	void (*phy_release)(struct sas_phy *);
 	int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *);
 	int (*smp_handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
 };


  parent reply	other threads:[~2012-01-06  0:59 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-06  0:59 [GIT PATCH v3 00/14] libsas: eh reworks (ata-eh vs discovery, races, ...) Dan Williams
2012-01-06  0:59 ` [PATCH v3 01/14] libsas: introduce sas_drain_work() Dan Williams
2012-01-06  0:59 ` [PATCH v3 02/14] libsas: remove ata_port.lock management duties from lldds Dan Williams
2012-01-06  0:59 ` [PATCH v3 03/14] libsas: prevent domain rediscovery competing with ata error handling Dan Williams
2012-01-09 19:14   ` Dan Williams
2012-01-09 20:03     ` Dan Williams
2012-01-06  0:59 ` [PATCH v3 04/14] libsas: fix timeout vs completion race Dan Williams
2012-01-06  0:59 ` Dan Williams [this message]
2012-01-06  0:59 ` [PATCH v3 06/14] libsas: sas_phy_enable via transport_sas_phy_reset Dan Williams
2012-01-06  0:59 ` [PATCH v3 07/14] libsas: async ata-eh Dan Williams
2012-01-06  0:59 ` [PATCH v3 08/14] isci: kill iphy->isci_port lookups Dan Williams
2012-01-23 23:45   ` Dan Williams
2012-01-06  0:59 ` [PATCH v3 09/14] isci: kill isci_port->status Dan Williams
2012-01-06  0:59 ` [PATCH v3 10/14] isci: fix interpretation of "hard" reset Dan Williams
2012-01-06  0:59 ` [PATCH v3 11/14] isci: stop interpreting ->lldd_lu_reset() as an ata soft-reset Dan Williams
2012-01-06  1:00 ` [PATCH v3 12/14] isci: ->lldd_ata_check_ready handler Dan Williams
2012-01-09  1:57   ` Jack Wang
2012-01-09 19:26     ` Dan Williams
2012-01-06  1:00 ` [PATCH v3 13/14] isci: remove bus and reset handlers Dan Williams
2012-01-06  1:00 ` [PATCH v3 14/14] isci: remove IDEV_EH hack to disable "discovery-time" ata resets Dan Williams
2012-01-06  1:46 ` [GIT PATCH v3 00/14] libsas: eh reworks (ata-eh vs discovery, races, ...) Dan Williams

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=20120106005925.11464.3339.stgit@localhost6.localdomain6 \
    --to=dan.j.williams@intel.com \
    --cc=linux-ide@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox