From 95ac7fd189b7e81a200b4d00b2bb6669b31acf3a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Nov 2011 17:59:45 -0800 Subject: [SCSI] libsas: remove unused ata_task_resp fields Commit 1e34c838 "[SCSI] libsas: remove spurious sata control register read/write" removed the routines to fake the presence of the sata control registers, now remove the unused data structure fields to kill any remaining confusion. Acked-by: Jack Wang Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 6a308d42d98f..6e64b038c649 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -171,9 +171,6 @@ struct sata_device { struct ata_port *ap; struct ata_host ata_host; struct ata_taskfile tf; - u32 sstatus; - u32 serror; - u32 scontrol; }; /* ---------- Domain device ---------- */ @@ -487,10 +484,6 @@ enum exec_status { struct ata_task_resp { u16 frame_len; u8 ending_fis[24]; /* dev to host or data-in */ - u32 sstatus; - u32 serror; - u32 scontrol; - u32 sactive; }; #define SAS_STATUS_BUF_SIZE 96 -- cgit v1.2.3 From 6f4e75a49fd07d707995865493b9f452302ae36b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Nov 2011 17:59:46 -0800 Subject: [SCSI] libsas: kill sas_slave_destroy Per commit 3e4ec344 "libata: kill ATA_FLAG_DISABLED" needing to set ATA_DEV_NONE is a holdover from before libsas converted to the "new-style" ata-eh. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 6e64b038c649..2b14348336d6 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -625,7 +625,6 @@ extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *); extern int sas_target_alloc(struct scsi_target *); extern int sas_slave_alloc(struct scsi_device *); extern int sas_slave_configure(struct scsi_device *); -extern void sas_slave_destroy(struct scsi_device *); extern int sas_change_queue_depth(struct scsi_device *, int new_depth, int reason); extern int sas_change_queue_type(struct scsi_device *, int qt); -- cgit v1.2.3 From 735f7d2fedf57380214221be7bed7f62d729e262 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Nov 2011 17:59:47 -0800 Subject: [SCSI] libsas: fix domain_device leak Arrange for the deallocation of a struct domain_device object when it no longer has: 1/ any children 2/ references by any scsi_targets 3/ references by a lldd The comment about domain_device lifetime in Documentation/scsi/libsas.txt is stale as it appears mainline never had a version of a struct domain_device that was registered as a kobject. We now manage domain_device reference counts on behalf of external agents. Reviewed-by: Jack Wang Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 2b14348336d6..7ecb5c1c0851 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -206,6 +206,7 @@ struct domain_device { void *lldd_dev; int gone; + struct kref kref; }; struct sas_discovery_event { -- cgit v1.2.3 From b15ebe0b5d0b95aeb1d84cae3649df1e0e065e9b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Nov 2011 17:59:49 -0800 Subject: [SCSI] libsas: replace event locks with atomic bitops The locks only served to make sure the pending event bitmask was updated consistently. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 7ecb5c1c0851..de63a664b5e5 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -215,7 +215,6 @@ struct sas_discovery_event { }; struct sas_discovery { - spinlock_t disc_event_lock; struct sas_discovery_event disc_work[DISC_NUM_EVENTS]; unsigned long pending; u8 fanout_sas_addr[8]; @@ -272,7 +271,6 @@ struct asd_sas_event { */ struct asd_sas_phy { /* private: */ - /* protected by ha->event_lock */ struct asd_sas_event port_events[PORT_NUM_EVENTS]; struct asd_sas_event phy_events[PHY_NUM_EVENTS]; @@ -337,7 +335,6 @@ enum sas_ha_state { struct sas_ha_struct { /* private: */ - spinlock_t event_lock; struct sas_ha_event ha_events[HA_NUM_EVENTS]; unsigned long pending; -- cgit v1.2.3 From f8daa6e6d83f60a721752cb53433bfdc1503b45f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 19 Dec 2011 17:02:25 -0800 Subject: [SCSI] libsas: convert ha->state to flags In preparation for adding new states (SAS_HA_DRAINING, SAS_HA_FROZEN), convert ha->state into a set of flags. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index de63a664b5e5..8e402d5a0640 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -330,7 +330,6 @@ struct sas_ha_event { enum sas_ha_state { SAS_HA_REGISTERED, - SAS_HA_UNREGISTERED }; struct sas_ha_struct { @@ -338,7 +337,7 @@ struct sas_ha_struct { struct sas_ha_event ha_events[HA_NUM_EVENTS]; unsigned long pending; - enum sas_ha_state state; + unsigned long state; spinlock_t state_lock; struct scsi_core core; -- cgit v1.2.3 From b1124cd3ec97406c767b90bf7e93ecd2d2915592 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 19 Dec 2011 16:42:34 -0800 Subject: [SCSI] libsas: introduce sas_drain_work() When an lldd invokes ->notify_port_event() it can trigger a chain of libsas events to: 1/ form the port and find the direct attached device 2/ if the attached device is an expander perform domain discovery A call to flush_workqueue() will only flush the initial port formation work. Currently libsas users need to call scsi_flush_work() up to the max depth of chain (which will grow from 2 to 3 when ata discovery is moved to its own discovery event). Instead of open coding multiple calls switch to use drain_workqueue() to flush sas work. drain_workqueue() does not handle new work submitted during the drain so libsas needs a bit of infrastructure to hold off unchained work submissions while a drain is in flight. A lldd ->notify() event is considered 'unchained' while a sas_discover_event() is 'chained'. As Tejun notes: "For now, I think it would be best to add private wrapper in libsas to support deferring unchained work items while draining." Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 8e402d5a0640..42900fa95a03 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -330,6 +330,7 @@ struct sas_ha_event { enum sas_ha_state { SAS_HA_REGISTERED, + SAS_HA_DRAINING, }; struct sas_ha_struct { @@ -337,6 +338,8 @@ struct sas_ha_struct { struct sas_ha_event ha_events[HA_NUM_EVENTS]; unsigned long pending; + struct list_head defer_q; /* work queued while draining */ + struct mutex drain_mutex; unsigned long state; spinlock_t state_lock; @@ -657,6 +660,7 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd); extern void sas_target_destroy(struct scsi_target *); extern int sas_slave_alloc(struct scsi_device *); extern int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg); +extern int sas_drain_work(struct sas_ha_struct *ha); extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, struct request *req); -- cgit v1.2.3 From e139942d77a6e3ac83bc322e826668054a8601d6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 7 Jan 2012 08:52:39 +0000 Subject: [SCSI] libsas: convert dev->gone to flags In preparation for adding tracking of another device state "destroy". Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 42900fa95a03..d792b13cfcf5 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -173,7 +173,10 @@ struct sata_device { struct ata_taskfile tf; }; -/* ---------- Domain device ---------- */ +enum { + SAS_DEV_GONE, +}; + struct domain_device { enum sas_dev_type dev_type; @@ -205,7 +208,7 @@ struct domain_device { }; void *lldd_dev; - int gone; + unsigned long state; struct kref kref; }; -- cgit v1.2.3 From 87c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Nov 2011 17:59:51 -0800 Subject: [SCSI] libsas: prevent domain rediscovery competing with ata error handling libata error handling provides for a timeout for link recovery. libsas must not rescan for previously known devices in this interval otherwise it may remove a device that is simply waiting for its link to recover. Let libata-eh make the determination of when the link is stable and prevent libsas (host workqueue) from taking action while this determination is pending. Using a mutex (ha->disco_mutex) to flush and disable revalidation while eh is running requires any discovery action that may block on eh be moved to its own context outside the lock. Probing ATA devices explicitly waits on ata-eh and the cache-flush-io issued during device removal may also pend awaiting eh completion. Essentially any rphy add/remove activity needs to run outside the lock. This adds two new cleanup states for sas_unregister_domain_devices() 'allocated-but-not-probed', and 'flagged-for-destruction'. In the 'allocated-but-not-probed' state dev->rphy points to a rphy that is known to have not been through a sas_rphy_add() event. At domain teardown check if this device is still pending probe and cleanup accordingly. Similarly if a device has already been queued for removal then sas_unregister_domain_devices has nothing to do. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index d792b13cfcf5..bd6e89ece2ab 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -86,7 +86,9 @@ enum discover_event { DISCE_DISCOVER_DOMAIN = 0U, DISCE_REVALIDATE_DOMAIN = 1, DISCE_PORT_GONE = 2, - DISC_NUM_EVENTS = 3, + DISCE_PROBE = 3, + DISCE_DESTRUCT = 4, + DISC_NUM_EVENTS = 5, }; /* ---------- Expander Devices ---------- */ @@ -175,6 +177,7 @@ struct sata_device { enum { SAS_DEV_GONE, + SAS_DEV_DESTROY, }; struct domain_device { @@ -191,6 +194,7 @@ struct domain_device { struct asd_sas_port *port; /* shortcut to root of the tree */ struct list_head dev_list_node; + struct list_head disco_list_node; /* awaiting probe or destruct */ enum sas_protocol iproto; enum sas_protocol tproto; @@ -226,7 +230,6 @@ struct sas_discovery { int max_level; }; - /* The port struct is Class:RW, driver:RO */ struct asd_sas_port { /* private: */ @@ -236,6 +239,8 @@ struct asd_sas_port { struct domain_device *port_dev; spinlock_t dev_list_lock; struct list_head dev_list; + struct list_head disco_list; + struct list_head destroy_list; enum sas_linkrate linkrate; struct sas_phy *phy; @@ -334,6 +339,7 @@ struct sas_ha_event { enum sas_ha_state { SAS_HA_REGISTERED, SAS_HA_DRAINING, + SAS_HA_ATA_EH_ACTIVE, }; struct sas_ha_struct { @@ -346,6 +352,8 @@ struct sas_ha_struct { unsigned long state; spinlock_t state_lock; + struct mutex disco_mutex; + struct scsi_core core; /* public: */ -- cgit v1.2.3 From b91bb296188118eea9fdc6093cfcf76bbe8589ba Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Nov 2011 17:59:52 -0800 Subject: [SCSI] libsas: use ->set_dmamode to notify lldds of NCQ parameters sas_discover_sata() notifies lldds of sata devices twice. Once to allow the 'identify' to be sent, and a second time to allow aic94xx (the only libsas driver that cares about sata_dev.identify) to setup NCQ parameters before the device becomes known to the midlayer. Replace this double notification and intervening 'identify' with an explicit ->lldd_ata_set_dmamode notification. With this change all ata internal commands are issued by libata, so we no longer need sas_issue_ata_cmd(). The data from the identify command only needs to be cached in one location so ata_device.id replaces domain_device.sata_dev.identify. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index bd6e89ece2ab..9c13a5c0bb3a 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -164,9 +164,6 @@ enum ata_command_set { struct sata_device { enum ata_command_set command_set; struct smp_resp rps_resp; /* report_phy_sata_resp */ - __le16 *identify_device; - __le16 *identify_packet_device; - u8 port_no; /* port number, if this is a PM (Port) */ struct list_head children; /* PM Ports if this is a PM */ @@ -609,6 +606,7 @@ struct sas_domain_function_template { int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); int (*lldd_I_T_nexus_reset)(struct domain_device *); int (*lldd_ata_soft_reset)(struct domain_device *); + void (*lldd_ata_set_dmamode)(struct domain_device *); int (*lldd_lu_reset)(struct domain_device *, u8 *lun); int (*lldd_query_task)(struct sas_task *); -- cgit v1.2.3 From 3dff5721e4f67e6231dfc419d30aaa7563bfffd4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 28 Nov 2011 12:08:22 -0800 Subject: [SCSI] libsas: close error handling vs sas_ata_task_done() race Since sas_ata does not implement ->freeze(), completions for scmds and internal commands can still arrive concurrent with ata_scsi_cmd_error_handler() and sas_ata_post_internal() respectively. By the time either of those is called libata has committed to completing the qc, and the ATA_PFLAG_FROZEN flag tells sas_ata_task_done() it has lost the race. In the sas_ata_post_internal() case we take on the additional responsibility of freeing the sas_task to close the race with sas_ata_task_done() freeing the the task while sas_ata_post_internal() is in the process of invoking ->lldd_abort_task(). Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 9c13a5c0bb3a..10eb2ea74431 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -662,7 +662,6 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *); 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); -- cgit v1.2.3 From a3a142524aa4b1539a64a55087bf12ffa4b1f94e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Dec 2011 23:24:42 -0800 Subject: [SCSI] libsas: prevent double completion of scmds from eh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We invoke task->task_done() to free the task in the eh case, but at this point we are prepared for scsi_eh_flush_done_q() to finish off the scmd. Introduce sas_end_task() to capture the final response status from the lldd and free the task. Also take the opportunity to kill this warning. drivers/scsi/libsas/sas_scsi_host.c: In function ‘sas_end_task’: drivers/scsi/libsas/sas_scsi_host.c:102:3: warning: case value ‘2’ not in enumerated type ‘enum exec_status’ [-Wswitch] Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 10eb2ea74431..071041b290d6 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -452,7 +452,10 @@ enum service_response { }; enum exec_status { - /* The SAM_STAT_.. codes fit in the lower 6 bits */ + /* The SAM_STAT_.. codes fit in the lower 6 bits, alias some of + * them here to silence 'case value not in enumerated type' warnings + */ + __SAM_STAT_CHECK_CONDITION = SAM_STAT_CHECK_CONDITION, SAS_DEV_NO_RESPONSE = 0x80, SAS_DATA_UNDERRUN, -- cgit v1.2.3 From 9095a64a9aead653df320e3a6fc70835c15d46e4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 28 Nov 2011 11:29:20 -0800 Subject: [SCSI] libsas: fix timeout vs completion race Until we have told the lldd to forget a task a timed out operation can return from the hardware at any time. Since completion frees the task we need to make sure that no tasks run their normal completion handler once eh has decided to manage the task. Similar to ata_scsi_cmd_error_handler() freeze completions to let eh judge the outcome of the race. Task collector mode is problematic because it presents a situation where a task can be timed out and aborted before the lldd has even seen it. For this case we need to guarantee that a task that an lldd has been told to forget does not get queued after the lldd says "never seen it". With sas_scsi_timed_out we achieve this with the ->task_queue_flush mutex, rather than adding more time. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 071041b290d6..aa7192ff4355 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -178,6 +178,7 @@ enum { }; struct domain_device { + spinlock_t done_lock; enum sas_dev_type dev_type; enum sas_linkrate linkrate; @@ -321,6 +322,7 @@ struct asd_sas_phy { struct scsi_core { struct Scsi_Host *shost; + struct mutex task_queue_flush; spinlock_t task_queue_lock; struct list_head task_queue; int task_queue_size; @@ -337,6 +339,7 @@ enum sas_ha_state { SAS_HA_REGISTERED, SAS_HA_DRAINING, SAS_HA_ATA_EH_ACTIVE, + SAS_HA_FROZEN, }; struct sas_ha_struct { -- cgit v1.2.3 From 3944f50995f947558c35fb16ae0288354756762c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 29 Nov 2011 12:08:50 -0800 Subject: [SCSI] libsas: let libata handle command timeouts libsas-eh if it successfully aborts an ata command will hide the timeout condition (AC_ERR_TIMEOUT) from libata. The command likely completes with the all-zero task->task_status it started with. Instead, interpret a TMF_RESP_FUNC_COMPLETE as the end of the sas_task but keep the scmd around for libata-eh to handle. Tested-by: Andrzej Jakowski Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index aa7192ff4355..6b80310e08af 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -382,7 +382,8 @@ struct sas_ha_struct { void *lldd_ha; /* not touched by sas class code */ - struct list_head eh_done_q; + struct list_head eh_done_q; /* complete via scsi_eh_flush_done_q */ + struct list_head eh_ata_q; /* scmds to promote from sas to ata eh */ }; #define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) -- cgit v1.2.3 From 2a559f4ba443265b4c58925b48296f1cf81b49f9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 4 Dec 2011 00:06:57 -0800 Subject: [SCSI] libsas: sas_phy_enable via transport_sas_phy_reset Execute the link-reset triggered by sas_phy_enable via transport_sas_phy_reset so that it can be managed by libata. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 6b80310e08af..f388ba536128 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -634,7 +634,6 @@ 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); int sas_queue_up(struct sas_task *task); extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *); -- cgit v1.2.3 From 89d3cf6ac3cdc4f15a82709f8c78ed169a98be5b Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Wed, 16 Nov 2011 09:44:13 +0000 Subject: [SCSI] libsas: add mutex for SMP task execution SAS does not tag SMP requests, and at least one lldd (isci) does not permit more than one in-flight request at a time. [jejb: fix sas_init_dev tab issues while we're at it] Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index f388ba536128..18704a2e4f07 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -153,6 +153,8 @@ struct expander_device { struct ex_phy *ex_phy; struct sas_port *parent_port; + + struct mutex cmd_mutex; }; /* ---------- SATA device ---------- */ -- cgit v1.2.3 From 36a399473902a57218dc493c5a814708a56b73ab Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Nov 2011 17:59:54 -0800 Subject: [SCSI] libsas: poll for ata device readiness after reset Use ata_wait_after_reset() to poll for link recovery after a reset. This combined with sas_ha->eh_mutex prevents expander rediscovery from probing phys in an intermediate state. Local discovery does not have a mechanism to filter link status changes during this timeout, so it remains the responsibility of lldds to prevent premature port teardown. Although once all lldd's support ->lldd_ata_check_ready() that could be used as a gate to local port teardown. The signature fis is re-transmitted when the link comes back so we should be revalidating the ata device class, but that is left to a future patch. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 18704a2e4f07..2079b18467a1 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -615,6 +615,7 @@ struct sas_domain_function_template { int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); int (*lldd_I_T_nexus_reset)(struct domain_device *); int (*lldd_ata_soft_reset)(struct domain_device *); + int (*lldd_ata_check_ready)(struct domain_device *); void (*lldd_ata_set_dmamode)(struct domain_device *); int (*lldd_lu_reset)(struct domain_device *, u8 *lun); int (*lldd_query_task)(struct sas_task *); -- cgit v1.2.3 From f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cd Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 21 Dec 2011 21:33:17 -0800 Subject: [SCSI] libsas: fix sas_find_local_phy(), take phy references In the direct-attached case this routine returns the phy on which this device was first discovered. Which is broken if we want to support wide-targets, as this phy reference can become stale even though the port is still active. In the expander-attached case this routine tries to lookup the phy by scanning the attached sas addresses of the parent expander, and BUG_ONs if it can't find it. However since eh and the libsas workqueue run independently we can still be attempting device recovery via eh after libsas has recorded the device as detached. This is even easier to hit now that eh is blocked while device domain rediscovery takes place, and that libata is fed more timed out commands increasing the chances that it will try to recover the ata device. Arrange for dev->phy to always point to a last known good phy, it may be stale after the port is torn down, but it will catch up for wide port reconfigurations, and never be NULL. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 2079b18467a1..55bab8633807 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -192,6 +192,7 @@ struct domain_device { struct domain_device *parent; struct list_head siblings; /* devices on the same level */ struct asd_sas_port *port; /* shortcut to root of the tree */ + struct sas_phy *phy; struct list_head dev_list_node; struct list_head disco_list_node; /* awaiting probe or destruct */ @@ -243,7 +244,6 @@ struct asd_sas_port { struct list_head destroy_list; enum sas_linkrate linkrate; - struct sas_phy *phy; struct work_struct work; /* public: */ @@ -429,6 +429,11 @@ static inline unsigned int to_sas_gpio_od(int device, int bit) return 3 * device + bit; } +static inline void sas_put_local_phy(struct sas_phy *phy) +{ + put_device(&phy->dev); +} + #ifdef CONFIG_SCSI_SAS_HOST_SMP int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count); #else @@ -684,7 +689,7 @@ extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, extern void sas_ssp_task_response(struct device *dev, struct sas_task *task, struct ssp_response_iu *iu); -struct sas_phy *sas_find_local_phy(struct domain_device *dev); +struct sas_phy *sas_get_local_phy(struct domain_device *dev); int sas_request_addr(struct Scsi_Host *shost, u8 *addr); -- cgit v1.2.3 From 7d05919aad080074453de880822fe5805875645f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 Jan 2012 14:39:13 -0800 Subject: [SCSI] libsas: mark all domain devices gone if root port disappears If the top level expander is hot removed, mark all child devices as gone before unregistration to short circuit futile recovery. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 55bab8633807..4a42be34fad0 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -664,7 +664,7 @@ void sas_init_ex_attr(void); int sas_ex_revalidate_domain(struct domain_device *); -void sas_unregister_domain_devices(struct asd_sas_port *port); +void sas_unregister_domain_devices(struct asd_sas_port *port, int gone); void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *); int sas_discover_event(struct asd_sas_port *, enum discover_event ev); -- cgit v1.2.3 From 9508a66f898d46e726a318469312b45e0b1d078b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 18 Jan 2012 20:47:01 -0800 Subject: [SCSI] libsas: async ata scanning libsas ata error handling is already async but this does not help the scan case. Move initial link recovery out from under host->scan_mutex, and delay synchronization with eh until after all port probe/recovery work has been queued. Device ordering is maintained with scan order by still calling sas_rphy_add() in order of domain discovery. Since we now scan the domain list when invoking libata-eh we need to be careful to check for fully initialized ata ports. Acked-by: Jack Wang Acked-by: Jeff Garzik Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 4a42be34fad0..20153d58e4e6 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -646,7 +646,6 @@ int sas_phy_reset(struct sas_phy *phy, int hard_reset); int sas_queue_up(struct sas_task *task); extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *); extern int sas_target_alloc(struct scsi_target *); -extern int sas_slave_alloc(struct scsi_device *); extern int sas_slave_configure(struct scsi_device *); extern int sas_change_queue_depth(struct scsi_device *, int new_depth, int reason); -- cgit v1.2.3 From 9a10b33caf78f897356ac006c455e6060a40af15 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 20 Jan 2012 15:26:03 -0800 Subject: [SCSI] libsas: revert ata srst libata issues follow up srsts when the controller has a hard time recording the signature-fis after a reset, or if the link supports port multipliers. libsas does not support port multipliers and no current libsas lldds appear to need help retrieving the signature fis. Revert it for now to remove confusion. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- include/scsi/libsas.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/scsi/libsas.h') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 20153d58e4e6..5f5ed1b8b41b 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -619,7 +619,6 @@ struct sas_domain_function_template { int (*lldd_clear_aca)(struct domain_device *, u8 *lun); int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); int (*lldd_I_T_nexus_reset)(struct domain_device *); - int (*lldd_ata_soft_reset)(struct domain_device *); int (*lldd_ata_check_ready)(struct domain_device *); void (*lldd_ata_set_dmamode)(struct domain_device *); int (*lldd_lu_reset)(struct domain_device *, u8 *lun); -- cgit v1.2.3