aboutsummaryrefslogtreecommitdiffstats
path: root/include/scsi
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-12-22 00:33:17 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-29 14:01:06 -0500
commitf41a0c441c3fe43e79ebeb75584dbb5bfa83e5cd (patch)
tree5a53adb90ebf31888184a9bff16ccc1869e2e4b3 /include/scsi
parent3a9c5560f677690f65038f399f4f598c79b83186 (diff)
[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 <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'include/scsi')
-rw-r--r--include/scsi/libsas.h9
-rw-r--r--include/scsi/scsi_transport_sas.h6
2 files changed, 13 insertions, 2 deletions
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 {
192 struct domain_device *parent; 192 struct domain_device *parent;
193 struct list_head siblings; /* devices on the same level */ 193 struct list_head siblings; /* devices on the same level */
194 struct asd_sas_port *port; /* shortcut to root of the tree */ 194 struct asd_sas_port *port; /* shortcut to root of the tree */
195 struct sas_phy *phy;
195 196
196 struct list_head dev_list_node; 197 struct list_head dev_list_node;
197 struct list_head disco_list_node; /* awaiting probe or destruct */ 198 struct list_head disco_list_node; /* awaiting probe or destruct */
@@ -243,7 +244,6 @@ struct asd_sas_port {
243 struct list_head destroy_list; 244 struct list_head destroy_list;
244 enum sas_linkrate linkrate; 245 enum sas_linkrate linkrate;
245 246
246 struct sas_phy *phy;
247 struct work_struct work; 247 struct work_struct work;
248 248
249/* public: */ 249/* public: */
@@ -429,6 +429,11 @@ static inline unsigned int to_sas_gpio_od(int device, int bit)
429 return 3 * device + bit; 429 return 3 * device + bit;
430} 430}
431 431
432static inline void sas_put_local_phy(struct sas_phy *phy)
433{
434 put_device(&phy->dev);
435}
436
432#ifdef CONFIG_SCSI_SAS_HOST_SMP 437#ifdef CONFIG_SCSI_SAS_HOST_SMP
433int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count); 438int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count);
434#else 439#else
@@ -684,7 +689,7 @@ extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
684 689
685extern void sas_ssp_task_response(struct device *dev, struct sas_task *task, 690extern void sas_ssp_task_response(struct device *dev, struct sas_task *task,
686 struct ssp_response_iu *iu); 691 struct ssp_response_iu *iu);
687struct sas_phy *sas_find_local_phy(struct domain_device *dev); 692struct sas_phy *sas_get_local_phy(struct domain_device *dev);
688 693
689int sas_request_addr(struct Scsi_Host *shost, u8 *addr); 694int sas_request_addr(struct Scsi_Host *shost, u8 *addr);
690 695
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 42817facaeda..98b3a20a0102 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -209,6 +209,12 @@ void sas_port_add_phy(struct sas_port *, struct sas_phy *);
209void sas_port_delete_phy(struct sas_port *, struct sas_phy *); 209void sas_port_delete_phy(struct sas_port *, struct sas_phy *);
210void sas_port_mark_backlink(struct sas_port *); 210void sas_port_mark_backlink(struct sas_port *);
211int scsi_is_sas_port(const struct device *); 211int scsi_is_sas_port(const struct device *);
212struct sas_phy *sas_port_get_phy(struct sas_port *port);
213static inline void sas_port_put_phy(struct sas_phy *phy)
214{
215 if (phy)
216 put_device(&phy->dev);
217}
212 218
213extern struct scsi_transport_template * 219extern struct scsi_transport_template *
214sas_attach_transport(struct sas_function_template *); 220sas_attach_transport(struct sas_function_template *);