aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/aic94xx/aic94xx_tmf.c9
-rw-r--r--drivers/scsi/isci/task.c9
-rw-r--r--drivers/scsi/libsas/sas_ata.c7
-rw-r--r--drivers/scsi/libsas/sas_discover.c24
-rw-r--r--drivers/scsi/libsas/sas_expander.c5
-rw-r--r--drivers/scsi/libsas/sas_internal.h1
-rw-r--r--drivers/scsi/libsas/sas_port.c7
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c38
-rw-r--r--drivers/scsi/mvsas/mv_sas.c3
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c19
-rw-r--r--drivers/scsi/scsi_transport_sas.c23
-rw-r--r--include/scsi/libsas.h9
-rw-r--r--include/scsi/scsi_transport_sas.h6
13 files changed, 116 insertions, 44 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index 0add73bdf2a4..50b914ffab94 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -181,7 +181,7 @@ static int asd_clear_nexus_I_T(struct domain_device *dev,
181int asd_I_T_nexus_reset(struct domain_device *dev) 181int asd_I_T_nexus_reset(struct domain_device *dev)
182{ 182{
183 int res, tmp_res, i; 183 int res, tmp_res, i;
184 struct sas_phy *phy = sas_find_local_phy(dev); 184 struct sas_phy *phy = sas_get_local_phy(dev);
185 /* Standard mandates link reset for ATA (type 0) and 185 /* Standard mandates link reset for ATA (type 0) and
186 * hard reset for SSP (type 1) */ 186 * hard reset for SSP (type 1) */
187 int reset_type = (dev->dev_type == SATA_DEV || 187 int reset_type = (dev->dev_type == SATA_DEV ||
@@ -201,7 +201,7 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
201 for (i = 0 ; i < 3; i++) { 201 for (i = 0 ; i < 3; i++) {
202 tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME); 202 tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME);
203 if (tmp_res == TC_RESUME) 203 if (tmp_res == TC_RESUME)
204 return res; 204 goto out;
205 msleep(500); 205 msleep(500);
206 } 206 }
207 207
@@ -211,7 +211,10 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
211 dev_printk(KERN_ERR, &phy->dev, 211 dev_printk(KERN_ERR, &phy->dev,
212 "Failed to resume nexus after reset 0x%x\n", tmp_res); 212 "Failed to resume nexus after reset 0x%x\n", tmp_res);
213 213
214 return TMF_RESP_FUNC_FAILED; 214 res = TMF_RESP_FUNC_FAILED;
215 out:
216 sas_put_local_phy(phy);
217 return res;
215} 218}
216 219
217static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun) 220static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun)
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 4bd88ef83cdf..b96e6044eda9 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -1332,7 +1332,7 @@ isci_task_request_complete(struct isci_host *ihost,
1332static int isci_reset_device(struct isci_host *ihost, 1332static int isci_reset_device(struct isci_host *ihost,
1333 struct isci_remote_device *idev) 1333 struct isci_remote_device *idev)
1334{ 1334{
1335 struct sas_phy *phy = sas_find_local_phy(idev->domain_dev); 1335 struct sas_phy *phy = sas_get_local_phy(idev->domain_dev);
1336 enum sci_status status; 1336 enum sci_status status;
1337 unsigned long flags; 1337 unsigned long flags;
1338 int rc; 1338 int rc;
@@ -1347,8 +1347,8 @@ static int isci_reset_device(struct isci_host *ihost,
1347 dev_dbg(&ihost->pdev->dev, 1347 dev_dbg(&ihost->pdev->dev,
1348 "%s: sci_remote_device_reset(%p) returned %d!\n", 1348 "%s: sci_remote_device_reset(%p) returned %d!\n",
1349 __func__, idev, status); 1349 __func__, idev, status);
1350 1350 rc = TMF_RESP_FUNC_FAILED;
1351 return TMF_RESP_FUNC_FAILED; 1351 goto out;
1352 } 1352 }
1353 spin_unlock_irqrestore(&ihost->scic_lock, flags); 1353 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1354 1354
@@ -1369,7 +1369,8 @@ static int isci_reset_device(struct isci_host *ihost,
1369 } 1369 }
1370 1370
1371 dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev); 1371 dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev);
1372 1372 out:
1373 sas_put_local_phy(phy);
1373 return rc; 1374 return rc;
1374} 1375}
1375 1376
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 5fdb63ad94b7..92f7e78a096c 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -284,9 +284,10 @@ static int smp_ata_check_ready(struct ata_link *link)
284 struct ata_port *ap = link->ap; 284 struct ata_port *ap = link->ap;
285 struct domain_device *dev = ap->private_data; 285 struct domain_device *dev = ap->private_data;
286 struct domain_device *ex_dev = dev->parent; 286 struct domain_device *ex_dev = dev->parent;
287 struct sas_phy *phy = sas_find_local_phy(dev); 287 struct sas_phy *phy = sas_get_local_phy(dev);
288 288
289 res = sas_get_phy_attached_sas_addr(ex_dev, phy->number, addr); 289 res = sas_get_phy_attached_sas_addr(ex_dev, phy->number, addr);
290 sas_put_local_phy(phy);
290 /* break the wait early if the expander is unreachable, 291 /* break the wait early if the expander is unreachable,
291 * otherwise keep polling 292 * otherwise keep polling
292 */ 293 */
@@ -319,10 +320,10 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
319 unsigned long deadline) 320 unsigned long deadline)
320{ 321{
321 int ret = 0, res; 322 int ret = 0, res;
323 struct sas_phy *phy;
322 struct ata_port *ap = link->ap; 324 struct ata_port *ap = link->ap;
323 int (*check_ready)(struct ata_link *link); 325 int (*check_ready)(struct ata_link *link);
324 struct domain_device *dev = ap->private_data; 326 struct domain_device *dev = ap->private_data;
325 struct sas_phy *phy = sas_find_local_phy(dev);
326 struct sas_internal *i = dev_to_sas_internal(dev); 327 struct sas_internal *i = dev_to_sas_internal(dev);
327 328
328 res = i->dft->lldd_I_T_nexus_reset(dev); 329 res = i->dft->lldd_I_T_nexus_reset(dev);
@@ -330,10 +331,12 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
330 if (res != TMF_RESP_FUNC_COMPLETE) 331 if (res != TMF_RESP_FUNC_COMPLETE)
331 SAS_DPRINTK("%s: Unable to reset ata device?\n", __func__); 332 SAS_DPRINTK("%s: Unable to reset ata device?\n", __func__);
332 333
334 phy = sas_get_local_phy(dev);
333 if (scsi_is_sas_phy_local(phy)) 335 if (scsi_is_sas_phy_local(phy))
334 check_ready = local_ata_check_ready; 336 check_ready = local_ata_check_ready;
335 else 337 else
336 check_ready = smp_ata_check_ready; 338 check_ready = smp_ata_check_ready;
339 sas_put_local_phy(phy);
337 340
338 ret = ata_wait_after_reset(link, deadline, check_ready); 341 ret = ata_wait_after_reset(link, deadline, check_ready);
339 if (ret && ret != -EAGAIN) 342 if (ret && ret != -EAGAIN)
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index c56cc6400819..789b50861bb9 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -147,6 +147,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
147 memset(port->disc.eeds_a, 0, SAS_ADDR_SIZE); 147 memset(port->disc.eeds_a, 0, SAS_ADDR_SIZE);
148 memset(port->disc.eeds_b, 0, SAS_ADDR_SIZE); 148 memset(port->disc.eeds_b, 0, SAS_ADDR_SIZE);
149 port->disc.max_level = 0; 149 port->disc.max_level = 0;
150 sas_device_set_phy(dev, port->port);
150 151
151 dev->rphy = rphy; 152 dev->rphy = rphy;
152 153
@@ -234,6 +235,9 @@ void sas_free_device(struct kref *kref)
234 if (dev->parent) 235 if (dev->parent)
235 sas_put_device(dev->parent); 236 sas_put_device(dev->parent);
236 237
238 sas_port_put_phy(dev->phy);
239 dev->phy = NULL;
240
237 /* remove the phys and ports, everything else should be gone */ 241 /* remove the phys and ports, everything else should be gone */
238 if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) 242 if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV)
239 kfree(dev->ex_dev.ex_phy); 243 kfree(dev->ex_dev.ex_phy);
@@ -308,6 +312,26 @@ void sas_unregister_domain_devices(struct asd_sas_port *port)
308 312
309} 313}
310 314
315void sas_device_set_phy(struct domain_device *dev, struct sas_port *port)
316{
317 struct sas_ha_struct *ha;
318 struct sas_phy *new_phy;
319
320 if (!dev)
321 return;
322
323 ha = dev->port->ha;
324 new_phy = sas_port_get_phy(port);
325
326 /* pin and record last seen phy */
327 spin_lock_irq(&ha->phy_port_lock);
328 if (new_phy) {
329 sas_port_put_phy(dev->phy);
330 dev->phy = new_phy;
331 }
332 spin_unlock_irq(&ha->phy_port_lock);
333}
334
311/* ---------- Discovery and Revalidation ---------- */ 335/* ---------- Discovery and Revalidation ---------- */
312 336
313/** 337/**
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 6fb1f3afd1e0..68a80a00f73f 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -723,6 +723,7 @@ static struct domain_device *sas_ex_discover_end_dev(
723 } 723 }
724 } 724 }
725 sas_ex_get_linkrate(parent, child, phy); 725 sas_ex_get_linkrate(parent, child, phy);
726 sas_device_set_phy(child, phy->port);
726 727
727#ifdef CONFIG_SCSI_SAS_ATA 728#ifdef CONFIG_SCSI_SAS_ATA
728 if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) { 729 if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) {
@@ -1810,7 +1811,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
1810{ 1811{
1811 struct expander_device *ex_dev = &parent->ex_dev; 1812 struct expander_device *ex_dev = &parent->ex_dev;
1812 struct ex_phy *phy = &ex_dev->ex_phy[phy_id]; 1813 struct ex_phy *phy = &ex_dev->ex_phy[phy_id];
1813 struct domain_device *child, *n; 1814 struct domain_device *child, *n, *found = NULL;
1814 if (last) { 1815 if (last) {
1815 list_for_each_entry_safe(child, n, 1816 list_for_each_entry_safe(child, n,
1816 &ex_dev->children, siblings) { 1817 &ex_dev->children, siblings) {
@@ -1822,6 +1823,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
1822 sas_unregister_ex_tree(parent->port, child); 1823 sas_unregister_ex_tree(parent->port, child);
1823 else 1824 else
1824 sas_unregister_dev(parent->port, child); 1825 sas_unregister_dev(parent->port, child);
1826 found = child;
1825 break; 1827 break;
1826 } 1828 }
1827 } 1829 }
@@ -1830,6 +1832,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
1830 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 1832 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
1831 if (phy->port) { 1833 if (phy->port) {
1832 sas_port_delete_phy(phy->port, phy->phy); 1834 sas_port_delete_phy(phy->port, phy->phy);
1835 sas_device_set_phy(found, phy->port);
1833 if (phy->port->num_phys == 0) 1836 if (phy->port->num_phys == 0)
1834 sas_port_delete(phy->port); 1837 sas_port_delete(phy->port);
1835 phy->port = NULL; 1838 phy->port = NULL;
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index a9a3bb94c1bc..c8febc71c40d 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -87,6 +87,7 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id,
87 enum phy_func phy_func, struct sas_phy_linkrates *); 87 enum phy_func phy_func, struct sas_phy_linkrates *);
88int sas_smp_get_phy_events(struct sas_phy *phy); 88int sas_smp_get_phy_events(struct sas_phy *phy);
89 89
90void sas_device_set_phy(struct domain_device *dev, struct sas_port *port);
90struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); 91struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
91struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); 92struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
92int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id, 93int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id,
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index 2980bde4e34a..31adcd1b4191 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -108,9 +108,6 @@ static void sas_form_port(struct asd_sas_phy *phy)
108 port->num_phys++; 108 port->num_phys++;
109 port->phy_mask |= (1U << phy->id); 109 port->phy_mask |= (1U << phy->id);
110 110
111 if (!port->phy)
112 port->phy = phy->phy;
113
114 if (*(u64 *)port->attached_sas_addr == 0) { 111 if (*(u64 *)port->attached_sas_addr == 0) {
115 port->class = phy->class; 112 port->class = phy->class;
116 memcpy(port->attached_sas_addr, phy->attached_sas_addr, 113 memcpy(port->attached_sas_addr, phy->attached_sas_addr,
@@ -175,8 +172,10 @@ void sas_deform_port(struct asd_sas_phy *phy, int gone)
175 sas_unregister_domain_devices(port); 172 sas_unregister_domain_devices(port);
176 sas_port_delete(port->port); 173 sas_port_delete(port->port);
177 port->port = NULL; 174 port->port = NULL;
178 } else 175 } else {
179 sas_port_delete_phy(port->port, phy->phy); 176 sas_port_delete_phy(port->port, phy->phy);
177 sas_device_set_phy(dev, port->port);
178 }
180 179
181 if (si->dft->lldd_port_deformed) 180 if (si->dft->lldd_port_deformed)
182 si->dft->lldd_port_deformed(phy); 181 si->dft->lldd_port_deformed(phy);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 5cc44fddfe95..94ef76316c31 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -439,30 +439,26 @@ static int sas_recover_I_T(struct domain_device *dev)
439 return res; 439 return res;
440} 440}
441 441
442/* Find the sas_phy that's attached to this device */ 442/* take a reference on the last known good phy for this device */
443struct sas_phy *sas_find_local_phy(struct domain_device *dev) 443struct sas_phy *sas_get_local_phy(struct domain_device *dev)
444{ 444{
445 struct domain_device *pdev = dev->parent; 445 struct sas_ha_struct *ha = dev->port->ha;
446 struct ex_phy *exphy = NULL; 446 struct sas_phy *phy;
447 int i; 447 unsigned long flags;
448 448
449 /* Directly attached device */ 449 /* a published domain device always has a valid phy, it may be
450 if (!pdev) 450 * stale, but it is never NULL
451 return dev->port->phy; 451 */
452 BUG_ON(!dev->phy);
452 453
453 /* Otherwise look in the expander */ 454 spin_lock_irqsave(&ha->phy_port_lock, flags);
454 for (i = 0; i < pdev->ex_dev.num_phys; i++) 455 phy = dev->phy;
455 if (!memcmp(dev->sas_addr, 456 get_device(&phy->dev);
456 pdev->ex_dev.ex_phy[i].attached_sas_addr, 457 spin_unlock_irqrestore(&ha->phy_port_lock, flags);
457 SAS_ADDR_SIZE)) {
458 exphy = &pdev->ex_dev.ex_phy[i];
459 break;
460 }
461 458
462 BUG_ON(!exphy); 459 return phy;
463 return exphy->phy;
464} 460}
465EXPORT_SYMBOL_GPL(sas_find_local_phy); 461EXPORT_SYMBOL_GPL(sas_get_local_phy);
466 462
467/* Attempt to send a LUN reset message to a device */ 463/* Attempt to send a LUN reset message to a device */
468int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) 464int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
@@ -489,7 +485,7 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
489int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) 485int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
490{ 486{
491 struct domain_device *dev = cmd_to_domain_dev(cmd); 487 struct domain_device *dev = cmd_to_domain_dev(cmd);
492 struct sas_phy *phy = sas_find_local_phy(dev); 488 struct sas_phy *phy = sas_get_local_phy(dev);
493 int res; 489 int res;
494 490
495 res = sas_phy_reset(phy, 1); 491 res = sas_phy_reset(phy, 1);
@@ -497,6 +493,8 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
497 SAS_DPRINTK("Bus reset of %s failed 0x%x\n", 493 SAS_DPRINTK("Bus reset of %s failed 0x%x\n",
498 kobject_name(&phy->dev.kobj), 494 kobject_name(&phy->dev.kobj),
499 res); 495 res);
496 sas_put_local_phy(phy);
497
500 if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) 498 if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
501 return SUCCESS; 499 return SUCCESS;
502 500
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index cd882230591f..b68a65390f0d 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -1474,10 +1474,11 @@ static int mvs_debug_issue_ssp_tmf(struct domain_device *dev,
1474static int mvs_debug_I_T_nexus_reset(struct domain_device *dev) 1474static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)
1475{ 1475{
1476 int rc; 1476 int rc;
1477 struct sas_phy *phy = sas_find_local_phy(dev); 1477 struct sas_phy *phy = sas_get_local_phy(dev);
1478 int reset_type = (dev->dev_type == SATA_DEV || 1478 int reset_type = (dev->dev_type == SATA_DEV ||
1479 (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; 1479 (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
1480 rc = sas_phy_reset(phy, reset_type); 1480 rc = sas_phy_reset(phy, reset_type);
1481 sas_put_local_phy(phy);
1481 msleep(2000); 1482 msleep(2000);
1482 return rc; 1483 return rc;
1483} 1484}
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 310860e37d98..3b11edd4a50c 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -967,12 +967,14 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
967 967
968 pm8001_dev = dev->lldd_dev; 968 pm8001_dev = dev->lldd_dev;
969 pm8001_ha = pm8001_find_ha_by_dev(dev); 969 pm8001_ha = pm8001_find_ha_by_dev(dev);
970 phy = sas_find_local_phy(dev); 970 phy = sas_get_local_phy(dev);
971 971
972 if (dev_is_sata(dev)) { 972 if (dev_is_sata(dev)) {
973 DECLARE_COMPLETION_ONSTACK(completion_setstate); 973 DECLARE_COMPLETION_ONSTACK(completion_setstate);
974 if (scsi_is_sas_phy_local(phy)) 974 if (scsi_is_sas_phy_local(phy)) {
975 return 0; 975 rc = 0;
976 goto out;
977 }
976 rc = sas_phy_reset(phy, 1); 978 rc = sas_phy_reset(phy, 1);
977 msleep(2000); 979 msleep(2000);
978 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , 980 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
@@ -981,12 +983,14 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
981 rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, 983 rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
982 pm8001_dev, 0x01); 984 pm8001_dev, 0x01);
983 wait_for_completion(&completion_setstate); 985 wait_for_completion(&completion_setstate);
984 } else{ 986 } else {
985 rc = sas_phy_reset(phy, 1); 987 rc = sas_phy_reset(phy, 1);
986 msleep(2000); 988 msleep(2000);
987 } 989 }
988 PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n", 990 PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
989 pm8001_dev->device_id, rc)); 991 pm8001_dev->device_id, rc));
992 out:
993 sas_put_local_phy(phy);
990 return rc; 994 return rc;
991} 995}
992 996
@@ -998,10 +1002,11 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
998 struct pm8001_device *pm8001_dev = dev->lldd_dev; 1002 struct pm8001_device *pm8001_dev = dev->lldd_dev;
999 struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); 1003 struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
1000 if (dev_is_sata(dev)) { 1004 if (dev_is_sata(dev)) {
1001 struct sas_phy *phy = sas_find_local_phy(dev); 1005 struct sas_phy *phy = sas_get_local_phy(dev);
1002 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , 1006 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
1003 dev, 1, 0); 1007 dev, 1, 0);
1004 rc = sas_phy_reset(phy, 1); 1008 rc = sas_phy_reset(phy, 1);
1009 sas_put_local_phy(phy);
1005 rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, 1010 rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
1006 pm8001_dev, 0x01); 1011 pm8001_dev, 0x01);
1007 msleep(2000); 1012 msleep(2000);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index ab3bd0b5ffd9..7d69a25d2004 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -1060,6 +1060,29 @@ int scsi_is_sas_port(const struct device *dev)
1060EXPORT_SYMBOL(scsi_is_sas_port); 1060EXPORT_SYMBOL(scsi_is_sas_port);
1061 1061
1062/** 1062/**
1063 * sas_port_get_phy - try to take a reference on a port member
1064 * @port: port to check
1065 */
1066struct sas_phy *sas_port_get_phy(struct sas_port *port)
1067{
1068 struct sas_phy *phy;
1069
1070 mutex_lock(&port->phy_list_mutex);
1071 if (list_empty(&port->phy_list))
1072 phy = NULL;
1073 else {
1074 struct list_head *ent = port->phy_list.next;
1075
1076 phy = list_entry(ent, typeof(*phy), port_siblings);
1077 get_device(&phy->dev);
1078 }
1079 mutex_unlock(&port->phy_list_mutex);
1080
1081 return phy;
1082}
1083EXPORT_SYMBOL(sas_port_get_phy);
1084
1085/**
1063 * sas_port_add_phy - add another phy to a port to form a wide port 1086 * sas_port_add_phy - add another phy to a port to form a wide port
1064 * @port: port to add the phy to 1087 * @port: port to add the phy to
1065 * @phy: phy to add 1088 * @phy: phy to add
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 *);