aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/isci/port.c31
-rw-r--r--drivers/scsi/isci/port.h3
-rw-r--r--drivers/scsi/isci/task.c24
3 files changed, 37 insertions, 21 deletions
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index f9d20c1e63ca..e55ef65f5212 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -305,7 +305,9 @@ static void port_state_machine_change(struct isci_port *iport,
305static void isci_port_hard_reset_complete(struct isci_port *isci_port, 305static void isci_port_hard_reset_complete(struct isci_port *isci_port,
306 enum sci_status completion_status) 306 enum sci_status completion_status)
307{ 307{
308 dev_dbg(&isci_port->isci_host->pdev->dev, 308 struct isci_host *ihost = isci_port->owning_controller;
309
310 dev_dbg(&ihost->pdev->dev,
309 "%s: isci_port = %p, completion_status=%x\n", 311 "%s: isci_port = %p, completion_status=%x\n",
310 __func__, isci_port, completion_status); 312 __func__, isci_port, completion_status);
311 313
@@ -316,23 +318,24 @@ static void isci_port_hard_reset_complete(struct isci_port *isci_port,
316 318
317 /* The reset failed. The port state is now SCI_PORT_FAILED. */ 319 /* The reset failed. The port state is now SCI_PORT_FAILED. */
318 if (isci_port->active_phy_mask == 0) { 320 if (isci_port->active_phy_mask == 0) {
321 int phy_idx = isci_port->last_active_phy;
322 struct isci_phy *iphy = &ihost->phys[phy_idx];
319 323
320 /* Generate the link down now to the host, since it 324 /* Generate the link down now to the host, since it
321 * was intercepted by the hard reset state machine when 325 * was intercepted by the hard reset state machine when
322 * it really happened. 326 * it really happened.
323 */ 327 */
324 isci_port_link_down(isci_port->isci_host, 328 isci_port_link_down(ihost, iphy, isci_port);
325 &isci_port->isci_host->phys[
326 isci_port->last_active_phy],
327 isci_port);
328 } 329 }
329 /* Advance the port state so that link state changes will be 330 /* Advance the port state so that link state changes will be
330 * noticed. 331 * noticed.
331 */ 332 */
332 port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING); 333 port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING);
333 334
334 } 335 }
335 complete_all(&isci_port->hard_reset_complete); 336 clear_bit(IPORT_RESET_PENDING, &isci_port->state);
337 wake_up(&ihost->eventq);
338
336} 339}
337 340
338/* This method will return a true value if the specified phy can be assigned to 341/* This method will return a true value if the specified phy can be assigned to
@@ -1610,6 +1613,11 @@ void sci_port_broadcast_change_received(struct isci_port *iport, struct isci_phy
1610 isci_port_bc_change_received(ihost, iport, iphy); 1613 isci_port_bc_change_received(ihost, iport, iphy);
1611} 1614}
1612 1615
1616static void wait_port_reset(struct isci_host *ihost, struct isci_port *iport)
1617{
1618 wait_event(ihost->eventq, !test_bit(IPORT_RESET_PENDING, &iport->state));
1619}
1620
1613int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport, 1621int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport,
1614 struct isci_phy *iphy) 1622 struct isci_phy *iphy)
1615{ 1623{
@@ -1620,9 +1628,8 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
1620 dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n", 1628 dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n",
1621 __func__, iport); 1629 __func__, iport);
1622 1630
1623 init_completion(&iport->hard_reset_complete);
1624
1625 spin_lock_irqsave(&ihost->scic_lock, flags); 1631 spin_lock_irqsave(&ihost->scic_lock, flags);
1632 set_bit(IPORT_RESET_PENDING, &iport->state);
1626 1633
1627 #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT 1634 #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT
1628 status = sci_port_hard_reset(iport, ISCI_PORT_RESET_TIMEOUT); 1635 status = sci_port_hard_reset(iport, ISCI_PORT_RESET_TIMEOUT);
@@ -1630,7 +1637,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
1630 spin_unlock_irqrestore(&ihost->scic_lock, flags); 1637 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1631 1638
1632 if (status == SCI_SUCCESS) { 1639 if (status == SCI_SUCCESS) {
1633 wait_for_completion(&iport->hard_reset_complete); 1640 wait_port_reset(ihost, iport);
1634 1641
1635 dev_dbg(&ihost->pdev->dev, 1642 dev_dbg(&ihost->pdev->dev,
1636 "%s: iport = %p; hard reset completion\n", 1643 "%s: iport = %p; hard reset completion\n",
@@ -1644,6 +1651,8 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
1644 __func__, iport, iport->hard_reset_status); 1651 __func__, iport, iport->hard_reset_status);
1645 } 1652 }
1646 } else { 1653 } else {
1654 clear_bit(IPORT_RESET_PENDING, &iport->state);
1655 wake_up(&ihost->eventq);
1647 ret = TMF_RESP_FUNC_FAILED; 1656 ret = TMF_RESP_FUNC_FAILED;
1648 1657
1649 dev_err(&ihost->pdev->dev, 1658 dev_err(&ihost->pdev->dev,
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index 265972939e3a..a0dcdaeac3b2 100644
--- a/drivers/scsi/isci/port.h
+++ b/drivers/scsi/isci/port.h
@@ -98,7 +98,8 @@ struct isci_port {
98 struct isci_host *isci_host; 98 struct isci_host *isci_host;
99 struct list_head remote_dev_list; 99 struct list_head remote_dev_list;
100 struct list_head domain_dev_list; 100 struct list_head domain_dev_list;
101 struct completion hard_reset_complete; 101 #define IPORT_RESET_PENDING 0
102 unsigned long state;
102 enum sci_status hard_reset_status; 103 enum sci_status hard_reset_status;
103 struct sci_base_state_machine sm; 104 struct sci_base_state_machine sm;
104 bool ready_exit; 105 bool ready_exit;
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index b96e6044eda9..c4d324ccee11 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -1330,29 +1330,35 @@ isci_task_request_complete(struct isci_host *ihost,
1330} 1330}
1331 1331
1332static int isci_reset_device(struct isci_host *ihost, 1332static int isci_reset_device(struct isci_host *ihost,
1333 struct domain_device *dev,
1333 struct isci_remote_device *idev) 1334 struct isci_remote_device *idev)
1334{ 1335{
1335 struct sas_phy *phy = sas_get_local_phy(idev->domain_dev);
1336 enum sci_status status;
1337 unsigned long flags;
1338 int rc; 1336 int rc;
1337 unsigned long flags;
1338 enum sci_status status;
1339 struct sas_phy *phy = sas_get_local_phy(dev);
1340 struct isci_port *iport = dev->port->lldd_port;
1339 1341
1340 dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); 1342 dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev);
1341 1343
1342 spin_lock_irqsave(&ihost->scic_lock, flags); 1344 spin_lock_irqsave(&ihost->scic_lock, flags);
1343 status = sci_remote_device_reset(idev); 1345 status = sci_remote_device_reset(idev);
1344 if (status != SCI_SUCCESS) { 1346 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1345 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1346 1347
1348 if (status != SCI_SUCCESS) {
1347 dev_dbg(&ihost->pdev->dev, 1349 dev_dbg(&ihost->pdev->dev,
1348 "%s: sci_remote_device_reset(%p) returned %d!\n", 1350 "%s: sci_remote_device_reset(%p) returned %d!\n",
1349 __func__, idev, status); 1351 __func__, idev, status);
1350 rc = TMF_RESP_FUNC_FAILED; 1352 rc = TMF_RESP_FUNC_FAILED;
1351 goto out; 1353 goto out;
1352 } 1354 }
1353 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1354 1355
1355 rc = sas_phy_reset(phy, true); 1356 if (scsi_is_sas_phy_local(phy)) {
1357 struct isci_phy *iphy = &ihost->phys[phy->number];
1358
1359 rc = isci_port_perform_hard_reset(ihost, iport, iphy);
1360 } else
1361 rc = sas_phy_reset(phy, !dev_is_sata(dev));
1356 1362
1357 /* Terminate in-progress I/O now. */ 1363 /* Terminate in-progress I/O now. */
1358 isci_remote_device_nuke_requests(ihost, idev); 1364 isci_remote_device_nuke_requests(ihost, idev);
@@ -1390,7 +1396,7 @@ int isci_task_I_T_nexus_reset(struct domain_device *dev)
1390 goto out; 1396 goto out;
1391 } 1397 }
1392 1398
1393 ret = isci_reset_device(ihost, idev); 1399 ret = isci_reset_device(ihost, dev, idev);
1394 out: 1400 out:
1395 isci_put_device(idev); 1401 isci_put_device(idev);
1396 return ret; 1402 return ret;
@@ -1413,7 +1419,7 @@ int isci_bus_reset_handler(struct scsi_cmnd *cmd)
1413 goto out; 1419 goto out;
1414 } 1420 }
1415 1421
1416 ret = isci_reset_device(ihost, idev); 1422 ret = isci_reset_device(ihost, dev, idev);
1417 out: 1423 out:
1418 isci_put_device(idev); 1424 isci_put_device(idev);
1419 return ret; 1425 return ret;