aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/port.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-11-30 14:57:34 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-29 16:11:54 -0500
commit9277699121b81891e303ada0a53fa1d04b7ffe72 (patch)
treeed8fde54c953025be2a59697dd912f581536c782 /drivers/scsi/isci/port.c
parentfca4ecbdc440337b3c257b38c2f4cc8d0ca0286c (diff)
[SCSI] isci: fix interpretation of "hard" reset
A hard reset to isci in the direct-attached case is one where the driver internally manages debouncing the link. In the sas-expander-attached case a hard reset is one that clears affiliations. The driver should not be prematurely dropping affiliations at run time, that decision (to force expander hard resets to ata devices) is left to userspace to manage. So, arrange for I_T_nexus resets to be sas-link-resets in the expander-attached case and isci-hard-resets in the direct-attached case. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/isci/port.c')
-rw-r--r--drivers/scsi/isci/port.c31
1 files changed, 20 insertions, 11 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,