diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_tmf.c | 9 | ||||
-rw-r--r-- | drivers/scsi/isci/task.c | 9 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 7 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_discover.c | 24 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 5 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_internal.h | 1 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_port.c | 7 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 38 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.c | 3 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 19 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 23 |
11 files changed, 103 insertions, 42 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, | |||
181 | int asd_I_T_nexus_reset(struct domain_device *dev) | 181 | int 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 | ||
217 | static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun) | 220 | static 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, | |||
1332 | static int isci_reset_device(struct isci_host *ihost, | 1332 | static 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 | ||
315 | void 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 *); |
88 | int sas_smp_get_phy_events(struct sas_phy *phy); | 88 | int sas_smp_get_phy_events(struct sas_phy *phy); |
89 | 89 | ||
90 | void sas_device_set_phy(struct domain_device *dev, struct sas_port *port); | ||
90 | struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); | 91 | struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); |
91 | struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); | 92 | struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); |
92 | int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id, | 93 | int 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 */ |
443 | struct sas_phy *sas_find_local_phy(struct domain_device *dev) | 443 | struct 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 | } |
465 | EXPORT_SYMBOL_GPL(sas_find_local_phy); | 461 | EXPORT_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 */ |
468 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | 464 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) |
@@ -489,7 +485,7 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
489 | int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) | 485 | int 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, | |||
1474 | static int mvs_debug_I_T_nexus_reset(struct domain_device *dev) | 1474 | static 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) | |||
1060 | EXPORT_SYMBOL(scsi_is_sas_port); | 1060 | EXPORT_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 | */ | ||
1066 | struct 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 | } | ||
1083 | EXPORT_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 |