From b218a0d8e250e0ae8fd4d4e45bd66a588b380752 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:14:55 -0800 Subject: [SCSI] libsas: Don't give scsi_cmnds to the EH if they never made it to the SAS LLDD or have already returned On a system with many SAS targets, it appears possible that a scsi_cmnd can time out without ever making it to the SAS LLDD or at the same time that a completion is occurring. In both of these cases, telling the LLDD to abort the sas_task makes no sense because the LLDD won't know about the sas_task; what we really want to do is to increase the timer. Note that this involves creating another sas_task bit to indicate whether or not the task has been sent to the LLDD; I could have implemented this by slightly redefining SAS_TASK_STATE_PENDING, but this way seems cleaner. This second version amends the aic94xx portion to set the TASK_AT_INITIATOR flag for all sas_tasks that were passed to lldd_execute_task. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 0c775fc..da96bcf 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -554,6 +554,7 @@ struct sas_task { #define SAS_TASK_STATE_DONE 2 #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) { -- cgit v1.1 From acbf167d4ad8c27f9743a4b539d51ae9535bf21c Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:14:57 -0800 Subject: [SCSI] libsas: Add a sysfs knob to enable/disable a phy This patch lets a user arbitrarily enable or disable a phy via sysfs. Potential applications include shutting down a phy to replace one lane of wide port, and (more importantly) providing a method for the libata SATL to control the phy. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- include/scsi/libsas.h | 3 +++ include/scsi/scsi_transport_sas.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index da96bcf..0689d66 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -614,6 +614,9 @@ struct sas_domain_function_template { extern int sas_register_ha(struct sas_ha_struct *); extern int sas_unregister_ha(struct sas_ha_struct *); +int sas_set_phy_speed(struct sas_phy *phy, + struct sas_phy_linkrates *rates); +int sas_phy_enable(struct sas_phy *phy, int enabled); int sas_phy_reset(struct sas_phy *phy, int hard_reset); extern int sas_queuecommand(struct scsi_cmnd *, void (*scsi_done)(struct scsi_cmnd *)); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 59633a82d..45d5859 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -54,6 +54,7 @@ struct sas_identify { struct sas_phy { struct device dev; int number; + int enabled; /* phy identification */ struct sas_identify identify; @@ -163,6 +164,7 @@ struct sas_function_template { int (*get_enclosure_identifier)(struct sas_rphy *, u64 *); int (*get_bay_identifier)(struct sas_rphy *); int (*phy_reset)(struct sas_phy *, int); + int (*phy_enable)(struct sas_phy *, int); int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *); }; -- cgit v1.1 From 37958fb040cf6f88b354b9fa7e846014ffbd3b73 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:15 -0800 Subject: [SCSI] libsas: Remove SAS_TASK_INITIATOR_ABORTED flag This flag is no longer necessary because we push tasks to be aborted into the EH as soon as we possibly can, and let the SCSI EH code take care of the coordination for which this flag was used. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 0689d66..1d39485 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -553,7 +553,6 @@ struct sas_task { #define SAS_TASK_STATE_PENDING 1 #define SAS_TASK_STATE_DONE 2 #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) -- cgit v1.1 From 3ebf6922b0833807e54c73f4794c74baf9945fc8 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:17 -0800 Subject: [SCSI] libsas: Enable the EH strategy handler to reset a phy after a command When a SAS LLDD needs to request a device port reset, it needs to have all commands aborted before it can reset the port. Since commands are put on the EH's list in the order that they were queued, the LLDD can set a "need reset" flag in the last task to be aborted so that the EH can reset the port after all commands are aborted. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 1d39485..75df71f 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -553,6 +553,7 @@ struct sas_task { #define SAS_TASK_STATE_PENDING 1 #define SAS_TASK_STATE_DONE 2 #define SAS_TASK_STATE_ABORTED 4 +#define SAS_TASK_NEED_DEV_RESET 8 #define SAS_TASK_AT_INITIATOR 16 static inline struct sas_task *sas_alloc_task(gfp_t flags) -- cgit v1.1 From 396819fba821ad56f1b90090d256f0ab726c89c5 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:20 -0800 Subject: [SCSI] libsas: Delay issuing ABORT TASK TMF until the error handler sas_task_abort() should simply abort the upper-level SCSI command and wait until the error handler to send the actual ABORT TASK command. By deferring things to the EH we simplify the concurrency coordination and eliminate some race conditions. Note that sas_task_abort has a few hooks to handle libsas internal commands properly too. Also rename do_sas_task_abort to __sas_task_abort just in case we really want to abort the task *right now* and we don't have a scsi_cmnd attached to the command. This is a hook for libata internal commands to abort. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- include/scsi/libsas.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 75df71f..c834263 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -650,6 +650,7 @@ void sas_unregister_dev(struct domain_device *); void sas_init_dev(struct domain_device *); -void sas_task_abort(struct work_struct *); +void sas_task_abort(struct sas_task *); +int __sas_task_abort(struct sas_task *); #endif /* _SASLIB_H_ */ -- cgit v1.1 From 6b0efb8516a5298e12033df61f9e0c376a306adb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:43 -0800 Subject: [SCSI] libsas: Add SAS_HA state flags to avoid queueing events while unloading Track sas_ha_struct state so that we ignore events that come in while we're shutting things down. Signed-off-by: Malahal Naineni Signed-off-by: James Bottomley --- include/scsi/libsas.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index c834263..ca39392 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -323,12 +323,20 @@ struct sas_ha_event { struct sas_ha_struct *ha; }; +enum sas_ha_state { + SAS_HA_REGISTERED, + SAS_HA_UNREGISTERED +}; + struct sas_ha_struct { /* private: */ spinlock_t event_lock; struct sas_ha_event ha_events[HA_NUM_EVENTS]; unsigned long pending; + enum sas_ha_state state; + spinlock_t state_lock; + struct scsi_core core; /* public: */ -- cgit v1.1 From 6f63caae2172e97e528b58319480217b0b36542e Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:43 -0800 Subject: [SCSI] libsas: Clean up discovery failure handler code sas_rphy_delete does two things: it removes the sas_rphy from the transport layer and frees the sas_rphy. This can be broken down into two functions, sas_rphy_remove and sas_rphy_free; sas_rphy_remove is of interest to sas_discover_root_expander because it calls functions that require sas_rphy_add as a prerequisite and can fail (namely sas_discover_expander). In that case, sas_discover_root_expander needs to be able to undo the effects of sas_rphy_add yet leave the job of freeing the sas_rphy to the caller of sas_discover_root_expander. This patch also removes some unnecessary code from sas_discover_end_dev to eliminate an unnecessary cycle of sas_notify_lldd_gone/found for SAS devices, thus eliminating a sas_rphy_remove call (and fixing a race condition where a SCSI target scan can come in between the gone and found call). It also moves the sas_rphy_free calls into sas_discover_domain and sas_ex_discover_end_dev to complement the sas_rphy_allocation via sas_get_port_device. This patch does not change the semantics of sas_rphy_delete. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- include/scsi/scsi_transport_sas.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 45d5859..9aedc19 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -182,6 +182,7 @@ extern struct sas_rphy *sas_end_device_alloc(struct sas_port *); extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type); void sas_rphy_free(struct sas_rphy *); extern int sas_rphy_add(struct sas_rphy *); +extern void sas_rphy_remove(struct sas_rphy *); extern void sas_rphy_delete(struct sas_rphy *); extern int scsi_is_sas_rphy(const struct device *); -- cgit v1.1 From ad689233bee854dced741c91aff12a8771a22f6f Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:52 -0800 Subject: [SCSI] libsas: Handle SCSI commands that complete with failure codes This patch moves the code that handles SAS failures out of the main EH function and into a separate function. It also detects commands that have no sas_task (i.e. they completed, but with error data) and sends them into scsi_error for processing. This allows us to handle SCSI errors (and enables auto-spinup as a side effect) instead of dropping them on the floor and falling into an infinite loop. It also requires the implementation of a device reset function, which the SAS failure code has been modified to employ for REQ_DEVICE_RESET. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index ca39392..b200233 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -660,5 +660,6 @@ void sas_init_dev(struct domain_device *); void sas_task_abort(struct sas_task *); int __sas_task_abort(struct sas_task *); +int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); #endif /* _SASLIB_H_ */ -- cgit v1.1 From 502c62f17aa7daa78d5da963305251b872885ff9 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:41:12 -0700 Subject: [SCSI] spi transport class: export spi_dv_pending Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- include/scsi/scsi_transport_spi.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index da180f7..286e962 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h @@ -85,6 +85,7 @@ struct spi_host_attrs { #define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en) #define spi_hold_mcs(x) (((struct spi_transport_attrs *)&(x)->starget_data)->hold_mcs) #define spi_initial_dv(x) (((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv) +#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) #define spi_support_sync(x) (((struct spi_transport_attrs *)&(x)->starget_data)->support_sync) #define spi_support_wide(x) (((struct spi_transport_attrs *)&(x)->starget_data)->support_wide) -- cgit v1.1 From a9344e68ac0a656475006737dbc258d69fe4f7b0 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 29 Jan 2007 23:48:19 -0800 Subject: [SCSI] libsas: Add an LU reset mechanism to the error handler After discussion with andmike and dougg, it seems that the purpose of eh_device_reset_handler is to issue LU resets, and that eh_bus_reset_handler would be a more appropriate place for a phy reset. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index b200233..8516ba6 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -661,5 +661,6 @@ void sas_init_dev(struct domain_device *); void sas_task_abort(struct sas_task *); int __sas_task_abort(struct sas_task *); int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); +int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd); #endif /* _SASLIB_H_ */ -- cgit v1.1